Asterisk - The Open Source Telephony Project  18.5.0
Data Structures | Macros | Enumerations | Functions | Variables
res_pjsip_session.c File Reference
#include "asterisk.h"
#include <pjsip.h>
#include <pjsip_ua.h>
#include <pjlib.h>
#include <pjmedia.h>
#include "asterisk/res_pjsip.h"
#include "asterisk/res_pjsip_session.h"
#include "asterisk/res_pjsip_session_caps.h"
#include "asterisk/callerid.h"
#include "asterisk/datastore.h"
#include "asterisk/module.h"
#include "asterisk/logger.h"
#include "asterisk/astobj2.h"
#include "asterisk/lock.h"
#include "asterisk/uuid.h"
#include "asterisk/pbx.h"
#include "asterisk/taskprocessor.h"
#include "asterisk/causes.h"
#include "asterisk/sdp_srtp.h"
#include "asterisk/dsp.h"
#include "asterisk/acl.h"
#include "asterisk/features_config.h"
#include "asterisk/pickup.h"
#include "asterisk/test.h"
#include "asterisk/stream.h"
#include "asterisk/vector.h"
Include dependency graph for res_pjsip_session.c:

Go to the source code of this file.

Data Structures

struct  ast_sip_session_delayed_request
 Structure used for sending delayed requests. More...
 
struct  ast_sip_session_suspender
 struct controlling the suspension of the session's serializer. More...
 
struct  new_invite
 
struct  sdp_handler_list
 
struct  sip_session_media_bundle_group
 Bundle group building structure. More...
 

Macros

#define CHECKER()
 
#define DATASTORE_BUCKETS   53
 
#define DEFAULT_NUM_SESSION_MEDIA   2
 
#define FREE_STATE()
 
#define GET_STREAM_NAME_SAFE(_stream)   (_stream ? ast_stream_get_name(_stream) : "")
 
#define GET_STREAM_SAFE(_topology, _i)   (_i < ast_stream_topology_get_count(_topology) ? ast_stream_topology_get_stream(_topology, _i) : NULL)
 
#define GET_STREAM_STATE_SAFE(_stream)   (_stream ? ast_stream_get_state(_stream) : AST_STREAM_STATE_END)
 
#define MEDIA_BUCKETS   7
 
#define MOD_DATA_NAT_HOOK   "nat_hook"
 
#define MOD_DATA_ON_RESPONSE   "on_response"
 
#define print_debug_details(inv, tsx, e)   __print_debug_details(__PRETTY_FUNCTION__, (inv), (tsx), (e))
 
#define RESET_STATE(__num)
 
#define SDP_HANDLER_BUCKETS   11
 
#define STATE_NONE(_stream_state)   (_stream_state == AST_STREAM_STATE_END)
 
#define STATE_REMOVED(_stream_state)   (_stream_state == AST_STREAM_STATE_REMOVED)
 
#define STREAM_REMOVED(_stream)   (ast_stream_get_state(_stream) == AST_STREAM_STATE_REMOVED)
 

Enumerations

enum  delayed_method { DELAYED_METHOD_INVITE, DELAYED_METHOD_UPDATE, DELAYED_METHOD_BYE }
 
enum  sip_get_destination_result { SIP_GET_DEST_EXTEN_FOUND, SIP_GET_DEST_EXTEN_NOT_FOUND, SIP_GET_DEST_EXTEN_PARTIAL, SIP_GET_DEST_UNSUPPORTED_URI }
 

Functions

static void __print_debug_details (const char *function, pjsip_inv_session *inv, pjsip_transaction *tsx, pjsip_event *e)
 
static void __reg_module (void)
 
static void __unreg_module (void)
 
static int add_bundle_groups (struct ast_sip_session *session, pj_pool_t *pool, pjmedia_sdp_session *answer)
 
static int add_sdp_streams (struct ast_sip_session_media *session_media, struct ast_sip_session *session, pjmedia_sdp_session *answer, const struct pjmedia_sdp_session *remote, struct ast_stream *stream)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
struct ast_sip_channel_pvtast_sip_channel_pvt_alloc (void *pvt, struct ast_sip_session *session)
 Allocate a new SIP channel pvt structure. More...
 
struct ast_sip_sessionast_sip_dialog_get_session (pjsip_dialog *dlg)
 Retrieves a session from a dialog. More...
 
int ast_sip_session_add_datastore (struct ast_sip_session *session, struct ast_datastore *datastore)
 Add a datastore to a SIP session. More...
 
struct ast_sip_sessionast_sip_session_alloc (struct ast_sip_endpoint *endpoint, struct ast_sip_contact *contact, pjsip_inv_session *inv_session, pjsip_rx_data *rdata)
 Allocate a new SIP session. More...
 
struct ast_datastoreast_sip_session_alloc_datastore (const struct ast_datastore_info *info, const char *uid)
 Alternative for ast_datastore_alloc() More...
 
int ast_sip_session_create_invite (struct ast_sip_session *session, pjsip_tx_data **tdata)
 Creates an INVITE request. More...
 
struct ast_sip_sessionast_sip_session_create_outgoing (struct ast_sip_endpoint *endpoint, struct ast_sip_contact *contact, const char *location, const char *request_user, struct ast_stream_topology *req_topology)
 Create a new outgoing SIP session. More...
 
int ast_sip_session_defer_termination (struct ast_sip_session *session)
 Defer local termination of a session until remote side terminates, or an amount of time passes. More...
 
void ast_sip_session_defer_termination_cancel (struct ast_sip_session *session)
 Cancel a pending deferred termination. More...
 
void ast_sip_session_end_if_deferred (struct ast_sip_session *session)
 End the session if it had been previously deferred. More...
 
struct ast_datastoreast_sip_session_get_datastore (struct ast_sip_session *session, const char *name)
 Retrieve a session datastore. More...
 
const char * ast_sip_session_get_name (const struct ast_sip_session *session)
 Get the channel or endpoint name associated with the session. More...
 
int ast_sip_session_is_pending_stream_default (const struct ast_sip_session *session, const struct ast_stream *stream)
 Determines if a provided pending stream will be the default stream or not. More...
 
int ast_sip_session_media_add_read_callback (struct ast_sip_session *session, struct ast_sip_session_media *session_media, int fd, ast_sip_session_media_read_cb callback)
 Set a read callback for a media session with a specific file descriptor. More...
 
struct ast_sip_session_mediaast_sip_session_media_get_transport (struct ast_sip_session *session, struct ast_sip_session_media *session_media)
 Retrieve the underlying media session that is acting as transport for a media session. More...
 
int ast_sip_session_media_set_write_callback (struct ast_sip_session *session, struct ast_sip_session_media *session_media, ast_sip_session_media_write_cb callback)
 Set a write callback for a media session. More...
 
struct ast_sip_session_mediaast_sip_session_media_state_add (struct ast_sip_session *session, struct ast_sip_session_media_state *media_state, enum ast_media_type type, int position)
 Allocate an ast_session_media and add it to the media state's vector. More...
 
struct ast_sip_session_media_stateast_sip_session_media_state_alloc (void)
 Allocate a session media state structure. More...
 
struct ast_sip_session_media_stateast_sip_session_media_state_clone (const struct ast_sip_session_media_state *media_state)
 Clone a media state. More...
 
void ast_sip_session_media_state_free (struct ast_sip_session_media_state *media_state)
 Free a session media state structure. More...
 
void ast_sip_session_media_state_reset (struct ast_sip_session_media_state *media_state)
 Reset a media state to a clean state. More...
 
void ast_sip_session_media_stats_save (struct ast_sip_session *sip_session, struct ast_sip_session_media_state *media_state)
 Save a media stats. More...
 
int ast_sip_session_refresh (struct ast_sip_session *session, ast_sip_session_request_creation_cb on_request_creation, ast_sip_session_sdp_creation_cb on_sdp_creation, ast_sip_session_response_cb on_response, enum ast_sip_session_refresh_method method, int generate_new_sdp, struct ast_sip_session_media_state *media_state)
 Send a reinvite or UPDATE on a session. More...
 
int ast_sip_session_regenerate_answer (struct ast_sip_session *session, ast_sip_session_sdp_creation_cb on_sdp_creation)
 Regenerate SDP Answer. More...
 
int ast_sip_session_register_sdp_handler (struct ast_sip_session_sdp_handler *handler, const char *stream_type)
 Register an SDP handler. More...
 
void ast_sip_session_remove_datastore (struct ast_sip_session *session, const char *name)
 Remove a session datastore from the session. More...
 
void ast_sip_session_resume_reinvite (struct ast_sip_session *session)
 Resumes processing of a deferred incoming re-invite. More...
 
void ast_sip_session_send_request (struct ast_sip_session *session, pjsip_tx_data *tdata)
 Send a SIP request. More...
 
void ast_sip_session_send_request_with_cb (struct ast_sip_session *session, pjsip_tx_data *tdata, ast_sip_session_response_cb on_response)
 Send a SIP request and get called back when a response is received. More...
 
void ast_sip_session_send_response (struct ast_sip_session *session, pjsip_tx_data *tdata)
 Send a SIP response. More...
 
void ast_sip_session_suspend (struct ast_sip_session *session)
 Request and wait for the session serializer to be suspended. More...
 
void ast_sip_session_terminate (struct ast_sip_session *session, int response)
 Terminate a session and, if possible, send the provided response code. More...
 
void ast_sip_session_unregister_sdp_handler (struct ast_sip_session_sdp_handler *handler, const char *stream_type)
 Unregister an SDP handler. More...
 
void ast_sip_session_unsuspend (struct ast_sip_session *session)
 Request the session serializer be unsuspended. More...
 
 AST_TEST_DEFINE (test_resolve_refresh_media_states)
 
static int check_content_disposition (pjsip_rx_data *rdata)
 
static int check_content_disposition_in_multipart (pjsip_multipart_part *part)
 
static void check_delayed_requests (struct ast_sip_session *session, int(*cb)(void *vsession))
 
static int check_request_status (pjsip_inv_session *inv, pjsip_event *e)
 
static int check_sdp_content_type_supported (pjsip_media_type *content_type)
 
static struct pjmedia_sdp_session * create_local_sdp (pjsip_inv_session *inv, struct ast_sip_session *session, const pjmedia_sdp_session *offer)
 
static int datastore_cmp (void *obj, void *arg, int flags)
 
static int datastore_hash (const void *obj, int flags)
 
static int delay_request (struct ast_sip_session *session, ast_sip_session_request_creation_cb on_request, ast_sip_session_sdp_creation_cb on_sdp_creation, ast_sip_session_response_cb on_response, int generate_new_sdp, enum delayed_method method, struct ast_sip_session_media_state *pending_media_state, struct ast_sip_session_media_state *active_media_state, int queue_head)
 
static const char * delayed_method2str (enum delayed_method method)
 
static struct ast_sip_session_delayed_requestdelayed_request_alloc (enum delayed_method method, ast_sip_session_request_creation_cb on_request_creation, ast_sip_session_sdp_creation_cb on_sdp_creation, ast_sip_session_response_cb on_response, int generate_new_sdp, struct ast_sip_session_media_state *pending_media_state, struct ast_sip_session_media_state *active_media_state)
 
static void delayed_request_free (struct ast_sip_session_delayed_request *delay)
 
static pj_bool_t does_method_match (const pj_str_t *message_method, const char *supplement_method)
 
static pjmedia_sdp_session * generate_session_refresh_sdp (struct ast_sip_session *session)
 
static enum sip_get_destination_result get_destination (struct ast_sip_session *session, pjsip_rx_data *rdata)
 Determine where in the dialplan a call should go. More...
 
static int get_mid_bundle_group (const pjmedia_sdp_session *sdp, const char *mid)
 
static int handle_incoming (struct ast_sip_session *session, pjsip_rx_data *rdata, enum ast_sip_session_response_priority response_priority)
 
static void handle_incoming_before_media (pjsip_inv_session *inv, struct ast_sip_session *session, pjsip_rx_data *rdata)
 
static void handle_incoming_request (struct ast_sip_session *session, pjsip_rx_data *rdata)
 
static void handle_incoming_response (struct ast_sip_session *session, pjsip_rx_data *rdata, enum ast_sip_session_response_priority response_priority)
 
static int handle_incoming_sdp (struct ast_sip_session *session, const pjmedia_sdp_session *sdp)
 
static int handle_negotiated_sdp (struct ast_sip_session *session, const pjmedia_sdp_session *local, const pjmedia_sdp_session *remote)
 
static int handle_negotiated_sdp_session_media (struct ast_sip_session_media *session_media, struct ast_sip_session *session, const pjmedia_sdp_session *local, const pjmedia_sdp_session *remote, int index, struct ast_stream *asterisk_stream)
 
static void handle_new_invite_request (pjsip_rx_data *rdata)
 
static void handle_outgoing_request (struct ast_sip_session *session, pjsip_tx_data *tdata)
 
static void handle_outgoing_response (struct ast_sip_session *session, pjsip_tx_data *tdata)
 
static void handle_session_begin (struct ast_sip_session *session)
 
static void handle_session_destroy (struct ast_sip_session *session)
 
static void handle_session_end (struct ast_sip_session *session)
 
static pj_bool_t has_supplement (const struct ast_sip_session *session, const pjsip_rx_data *rdata)
 
static struct ast_sip_session_media_stateinternal_sip_session_media_state_alloc (size_t sessions, size_t read_callbacks)
 
static int invite_collision_timeout (void *vsession)
 
static int invite_proceeding (void *vsession)
 
static int invite_terminated (void *vsession)
 
static int is_media_state_valid (const char *session_name, struct ast_sip_session_media_state *state)
 
static int is_stream_limitation_reached (enum ast_media_type type, const struct ast_sip_endpoint *endpoint, int *type_streams)
 
static int load_module (void)
 
static int media_stats_local_ssrc_cmp (const struct ast_rtp_instance_stats *vec_elem, const struct ast_rtp_instance_stats *srch)
 
static int new_invite (struct new_invite *invite)
 
static int new_invite_initial_answer (pjsip_inv_session *inv_session, pjsip_rx_data *rdata, int answer_code, int terminate_code, pj_bool_t notify)
 
static pj_bool_t outbound_invite_auth (pjsip_rx_data *rdata)
 
static pjsip_inv_session * pre_session_setup (pjsip_rx_data *rdata, const struct ast_sip_endpoint *endpoint)
 
static int remove_handler (void *obj, void *arg, void *data, int flags)
 
static void remove_stream_from_bundle (struct ast_sip_session_media *session_media, struct ast_stream *stream)
 
static void reschedule_reinvite (struct ast_sip_session *session, ast_sip_session_response_cb on_response)
 
static void resend_reinvite (pj_timer_heap_t *timer, pj_timer_entry *entry)
 
static struct ast_sip_session_media_stateresolve_refresh_media_states (const char *session_name, struct ast_sip_session_media_state *delayed_pending_state, struct ast_sip_session_media_state *delayed_active_state, struct ast_sip_session_media_state *current_active_state, int run_post_validation)
 
static int sdp_handler_list_cmp (void *obj, void *arg, int flags)
 
static int sdp_handler_list_hash (const void *obj, int flags)
 
static int sdp_requires_deferral (struct ast_sip_session *session, const pjmedia_sdp_session *sdp)
 Determine whether the SDP provided requires deferral of negotiating or not. More...
 
static int send_delayed_request (struct ast_sip_session *session, struct ast_sip_session_delayed_request *delay)
 
static void session_datastore_destroy (void *obj)
 
static void session_destructor (void *obj)
 
static int session_end (void *vsession)
 
static int session_end_completion (void *vsession)
 
static int session_end_if_disconnected (int id, pjsip_inv_session *inv)
 
static void session_inv_on_create_offer (pjsip_inv_session *inv, pjmedia_sdp_session **p_offer)
 
static void session_inv_on_media_update (pjsip_inv_session *inv, pj_status_t status)
 
static void session_inv_on_new_session (pjsip_inv_session *inv, pjsip_event *e)
 
static pjsip_redirect_op session_inv_on_redirected (pjsip_inv_session *inv, const pjsip_uri *target, const pjsip_event *e)
 
static void session_inv_on_rx_offer (pjsip_inv_session *inv, const pjmedia_sdp_session *offer)
 
static void session_inv_on_state_changed (pjsip_inv_session *inv, pjsip_event *e)
 
static void session_inv_on_tsx_state_changed (pjsip_inv_session *inv, pjsip_transaction *tsx, pjsip_event *e)
 
static void session_media_dtor (void *obj)
 
static void session_media_set_handler (struct ast_sip_session_media *session_media, struct ast_sip_session_sdp_handler *handler)
 Set an SDP stream handler for a corresponding session media. More...
 
static pj_bool_t session_on_rx_request (pjsip_rx_data *rdata)
 Called when a new SIP request comes into PJSIP. More...
 
static pj_bool_t session_on_rx_response (pjsip_rx_data *rdata)
 
static void session_on_tsx_state (pjsip_transaction *tsx, pjsip_event *e)
 
static void session_outgoing_nat_hook (pjsip_tx_data *tdata, struct ast_sip_transport *transport)
 Hook for modifying outgoing messages with SDP to contain the proper address information. More...
 
static pj_bool_t session_reinvite_on_rx_request (pjsip_rx_data *rdata)
 
static void session_termination_cb (pj_timer_heap_t *timer_heap, struct pj_timer_entry *entry)
 
static int session_termination_task (void *data)
 
static void set_from_header (struct ast_sip_session *session)
 
static int set_mid_and_bundle_group (struct ast_sip_session *session, struct ast_sip_session_media *session_media, const pjmedia_sdp_session *sdp, const struct pjmedia_sdp_media *stream)
 
static void set_remote_mslabel_and_stream_group (struct ast_sip_session *session, struct ast_sip_session_media *session_media, const pjmedia_sdp_session *sdp, const struct pjmedia_sdp_media *stream, struct ast_stream *asterisk_stream)
 
static int setup_outbound_invite_auth (pjsip_dialog *dlg)
 
static void sip_channel_destroy (void *obj)
 Destructor for SIP channel. More...
 
static void sip_session_defer_termination_stop_timer (struct ast_sip_session *session)
 
static int sip_session_refresh (struct ast_sip_session *session, ast_sip_session_request_creation_cb on_request_creation, ast_sip_session_sdp_creation_cb on_sdp_creation, ast_sip_session_response_cb on_response, enum ast_sip_session_refresh_method method, int generate_new_sdp, struct ast_sip_session_media_state *pending_media_state, struct ast_sip_session_media_state *active_media_state, int queued)
 
static int sip_session_suspend_task (void *data)
 
static void sip_session_suspender_dtor (void *vdoomed)
 
static int stream_destroy (void *obj, void *arg, int flags)
 
static int test_is_media_session_equal (struct ast_sip_session_media *left, struct ast_sip_session_media *right)
 
static int test_is_media_state_equal (struct ast_sip_session_media_state *left, struct ast_sip_session_media_state *right, int assert_on_failure)
 
static struct ast_sip_session_mediatest_media_add (struct ast_sip_session_media_state *media_state, const char *name, enum ast_media_type type, enum ast_stream_state state, int position)
 
static struct ast_streamtest_stream_alloc (const char *name, enum ast_media_type type, enum ast_stream_state state)
 
static int unload_module (void)
 
static int update_completed (void *vsession)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "PJSIP Session resource" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "30ef0c93b36035ec78c9cfd712d36d9b" , .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_APP_DEPEND, .requires = "res_pjsip", }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static pjsip_inv_callback inv_callback
 
static struct ast_sip_nat_hooknat_hook
 NAT hook for modifying outgoing messages with SDP. More...
 
static pjsip_module outbound_invite_auth_module
 
static struct ao2_containersdp_handlers
 Registered SDP stream handlers. More...
 
static pjsip_module session_module
 
static pjsip_module session_reinvite_module
 

Macro Definition Documentation

◆ CHECKER

#define CHECKER ( )

Referenced by AST_TEST_DEFINE().

◆ DATASTORE_BUCKETS

#define DATASTORE_BUCKETS   53

Definition at line 1226 of file res_pjsip_session.c.

Referenced by ast_sip_session_alloc().

◆ DEFAULT_NUM_SESSION_MEDIA

#define DEFAULT_NUM_SESSION_MEDIA   2

Definition at line 61 of file res_pjsip_session.c.

Referenced by ast_sip_session_media_state_alloc().

◆ FREE_STATE

#define FREE_STATE ( )

◆ GET_STREAM_NAME_SAFE

#define GET_STREAM_NAME_SAFE (   _stream)    (_stream ? ast_stream_get_name(_stream) : "")

Definition at line 1739 of file res_pjsip_session.c.

Referenced by is_media_state_valid(), and resolve_refresh_media_states().

◆ GET_STREAM_SAFE

#define GET_STREAM_SAFE (   _topology,
  _i 
)    (_i < ast_stream_topology_get_count(_topology) ? ast_stream_topology_get_stream(_topology, _i) : NULL)

Definition at line 1737 of file res_pjsip_session.c.

Referenced by resolve_refresh_media_states().

◆ GET_STREAM_STATE_SAFE

#define GET_STREAM_STATE_SAFE (   _stream)    (_stream ? ast_stream_get_state(_stream) : AST_STREAM_STATE_END)

Definition at line 1738 of file res_pjsip_session.c.

Referenced by resolve_refresh_media_states().

◆ MEDIA_BUCKETS

#define MEDIA_BUCKETS   7

Definition at line 1227 of file res_pjsip_session.c.

◆ MOD_DATA_NAT_HOOK

#define MOD_DATA_NAT_HOOK   "nat_hook"

Definition at line 58 of file res_pjsip_session.c.

Referenced by session_outgoing_nat_hook().

◆ MOD_DATA_ON_RESPONSE

#define MOD_DATA_ON_RESPONSE   "on_response"

◆ print_debug_details

#define print_debug_details (   inv,
  tsx,
 
)    __print_debug_details(__PRETTY_FUNCTION__, (inv), (tsx), (e))

◆ RESET_STATE

#define RESET_STATE (   __num)

Referenced by AST_TEST_DEFINE().

◆ SDP_HANDLER_BUCKETS

#define SDP_HANDLER_BUCKETS   11

Definition at line 55 of file res_pjsip_session.c.

Referenced by load_module().

◆ STATE_NONE

#define STATE_NONE (   _stream_state)    (_stream_state == AST_STREAM_STATE_END)

Definition at line 1736 of file res_pjsip_session.c.

Referenced by resolve_refresh_media_states().

◆ STATE_REMOVED

#define STATE_REMOVED (   _stream_state)    (_stream_state == AST_STREAM_STATE_REMOVED)

Definition at line 1735 of file res_pjsip_session.c.

Referenced by resolve_refresh_media_states().

◆ STREAM_REMOVED

#define STREAM_REMOVED (   _stream)    (ast_stream_get_state(_stream) == AST_STREAM_STATE_REMOVED)

Definition at line 1734 of file res_pjsip_session.c.

Referenced by is_media_state_valid(), and resolve_refresh_media_states().

Enumeration Type Documentation

◆ delayed_method

Enumerator
DELAYED_METHOD_INVITE 
DELAYED_METHOD_UPDATE 
DELAYED_METHOD_BYE 

Definition at line 1295 of file res_pjsip_session.c.

◆ sip_get_destination_result

Enumerator
SIP_GET_DEST_EXTEN_FOUND 

The extension was successfully found

SIP_GET_DEST_EXTEN_NOT_FOUND 

The extension specified in the RURI was not found

SIP_GET_DEST_EXTEN_PARTIAL 

The extension specified in the RURI was a partial match

SIP_GET_DEST_UNSUPPORTED_URI 

The RURI is of an unsupported scheme

Definition at line 3645 of file res_pjsip_session.c.

3645  {
3646  /*! The extension was successfully found */
3648  /*! The extension specified in the RURI was not found */
3650  /*! The extension specified in the RURI was a partial match */
3652  /*! The RURI is of an unsupported scheme */
3654 };

Function Documentation

◆ __print_debug_details()

static void __print_debug_details ( const char *  function,
pjsip_inv_session *  inv,
pjsip_transaction *  tsx,
pjsip_event *  e 
)
static

Definition at line 4347 of file res_pjsip_session.c.

References ast_channel_name(), ast_log, ast_sorcery_object_get_id(), ast_sip_session::channel, DEBUG_ATLEAST, ast_sip_session::endpoint, LOG_DEBUG, and NULL.

4348 {
4349  int id = session_module.id;
4350  struct ast_sip_session *session = NULL;
4351 
4352  if (!DEBUG_ATLEAST(5)) {
4353  /* Debug not spamy enough */
4354  return;
4355  }
4356 
4357  ast_log(LOG_DEBUG, "Function %s called on event %s\n",
4358  function, pjsip_event_str(e->type));
4359  if (!inv) {
4360  ast_log(LOG_DEBUG, "Transaction %p does not belong to an inv_session?\n", tsx);
4361  ast_log(LOG_DEBUG, "The transaction state is %s\n",
4362  pjsip_tsx_state_str(tsx->state));
4363  return;
4364  }
4365  if (id > -1) {
4366  session = inv->mod_data[session_module.id];
4367  }
4368  if (!session) {
4369  ast_log(LOG_DEBUG, "inv_session %p has no ast session\n", inv);
4370  } else {
4371  ast_log(LOG_DEBUG, "The state change pertains to the endpoint '%s(%s)'\n",
4373  session->channel ? ast_channel_name(session->channel) : "");
4374  }
4375  if (inv->invite_tsx) {
4376  ast_log(LOG_DEBUG, "The inv session still has an invite_tsx (%p)\n",
4377  inv->invite_tsx);
4378  } else {
4379  ast_log(LOG_DEBUG, "The inv session does NOT have an invite_tsx\n");
4380  }
4381  if (tsx) {
4382  ast_log(LOG_DEBUG, "The %s %.*s transaction involved in this state change is %p\n",
4383  pjsip_role_name(tsx->role),
4384  (int) pj_strlen(&tsx->method.name), pj_strbuf(&tsx->method.name),
4385  tsx);
4386  ast_log(LOG_DEBUG, "The current transaction state is %s\n",
4387  pjsip_tsx_state_str(tsx->state));
4388  ast_log(LOG_DEBUG, "The transaction state change event is %s\n",
4389  pjsip_event_str(e->body.tsx_state.type));
4390  } else {
4391  ast_log(LOG_DEBUG, "There is no transaction involved in this state change\n");
4392  }
4393  ast_log(LOG_DEBUG, "The current inv state is %s\n", pjsip_inv_state_name(inv->state));
4394 }
struct ast_sip_endpoint * endpoint
#define NULL
Definition: resample.c:96
#define LOG_DEBUG
Definition: logger.h:241
A structure describing a SIP session.
#define ast_log
Definition: astobj2.c:42
static struct ast_mansession session
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
struct ast_channel * channel
static pjsip_module session_module
const char * ast_channel_name(const struct ast_channel *chan)
#define DEBUG_ATLEAST(level)
Definition: logger.h:441

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 6128 of file res_pjsip_session.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 6128 of file res_pjsip_session.c.

◆ add_bundle_groups()

static int add_bundle_groups ( struct ast_sip_session session,
pj_pool_t *  pool,
pjmedia_sdp_session *  answer 
)
static

Definition at line 5011 of file res_pjsip_session.c.

References ast_free, ast_str_append(), ast_str_buffer(), ast_str_create, ast_str_set(), AST_VECTOR_GET, AST_VECTOR_SIZE, sip_session_media_bundle_group::attr_string, ast_sip_endpoint_media_configuration::bundle, ast_sip_session_media::bundle_group, ast_sip_session::endpoint, ast_sip_endpoint::media, ast_sip_session_media::mid, sip_session_media_bundle_group::mids, ast_sip_session::pending_media_state, and ast_sip_endpoint_media_configuration::webrtc.

Referenced by create_local_sdp().

5012 {
5013  pj_str_t stmp;
5014  pjmedia_sdp_attr *attr;
5015  struct sip_session_media_bundle_group bundle_groups[PJMEDIA_MAX_SDP_MEDIA];
5016  int index, mid_id;
5017  struct sip_session_media_bundle_group *bundle_group;
5018 
5019  if (session->endpoint->media.webrtc) {
5020  attr = pjmedia_sdp_attr_create(pool, "msid-semantic", pj_cstr(&stmp, "WMS *"));
5021  pjmedia_sdp_attr_add(&answer->attr_count, answer->attr, attr);
5022  }
5023 
5024  if (!session->endpoint->media.bundle) {
5025  return 0;
5026  }
5027 
5028  memset(bundle_groups, 0, sizeof(bundle_groups));
5029 
5030  /* Build the bundle group layout so we can then add it to the SDP */
5031  for (index = 0; index < AST_VECTOR_SIZE(&session->pending_media_state->sessions); ++index) {
5032  struct ast_sip_session_media *session_media = AST_VECTOR_GET(&session->pending_media_state->sessions, index);
5033 
5034  /* If this stream is not part of a bundle group we can't add it */
5035  if (session_media->bundle_group == -1) {
5036  continue;
5037  }
5038 
5039  bundle_group = &bundle_groups[session_media->bundle_group];
5040 
5041  /* If this is the first mid then we need to allocate the attribute string and place BUNDLE in front */
5042  if (!bundle_group->mids[0]) {
5043  bundle_group->mids[0] = session_media->mid;
5044  bundle_group->attr_string = ast_str_create(64);
5045  if (!bundle_group->attr_string) {
5046  continue;
5047  }
5048 
5049  ast_str_set(&bundle_group->attr_string, 0, "BUNDLE %s", session_media->mid);
5050  continue;
5051  }
5052 
5053  for (mid_id = 1; mid_id < PJMEDIA_MAX_SDP_MEDIA; ++mid_id) {
5054  if (!bundle_group->mids[mid_id]) {
5055  bundle_group->mids[mid_id] = session_media->mid;
5056  ast_str_append(&bundle_group->attr_string, 0, " %s", session_media->mid);
5057  break;
5058  } else if (!strcmp(bundle_group->mids[mid_id], session_media->mid)) {
5059  break;
5060  }
5061  }
5062  }
5063 
5064  /* Add all bundle groups that have mids to the SDP */
5065  for (index = 0; index < PJMEDIA_MAX_SDP_MEDIA; ++index) {
5066  bundle_group = &bundle_groups[index];
5067 
5068  if (!bundle_group->attr_string) {
5069  continue;
5070  }
5071 
5072  attr = pjmedia_sdp_attr_create(pool, "group", pj_cstr(&stmp, ast_str_buffer(bundle_group->attr_string)));
5073  pjmedia_sdp_attr_add(&answer->attr_count, answer->attr, attr);
5074 
5075  ast_free(bundle_group->attr_string);
5076  }
5077 
5078  return 0;
5079 }
struct ast_sip_endpoint * endpoint
Bundle group building structure.
struct ast_sip_session_media_state * pending_media_state
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
char * mid
Media identifier for this stream (may be shared across multiple streams)
static pj_pool_t * pool
Global memory pool for configuration and timers.
struct ast_str * attr_string
SDP attribute string.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1091
struct ast_sip_endpoint_media_configuration media
Definition: res_pjsip.h:841
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1065
static int answer(void *data)
Definition: chan_pjsip.c:682
char * mids[PJMEDIA_MAX_SDP_MEDIA]
The media identifiers in this bundle group.
#define ast_free(a)
Definition: astmm.h:182
int bundle_group
The bundle group the stream belongs to.
A structure containing SIP session media information.
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:682
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:611
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620

◆ add_sdp_streams()

static int add_sdp_streams ( struct ast_sip_session_media session_media,
struct ast_sip_session session,
pjmedia_sdp_session *  answer,
const struct pjmedia_sdp_session *  remote,
struct ast_stream stream 
)
static

Definition at line 4957 of file res_pjsip_session.c.

References ao2_cleanup, ao2_find, ast_codec_media_type2str(), AST_LIST_TRAVERSE, ast_sip_session_get_name(), ast_str_tmp, ast_stream_to_str(), ast_sip_session_sdp_handler::create_outgoing_sdp_stream, handler(), ast_sip_session_media::handler, ast_sip_session_sdp_handler::next, NULL, OBJ_KEY, RAII_VAR, SCOPE_ENTER, SCOPE_EXIT_RTN_VALUE, session_media_set_handler(), and ast_sip_session_media::type.

Referenced by create_local_sdp().

4961 {
4962  struct ast_sip_session_sdp_handler *handler = session_media->handler;
4963  RAII_VAR(struct sdp_handler_list *, handler_list, NULL, ao2_cleanup);
4964  int res = 0;
4965  SCOPE_ENTER(1, "%s Stream: %s\n", ast_sip_session_get_name(session),
4966  ast_str_tmp(128, ast_stream_to_str(stream, &STR_TMP)));
4967 
4968  if (handler) {
4969  /* if an already assigned handler reports a catastrophic error, fail */
4970  res = handler->create_outgoing_sdp_stream(session, session_media, answer, remote, stream);
4971  if (res < 0) {
4972  SCOPE_EXIT_RTN_VALUE(-1, "Coudn't create sdp stream\n");
4973  }
4974  SCOPE_EXIT_RTN_VALUE(0, "Had handler\n");
4975  }
4976 
4977  handler_list = ao2_find(sdp_handlers, ast_codec_media_type2str(session_media->type), OBJ_KEY);
4978  if (!handler_list) {
4979  SCOPE_EXIT_RTN_VALUE(0, "No handlers\n");
4980  }
4981 
4982  /* no handler for this stream type and we have a list to search */
4983  AST_LIST_TRAVERSE(&handler_list->list, handler, next) {
4984  if (handler == session_media->handler) {
4985  continue;
4986  }
4987  res = handler->create_outgoing_sdp_stream(session, session_media, answer, remote, stream);
4988  if (res < 0) {
4989  /* catastrophic error */
4990  SCOPE_EXIT_RTN_VALUE(-1, "Coudn't create sdp stream\n");
4991  }
4992  if (res > 0) {
4993  /* Handled by this handler. Move to the next stream */
4994  session_media_set_handler(session_media, handler);
4995  SCOPE_EXIT_RTN_VALUE(0, "Handled\n");
4996  }
4997  }
4998 
4999  /* streams that weren't handled won't be included in generated outbound SDP */
5000  SCOPE_EXIT_RTN_VALUE(0, "Not handled\n");
5001 }
const char * ast_stream_to_str(const struct ast_stream *stream, struct ast_str **buf)
Get a string representing the stream for debugging/display purposes.
Definition: stream.c:337
#define OBJ_KEY
Definition: astobj2.h:1155
A handler for SDPs in SIP sessions.
const char * ast_codec_media_type2str(enum ast_media_type type)
Conversion function to take a media type and turn it into a string.
Definition: codec.c:347
#define NULL
Definition: resample.c:96
#define ast_str_tmp(init_len, __expr)
Definition: strings.h:1136
struct ast_sip_session_sdp_handler * next
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
static void session_media_set_handler(struct ast_sip_session_media *session_media, struct ast_sip_session_sdp_handler *handler)
Set an SDP stream handler for a corresponding session media.
static int answer(void *data)
Definition: chan_pjsip.c:682
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define SCOPE_ENTER(level,...)
Non RAII_VAR Scope Trace macros The advantage of these macros is that the EXITs will have the actual ...
Definition: logger.h:780
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
const char * ast_sip_session_get_name(const struct ast_sip_session *session)
Get the channel or endpoint name associated with the session.
#define SCOPE_EXIT_RTN_VALUE(__return_value,...)
Scope Exit with return value.
Definition: logger.h:875
enum ast_media_type type
Media type of this session media.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
struct ast_sip_session_sdp_handler * handler
SDP handler that setup the RTP.
static void handler(const char *name, int response_code, struct ast_variable *get_params, struct ast_variable *path_vars, struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
Definition: test_ari.c:59
static struct ao2_container * sdp_handlers
Registered SDP stream handlers.
int(* create_outgoing_sdp_stream)(struct ast_sip_session *session, struct ast_sip_session_media *session_media, struct pjmedia_sdp_session *sdp, const struct pjmedia_sdp_session *remote, struct ast_stream *stream)
Create an SDP media stream and add it to the outgoing SDP offer or answer.

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 6128 of file res_pjsip_session.c.

◆ ast_sip_channel_pvt_alloc()

struct ast_sip_channel_pvt* ast_sip_channel_pvt_alloc ( void *  pvt,
struct ast_sip_session session 
)

Allocate a new SIP channel pvt structure.

Parameters
pvtPointer to channel specific information
sessionPointer to SIP session
Return values
non-NULLsuccess
NULLfailure

Definition at line 2974 of file res_pjsip_session.c.

References ao2_alloc, ao2_ref, NULL, ast_sip_channel_pvt::pvt, session, ast_sip_channel_pvt::session, and sip_channel_destroy().

Referenced by chan_pjsip_new().

2975 {
2976  struct ast_sip_channel_pvt *channel = ao2_alloc(sizeof(*channel), sip_channel_destroy);
2977 
2978  if (!channel) {
2979  return NULL;
2980  }
2981 
2982  ao2_ref(pvt, +1);
2983  channel->pvt = pvt;
2984  ao2_ref(session, +1);
2985  channel->session = session;
2986 
2987  return channel;
2988 }
void * pvt
Pointer to channel specific implementation information, must be ao2 object.
A structure which contains a channel implementation and session.
struct ast_sip_session * session
Pointer to session.
Definition: muted.c:95
#define NULL
Definition: resample.c:96
static struct ast_mansession session
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
static void sip_channel_destroy(void *obj)
Destructor for SIP channel.

◆ ast_sip_dialog_get_session()

struct ast_sip_session* ast_sip_dialog_get_session ( pjsip_dialog *  dlg)

Retrieves a session from a dialog.

Parameters
dlgThe dialog to retrieve the session from
Return values
non-NULLif session exists
NULLif no session
Note
The reference count of the session is increased when returned
This function must be called with the dialog locked

Definition at line 3630 of file res_pjsip_session.c.

References ao2_ref, ast_sip_session::inv_session, NULL, and session.

Referenced by assign_uuid(), refer_incoming_attended_request(), refer_incoming_invite_request(), session_outgoing_nat_hook(), and session_reinvite_on_rx_request().

3631 {
3632  pjsip_inv_session *inv_session = pjsip_dlg_get_inv_session(dlg);
3633  struct ast_sip_session *session;
3634 
3635  if (!inv_session ||
3636  !(session = inv_session->mod_data[session_module.id])) {
3637  return NULL;
3638  }
3639 
3640  ao2_ref(session, +1);
3641 
3642  return session;
3643 }
#define NULL
Definition: resample.c:96
A structure describing a SIP session.
static struct ast_mansession session
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static pjsip_module session_module

◆ ast_sip_session_add_datastore()

int ast_sip_session_add_datastore ( struct ast_sip_session session,
struct ast_datastore datastore 
)

Add a datastore to a SIP session.

Note that SIP uses reference counted datastores. The datastore passed into this function must have been allocated using ao2_alloc() or there will be serious problems.

Parameters
sessionThe session to add the datastore to
datastoreThe datastore to be added to the session
Return values
0Success
-1Failure

Definition at line 1273 of file res_pjsip_session.c.

References ao2_link, ast_assert, ast_strlen_zero, ast_sip_session::datastores, ast_datastore::info, NULL, and ast_datastore::uid.

Referenced by add_header(), chan_pjsip_incoming_request(), chan_pjsip_session_begin(), handle_incoming_request(), incoming_request(), session_refresh_state_get_or_alloc(), and t38_state_get_or_alloc().

1274 {
1275  ast_assert(datastore != NULL);
1276  ast_assert(datastore->info != NULL);
1277  ast_assert(ast_strlen_zero(datastore->uid) == 0);
1278 
1279  if (!ao2_link(session->datastores, datastore)) {
1280  return -1;
1281  }
1282  return 0;
1283 }
struct ao2_container * datastores
#define ast_assert(a)
Definition: utils.h:695
#define NULL
Definition: resample.c:96
const char * uid
Definition: datastore.h:69
#define ast_strlen_zero(foo)
Definition: strings.h:52
const struct ast_datastore_info * info
Definition: datastore.h:71
#define ao2_link(container, obj)
Definition: astobj2.h:1549

◆ ast_sip_session_alloc()

struct ast_sip_session* ast_sip_session_alloc ( struct ast_sip_endpoint endpoint,
struct ast_sip_contact contact,
pjsip_inv_session *  inv,
pjsip_rx_data *  rdata 
)

Allocate a new SIP session.

This will take care of allocating the datastores container on the session as well as placing all registered supplements onto the session.

The endpoint that is passed in will have its reference count increased by one since the session will be keeping a reference to the endpoint. The session will relinquish this reference when the session is destroyed.

Parameters
endpointThe endpoint that this session communicates with
contactThe contact associated with this session
inv_sessionThe PJSIP INVITE session data
rdataINVITE request received (NULL if for outgoing allocation)

Definition at line 2990 of file res_pjsip_session.c.

References ast_sip_session::active_media_state, ao2_alloc, AO2_ALLOC_OPT_LOCK_MUTEX, ao2_bump, ao2_cleanup, ao2_container_alloc_hash, ao2_ref, ast_dsp_new(), ast_dsp_set_features(), ast_format_cap_alloc, AST_FORMAT_CAP_FLAG_DEFAULT, AST_LIST_HEAD_INIT, AST_LIST_HEAD_INIT_NOLOCK, ast_log, ast_party_id_init(), ast_sip_create_serializer(), ast_sip_dialog_set_endpoint(), ast_sip_dialog_set_serializer(), AST_SIP_DTMF_AUTO, AST_SIP_DTMF_INBAND, ast_sip_get_distributor_serializer(), ast_sip_session_add_supplements(), ast_sip_session_media_state_alloc(), ast_sorcery_object_get_id(), ast_taskprocessor_build_name(), AST_TASKPROCESSOR_MAX_NAME, AST_VECTOR_INIT, ast_sip_session::authentication_challenge_count, ast_sip_session::contact, DATASTORE_BUCKETS, datastore_cmp(), datastore_hash(), ast_sip_session::datastores, ast_sip_session::delayed_requests, ast_sip_session::direct_media_cap, ast_sip_session::dsp, DSP_FEATURE_DIGIT_DETECT, DSP_FEATURE_FAX_DETECT, ast_sip_session::dtmf, ast_sip_endpoint::dtmf, ast_sip_session::endpoint, ast_sip_endpoint::faxdetect, handle_session_begin(), ast_sip_session::id, ast_sip_session::inv_session, LOG_ERROR, ast_sip_session::moh_passthrough, ast_sip_endpoint::moh_passthrough, NULL, ast_sip_session::pending_media_state, RAII_VAR, ast_sip_session::serializer, session, session_destructor(), and ast_sip_session::supplements.

Referenced by ast_sip_session_create_outgoing(), and handle_new_invite_request().

2992 {
2994  struct ast_sip_session *ret_session;
2995  int dsp_features = 0;
2996 
2998  if (!session) {
2999  return NULL;
3000  }
3001 
3002  AST_LIST_HEAD_INIT(&session->supplements);
3003  AST_LIST_HEAD_INIT_NOLOCK(&session->delayed_requests);
3004  ast_party_id_init(&session->id);
3005 
3007  if (!session->direct_media_cap) {
3008  return NULL;
3009  }
3012  if (!session->datastores) {
3013  return NULL;
3014  }
3015  session->active_media_state = ast_sip_session_media_state_alloc();
3016  if (!session->active_media_state) {
3017  return NULL;
3018  }
3019  session->pending_media_state = ast_sip_session_media_state_alloc();
3020  if (!session->pending_media_state) {
3021  return NULL;
3022  }
3023  if (AST_VECTOR_INIT(&session->media_stats, 1) < 0) {
3024  return NULL;
3025  }
3026 
3027  if (endpoint->dtmf == AST_SIP_DTMF_INBAND || endpoint->dtmf == AST_SIP_DTMF_AUTO) {
3028  dsp_features |= DSP_FEATURE_DIGIT_DETECT;
3029  }
3030  if (endpoint->faxdetect) {
3031  dsp_features |= DSP_FEATURE_FAX_DETECT;
3032  }
3033  if (dsp_features) {
3034  session->dsp = ast_dsp_new();
3035  if (!session->dsp) {
3036  return NULL;
3037  }
3038 
3039  ast_dsp_set_features(session->dsp, dsp_features);
3040  }
3041 
3042  session->endpoint = ao2_bump(endpoint);
3043 
3044  if (rdata) {
3045  /*
3046  * We must continue using the serializer that the original
3047  * INVITE came in on for the dialog. There may be
3048  * retransmissions already enqueued in the original
3049  * serializer that can result in reentrancy and message
3050  * sequencing problems.
3051  */
3052  session->serializer = ast_sip_get_distributor_serializer(rdata);
3053  } else {
3054  char tps_name[AST_TASKPROCESSOR_MAX_NAME + 1];
3055 
3056  /* Create name with seq number appended. */
3057  ast_taskprocessor_build_name(tps_name, sizeof(tps_name), "pjsip/outsess/%s",
3058  ast_sorcery_object_get_id(endpoint));
3059 
3060  session->serializer = ast_sip_create_serializer(tps_name);
3061  }
3062  if (!session->serializer) {
3063  return NULL;
3064  }
3066  ast_sip_dialog_set_endpoint(inv_session->dlg, endpoint);
3067 
3068  /* When a PJSIP INVITE session is created it is created with a reference
3069  * count of 1, with that reference being managed by the underlying state
3070  * of the INVITE session itself. When the INVITE session transitions to
3071  * a DISCONNECTED state that reference is released. This means we can not
3072  * rely on that reference to ensure the INVITE session remains for the
3073  * lifetime of our session. To ensure it does we add our own reference
3074  * and release it when our own session goes away, ensuring that the INVITE
3075  * session remains for the lifetime of session.
3076  */
3077 
3078 #ifdef HAVE_PJSIP_INV_SESSION_REF
3079  if (pjsip_inv_add_ref(inv_session) != PJ_SUCCESS) {
3080  ast_log(LOG_ERROR, "Can't increase the session reference counter\n");
3081  return NULL;
3082  }
3083 #endif
3084 
3085  pjsip_dlg_inc_session(inv_session->dlg, &session_module);
3086  inv_session->mod_data[session_module.id] = ao2_bump(session);
3087  session->contact = ao2_bump(contact);
3088  session->inv_session = inv_session;
3089 
3090  session->dtmf = endpoint->dtmf;
3091  session->moh_passthrough = endpoint->moh_passthrough;
3092 
3094  /* Release the ref held by session->inv_session */
3095  ao2_ref(session, -1);
3096  return NULL;
3097  }
3098 
3099  session->authentication_challenge_count = 0;
3100 
3101  /* Fire seesion begin handlers */
3103 
3104  /* Avoid unnecessary ref manipulation to return a session */
3105  ret_session = session;
3106  session = NULL;
3107  return ret_session;
3108 }
enum ast_sip_dtmf_mode dtmf
Definition: res_pjsip.h:857
void ast_taskprocessor_build_name(char *buf, unsigned int size, const char *format,...)
Build a taskprocessor name with a sequence number on the end.
#define DSP_FEATURE_DIGIT_DETECT
Definition: dsp.h:28
void ast_sip_dialog_set_serializer(pjsip_dialog *dlg, struct ast_taskprocessor *serializer)
Set a serializer on a SIP dialog so requests and responses are automatically serialized.
struct ast_dsp * ast_dsp_new(void)
Allocates a new dsp, assumes 8khz for internal sample rate.
Definition: dsp.c:1745
void ast_sip_dialog_set_endpoint(pjsip_dialog *dlg, struct ast_sip_endpoint *endpoint)
Set an endpoint on a SIP dialog so in-dialog requests do not undergo endpoint lookup.
#define NULL
Definition: resample.c:96
#define AST_TASKPROCESSOR_MAX_NAME
Suggested maximum taskprocessor name length (less null terminator).
Definition: taskprocessor.h:60
struct pjsip_inv_session * inv_session
A structure describing a SIP session.
#define DATASTORE_BUCKETS
#define ao2_bump(obj)
Definition: astobj2.h:491
#define ast_log
Definition: astobj2.c:42
static void session_destructor(void *obj)
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:113
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
static struct ast_mansession session
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define DSP_FEATURE_FAX_DETECT
Definition: dsp.h:29
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
static pjsip_module session_module
#define ast_format_cap_alloc(flags)
Definition: format_cap.h:52
static int datastore_hash(const void *obj, int flags)
#define LOG_ERROR
Definition: logger.h:285
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Definition: astobj2.h:1310
static int datastore_cmp(void *obj, void *arg, int flags)
struct ast_taskprocessor * ast_sip_create_serializer(const char *name)
Create a new serializer for SIP tasks.
Definition: res_pjsip.c:5133
unsigned int faxdetect
Definition: res_pjsip.h:869
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
struct ast_taskprocessor * ast_sip_get_distributor_serializer(pjsip_rx_data *rdata)
Determine the distributor serializer for the SIP message.
void ast_dsp_set_features(struct ast_dsp *dsp, int features)
Select feature set.
Definition: dsp.c:1755
#define AST_LIST_HEAD_INIT(head)
Initializes a list head structure.
Definition: linkedlists.h:625
unsigned int moh_passthrough
Definition: res_pjsip.h:879
static void handle_session_begin(struct ast_sip_session *session)
void ast_party_id_init(struct ast_party_id *init)
Initialize the given party id structure.
Definition: channel.c:1757
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
Definition: linkedlists.h:680
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
int ast_sip_session_add_supplements(struct ast_sip_session *session)
Add supplements to a SIP session.
Definition: pjsip_session.c:90
struct ast_sip_session_media_state * ast_sip_session_media_state_alloc(void)
Allocate a session media state structure.

◆ ast_sip_session_alloc_datastore()

struct ast_datastore* ast_sip_session_alloc_datastore ( const struct ast_datastore_info info,
const char *  uid 
)

Alternative for ast_datastore_alloc()

There are two major differences between this and ast_datastore_alloc() 1) This allocates a refcounted object 2) This will fill in a uid if one is not provided

DO NOT call ast_datastore_free() on a datastore allocated in this way since that function will attempt to free the datastore rather than play nicely with its refcount.

Parameters
infoCallbacks for datastore
uidIdentifier for datastore
Return values
NULLFailed to allocate datastore
non-NULLNewly allocated datastore

Definition at line 1243 of file res_pjsip_session.c.

References ao2_alloc, ao2_cleanup, ao2_ref, ast_strdup, ast_strlen_zero, ast_uuid_generate_str(), AST_UUID_STR_LEN, sip_to_pjsip::info(), NULL, RAII_VAR, session_datastore_destroy(), and ast_datastore::uid.

Referenced by add_header(), chan_pjsip_incoming_request(), chan_pjsip_session_begin(), handle_incoming_request(), incoming_request(), session_refresh_state_get_or_alloc(), and t38_state_get_or_alloc().

1244 {
1245  RAII_VAR(struct ast_datastore *, datastore, NULL, ao2_cleanup);
1246  char uuid_buf[AST_UUID_STR_LEN];
1247  const char *uid_ptr = uid;
1248 
1249  if (!info) {
1250  return NULL;
1251  }
1252 
1253  datastore = ao2_alloc(sizeof(*datastore), session_datastore_destroy);
1254  if (!datastore) {
1255  return NULL;
1256  }
1257 
1258  datastore->info = info;
1259  if (ast_strlen_zero(uid)) {
1260  /* They didn't provide an ID so we'll provide one ourself */
1261  uid_ptr = ast_uuid_generate_str(uuid_buf, sizeof(uuid_buf));
1262  }
1263 
1264  datastore->uid = ast_strdup(uid_ptr);
1265  if (!datastore->uid) {
1266  return NULL;
1267  }
1268 
1269  ao2_ref(datastore, +1);
1270  return datastore;
1271 }
#define AST_UUID_STR_LEN
Definition: uuid.h:27
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
Structure for a data store object.
Definition: datastore.h:68
#define NULL
Definition: resample.c:96
static void session_datastore_destroy(void *obj)
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
#define ao2_ref(o, delta)
Definition: astobj2.h:464
def info(msg)
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
char * ast_uuid_generate_str(char *buf, size_t size)
Generate a UUID string.
Definition: uuid.c:143
#define ao2_cleanup(obj)
Definition: astobj2.h:1958

◆ ast_sip_session_create_invite()

int ast_sip_session_create_invite ( struct ast_sip_session session,
pjsip_tx_data **  tdata 
)

Creates an INVITE request.

Parameters
sessionStarting session for the INVITE
tdataThe created request.

Definition at line 2847 of file res_pjsip_session.c.

References ast_sip_session_get_name(), create_local_sdp(), ast_sip_session::endpoint, ast_sip_session::inv_session, NULL, ast_sip_endpoint::preferred_codec_only, SCOPE_ENTER, SCOPE_EXIT_RTN_VALUE, and set_from_header().

Referenced by call().

2848 {
2849  pjmedia_sdp_session *offer;
2850  SCOPE_ENTER(1, "%s\n", ast_sip_session_get_name(session));
2851 
2852  if (!(offer = create_local_sdp(session->inv_session, session, NULL))) {
2853  pjsip_inv_terminate(session->inv_session, 500, PJ_FALSE);
2854  SCOPE_EXIT_RTN_VALUE(-1, "Couldn't create offer\n");
2855  }
2856 
2857  pjsip_inv_set_local_sdp(session->inv_session, offer);
2858  pjmedia_sdp_neg_set_prefer_remote_codec_order(session->inv_session->neg, PJ_FALSE);
2859 #ifdef PJMEDIA_SDP_NEG_ANSWER_MULTIPLE_CODECS
2860  if (!session->endpoint->preferred_codec_only) {
2861  pjmedia_sdp_neg_set_answer_multiple_codecs(session->inv_session->neg, PJ_TRUE);
2862  }
2863 #endif
2864 
2865  /*
2866  * We MUST call set_from_header() before pjsip_inv_invite. If we don't, the
2867  * From in the initial INVITE will be wrong but the rest of the messages will be OK.
2868  */
2869  set_from_header(session);
2870 
2871  if (pjsip_inv_invite(session->inv_session, tdata) != PJ_SUCCESS) {
2872  SCOPE_EXIT_RTN_VALUE(-1, "pjsip_inv_invite failed\n");
2873  }
2874 
2876 }
struct ast_sip_endpoint * endpoint
static void set_from_header(struct ast_sip_session *session)
#define NULL
Definition: resample.c:96
struct pjsip_inv_session * inv_session
unsigned int preferred_codec_only
Definition: res_pjsip.h:889
#define SCOPE_ENTER(level,...)
Non RAII_VAR Scope Trace macros The advantage of these macros is that the EXITs will have the actual ...
Definition: logger.h:780
const char * ast_sip_session_get_name(const struct ast_sip_session *session)
Get the channel or endpoint name associated with the session.
#define SCOPE_EXIT_RTN_VALUE(__return_value,...)
Scope Exit with return value.
Definition: logger.h:875
static struct pjmedia_sdp_session * create_local_sdp(pjsip_inv_session *inv, struct ast_sip_session *session, const pjmedia_sdp_session *offer)

◆ ast_sip_session_create_outgoing()

struct ast_sip_session* ast_sip_session_create_outgoing ( struct ast_sip_endpoint endpoint,
struct ast_sip_contact contact,
const char *  location,
const char *  request_user,
struct ast_stream_topology req_topology 
)

Create a new outgoing SIP session.

The endpoint that is passed in will have its reference count increased by one since the session will be keeping a reference to the endpoint. The session will relinquish this reference when the session is destroyed.

Parameters
endpointThe endpoint that this session uses for settings
contactThe contact that this session will communicate with
locationName of the location to call, be it named location or explicit URI. Overrides contact if present.
request_userOptional request user to place in the request URI if permitted
req_topologyThe requested capabilities

Definition at line 3317 of file res_pjsip_session.c.

References ao2_bump, ao2_cleanup, ao2_ref, ast_sip_session::aor, ast_sip_endpoint::aors, ast_log, ast_party_id_copy(), AST_SIP_CONTACT_FILTER_REACHABLE, ast_sip_create_dialog_uac(), ast_sip_location_retrieve_contact_and_aor_from_list_filtered(), ast_sip_session_alloc(), ast_sip_session_create_joint_call_stream(), AST_SIP_SESSION_OUTGOING_CALL, ast_sorcery_object_get_id(), ast_str_tmp, ast_stream_free(), ast_stream_get_format_count(), ast_stream_get_state(), AST_STREAM_STATE_REMOVED, ast_stream_topology_alloc(), ast_stream_topology_append_stream(), ast_stream_topology_clone(), ast_stream_topology_get_count(), ast_stream_topology_get_stream(), ast_stream_topology_to_str(), ast_strlen_zero, ast_sip_session::call_direction, ast_sip_endpoint::extensions, ast_sip_endpoint_extensions::flags, ast_sip_session::id, ast_sip_endpoint::id, LOG_ERROR, ast_sip_endpoint::media, ast_sip_timer_options::min_se, NULL, ast_sip_session::pending_media_state, RAII_VAR, S_OR, SCOPE_ENTER, SCOPE_EXIT_RTN_VALUE, ast_sip_endpoint_id_configuration::self, ast_sip_timer_options::sess_expires, session, session_end(), session_end_completion(), setup_outbound_invite_auth(), timer, ast_sip_endpoint_extensions::timer, ast_sip_session_media_state::topology, ast_sip_endpoint_media_configuration::topology, and ast_sip_contact::uri.

Referenced by request().

3320 {
3321  const char *uri = NULL;
3322  RAII_VAR(struct ast_sip_aor *, found_aor, NULL, ao2_cleanup);
3323  RAII_VAR(struct ast_sip_contact *, found_contact, NULL, ao2_cleanup);
3324  pjsip_timer_setting timer;
3325  pjsip_dialog *dlg;
3326  struct pjsip_inv_session *inv_session;
3328  struct ast_sip_session *ret_session;
3329  SCOPE_ENTER(1, "%s %s Topology: %s\n", ast_sorcery_object_get_id(endpoint), request_user,
3330  ast_str_tmp(256, ast_stream_topology_to_str(req_topology, &STR_TMP)));
3331 
3332  /* If no location has been provided use the AOR list from the endpoint itself */
3333  if (location || !contact) {
3334  location = S_OR(location, endpoint->aors);
3335 
3337  &found_aor, &found_contact);
3338  if (!found_contact || ast_strlen_zero(found_contact->uri)) {
3339  uri = location;
3340  } else {
3341  uri = found_contact->uri;
3342  }
3343  } else {
3344  uri = contact->uri;
3345  }
3346 
3347  /* If we still have no URI to dial fail to create the session */
3348  if (ast_strlen_zero(uri)) {
3349  ast_log(LOG_ERROR, "Endpoint '%s': No URI available. Is endpoint registered?\n",
3350  ast_sorcery_object_get_id(endpoint));
3351  SCOPE_EXIT_RTN_VALUE(NULL, "No URI\n");
3352  }
3353 
3354  if (!(dlg = ast_sip_create_dialog_uac(endpoint, uri, request_user))) {
3355  SCOPE_EXIT_RTN_VALUE(NULL, "Couldn't create dialog\n");
3356  }
3357 
3358  if (setup_outbound_invite_auth(dlg)) {
3359  pjsip_dlg_terminate(dlg);
3360  SCOPE_EXIT_RTN_VALUE(NULL, "Couldn't setup auth\n");
3361  }
3362 
3363  if (pjsip_inv_create_uac(dlg, NULL, endpoint->extensions.flags, &inv_session) != PJ_SUCCESS) {
3364  pjsip_dlg_terminate(dlg);
3365  SCOPE_EXIT_RTN_VALUE(NULL, "Couldn't create uac\n");
3366  }
3367 #if defined(HAVE_PJSIP_REPLACE_MEDIA_STREAM) || defined(PJMEDIA_SDP_NEG_ALLOW_MEDIA_CHANGE)
3368  inv_session->sdp_neg_flags = PJMEDIA_SDP_NEG_ALLOW_MEDIA_CHANGE;
3369 #endif
3370 
3371  pjsip_timer_setting_default(&timer);
3372  timer.min_se = endpoint->extensions.timer.min_se;
3373  timer.sess_expires = endpoint->extensions.timer.sess_expires;
3374  pjsip_timer_init_session(inv_session, &timer);
3375 
3376  session = ast_sip_session_alloc(endpoint, found_contact ? found_contact : contact,
3377  inv_session, NULL);
3378  if (!session) {
3379  pjsip_inv_terminate(inv_session, 500, PJ_FALSE);
3380  return NULL;
3381  }
3382  session->aor = ao2_bump(found_aor);
3383  session->call_direction = AST_SIP_SESSION_OUTGOING_CALL;
3384 
3385  ast_party_id_copy(&session->id, &endpoint->id.self);
3386 
3387  if (ast_stream_topology_get_count(req_topology) > 0) {
3388  /* get joint caps between req_topology and endpoint topology */
3389  int i;
3390 
3391  for (i = 0; i < ast_stream_topology_get_count(req_topology); ++i) {
3392  struct ast_stream *req_stream;
3393  struct ast_stream *clone_stream;
3394 
3395  req_stream = ast_stream_topology_get_stream(req_topology, i);
3396 
3397  if (ast_stream_get_state(req_stream) == AST_STREAM_STATE_REMOVED) {
3398  continue;
3399  }
3400 
3401  clone_stream = ast_sip_session_create_joint_call_stream(session, req_stream);
3402  if (!clone_stream || ast_stream_get_format_count(clone_stream) == 0) {
3403  ast_stream_free(clone_stream);
3404  continue;
3405  }
3406 
3407  if (!session->pending_media_state->topology) {
3408  session->pending_media_state->topology = ast_stream_topology_alloc();
3409  if (!session->pending_media_state->topology) {
3410  pjsip_inv_terminate(inv_session, 500, PJ_FALSE);
3411  ao2_ref(session, -1);
3412  SCOPE_EXIT_RTN_VALUE(NULL, "Couldn't create topology\n");
3413  }
3414  }
3415 
3416  if (ast_stream_topology_append_stream(session->pending_media_state->topology, clone_stream) < 0) {
3417  ast_stream_free(clone_stream);
3418  continue;
3419  }
3420  }
3421  }
3422 
3423  if (!session->pending_media_state->topology) {
3424  /* Use the configured topology on the endpoint as the pending one */
3425  session->pending_media_state->topology = ast_stream_topology_clone(endpoint->media.topology);
3426  if (!session->pending_media_state->topology) {
3427  pjsip_inv_terminate(inv_session, 500, PJ_FALSE);
3428  ao2_ref(session, -1);
3429  SCOPE_EXIT_RTN_VALUE(NULL, "Couldn't clone topology\n");
3430  }
3431  }
3432 
3433  if (pjsip_dlg_add_usage(dlg, &session_module, NULL) != PJ_SUCCESS) {
3434  pjsip_inv_terminate(inv_session, 500, PJ_FALSE);
3435  /* Since we are not notifying ourselves that the INVITE session is being terminated
3436  * we need to manually drop its reference to session
3437  */
3438  ao2_ref(session, -1);
3439  SCOPE_EXIT_RTN_VALUE(NULL, "Couldn't add usage\n");
3440  }
3441 
3442  /* Avoid unnecessary ref manipulation to return a session */
3443  ret_session = session;
3444  session = NULL;
3445  SCOPE_EXIT_RTN_VALUE(ret_session);
3446 }
struct ast_sip_session * ast_sip_session_alloc(struct ast_sip_endpoint *endpoint, struct ast_sip_contact *contact, pjsip_inv_session *inv_session, pjsip_rx_data *rdata)
Allocate a new SIP session.
unsigned int sess_expires
Definition: res_pjsip.h:567
A SIP address of record.
Definition: res_pjsip.h:361
static int setup_outbound_invite_auth(pjsip_dialog *dlg)
void ast_party_id_copy(struct ast_party_id *dest, const struct ast_party_id *src)
Copy the source party id information to the destination party id.
Definition: channel.c:1765
Set when the stream has been removed/declined.
Definition: stream.h:78
int ast_stream_get_format_count(const struct ast_stream *stream)
Get the count of the current negotiated formats of a stream.
Definition: stream.c:358
struct ast_stream * ast_stream_topology_get_stream(const struct ast_stream_topology *topology, unsigned int position)
Get a specific stream from the topology.
Definition: stream.c:788
#define NULL
Definition: resample.c:96
int ast_stream_topology_append_stream(struct ast_stream_topology *topology, struct ast_stream *stream)
Append a stream to the topology.
Definition: stream.c:748
A structure describing a SIP session.
#define ast_strlen_zero(foo)
Definition: strings.h:52
struct ast_sip_endpoint_media_configuration media
Definition: res_pjsip.h:841
#define ao2_bump(obj)
Definition: astobj2.h:491
unsigned int min_se
Definition: res_pjsip.h:565
#define ast_str_tmp(init_len, __expr)
Definition: strings.h:1136
#define ast_log
Definition: astobj2.c:42
const char * ast_stream_topology_to_str(const struct ast_stream_topology *topology, struct ast_str **buf)
Get a string representing the topology for debugging/display purposes.
Definition: stream.c:936
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
static struct ast_mansession session
#define ao2_ref(o, delta)
Definition: astobj2.h:464
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
static pjsip_module session_module
void ast_sip_location_retrieve_contact_and_aor_from_list_filtered(const char *aor_list, unsigned int flags, struct ast_sip_aor **aor, struct ast_sip_contact **contact)
Retrieve the first bound contact AND the AOR chosen from a list of AORs and filter based on flags...
Definition: location.c:272
struct ast_sip_endpoint_id_configuration id
Definition: res_pjsip.h:847
#define LOG_ERROR
Definition: logger.h:285
struct ast_stream_topology * ast_stream_topology_alloc(void)
Create a stream topology.
Definition: stream.c:650
Contact associated with an address of record.
Definition: res_pjsip.h:281
struct ast_sip_timer_options timer
Definition: res_pjsip.h:580
#define SCOPE_ENTER(level,...)
Non RAII_VAR Scope Trace macros The advantage of these macros is that the EXITs will have the actual ...
Definition: logger.h:780
int ast_stream_topology_get_count(const struct ast_stream_topology *topology)
Get the number of streams in a topology.
Definition: stream.c:765
struct ast_stream_topology * ast_stream_topology_clone(const struct ast_stream_topology *topology)
Create a deep clone of an existing stream topology.
Definition: stream.c:667
#define SCOPE_EXIT_RTN_VALUE(__return_value,...)
Scope Exit with return value.
Definition: logger.h:875
void ast_stream_free(struct ast_stream *stream)
Destroy a media stream representation.
Definition: stream.c:292
struct ast_stream_topology * topology
Definition: res_pjsip.h:772
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
struct ast_party_id self
Definition: res_pjsip.h:629
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
struct ast_sip_endpoint_extensions extensions
Definition: res_pjsip.h:839
pjsip_dialog * ast_sip_create_dialog_uac(const struct ast_sip_endpoint *endpoint, const char *aor_name, const char *request_user)
General purpose method for creating a UAC dialog with an endpoint.
Definition: res_pjsip.c:4028
Return only reachable or unknown contacts.
Definition: res_pjsip.h:1009
const ast_string_field aors
Definition: res_pjsip.h:821
const ast_string_field uri
Definition: res_pjsip.h:303
static struct ast_timer * timer
Definition: chan_iax2.c:360
enum ast_stream_state ast_stream_get_state(const struct ast_stream *stream)
Get the current state of a stream.
Definition: stream.c:373
struct ast_stream * ast_sip_session_create_joint_call_stream(const struct ast_sip_session *session, struct ast_stream *remote)
Create a new stream of joint capabilities.

◆ ast_sip_session_defer_termination()

int ast_sip_session_defer_termination ( struct ast_sip_session session)

Defer local termination of a session until remote side terminates, or an amount of time passes.

Parameters
sessionThe session to defer termination on
Return values
0Success
-1Failure

Definition at line 3554 of file res_pjsip_session.c.

References ao2_ref, ast_assert, ast_sip_get_pjsip_endpoint(), ast_sip_session::defer_end, ast_sip_session::defer_terminate, ast_sip_session::ended_while_deferred, ast_sip_session::scheduled_termination, and session_termination_cb().

Referenced by refer_incoming_attended_request(), and refer_incoming_blind_request().

3555 {
3556  pj_time_val delay = { .sec = 60, };
3557  int res;
3558 
3559  /* The session should not have an active deferred termination request. */
3560  ast_assert(!session->defer_terminate);
3561 
3562  session->defer_terminate = 1;
3563 
3564  session->defer_end = 1;
3565  session->ended_while_deferred = 0;
3566 
3567  ao2_ref(session, +1);
3568  pj_timer_entry_init(&session->scheduled_termination, 0, session, session_termination_cb);
3569 
3570  res = (pjsip_endpt_schedule_timer(ast_sip_get_pjsip_endpoint(),
3571  &session->scheduled_termination, &delay) != PJ_SUCCESS) ? -1 : 0;
3572  if (res) {
3573  session->defer_terminate = 0;
3574  ao2_ref(session, -1);
3575  }
3576  return res;
3577 }
unsigned int defer_end
unsigned int defer_terminate
unsigned int ended_while_deferred
static void session_termination_cb(pj_timer_heap_t *timer_heap, struct pj_timer_entry *entry)
#define ast_assert(a)
Definition: utils.h:695
#define ao2_ref(o, delta)
Definition: astobj2.h:464
pj_timer_entry scheduled_termination
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
Definition: res_pjsip.c:3718

◆ ast_sip_session_defer_termination_cancel()

void ast_sip_session_defer_termination_cancel ( struct ast_sip_session session)

Cancel a pending deferred termination.

Parameters
sessionThe session to cancel a deferred termination on.

Definition at line 3596 of file res_pjsip_session.c.

References ast_sip_session_terminate(), ast_sip_session::defer_terminate, sip_session_defer_termination_stop_timer(), and ast_sip_session::terminate_while_deferred.

Referenced by defer_termination_cancel_task(), refer_incoming_attended_request(), and refer_incoming_blind_request().

3597 {
3598  if (!session->defer_terminate) {
3599  /* Already canceled or timer fired. */
3600  return;
3601  }
3602 
3603  session->defer_terminate = 0;
3604 
3605  if (session->terminate_while_deferred) {
3606  /* Complete the termination started by the upper layer. */
3607  ast_sip_session_terminate(session, 0);
3608  }
3609 
3610  /* Stop the termination timer if it is still running. */
3612 }
unsigned int defer_terminate
unsigned int terminate_while_deferred
static void sip_session_defer_termination_stop_timer(struct ast_sip_session *session)
void ast_sip_session_terminate(struct ast_sip_session *session, int response)
Terminate a session and, if possible, send the provided response code.

◆ ast_sip_session_end_if_deferred()

void ast_sip_session_end_if_deferred ( struct ast_sip_session session)

End the session if it had been previously deferred.

Parameters
sessionThe session to end if it had been deferred

Definition at line 3614 of file res_pjsip_session.c.

References ast_debug, ast_sip_session_get_name(), ast_sip_session::defer_end, ast_sip_session::ended_while_deferred, and session_end().

Referenced by defer_termination_cancel_task(), refer_attended_task(), refer_incoming_attended_request(), refer_incoming_blind_request(), and session_end_if_deferred_task().

3615 {
3616  if (!session->defer_end) {
3617  return;
3618  }
3619 
3620  session->defer_end = 0;
3621 
3622  if (session->ended_while_deferred) {
3623  /* Complete the session end started by the remote hangup. */
3624  ast_debug(3, "%s: Ending session after being deferred\n", ast_sip_session_get_name(session));
3625  session->ended_while_deferred = 0;
3626  session_end(session);
3627  }
3628 }
unsigned int defer_end
unsigned int ended_while_deferred
static int session_end(void *vsession)
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
const char * ast_sip_session_get_name(const struct ast_sip_session *session)
Get the channel or endpoint name associated with the session.

◆ ast_sip_session_get_datastore()

struct ast_datastore* ast_sip_session_get_datastore ( struct ast_sip_session session,
const char *  name 
)

Retrieve a session datastore.

The datastore retrieved will have its reference count incremented. When the caller is done with the datastore, the reference counted needs to be decremented using ao2_ref().

Parameters
sessionThe session from which to retrieve the datastore
nameThe name of the datastore to retrieve
Return values
NULLFailed to find the specified datastore
non-NULLThe specified datastore

Definition at line 1285 of file res_pjsip_session.c.

References ao2_find, ast_sip_session::datastores, and OBJ_KEY.

Referenced by add_header(), chan_pjsip_get_rtp_peer(), channel_read_pjsip(), direct_media_mitigate_glare(), handle_outgoing_response(), incoming_request(), outgoing_request(), read_header(), remove_header(), session_refresh_state_get_or_alloc(), t38_automatic_reject(), t38_state_get_or_alloc(), and update_header().

1286 {
1287  return ao2_find(session->datastores, name, OBJ_KEY);
1288 }
#define OBJ_KEY
Definition: astobj2.h:1155
struct ao2_container * datastores
static const char name[]
Definition: cdr_mysql.c:74
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756

◆ ast_sip_session_get_name()

const char* ast_sip_session_get_name ( const struct ast_sip_session session)

Get the channel or endpoint name associated with the session.

Since
18.0.0
Parameters
session
Return values
Channelname or endpoint name or "unknown"

Definition at line 115 of file res_pjsip_session.c.

References ast_channel_name(), ast_sorcery_object_get_id(), ast_sip_session::channel, and ast_sip_session::endpoint.

Referenced by add_sdp_streams(), answer(), apply_negotiated_sdp_stream(), ast_sip_session_create_invite(), ast_sip_session_end_if_deferred(), ast_sip_session_media_state_add(), ast_sip_session_regenerate_answer(), ast_sip_session_terminate(), call(), chan_pjsip_call(), chan_pjsip_incoming_ack(), chan_pjsip_incoming_request(), chan_pjsip_incoming_response(), chan_pjsip_incoming_response_update_cause(), chan_pjsip_new(), chan_pjsip_session_begin(), chan_pjsip_session_end(), create_local_sdp(), create_outgoing_sdp_stream(), delay_request(), generate_session_refresh_sdp(), get_codecs(), get_destination(), handle_incoming_before_media(), handle_incoming_request(), handle_incoming_response(), handle_incoming_sdp(), handle_negotiated_sdp(), handle_negotiated_sdp_session_media(), handle_new_invite_request(), handle_outgoing_request(), handle_outgoing_response(), invite_collision_timeout(), invite_proceeding(), invite_terminated(), negotiate_incoming_sdp_stream(), new_invite(), on_topology_change_response(), outbound_invite_auth(), pbx_start_incoming_request(), reschedule_reinvite(), resend_reinvite(), sdp_requires_deferral(), send_delayed_request(), send_topology_change_refresh(), session_destructor(), session_inv_on_media_update(), session_inv_on_rx_offer(), session_inv_on_state_changed(), session_inv_on_tsx_state_changed(), session_on_rx_request(), session_on_rx_response(), session_on_tsx_state(), session_outgoing_nat_hook(), set_caps(), set_from_header(), set_incoming_call_offer_cap(), and sip_session_refresh().

116 {
117  if (!session) {
118  return "(null session)";
119  }
120  if (session->channel) {
121  return ast_channel_name(session->channel);
122  } else if (session->endpoint) {
123  return ast_sorcery_object_get_id(session->endpoint);
124  } else {
125  return "unknown";
126  }
127 }
struct ast_sip_endpoint * endpoint
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
struct ast_channel * channel
const char * ast_channel_name(const struct ast_channel *chan)

◆ ast_sip_session_is_pending_stream_default()

int ast_sip_session_is_pending_stream_default ( const struct ast_sip_session session,
const struct ast_stream stream 
)

Determines if a provided pending stream will be the default stream or not.

Since
15.0.0
Parameters
sessionThe session to check against
streamThe pending stream
Return values
1if stream will be default
0if stream will NOT be the default

Definition at line 359 of file res_pjsip_session.c.

References ast_channel_name(), ast_log, ast_stream_get_state(), ast_stream_get_type(), AST_STREAM_STATE_REMOVED, ast_stream_topology_get_count(), ast_stream_topology_get_stream(), ast_sip_session::channel, LOG_WARNING, ast_sip_session::pending_media_state, and ast_sip_session_media_state::topology.

Referenced by create_outgoing_sdp_stream(), handle_incoming_sdp(), handle_negotiated_sdp_session_media(), negotiate_incoming_sdp_stream(), sdp_requires_deferral(), and set_caps().

360 {
361  int index;
362 
363  if (!session->pending_media_state->topology) {
364  ast_log(LOG_WARNING, "Pending topology was NULL for channel '%s'\n",
365  session->channel ? ast_channel_name(session->channel) : "unknown");
366  return 0;
367  }
368 
370  return 0;
371  }
372 
373  for (index = 0; index < ast_stream_topology_get_count(session->pending_media_state->topology); ++index) {
375  ast_stream_get_type(stream)) {
376  continue;
377  }
378 
379  return ast_stream_topology_get_stream(session->pending_media_state->topology, index) == stream ? 1 : 0;
380  }
381 
382  return 0;
383 }
struct ast_sip_session_media_state * pending_media_state
enum ast_media_type ast_stream_get_type(const struct ast_stream *stream)
Get the media type of a stream.
Definition: stream.c:316
#define LOG_WARNING
Definition: logger.h:274
Set when the stream has been removed/declined.
Definition: stream.h:78
struct ast_stream * ast_stream_topology_get_stream(const struct ast_stream_topology *topology, unsigned int position)
Get a specific stream from the topology.
Definition: stream.c:788
#define ast_log
Definition: astobj2.c:42
struct ast_channel * channel
int ast_stream_topology_get_count(const struct ast_stream_topology *topology)
Get the number of streams in a topology.
Definition: stream.c:765
struct ast_stream_topology * topology
The media stream topology.
const char * ast_channel_name(const struct ast_channel *chan)
enum ast_stream_state ast_stream_get_state(const struct ast_stream *stream)
Get the current state of a stream.
Definition: stream.c:373

◆ ast_sip_session_media_add_read_callback()

int ast_sip_session_media_add_read_callback ( struct ast_sip_session session,
struct ast_sip_session_media session_media,
int  fd,
ast_sip_session_media_read_cb  callback 
)

Set a read callback for a media session with a specific file descriptor.

Since
15.0.0
Parameters
sessionThe session
session_mediaThe media session
fdThe file descriptor
callbackThe read callback
Return values
0the read callback was successfully added
-1the read callback could not be added
Note
This operations on the pending media state

Definition at line 385 of file res_pjsip_session.c.

References AST_VECTOR_APPEND, ast_sip_session_media_read_callback_state::fd, and ast_sip_session::pending_media_state.

Referenced by apply_negotiated_sdp_stream().

387 {
388  struct ast_sip_session_media_read_callback_state callback_state = {
389  .fd = fd,
390  .read_callback = callback,
391  .session = session_media,
392  };
393 
394  /* The contents of the vector are whole structs and not pointers */
395  return AST_VECTOR_APPEND(&session->pending_media_state->read_callbacks, callback_state);
396 }
struct ast_sip_session_media_state * pending_media_state
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256
Structure which contains read callback information.
int fd
The file descriptor itself.

◆ ast_sip_session_media_get_transport()

struct ast_sip_session_media* ast_sip_session_media_get_transport ( struct ast_sip_session session,
struct ast_sip_session_media session_media 
)

Retrieve the underlying media session that is acting as transport for a media session.

Since
15.0.0
Parameters
sessionThe session
session_mediaThe media session to retrieve the transport for
Note
This operates on the pending media state
This function is guaranteed to return non-NULL

Definition at line 414 of file res_pjsip_session.c.

References ast_strlen_zero, AST_VECTOR_GET, AST_VECTOR_SIZE, ast_sip_endpoint_media_configuration::bundle, ast_sip_session_media::bundle_group, ast_sip_session::endpoint, ast_sip_endpoint::media, ast_sip_session_media::mid, and ast_sip_session::pending_media_state.

Referenced by apply_negotiated_sdp_stream(), create_outgoing_sdp_stream(), and negotiate_incoming_sdp_stream().

415 {
416  int index;
417 
418  if (!session->endpoint->media.bundle || ast_strlen_zero(session_media->mid)) {
419  return session_media;
420  }
421 
422  for (index = 0; index < AST_VECTOR_SIZE(&session->pending_media_state->sessions); ++index) {
423  struct ast_sip_session_media *bundle_group_session_media;
424 
425  bundle_group_session_media = AST_VECTOR_GET(&session->pending_media_state->sessions, index);
426 
427  /* The first session which is in the bundle group is considered the authoritative session for transport */
428  if (bundle_group_session_media->bundle_group == session_media->bundle_group) {
429  return bundle_group_session_media;
430  }
431  }
432 
433  return session_media;
434 }
struct ast_sip_endpoint * endpoint
struct ast_sip_session_media_state * pending_media_state
char * mid
Media identifier for this stream (may be shared across multiple streams)
#define ast_strlen_zero(foo)
Definition: strings.h:52
struct ast_sip_endpoint_media_configuration media
Definition: res_pjsip.h:841
int bundle_group
The bundle group the stream belongs to.
A structure containing SIP session media information.
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:682
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:611

◆ ast_sip_session_media_set_write_callback()

int ast_sip_session_media_set_write_callback ( struct ast_sip_session session,
struct ast_sip_session_media session_media,
ast_sip_session_media_write_cb  callback 
)

Set a write callback for a media session.

Since
15.0.0
Parameters
sessionThe session
session_mediaThe media session
callbackThe write callback
Return values
0the write callback was successfully add
-1the write callback is already set to something different
Note
This operates on the pending media state

Definition at line 398 of file res_pjsip_session.c.

References ast_sip_session_media::write_callback.

Referenced by apply_negotiated_sdp_stream().

400 {
401  if (session_media->write_callback) {
402  if (session_media->write_callback == callback) {
403  return 0;
404  }
405 
406  return -1;
407  }
408 
409  session_media->write_callback = callback;
410 
411  return 0;
412 }
ast_sip_session_media_write_cb write_callback
The write callback when writing frames.

◆ ast_sip_session_media_state_add()

struct ast_sip_session_media* ast_sip_session_media_state_add ( struct ast_sip_session session,
struct ast_sip_session_media_state media_state,
enum ast_media_type  type,
int  position 
)

Allocate an ast_session_media and add it to the media state's vector.

Since
15.0.0

This allocates a session media of the specified type. The position argument determines where in the vector that the new session media will be inserted.

Note
The returned ast_session_media is the reference held by the vector. Callers of this function must NOT decrement the refcount of the session media.
Parameters
sessionSession on which to query active media state for
media_stateMedia state to place the session media into
typeThe type of the session media
positionPosition at which to insert the new session media.
Note
The active media state will be queried and if a media session already exists at the given position for the same type it will be reused instead of allocating a new one.
Return values
non-NULLsuccess
NULLfailure

Definition at line 490 of file res_pjsip_session.c.

References ast_sip_session::active_media_state, AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_alloc_options, ao2_cleanup, ao2_ref, ast_asprintf, ast_codec_media_type2str(), ast_free, ast_sip_session_get_name(), ast_strdup, ast_stream_get_name(), ast_stream_get_state(), AST_STREAM_STATE_REMOVED, ast_stream_topology_get_stream(), ast_trace, AST_VECTOR_GET, AST_VECTOR_REPLACE, AST_VECTOR_SIZE, ast_sip_endpoint_media_configuration::bundle, ast_sip_session_media::bundle_group, ast_sip_session_media::bundled, ast_sip_session_media_state::default_session, ast_sip_session_media::encryption, ast_sip_media_rtp_configuration::encryption, ast_sip_session::endpoint, ast_sip_media_rtp_configuration::ice_support, ast_sip_session_media::keepalive_sched_id, ast_sip_endpoint::media, ast_sip_session_media::mid, NULL, ast_sip_session_media::remote_ice, ast_sip_session_media::remote_rtcp_mux, ast_sip_endpoint_media_configuration::rtcp_mux, ast_sip_endpoint_media_configuration::rtp, SCOPE_ENTER, SCOPE_EXIT_RTN_VALUE, session_media_dtor(), ast_sip_session_media::stream_name, ast_sip_session_media::stream_num, ast_sip_session_media::timeout_sched_id, ast_sip_session_media_state::topology, ast_sip_session_media::type, type, and ast_sip_endpoint_media_configuration::webrtc.

Referenced by create_local_sdp(), handle_incoming_sdp(), sdp_requires_deferral(), and t38_create_media_state().

492 {
493  struct ast_sip_session_media *session_media = NULL;
494  struct ast_sip_session_media *current_session_media = NULL;
495  SCOPE_ENTER(1, "%s Adding position %d\n", ast_sip_session_get_name(session), position);
496 
497  /* It is possible for this media state to already contain a session for the stream. If this
498  * is the case we simply return it.
499  */
500  if (position < AST_VECTOR_SIZE(&media_state->sessions)) {
501  current_session_media = AST_VECTOR_GET(&media_state->sessions, position);
502  if (current_session_media && current_session_media->type == type) {
503  SCOPE_EXIT_RTN_VALUE(current_session_media, "Using existing media_session\n");
504  }
505  }
506 
507  /* Determine if we can reuse the session media from the active media state if present */
508  if (position < AST_VECTOR_SIZE(&session->active_media_state->sessions)) {
509  session_media = AST_VECTOR_GET(&session->active_media_state->sessions, position);
510  /* A stream can never exist without an accompanying media session */
511  if (session_media->type == type) {
512  ao2_ref(session_media, +1);
513  ast_trace(1, "Reusing existing media session\n");
514  /*
515  * If this session_media was previously removed, its bundle group was probably reset
516  * to -1 so if bundling is enabled on the endpoint, we need to reset it to 0, set
517  * the bundled flag and reset its mid.
518  */
519  if (session->endpoint->media.bundle && session_media->bundle_group == -1) {
520  session_media->bundled = session->endpoint->media.webrtc;
521  session_media->bundle_group = 0;
522  ast_free(session_media->mid);
523  if (ast_asprintf(&session_media->mid, "%s-%d", ast_codec_media_type2str(type), position) < 0) {
524  ao2_ref(session_media, -1);
525  SCOPE_EXIT_RTN_VALUE(NULL, "Couldn't alloc mid\n");
526  }
527  }
528  } else {
529  ast_trace(1, "Can't reuse existing media session because the types are different. %s <> %s\n",
531  session_media = NULL;
532  }
533  }
534 
535  if (!session_media) {
536  /* No existing media session we can use so create a new one */
537  session_media = ao2_alloc_options(sizeof(*session_media), session_media_dtor, AO2_ALLOC_OPT_LOCK_NOLOCK);
538  if (!session_media) {
539  return NULL;
540  }
541  ast_trace(1, "Creating new media session\n");
542 
543  session_media->encryption = session->endpoint->media.rtp.encryption;
544  session_media->remote_ice = session->endpoint->media.rtp.ice_support;
545  session_media->remote_rtcp_mux = session->endpoint->media.rtcp_mux;
546  session_media->keepalive_sched_id = -1;
547  session_media->timeout_sched_id = -1;
548  session_media->type = type;
549  session_media->stream_num = position;
550 
551  if (session->endpoint->media.bundle) {
552  /* This is a new stream so create a new mid based on media type and position, which makes it unique.
553  * If this is the result of an offer the mid will just end up getting replaced.
554  */
555  if (ast_asprintf(&session_media->mid, "%s-%d", ast_codec_media_type2str(type), position) < 0) {
556  ao2_ref(session_media, -1);
557  SCOPE_EXIT_RTN_VALUE(NULL, "Couldn't alloc mid\n");
558  }
559  session_media->bundle_group = 0;
560 
561  /* Some WebRTC clients can't handle an offer to bundle media streams. Instead they expect them to
562  * already be bundled. Every client handles this scenario though so if WebRTC is enabled just go
563  * ahead and treat the streams as having already been bundled.
564  */
565  session_media->bundled = session->endpoint->media.webrtc;
566  } else {
567  session_media->bundle_group = -1;
568  }
569  }
570 
571  ast_free(session_media->stream_name);
572  session_media->stream_name = ast_strdup(ast_stream_get_name(ast_stream_topology_get_stream(media_state->topology, position)));
573 
574  if (AST_VECTOR_REPLACE(&media_state->sessions, position, session_media)) {
575  ao2_ref(session_media, -1);
576 
577  SCOPE_EXIT_RTN_VALUE(NULL, "Couldn't replace media_session\n");
578  }
579 
580  ao2_cleanup(current_session_media);
581 
582  /* If this stream will be active in some way and it is the first of this type then consider this the default media session to match */
584  ast_trace(1, "Setting media session as default for %s\n", ast_codec_media_type2str(session_media->type));
585 
586  media_state->default_session[type] = session_media;
587  }
588 
589  SCOPE_EXIT_RTN_VALUE(session_media, "Done\n");
590 }
static const char type[]
Definition: chan_ooh323.c:109
struct ast_sip_endpoint * endpoint
char * mid
Media identifier for this stream (may be shared across multiple streams)
const char * ast_codec_media_type2str(enum ast_media_type type)
Conversion function to take a media type and turn it into a string.
Definition: codec.c:347
Set when the stream has been removed/declined.
Definition: stream.h:78
struct ast_sip_session_media * default_session[AST_MEDIA_TYPE_END]
Default media sessions for each type.
#define ast_trace(level,...)
Print a basic trace message.
Definition: logger.h:692
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:406
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
struct ast_stream * ast_stream_topology_get_stream(const struct ast_stream_topology *topology, unsigned int position)
Get a specific stream from the topology.
Definition: stream.c:788
#define NULL
Definition: resample.c:96
enum ast_sip_session_media_encryption encryption
What type of encryption is in use on this stream.
unsigned int bundled
Whether this stream is currently bundled or not.
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition: astmm.h:269
struct ast_sip_session_media_state * active_media_state
char * stream_name
Stream name.
struct ast_sip_endpoint_media_configuration media
Definition: res_pjsip.h:841
struct ast_sip_media_rtp_configuration rtp
Definition: res_pjsip.h:764
#define ao2_ref(o, delta)
Definition: astobj2.h:464
enum ast_sip_session_media_encryption encryption
Definition: res_pjsip.h:711
int stream_num
The stream number to place into any resulting frames.
static void session_media_dtor(void *obj)
int timeout_sched_id
Scheduler ID for RTP timeout.
#define ast_free(a)
Definition: astmm.h:182
#define SCOPE_ENTER(level,...)
Non RAII_VAR Scope Trace macros The advantage of these macros is that the EXITs will have the actual ...
Definition: logger.h:780
int bundle_group
The bundle group the stream belongs to.
const char * ast_sip_session_get_name(const struct ast_sip_session *session)
Get the channel or endpoint name associated with the session.
int keepalive_sched_id
Scheduler ID for RTP keepalive.
A structure containing SIP session media information.
#define SCOPE_EXIT_RTN_VALUE(__return_value,...)
Scope Exit with return value.
Definition: logger.h:875
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:682
enum ast_media_type type
Media type of this session media.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
struct ast_stream_topology * topology
The media stream topology.
#define AST_VECTOR_REPLACE(vec, idx, elem)
Replace an element at a specific position in a vector, growing the vector if needed.
Definition: vector.h:284
unsigned int remote_rtcp_mux
Does remote support rtcp_mux.
const char * ast_stream_get_name(const struct ast_stream *stream)
Get the name of a stream.
Definition: stream.c:309
enum ast_stream_state ast_stream_get_state(const struct ast_stream *stream)
Get the current state of a stream.
Definition: stream.c:373
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:611
unsigned int remote_ice
Does remote support ice.

◆ ast_sip_session_media_state_alloc()

struct ast_sip_session_media_state* ast_sip_session_media_state_alloc ( void  )

Allocate a session media state structure.

Since
15.0.0
Return values
non-NULLsuccess
NULLfailure

Definition at line 238 of file res_pjsip_session.c.

References DEFAULT_NUM_SESSION_MEDIA, and internal_sip_session_media_state_alloc().

Referenced by ast_sip_session_alloc(), session_refresh_state_get_or_alloc(), t38_create_media_state(), and topology_change_refresh_data_alloc().

239 {
242 }
#define DEFAULT_NUM_SESSION_MEDIA
static struct ast_sip_session_media_state * internal_sip_session_media_state_alloc(size_t sessions, size_t read_callbacks)

◆ ast_sip_session_media_state_clone()

struct ast_sip_session_media_state* ast_sip_session_media_state_clone ( const struct ast_sip_session_media_state media_state)

Clone a media state.

Since
15.0.0
Parameters
media_stateThe media state to clone
Return values
non-NULLsuccess
NULLfailure

Definition at line 297 of file res_pjsip_session.c.

References ao2_bump, ao2_cleanup, ast_sip_session_media_state_free(), ast_stream_get_state(), ast_stream_get_type(), AST_STREAM_STATE_REMOVED, ast_stream_topology_clone(), ast_stream_topology_get_stream(), AST_VECTOR_GET, AST_VECTOR_GET_ADDR, AST_VECTOR_REPLACE, AST_VECTOR_SIZE, ast_sip_session_media_state::default_session, internal_sip_session_media_state_alloc(), NULL, ast_sip_session_media_read_callback_state::read_callback, ast_sip_session_media_state::topology, and type.

Referenced by handle_negotiated_sdp(), reschedule_reinvite(), resolve_refresh_media_states(), sip_session_refresh(), and t38_reinvite_sdp_cb().

298 {
299  struct ast_sip_session_media_state *cloned;
300  int index;
301 
302  if (!media_state) {
303  return NULL;
304  }
305 
307  AST_VECTOR_SIZE(&media_state->sessions),
308  AST_VECTOR_SIZE(&media_state->read_callbacks));
309  if (!cloned) {
310  return NULL;
311  }
312 
313  if (media_state->topology) {
314  cloned->topology = ast_stream_topology_clone(media_state->topology);
315  if (!cloned->topology) {
317  return NULL;
318  }
319  }
320 
321  for (index = 0; index < AST_VECTOR_SIZE(&media_state->sessions); ++index) {
322  struct ast_sip_session_media *session_media = AST_VECTOR_GET(&media_state->sessions, index);
324 
325  ao2_bump(session_media);
326  if (AST_VECTOR_REPLACE(&cloned->sessions, index, session_media)) {
327  ao2_cleanup(session_media);
328  }
330  !cloned->default_session[type]) {
331  cloned->default_session[type] = session_media;
332  }
333  }
334 
335  for (index = 0; index < AST_VECTOR_SIZE(&media_state->read_callbacks); ++index) {
336  struct ast_sip_session_media_read_callback_state *read_callback = AST_VECTOR_GET_ADDR(&media_state->read_callbacks, index);
337 
338  AST_VECTOR_REPLACE(&cloned->read_callbacks, index, *read_callback);
339  }
340 
341  return cloned;
342 }
static const char type[]
Definition: chan_ooh323.c:109
Structure which contains media state information (streams, sessions)
enum ast_media_type ast_stream_get_type(const struct ast_stream *stream)
Get the media type of a stream.
Definition: stream.c:316
void ast_sip_session_media_state_free(struct ast_sip_session_media_state *media_state)
Free a session media state structure.
Set when the stream has been removed/declined.
Definition: stream.h:78
struct ast_sip_session_media * default_session[AST_MEDIA_TYPE_END]
Default media sessions for each type.
struct ast_stream * ast_stream_topology_get_stream(const struct ast_stream_topology *topology, unsigned int position)
Get a specific stream from the topology.
Definition: stream.c:788
#define NULL
Definition: resample.c:96
#define ao2_bump(obj)
Definition: astobj2.h:491
#define AST_VECTOR_GET_ADDR(vec, idx)
Get an address of element in a vector.
Definition: vector.h:670
static struct ast_sip_session_media_state * internal_sip_session_media_state_alloc(size_t sessions, size_t read_callbacks)
ast_sip_session_media_read_cb read_callback
The callback to invoke.
Structure which contains read callback information.
A structure containing SIP session media information.
struct ast_stream_topology * ast_stream_topology_clone(const struct ast_stream_topology *topology)
Create a deep clone of an existing stream topology.
Definition: stream.c:667
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:682
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
struct ast_stream_topology * topology
The media stream topology.
#define AST_VECTOR_REPLACE(vec, idx, elem)
Replace an element at a specific position in a vector, growing the vector if needed.
Definition: vector.h:284
ast_media_type
Types of media.
Definition: codec.h:30
enum ast_stream_state ast_stream_get_state(const struct ast_stream *stream)
Get the current state of a stream.
Definition: stream.c:373
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:611

◆ ast_sip_session_media_state_free()

void ast_sip_session_media_state_free ( struct ast_sip_session_media_state media_state)

Free a session media state structure.

Since
15.0.0

Definition at line 344 of file res_pjsip_session.c.

References ast_free, ast_sip_session_media_state_reset(), and AST_VECTOR_FREE.

Referenced by ast_sip_session_media_state_clone(), delay_request(), delayed_request_free(), handle_negotiated_sdp(), reschedule_reinvite(), resolve_refresh_media_states(), session_destructor(), session_refresh_state_destroy(), sip_session_refresh(), t38_create_media_state(), t38_reinvite_response_cb(), t38_state_destroy(), and topology_change_refresh_data_free().

345 {
346  if (!media_state) {
347  return;
348  }
349 
350  /* This will reset the internal state so we only have to free persistent things */
352 
353  AST_VECTOR_FREE(&media_state->sessions);
354  AST_VECTOR_FREE(&media_state->read_callbacks);
355 
356  ast_free(media_state);
357 }
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition: vector.h:174
#define ast_free(a)
Definition: astmm.h:182
void ast_sip_session_media_state_reset(struct ast_sip_session_media_state *media_state)
Reset a media state to a clean state.

◆ ast_sip_session_media_state_reset()

void ast_sip_session_media_state_reset ( struct ast_sip_session_media_state media_state)

Reset a media state to a clean state.

Since
15.0.0
Parameters
media_stateThe media state to reset

Definition at line 278 of file res_pjsip_session.c.

References ao2_cleanup, AST_MEDIA_TYPE_END, ast_stream_topology_free(), AST_VECTOR_ELEM_CLEANUP_NOOP, AST_VECTOR_RESET, ast_sip_session_media_state::default_session, NULL, and ast_sip_session_media_state::topology.

Referenced by ast_sip_session_media_state_free(), ast_sip_session_terminate(), handle_negotiated_sdp(), on_topology_change_response(), session_inv_on_media_update(), session_inv_on_rx_offer(), session_reinvite_on_rx_request(), sip_session_refresh(), and t38_reinvite_response_cb().

279 {
280  int index;
281 
282  if (!media_state) {
283  return;
284  }
285 
286  AST_VECTOR_RESET(&media_state->sessions, ao2_cleanup);
287  AST_VECTOR_RESET(&media_state->read_callbacks, AST_VECTOR_ELEM_CLEANUP_NOOP);
288 
289  for (index = 0; index < AST_MEDIA_TYPE_END; ++index) {
290  media_state->default_session[index] = NULL;
291  }
292 
293  ast_stream_topology_free(media_state->topology);
294  media_state->topology = NULL;
295 }
struct ast_sip_session_media * default_session[AST_MEDIA_TYPE_END]
Default media sessions for each type.
#define NULL
Definition: resample.c:96
#define AST_VECTOR_ELEM_CLEANUP_NOOP(elem)
Vector element cleanup that does nothing.
Definition: vector.h:573
#define AST_VECTOR_RESET(vec, cleanup)
Reset vector.
Definition: vector.h:627
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
struct ast_stream_topology * topology
The media stream topology.
void ast_stream_topology_free(struct ast_stream_topology *topology)
Unreference and destroy a stream topology.
Definition: stream.c:743

◆ ast_sip_session_media_stats_save()

void ast_sip_session_media_stats_save ( struct ast_sip_session sip_session,
struct ast_sip_session_media_state media_state 
)

Save a media stats.

Parameters
media_stateThe media state to save

Definition at line 244 of file res_pjsip_session.c.

References ast_calloc, ast_free, ast_rtp_instance_get_stats(), AST_RTP_INSTANCE_STAT_ALL, AST_VECTOR_APPEND, AST_VECTOR_GET, AST_VECTOR_REMOVE_CMP_UNORDERED, AST_VECTOR_SIZE, media_stats_local_ssrc_cmp(), NULL, and ast_sip_session_media::rtp.

Referenced by ast_sip_session_terminate(), and handle_negotiated_sdp().

245 {
246  int i;
247  int ret;
248 
249  if (!media_state || !sip_session) {
250  return;
251  }
252 
253  for (i = 0; i < AST_VECTOR_SIZE(&media_state->sessions); i++) {
254  struct ast_rtp_instance_stats *stats_tmp = NULL;
255  struct ast_sip_session_media *media = AST_VECTOR_GET(&media_state->sessions, i);
256  if (!media || !media->rtp) {
257  continue;
258  }
259 
260  stats_tmp = ast_calloc(1, sizeof(struct ast_rtp_instance_stats));
261  if (!stats_tmp) {
262  return;
263  }
264 
265  ret = ast_rtp_instance_get_stats(media->rtp, stats_tmp, AST_RTP_INSTANCE_STAT_ALL);
266  if (ret) {
267  ast_free(stats_tmp);
268  continue;
269  }
270 
271  /* remove all the duplicated stats if exist */
272  AST_VECTOR_REMOVE_CMP_UNORDERED(&sip_session->media_stats, stats_tmp, media_stats_local_ssrc_cmp, ast_free);
273 
274  AST_VECTOR_APPEND(&sip_session->media_stats, stats_tmp);
275  }
276 }
int ast_rtp_instance_get_stats(struct ast_rtp_instance *instance, struct ast_rtp_instance_stats *stats, enum ast_rtp_instance_stat stat)
Retrieve statistics about an RTP instance.
Definition: rtp_engine.c:2446
#define AST_VECTOR_REMOVE_CMP_UNORDERED(vec, value, cmp, cleanup)
Remove an element from a vector that matches the given comparison.
Definition: vector.h:488
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256
#define NULL
Definition: resample.c:96
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
A structure containing SIP session media information.
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:682
struct ast_rtp_instance * rtp
RTP instance itself.
static int media_stats_local_ssrc_cmp(const struct ast_rtp_instance_stats *vec_elem, const struct ast_rtp_instance_stats *srch)
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:611

◆ ast_sip_session_refresh()

int ast_sip_session_refresh ( struct ast_sip_session session,
ast_sip_session_request_creation_cb  on_request_creation,
ast_sip_session_sdp_creation_cb  on_sdp_creation,
ast_sip_session_response_cb  on_response,
enum ast_sip_session_refresh_method  method,
int  generate_new_sdp,
struct ast_sip_session_media_state media_state 
)

Send a reinvite or UPDATE on a session.

This method will inspect the session in order to construct an appropriate session refresh request. As with any outgoing request in res_pjsip_session, this will call into registered supplements in case they wish to add anything.

Note: The on_request_creation callback may or may not be called in the same thread where this function is called. Request creation may need to be delayed due to the current INVITE transaction state.

Parameters
sessionThe session on which the reinvite will be sent
on_request_creationCallback called when request is created
on_sdp_creationCallback called when SDP is created
on_responseCallback called when response for request is received
methodThe method that should be used when constructing the session refresh
generate_new_sdpBoolean to indicate if a new SDP should be created
media_stateOptional requested media state for the SDP
Return values
0Successfully sent refresh
-1Failure to send refresh
Note
If a media_state is passed in ownership will be taken in all cases

Definition at line 2524 of file res_pjsip_session.c.

References NULL, and sip_session_refresh().

Referenced by dtmf_mode_refresh_cb(), refresh_write_cb(), remote_send_hold_refresh(), send_direct_media_request(), send_topology_change_refresh(), t38_interpret_parameters(), and update_connected_line_information().

2530 {
2531  return sip_session_refresh(session, on_request_creation, on_sdp_creation,
2532  on_response, method, generate_new_sdp, media_state, NULL, 0);
2533 }
#define NULL
Definition: resample.c:96
static int sip_session_refresh(struct ast_sip_session *session, ast_sip_session_request_creation_cb on_request_creation, ast_sip_session_sdp_creation_cb on_sdp_creation, ast_sip_session_response_cb on_response, enum ast_sip_session_refresh_method method, int generate_new_sdp, struct ast_sip_session_media_state *pending_media_state, struct ast_sip_session_media_state *active_media_state, int queued)
const char * method
Definition: res_pjsip.c:4335

◆ ast_sip_session_regenerate_answer()

int ast_sip_session_regenerate_answer ( struct ast_sip_session session,
ast_sip_session_sdp_creation_cb  on_sdp_creation 
)

Regenerate SDP Answer.

This method is used when an SDP offer has been received but an SDP answer has not been sent yet. It requests that a new local SDP be created and set as the SDP answer. As with any outgoing request in res_pjsip_session, this will call into registered supplements in case they wish to add anything.

Parameters
sessionThe session on which the answer will be updated
on_sdp_creationCallback called when SDP is created
generate_new_sdpBoolean to indicate if a new SDP should be created
Return values
0Successfully updated the SDP answer
-1Failure to updated the SDP answer

Definition at line 2535 of file res_pjsip_session.c.

References ast_channel_name(), ast_log, ast_sip_session_get_name(), ast_sip_session::channel, create_local_sdp(), ast_sip_session::inv_session, LOG_WARNING, NULL, SCOPE_ENTER, and SCOPE_EXIT_RTN_VALUE.

Referenced by dtmf_mode_refresh_cb().

2537 {
2538  pjsip_inv_session *inv_session = session->inv_session;
2539  pjmedia_sdp_session *new_answer = NULL;
2540  const pjmedia_sdp_session *previous_offer = NULL;
2541  SCOPE_ENTER(1, "%s\n", ast_sip_session_get_name(session));
2542 
2543  /* The SDP answer can only be regenerated if it is still pending to be sent */
2544  if (!inv_session->neg || (pjmedia_sdp_neg_get_state(inv_session->neg) != PJMEDIA_SDP_NEG_STATE_REMOTE_OFFER &&
2545  pjmedia_sdp_neg_get_state(inv_session->neg) != PJMEDIA_SDP_NEG_STATE_WAIT_NEGO)) {
2546  ast_log(LOG_WARNING, "Requested to regenerate local SDP answer for channel '%s' but negotiation in state '%s'\n",
2547  ast_channel_name(session->channel), pjmedia_sdp_neg_state_str(pjmedia_sdp_neg_get_state(inv_session->neg)));
2548  SCOPE_EXIT_RTN_VALUE(-1, "Bad negotiation state\n");
2549  }
2550 
2551  pjmedia_sdp_neg_get_neg_remote(inv_session->neg, &previous_offer);
2552  if (pjmedia_sdp_neg_get_state(inv_session->neg) == PJMEDIA_SDP_NEG_STATE_WAIT_NEGO) {
2553  /* Transition the SDP negotiator back to when it received the remote offer */
2554  pjmedia_sdp_neg_negotiate(inv_session->pool, inv_session->neg, 0);
2555  pjmedia_sdp_neg_set_remote_offer(inv_session->pool, inv_session->neg, previous_offer);
2556  }
2557 
2558  new_answer = create_local_sdp(inv_session, session, previous_offer);
2559  if (!new_answer) {
2560  ast_log(LOG_WARNING, "Could not create a new local SDP answer for channel '%s'\n",
2561  ast_channel_name(session->channel));
2562  SCOPE_EXIT_RTN_VALUE(-1, "Couldn't create new SDP\n");
2563  }
2564 
2565  if (on_sdp_creation) {
2566  if (on_sdp_creation(session, new_answer)) {
2567  SCOPE_EXIT_RTN_VALUE(-1, "Callback failed\n");
2568  }
2569  }
2570 
2571  pjsip_inv_set_sdp_answer(inv_session, new_answer);
2572 
2574 }
#define LOG_WARNING
Definition: logger.h:274
#define NULL
Definition: resample.c:96
struct pjsip_inv_session * inv_session
#define ast_log
Definition: astobj2.c:42
struct ast_channel * channel
#define SCOPE_ENTER(level,...)
Non RAII_VAR Scope Trace macros The advantage of these macros is that the EXITs will have the actual ...
Definition: logger.h:780
const char * ast_sip_session_get_name(const struct ast_sip_session *session)
Get the channel or endpoint name associated with the session.
#define SCOPE_EXIT_RTN_VALUE(__return_value,...)
Scope Exit with return value.
Definition: logger.h:875
static struct pjmedia_sdp_session * create_local_sdp(pjsip_inv_session *inv, struct ast_sip_session *session, const pjmedia_sdp_session *offer)
const char * ast_channel_name(const struct ast_channel *chan)

◆ ast_sip_session_register_sdp_handler()

int ast_sip_session_register_sdp_handler ( struct ast_sip_session_sdp_handler handler,
const char *  stream_type 
)

Register an SDP handler.

An SDP handler is responsible for parsing incoming SDP streams and ensuring that Asterisk can cope with the contents. Similarly, the SDP handler will be responsible for constructing outgoing SDP streams.

Multiple handlers for the same stream type may be registered. They will be visited in the order they were registered. Handlers will be visited for each stream type until one claims to have handled the stream.

Parameters
handlerThe SDP handler to register
stream_typeThe type of media stream for which to call the handler
Return values
0Success
-1Failure

Definition at line 138 of file res_pjsip_session.c.

References ao2_alloc, ao2_cleanup, ao2_find, ao2_link, ast_debug, AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_log, ast_sip_session_sdp_handler::id, lock, LOG_WARNING, ast_sip_session_sdp_handler::next, NULL, OBJ_KEY, RAII_VAR, and SCOPED_AO2LOCK.

Referenced by load_module().

139 {
140  RAII_VAR(struct sdp_handler_list *, handler_list,
141  ao2_find(sdp_handlers, stream_type, OBJ_KEY), ao2_cleanup);
143 
144  if (handler_list) {
145  struct ast_sip_session_sdp_handler *iter;
146  /* Check if this handler is already registered for this stream type */
147  AST_LIST_TRAVERSE(&handler_list->list, iter, next) {
148  if (!strcmp(iter->id, handler->id)) {
149  ast_log(LOG_WARNING, "Handler '%s' already registered for stream type '%s'.\n", handler->id, stream_type);
150  return -1;
151  }
152  }
153  AST_LIST_INSERT_TAIL(&handler_list->list, handler, next);
154  ast_debug(1, "Registered SDP stream handler '%s' for stream type '%s'\n", handler->id, stream_type);
155 
156  return 0;
157  }
158 
159  /* No stream of this type has been registered yet, so we need to create a new list */
160  handler_list = ao2_alloc(sizeof(*handler_list) + strlen(stream_type), NULL);
161  if (!handler_list) {
162  return -1;
163  }
164  /* Safe use of strcpy */
165  strcpy(handler_list->stream_type, stream_type);
166  AST_LIST_HEAD_INIT_NOLOCK(&handler_list->list);
167  AST_LIST_INSERT_TAIL(&handler_list->list, handler, next);
168  if (!ao2_link(sdp_handlers, handler_list)) {
169  return -1;
170  }
171  ast_debug(1, "Registered SDP stream handler '%s' for stream type '%s'\n", handler->id, stream_type);
172 
173  return 0;
174 }
#define OBJ_KEY
Definition: astobj2.h:1155
#define LOG_WARNING
Definition: logger.h:274
A handler for SDPs in SIP sessions.
#define NULL
Definition: resample.c:96
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
struct ast_sip_session_sdp_handler * next
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
ast_mutex_t lock
Definition: app_meetme.c:1091
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:730
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define SCOPED_AO2LOCK(varname, obj)
scoped lock specialization for ao2 mutexes.
Definition: lock.h:602
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
Definition: linkedlists.h:680
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static struct ao2_container * sdp_handlers
Registered SDP stream handlers.
#define ao2_link(container, obj)
Definition: astobj2.h:1549

◆ ast_sip_session_remove_datastore()

void ast_sip_session_remove_datastore ( struct ast_sip_session session,
const char *  name 
)

Remove a session datastore from the session.

This operation may cause the datastore's free() callback to be called if the reference count reaches zero.

Parameters
sessionThe session to remove the datastore from
nameThe name of the datastore to remove

Definition at line 1290 of file res_pjsip_session.c.

References ao2_callback, ast_sip_session::datastores, NULL, OBJ_KEY, OBJ_NODATA, and OBJ_UNLINK.

Referenced by direct_media_mitigate_glare(), handle_outgoing_response(), outgoing_request(), refresh_write_cb(), and session_refresh_state_get_or_alloc().

1291 {
1292  ao2_callback(session->datastores, OBJ_KEY | OBJ_UNLINK | OBJ_NODATA, NULL, (void *) name);
1293 }
#define OBJ_KEY
Definition: astobj2.h:1155
struct ao2_container * datastores
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:1716
#define NULL
Definition: resample.c:96
static const char name[]
Definition: cdr_mysql.c:74

◆ ast_sip_session_resume_reinvite()

void ast_sip_session_resume_reinvite ( struct ast_sip_session session)

Resumes processing of a deferred incoming re-invite.

Parameters
sessionThe session which has a pending incoming re-invite
Note
When resuming a re-invite it is given to the pjsip stack as if it had just been received from a transport, this means that the deferral callback will be called again.

Definition at line 2798 of file res_pjsip_session.c.

References ast_sip_get_pjsip_endpoint(), ast_sip_session::channel, ast_sip_session::deferred_reinvite, and NULL.

Referenced by t38_automatic_reject(), and t38_interpret_parameters().

2799 {
2800  if (!session->deferred_reinvite) {
2801  return;
2802  }
2803 
2804  if (session->channel) {
2805  pjsip_endpt_process_rx_data(ast_sip_get_pjsip_endpoint(),
2806  session->deferred_reinvite, NULL, NULL);
2807  }
2808  pjsip_rx_data_free_cloned(session->deferred_reinvite);
2809  session->deferred_reinvite = NULL;
2810 }
#define NULL
Definition: resample.c:96
pjsip_rx_data * deferred_reinvite
struct ast_channel * channel
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
Definition: res_pjsip.c:3718

◆ ast_sip_session_send_request()

void ast_sip_session_send_request ( struct ast_sip_session session,
pjsip_tx_data *  tdata 
)

Send a SIP request.

This will send the SIP request specified in tdata and call into any registered supplements' outgoing_request callback.

Parameters
sessionThe session to which to send the request
tdataThe request to send

Definition at line 2842 of file res_pjsip_session.c.

References ast_sip_session_send_request_with_cb(), and NULL.

Referenced by ast_sip_session_terminate(), call(), check_request_status(), handle_incoming_before_media(), outbound_invite_auth(), session_inv_on_tsx_state_changed(), transmit_info_dtmf(), and transmit_info_with_vidupdate().

2843 {
2844  ast_sip_session_send_request_with_cb(session, tdata, NULL);
2845 }
#define NULL
Definition: resample.c:96
void ast_sip_session_send_request_with_cb(struct ast_sip_session *session, pjsip_tx_data *tdata, ast_sip_session_response_cb on_response)
Send a SIP request and get called back when a response is received.

◆ ast_sip_session_send_request_with_cb()

void ast_sip_session_send_request_with_cb ( struct ast_sip_session session,
pjsip_tx_data *  tdata,
ast_sip_session_response_cb  on_response 
)

Send a SIP request and get called back when a response is received.

This will send the request out exactly the same as ast_sip_send_request() does. The difference is that when a response arrives, the specified callback will be called into

Parameters
sessionThe session on which to send the request
tdataThe request to send
on_responseCallback to be called when a response is received

Definition at line 2818 of file res_pjsip_session.c.

References ast_sip_mod_data_set, handle_outgoing_request(), ast_sip_session::inv_session, and MOD_DATA_ON_RESPONSE.

Referenced by ast_sip_session_send_request(), session_inv_on_tsx_state_changed(), and sip_session_refresh().

2820 {
2821  pjsip_inv_session *inv_session = session->inv_session;
2822 
2823  /* For every request except BYE we disallow sending of the message when
2824  * the session has been disconnected. A BYE request is special though
2825  * because it can be sent again after the session is disconnected except
2826  * with credentials.
2827  */
2828  if (inv_session->state == PJSIP_INV_STATE_DISCONNECTED &&
2829  tdata->msg->line.req.method.id != PJSIP_BYE_METHOD) {
2830  return;
2831  }
2832 
2833  ast_sip_mod_data_set(tdata->pool, tdata->mod_data, session_module.id,
2834  MOD_DATA_ON_RESPONSE, on_response);
2835 
2836  handle_outgoing_request(session, tdata);
2837  pjsip_inv_send_msg(session->inv_session, tdata);
2838 
2839  return;
2840 }
#define MOD_DATA_ON_RESPONSE
struct pjsip_inv_session * inv_session
#define ast_sip_mod_data_set(pool, mod_data, id, key, val)
Utilizing a mod_data array for a given id, set the value associated with the given key...
Definition: res_pjsip.h:2670
static void handle_outgoing_request(struct ast_sip_session *session, pjsip_tx_data *tdata)
static pjsip_module session_module

◆ ast_sip_session_send_response()

void ast_sip_session_send_response ( struct ast_sip_session session,
pjsip_tx_data *  tdata 
)

Send a SIP response.

This will send the SIP response specified in tdata and call into any registered supplements' outgoing_response callback.

Parameters
sessionThe session on which to send the response.
tdataThe response to send

Definition at line 2576 of file res_pjsip_session.c.

References handle_outgoing_response(), ast_sip_session::inv_session, session_on_rx_request(), session_on_rx_response(), and session_on_tsx_state().

Referenced by answer(), ast_sip_session_terminate(), chan_pjsip_incoming_request(), indicate(), new_invite(), refer_incoming_invite_request(), transfer_redirect(), and update_connected_line_information().

2577 {
2578  handle_outgoing_response(session, tdata);
2579  pjsip_inv_send_msg(session->inv_session, tdata);
2580  return;
2581 }
struct pjsip_inv_session * inv_session
static void handle_outgoing_response(struct ast_sip_session *session, pjsip_tx_data *tdata)

◆ ast_sip_session_suspend()

void ast_sip_session_suspend ( struct ast_sip_session session)

Request and wait for the session serializer to be suspended.

Since
12.7.0
Parameters
sessionWhich session to suspend the serializer.
Note
No channel locks can be held while calling without risk of deadlock.
Returns
Nothing

Definition at line 3155 of file res_pjsip_session.c.

References ao2_alloc, ao2_lock, ao2_object_get_lockaddr(), ao2_ref, ao2_unlock, ast_assert, ast_cond_init, ast_cond_wait, ast_sip_push_task(), ast_taskprocessor_is_suspended(), ast_taskprocessor_is_task(), ast_taskprocessor_suspend(), ast_sip_session_suspender::cond_complete, ast_sip_session_suspender::cond_suspended, NULL, ast_sip_session::serializer, sip_session_suspend_task(), sip_session_suspender_dtor(), ast_sip_session::suspended, and ast_sip_session_suspender::suspended.

Referenced by chan_pjsip_indicate().

3156 {
3157  struct ast_sip_session_suspender *suspender;
3158  int res;
3159 
3160  ast_assert(session->suspended == NULL);
3161 
3162  if (ast_taskprocessor_is_task(session->serializer)) {
3163  /* I am the session's serializer thread so I cannot suspend. */
3164  return;
3165  }
3166 
3168  /* The serializer already suspended. */
3169  return;
3170  }
3171 
3172  suspender = ao2_alloc(sizeof(*suspender), sip_session_suspender_dtor);
3173  if (!suspender) {
3174  /* We will just have to hope that the system does not deadlock */
3175  return;
3176  }
3177  ast_cond_init(&suspender->cond_suspended, NULL);
3178  ast_cond_init(&suspender->cond_complete, NULL);
3179 
3180  ao2_ref(suspender, +1);
3181  res = ast_sip_push_task(session->serializer, sip_session_suspend_task, suspender);
3182  if (res) {
3183  /* We will just have to hope that the system does not deadlock */
3184  ao2_ref(suspender, -2);
3185  return;
3186  }
3187 
3188  session->suspended = suspender;
3189 
3190  /* Wait for the serializer to get suspended. */
3191  ao2_lock(suspender);
3192  while (!suspender->suspended) {
3193  ast_cond_wait(&suspender->cond_suspended, ao2_object_get_lockaddr(suspender));
3194  }
3195  ao2_unlock(suspender);
3196 
3198 }
#define ast_cond_wait(cond, mutex)
Definition: lock.h:203
#define ast_cond_init(cond, attr)
Definition: lock.h:199
#define ast_assert(a)
Definition: utils.h:695
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
void * ao2_object_get_lockaddr(void *obj)
Return the mutex lock address of an object.
Definition: astobj2.c:476
int ast_taskprocessor_suspend(struct ast_taskprocessor *tps)
Indicate the taskprocessor is suspended.
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
struct ast_taskprocessor * serializer
int ast_sip_push_task(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Pushes a task to SIP servants.
Definition: res_pjsip.c:5138
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
int ast_taskprocessor_is_task(struct ast_taskprocessor *tps)
Am I the given taskprocessor&#39;s current task.
struct controlling the suspension of the session&#39;s serializer.
int ast_taskprocessor_is_suspended(struct ast_taskprocessor *tps)
Get the task processor suspend status.
struct ast_sip_session_suspender * suspended
static void sip_session_suspender_dtor(void *vdoomed)
static int sip_session_suspend_task(void *data)

◆ ast_sip_session_terminate()

void ast_sip_session_terminate ( struct ast_sip_session session,
int  response 
)

Terminate a session and, if possible, send the provided response code.

Parameters
sessionThe session to terminate
responseThe response code to use for termination if possible
Warning
Calling this function MAY cause the last session reference to be released and the session destructor to be called. If you need to do something with session after this call, be sure to bump the ref count before calling terminate.

Definition at line 3451 of file res_pjsip_session.c.

References ast_sip_session::active_media_state, ast_debug, AST_LIST_REMOVE_HEAD, ast_sip_session_get_name(), ast_sip_session_media_state_reset(), ast_sip_session_media_stats_save(), ast_sip_session_send_request(), ast_sip_session_send_response(), ast_sip_session::defer_terminate, delay_request(), DELAYED_METHOD_BYE, delayed_request_free(), ast_sip_session::delayed_requests, ast_sip_session::inv_session, ast_sip_session_delayed_request::next, NULL, ast_sip_session::pending_media_state, SCOPE_ENTER, SCOPE_EXIT_RTN, session_end(), session_end_completion(), status, SWAP, and ast_sip_session::terminate_while_deferred.

Referenced by ast_sip_session_defer_termination_cancel(), chan_pjsip_incoming_request(), hangup(), send_delayed_request(), and session_termination_task().

3452 {
3453  pj_status_t status;
3454  pjsip_tx_data *packet = NULL;
3455  SCOPE_ENTER(1, "%s Response %d\n", ast_sip_session_get_name(session), response);
3456 
3457  if (session->defer_terminate) {
3458  session->terminate_while_deferred = 1;
3459  SCOPE_EXIT_RTN("Deferred\n");
3460  }
3461 
3462  if (!response) {
3463  response = 603;
3464  }
3465 
3466  /* The media sessions need to exist for the lifetime of the underlying channel
3467  * to ensure that anything (such as bridge_native_rtp) has access to them as
3468  * appropriate. Since ast_sip_session_terminate is called by chan_pjsip and other
3469  * places when the session is to be terminated we terminate any existing
3470  * media sessions here.
3471  */
3473  SWAP(session->active_media_state, session->pending_media_state);
3475 
3476  switch (session->inv_session->state) {
3477  case PJSIP_INV_STATE_NULL:
3478  if (!session->inv_session->invite_tsx) {
3479  /*
3480  * Normally, it's pjproject's transaction cleanup that ultimately causes the
3481  * final session reference to be released but if both STATE and invite_tsx are NULL,
3482  * we never created a transaction in the first place. In this case, we need to
3483  * do the cleanup ourselves.
3484  */
3485  /* Transfer the inv_session session reference to the session_end_task */
3486  session->inv_session->mod_data[session_module.id] = NULL;
3487  pjsip_inv_terminate(session->inv_session, response, PJ_TRUE);
3488  session_end(session);
3489  /*
3490  * session_end_completion will cleanup the final session reference unless
3491  * ast_sip_session_terminate's caller is holding one.
3492  */
3493  session_end_completion(session);
3494  } else {
3495  pjsip_inv_terminate(session->inv_session, response, PJ_TRUE);
3496  }
3497  break;
3498  case PJSIP_INV_STATE_CONFIRMED:
3499  if (session->inv_session->invite_tsx) {
3500  ast_debug(3, "%s: Delay sending BYE because of outstanding transaction...\n",
3501  ast_sip_session_get_name(session));
3502  /* If this is delayed the only thing that will happen is a BYE request so we don't
3503  * actually need to store the response code for when it happens.
3504  */
3505  delay_request(session, NULL, NULL, NULL, 0, DELAYED_METHOD_BYE, NULL, NULL, 1);
3506  break;
3507  }
3508  /* Fall through */
3509  default:
3510  status = pjsip_inv_end_session(session->inv_session, response, NULL, &packet);
3511  if (status == PJ_SUCCESS && packet) {
3512  struct ast_sip_session_delayed_request *delay;
3513 
3514  /* Flush any delayed requests so they cannot overlap this transaction. */
3515  while ((delay = AST_LIST_REMOVE_HEAD(&session->delayed_requests, next))) {
3516  delayed_request_free(delay);
3517  }
3518 
3519  if (packet->msg->type == PJSIP_RESPONSE_MSG) {
3520  ast_sip_session_send_response(session, packet);
3521  } else {
3522  ast_sip_session_send_request(session, packet);
3523  }
3524  }
3525  break;
3526  }
3527  SCOPE_EXIT_RTN();
3528 }
struct ast_sip_session_media_state * pending_media_state
static int session_end_completion(void *vsession)
void ast_sip_session_send_response(struct ast_sip_session *session, pjsip_tx_data *tdata)
Send a SIP response.
unsigned int defer_terminate
unsigned int terminate_while_deferred
static int delay_request(struct ast_sip_session *session, ast_sip_session_request_creation_cb on_request, ast_sip_session_sdp_creation_cb on_sdp_creation, ast_sip_session_response_cb on_response, int generate_new_sdp, enum delayed_method method, struct ast_sip_session_media_state *pending_media_state, struct ast_sip_session_media_state *active_media_state, int queue_head)
static void delayed_request_free(struct ast_sip_session_delayed_request *delay)
#define SWAP(a, b)
Definition: utils.h:230
struct ast_sip_session_delayed_request * next
#define NULL
Definition: resample.c:96
struct pjsip_inv_session * inv_session
struct ast_sip_session_media_state * active_media_state
static int session_end(void *vsession)
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
static pjsip_module session_module
#define SCOPE_EXIT_RTN(...)
Scope Exit with return.
Definition: logger.h:854
void ast_sip_session_media_stats_save(struct ast_sip_session *sip_session, struct ast_sip_session_media_state *media_state)
Save a media stats.
Structure used for sending delayed requests.
#define SCOPE_ENTER(level,...)
Non RAII_VAR Scope Trace macros The advantage of these macros is that the EXITs will have the actual ...
Definition: logger.h:780
const char * ast_sip_session_get_name(const struct ast_sip_session *session)
Get the channel or endpoint name associated with the session.
struct ast_sip_session::@309 delayed_requests
void ast_sip_session_media_state_reset(struct ast_sip_session_media_state *media_state)
Reset a media state to a clean state.
void ast_sip_session_send_request(struct ast_sip_session *session, pjsip_tx_data *tdata)
Send a SIP request.
jack_status_t status
Definition: app_jack.c:146

◆ ast_sip_session_unregister_sdp_handler()

void ast_sip_session_unregister_sdp_handler ( struct ast_sip_session_sdp_handler handler,
const char *  stream_type 
)

Unregister an SDP handler.

Parameters
handlerThe SDP handler to unregister
stream_typeStream type for which the SDP handler was registered

Definition at line 199 of file res_pjsip_session.c.

References ao2_callback_data, OBJ_KEY, OBJ_NODATA, OBJ_UNLINK, and remove_handler().

Referenced by unload_module().

200 {
201  ao2_callback_data(sdp_handlers, OBJ_KEY | OBJ_UNLINK | OBJ_NODATA, remove_handler, (void *)stream_type, handler);
202 }
#define OBJ_KEY
Definition: astobj2.h:1155
#define ao2_callback_data(container, flags, cb_fn, arg, data)
Definition: astobj2.h:1743
static int remove_handler(void *obj, void *arg, void *data, int flags)
static struct ao2_container * sdp_handlers
Registered SDP stream handlers.

◆ ast_sip_session_unsuspend()

void ast_sip_session_unsuspend ( struct ast_sip_session session)

Request the session serializer be unsuspended.

Since
12.7.0
Parameters
sessionWhich session to unsuspend the serializer.
Returns
Nothing

Definition at line 3200 of file res_pjsip_session.c.

References ao2_lock, ao2_ref, ao2_unlock, ast_cond_signal, ast_taskprocessor_unsuspend(), ast_sip_session_suspender::complete, ast_sip_session_suspender::cond_complete, NULL, ast_sip_session::serializer, and ast_sip_session::suspended.

Referenced by chan_pjsip_indicate().

3201 {
3202  struct ast_sip_session_suspender *suspender = session->suspended;
3203 
3204  if (!suspender) {
3205  /* Nothing to do */
3206  return;
3207  }
3208  session->suspended = NULL;
3209 
3210  /* Signal that the serializer task suspension is now complete. */
3211  ao2_lock(suspender);
3212  suspender->complete = 1;
3213  ast_cond_signal(&suspender->cond_complete);
3214  ao2_unlock(suspender);
3215 
3216  ao2_ref(suspender, -1);
3217 
3219 }
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
#define ast_cond_signal(cond)
Definition: lock.h:201
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
int ast_taskprocessor_unsuspend(struct ast_taskprocessor *tps)
Indicate the taskprocessor is unsuspended.
struct ast_taskprocessor * serializer
struct controlling the suspension of the session&#39;s serializer.
struct ast_sip_session_suspender * suspended

◆ AST_TEST_DEFINE()

AST_TEST_DEFINE ( test_resolve_refresh_media_states  )

Definition at line 5660 of file res_pjsip_session.c.

References AST_MEDIA_TYPE_AUDIO, AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_REMOVED, AST_STREAM_STATE_SENDONLY, AST_STREAM_STATE_SENDRECV, AST_TEST_NOT_RUN, AST_TEST_PASS, CHECKER, sip_to_pjsip::info(), NULL, RESET_STATE, SCOPE_ENTER, SCOPE_EXIT_RTN_VALUE, TEST_EXECUTE, TEST_INIT, and test_media_add().

5661 {
5662 #define FREE_STATE() \
5663 ({ \
5664  ast_sip_session_media_state_free(new_pending_state); \
5665  new_pending_state = NULL; \
5666  ast_sip_session_media_state_free(delayed_pending_state); \
5667  delayed_pending_state = NULL; \
5668  ast_sip_session_media_state_free(delayed_active_state); \
5669  delayed_active_state = NULL; \
5670  ast_sip_session_media_state_free(current_active_state); \
5671  current_active_state = NULL; \
5672  ast_sip_session_media_state_free(expected_pending_state); \
5673  expected_pending_state = NULL; \
5674 })
5675 
5676 #define RESET_STATE(__num) \
5677 ({ \
5678  testnum=__num; \
5679  ast_trace(-1, "Test %d\n", testnum); \
5680  test_failed = 0; \
5681  delayed_pending_state = ast_sip_session_media_state_alloc(); \
5682  delayed_pending_state->topology = ast_stream_topology_alloc(); \
5683  delayed_active_state = ast_sip_session_media_state_alloc(); \
5684  delayed_active_state->topology = ast_stream_topology_alloc(); \
5685  current_active_state = ast_sip_session_media_state_alloc(); \
5686  current_active_state->topology = ast_stream_topology_alloc(); \
5687  expected_pending_state = ast_sip_session_media_state_alloc(); \
5688  expected_pending_state->topology = ast_stream_topology_alloc(); \
5689 })
5690 
5691 #define CHECKER() \
5692 ({ \
5693  new_pending_state = resolve_refresh_media_states("unittest", delayed_pending_state, delayed_active_state, current_active_state, 1); \
5694  if (!test_is_media_state_equal(new_pending_state, expected_pending_state, 0)) { \
5695  res = AST_TEST_FAIL; \
5696  test_failed = 1; \
5697  ast_test_status_update(test, "da: %s\n", ast_str_tmp(256, ast_stream_topology_to_str(delayed_active_state->topology, &STR_TMP))); \
5698  ast_test_status_update(test, "dp: %s\n", ast_str_tmp(256, ast_stream_topology_to_str(delayed_pending_state->topology, &STR_TMP))); \
5699  ast_test_status_update(test, "ca: %s\n", ast_str_tmp(256, ast_stream_topology_to_str(current_active_state->topology, &STR_TMP))); \
5700  ast_test_status_update(test, "ep: %s\n", ast_str_tmp(256, ast_stream_topology_to_str(expected_pending_state->topology, &STR_TMP))); \
5701  ast_test_status_update(test, "np: %s\n", ast_str_tmp(256, ast_stream_topology_to_str(new_pending_state->topology, &STR_TMP))); \
5702  } \
5703  ast_test_status_update(test, "Test %d %s\n", testnum, test_failed ? "FAILED" : "passed"); \
5704  ast_trace(-1, "Test %d %s\n", testnum, test_failed ? "FAILED" : "passed"); \
5705  test_failed = 0; \
5706  FREE_STATE(); \
5707 })
5708 
5709 
5710  struct ast_sip_session_media_state * delayed_pending_state = NULL;
5711  struct ast_sip_session_media_state * delayed_active_state = NULL;
5712  struct ast_sip_session_media_state * current_active_state = NULL;
5713  struct ast_sip_session_media_state * new_pending_state = NULL;
5714  struct ast_sip_session_media_state * expected_pending_state = NULL;
5716  int test_failed = 0;
5717  int testnum = 0;
5718  SCOPE_ENTER(1);
5719 
5720  switch (cmd) {
5721  case TEST_INIT:
5722  info->name = "merge_refresh_topologies";
5723  info->category = "/res/res_pjsip_session/";
5724  info->summary = "Test merging of delayed request topologies";
5725  info->description = "Test merging of delayed request topologies";
5727  case TEST_EXECUTE:
5728  break;
5729  }
5730 
5731  RESET_STATE(1);
5732  test_media_add(delayed_active_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
5733  test_media_add(delayed_active_state, "myvideo1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5734  test_media_add(delayed_active_state, "myvideo2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5735 
5736  test_media_add(delayed_pending_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
5737  test_media_add(delayed_pending_state, "myvideo1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5738  test_media_add(delayed_pending_state, "myvideo2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5739  test_media_add(delayed_pending_state, "myvideo3", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5740 
5741  test_media_add(current_active_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
5742  test_media_add(current_active_state, "myvideo1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5743  test_media_add(current_active_state, "myvideo2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5744 
5745  test_media_add(expected_pending_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
5746  test_media_add(expected_pending_state, "myvideo1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5747  test_media_add(expected_pending_state, "myvideo2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5748  test_media_add(expected_pending_state, "myvideo3", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5749  CHECKER();
5750 
5751  RESET_STATE(2);
5752  test_media_add(delayed_active_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
5753  test_media_add(delayed_active_state, "myvideo1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5754  test_media_add(delayed_active_state, "myvideo2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5755 
5756  test_media_add(delayed_pending_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
5757  test_media_add(delayed_pending_state, "myvideo1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5758  test_media_add(delayed_pending_state, "myvideo2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5759  test_media_add(delayed_pending_state, "myvideo3", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5760 
5761  test_media_add(current_active_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
5762  test_media_add(current_active_state, "myvideo1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5763  test_media_add(current_active_state, "myvideo2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5764 
5765  test_media_add(expected_pending_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
5766  test_media_add(expected_pending_state, "myvideo1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5767  test_media_add(expected_pending_state, "myvideo2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5768  test_media_add(expected_pending_state, "myvideo3", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5769  CHECKER();
5770 
5771  RESET_STATE(3);
5772  test_media_add(delayed_active_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
5773  test_media_add(delayed_active_state, "myvideo1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5774  test_media_add(delayed_active_state, "myvideo2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5775 
5776  test_media_add(delayed_pending_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
5777  test_media_add(delayed_pending_state, "myvideo1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5778  test_media_add(delayed_pending_state, "myvideo2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5779  test_media_add(delayed_pending_state, "myvideo3", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5780 
5781  test_media_add(current_active_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
5782  test_media_add(current_active_state, "myvideo1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5783  test_media_add(current_active_state, "myvideo2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5784  test_media_add(current_active_state, "myvideo4", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5785  test_media_add(current_active_state, "myvideo5", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5786 
5787  test_media_add(expected_pending_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
5788  test_media_add(expected_pending_state, "myvideo1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5789  test_media_add(expected_pending_state, "myvideo2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5790  test_media_add(expected_pending_state, "myvideo4", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5791  test_media_add(expected_pending_state, "myvideo5", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5792  test_media_add(expected_pending_state, "myvideo3", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5793  CHECKER();
5794 
5795  RESET_STATE(4);
5796  test_media_add(delayed_active_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
5797  test_media_add(delayed_active_state, "myvideo1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5798  test_media_add(delayed_active_state, "myvideo2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5799 
5800  test_media_add(delayed_pending_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
5801  test_media_add(delayed_pending_state, "myvideo1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5802  test_media_add(delayed_pending_state, "myvideo2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5803  test_media_add(delayed_pending_state, "myvideo3", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5804 
5805  test_media_add(current_active_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
5806  test_media_add(current_active_state, "myvideo1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5807  test_media_add(current_active_state, "myvideo2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_REMOVED, -1);
5808 
5809  test_media_add(expected_pending_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
5810  test_media_add(expected_pending_state, "myvideo1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5811  test_media_add(expected_pending_state, "myvideo3", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5812  CHECKER();
5813 
5814  RESET_STATE(5);
5815  test_media_add(delayed_active_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
5816  test_media_add(delayed_active_state, "myvideo1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5817  test_media_add(delayed_active_state, "myvideo2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5818 
5819  test_media_add(delayed_pending_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
5820  test_media_add(delayed_pending_state, "myvideo1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5821  test_media_add(delayed_pending_state, "myvideo2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_REMOVED, -1);
5822 
5823  test_media_add(current_active_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
5824  test_media_add(current_active_state, "myvideo1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5825  test_media_add(current_active_state, "myvideo2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_REMOVED, -1);
5826 
5827  test_media_add(expected_pending_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
5828  test_media_add(expected_pending_state, "myvideo1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5829  test_media_add(expected_pending_state, "myvideo2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_REMOVED, -1);
5830  CHECKER();
5831 
5832  RESET_STATE(6);
5833  test_media_add(delayed_active_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
5834  test_media_add(delayed_active_state, "myvideo1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5835  test_media_add(delayed_active_state, "myvideo2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5836 
5837  test_media_add(delayed_pending_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
5838  test_media_add(delayed_pending_state, "myvideo1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5839  test_media_add(delayed_pending_state, "myvideo2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5840  test_media_add(delayed_pending_state, "myvideo3", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5841 
5842  test_media_add(current_active_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
5843  test_media_add(current_active_state, "myvideo1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5844  test_media_add(current_active_state, "myvideo2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_REMOVED, -1);
5845  test_media_add(current_active_state, "myvideo4", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5846 
5847  test_media_add(expected_pending_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
5848  test_media_add(expected_pending_state, "myvideo1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5849  test_media_add(expected_pending_state, "myvideo3", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5850  test_media_add(expected_pending_state, "myvideo4", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5851  CHECKER();
5852 
5853  RESET_STATE(7);
5854  test_media_add(delayed_active_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
5855  test_media_add(delayed_active_state, "myvideo1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5856  test_media_add(delayed_active_state, "myvideo2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5857 
5858  test_media_add(delayed_pending_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
5859  test_media_add(delayed_pending_state, "myvideo1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5860  test_media_add(delayed_pending_state, "myvideo2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5861  test_media_add(delayed_pending_state, "myvideo3", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5862  test_media_add(delayed_pending_state, "myvideo4", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5863 
5864  test_media_add(current_active_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
5865  test_media_add(current_active_state, "myvideo1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5866  test_media_add(current_active_state, "myvideo2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5867  test_media_add(current_active_state, "myvideo5", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5868  test_media_add(current_active_state, "myvideo6", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5869 
5870  test_media_add(expected_pending_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
5871  test_media_add(expected_pending_state, "myvideo1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5872  test_media_add(expected_pending_state, "myvideo2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5873  test_media_add(expected_pending_state, "myvideo5", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5874  test_media_add(expected_pending_state, "myvideo6", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5875  test_media_add(expected_pending_state, "myvideo3", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5876  test_media_add(expected_pending_state, "myvideo4", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5877  CHECKER();
5878 
5879  RESET_STATE(8);
5880  test_media_add(delayed_active_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
5881  test_media_add(delayed_active_state, "myvideo1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5882  test_media_add(delayed_active_state, "myvideo2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5883 
5884  test_media_add(delayed_pending_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
5885  test_media_add(delayed_pending_state, "myvideo1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5886  test_media_add(delayed_pending_state, "myvideo2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5887  test_media_add(delayed_pending_state, "myvideo3", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5888  test_media_add(delayed_pending_state, "myvideo4", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5889 
5890  test_media_add(current_active_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
5891  test_media_add(current_active_state, "myvideo1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5892  test_media_add(current_active_state, "myvideo2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_REMOVED, -1);
5893 
5894  test_media_add(expected_pending_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
5895  test_media_add(expected_pending_state, "myvideo1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5896  test_media_add(expected_pending_state, "myvideo3", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5897  test_media_add(expected_pending_state, "myvideo4", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5898  CHECKER();
5899 
5900  RESET_STATE(9);
5901  test_media_add(delayed_active_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
5902  test_media_add(delayed_active_state, "myvideo1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5903  test_media_add(delayed_active_state, "myvideo2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5904 
5905  test_media_add(delayed_pending_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
5906  test_media_add(delayed_pending_state, "myvideo1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5907  test_media_add(delayed_pending_state, "myvideo2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5908  test_media_add(delayed_pending_state, "myvideo3", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5909  test_media_add(delayed_pending_state, "myvideo4", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5910 
5911  test_media_add(current_active_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
5912  test_media_add(current_active_state, "myvideo1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_REMOVED, -1);
5913  test_media_add(current_active_state, "myvideo2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_REMOVED, -1);
5914 
5915  test_media_add(expected_pending_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
5916  test_media_add(expected_pending_state, "myvideo3", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5917  test_media_add(expected_pending_state, "myvideo4", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5918  CHECKER();
5919 
5920  RESET_STATE(10);
5921  test_media_add(delayed_active_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
5922  test_media_add(delayed_active_state, "myvideo1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5923  test_media_add(delayed_active_state, "myvideo2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5924 
5925  test_media_add(delayed_pending_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
5926  test_media_add(delayed_pending_state, "myvideo1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_REMOVED, -1);
5927  test_media_add(delayed_pending_state, "myvideo2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_REMOVED, -1);
5928 
5929  test_media_add(current_active_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
5930  test_media_add(current_active_state, "myvideo1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5931  test_media_add(current_active_state, "myvideo2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5932  test_media_add(current_active_state, "myvideo3", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5933 
5934  test_media_add(expected_pending_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
5935  test_media_add(expected_pending_state, "myvideo1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_REMOVED, -1);
5936  test_media_add(expected_pending_state, "myvideo2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_REMOVED, -1);
5937  test_media_add(expected_pending_state, "myvideo3", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5938  CHECKER();
5939 
5940  RESET_STATE(11);
5941  test_media_add(delayed_active_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
5942  test_media_add(delayed_active_state, "myvideo1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5943  test_media_add(delayed_active_state, "myvideo2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5944  test_media_add(delayed_active_state, "myvideo4", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5945 
5946  test_media_add(delayed_pending_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
5947  test_media_add(delayed_pending_state, "myvideo1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5948  test_media_add(delayed_pending_state, "myvideo2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5949  test_media_add(delayed_pending_state, "myvideo3", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5950 
5951  test_media_add(current_active_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
5952  test_media_add(current_active_state, "myvideo1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5953  test_media_add(current_active_state, "myvideo2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5954  test_media_add(current_active_state, "myvideo4", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5955 
5956  test_media_add(expected_pending_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
5957  test_media_add(expected_pending_state, "myvideo1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5958  test_media_add(expected_pending_state, "myvideo2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5959  test_media_add(expected_pending_state, "myvideo4", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5960  test_media_add(expected_pending_state, "myvideo3", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5961  CHECKER();
5962 
5963  RESET_STATE(12);
5964  test_media_add(delayed_active_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
5965  test_media_add(delayed_active_state, "292-1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5966  test_media_add(delayed_active_state, "296-2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5967 
5968  test_media_add(delayed_pending_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
5969  test_media_add(delayed_pending_state, "292-1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5970  test_media_add(delayed_pending_state, "296-2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5971  test_media_add(delayed_pending_state, "297-4", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5972  test_media_add(delayed_pending_state, "294-5", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5973 
5974  test_media_add(current_active_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
5975  test_media_add(current_active_state, "292-1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5976  test_media_add(current_active_state, "296-2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5977  test_media_add(current_active_state, "290-3", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5978  test_media_add(current_active_state, "297-4", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5979 
5980  test_media_add(expected_pending_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
5981  test_media_add(expected_pending_state, "292-1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5982  test_media_add(expected_pending_state, "296-2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5983  test_media_add(expected_pending_state, "290-3", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5984  test_media_add(expected_pending_state, "297-4", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5985  test_media_add(expected_pending_state, "294-5", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5986  CHECKER();
5987 
5988  RESET_STATE(13);
5989  test_media_add(delayed_active_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
5990  test_media_add(delayed_active_state, "293-1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5991  test_media_add(delayed_active_state, "292-2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5992  test_media_add(delayed_active_state, "294-3", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5993  test_media_add(delayed_active_state, "295-4", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5994  test_media_add(delayed_active_state, "296-5", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5995 
5996  test_media_add(delayed_pending_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
5997  test_media_add(delayed_pending_state, "293-1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5998  test_media_add(delayed_pending_state, "292-2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
5999  test_media_add(delayed_pending_state, "294-3", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
6000  test_media_add(delayed_pending_state, "295-4", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
6001  test_media_add(delayed_pending_state, "296-5", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
6002  test_media_add(delayed_pending_state, "298-7", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
6003 
6004  test_media_add(current_active_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
6005  test_media_add(current_active_state, "293-1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
6006  test_media_add(current_active_state, "292-2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
6007  test_media_add(current_active_state, "294-3", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
6008  test_media_add(current_active_state, "295-4", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
6009  test_media_add(current_active_state, "296-5", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
6010  test_media_add(current_active_state, "290-6", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
6011 
6012  test_media_add(expected_pending_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
6013  test_media_add(expected_pending_state, "293-1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
6014  test_media_add(expected_pending_state, "292-2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
6015  test_media_add(expected_pending_state, "294-3", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
6016  test_media_add(expected_pending_state, "295-4", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
6017  test_media_add(expected_pending_state, "296-5", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
6018  test_media_add(expected_pending_state, "290-6", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
6019  test_media_add(expected_pending_state, "298-7", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
6020  CHECKER();
6021 
6022  RESET_STATE(14);
6023  test_media_add(delayed_active_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
6024  test_media_add(delayed_active_state, "298-1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
6025  test_media_add(delayed_active_state, "297-2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
6026 
6027  test_media_add(delayed_pending_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
6028  test_media_add(delayed_pending_state, "298-1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
6029  test_media_add(delayed_pending_state, "294-4", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
6030  test_media_add(delayed_pending_state, "295-5", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
6031 
6032  test_media_add(current_active_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
6033  test_media_add(current_active_state, "298-1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
6034  test_media_add(current_active_state, "297-2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
6035  test_media_add(current_active_state, "291-3", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
6036  test_media_add(current_active_state, "294-4", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
6037 
6038  test_media_add(expected_pending_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
6039  test_media_add(expected_pending_state, "298-1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
6040  test_media_add(expected_pending_state, "297-2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
6041  test_media_add(expected_pending_state, "291-3", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
6042  test_media_add(expected_pending_state, "294-4", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
6043  test_media_add(expected_pending_state, "295-5", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
6044  CHECKER();
6045 
6046  RESET_STATE(15);
6047  test_media_add(delayed_active_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
6048  test_media_add(delayed_active_state, "298-1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
6049  test_media_add(delayed_active_state, "297-2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
6050 
6051  test_media_add(delayed_pending_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
6052  test_media_add(delayed_pending_state, "298-1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDONLY, -1);
6053  test_media_add(delayed_pending_state, "294-4", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
6054  test_media_add(delayed_pending_state, "295-5", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
6055 
6056  test_media_add(current_active_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
6057  test_media_add(current_active_state, "297-2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
6058  test_media_add(current_active_state, "291-3", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
6059  test_media_add(current_active_state, "294-4", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
6060  test_media_add(current_active_state, "298-1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
6061 
6062  test_media_add(expected_pending_state, "audio", AST_MEDIA_TYPE_AUDIO, AST_STREAM_STATE_SENDRECV, -1);
6063  test_media_add(expected_pending_state, "297-2", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
6064  test_media_add(expected_pending_state, "291-3", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
6065  test_media_add(expected_pending_state, "294-4", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
6066  test_media_add(expected_pending_state, "298-1", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDONLY, -1);
6067  test_media_add(expected_pending_state, "295-5", AST_MEDIA_TYPE_VIDEO, AST_STREAM_STATE_SENDRECV, -1);
6068  CHECKER();
6069 
6070  SCOPE_EXIT_RTN_VALUE(res);
6071 }
Structure which contains media state information (streams, sessions)
#define RESET_STATE(__num)
Set when the stream has been removed/declined.
Definition: stream.h:78
static struct ast_sip_session_media * test_media_add(struct ast_sip_session_media_state *media_state, const char *name, enum ast_media_type type, enum ast_stream_state state, int position)
#define NULL
Definition: resample.c:96
Set when the stream is sending and receiving media.
Definition: stream.h:82
def info(msg)
Set when the stream is sending media only.
Definition: stream.h:86
#define CHECKER()
#define SCOPE_ENTER(level,...)
Non RAII_VAR Scope Trace macros The advantage of these macros is that the EXITs will have the actual ...
Definition: logger.h:780
#define SCOPE_EXIT_RTN_VALUE(__return_value,...)
Scope Exit with return value.
Definition: logger.h:875
ast_test_result_state
Definition: test.h:200

◆ check_content_disposition()

static int check_content_disposition ( pjsip_rx_data *  rdata)
static

if there is required media we don't understand, return 1

Definition at line 3891 of file res_pjsip_session.c.

References check_content_disposition_in_multipart(), and NULL.

Referenced by new_invite().

3892 {
3893  pjsip_msg_body *body = rdata->msg_info.msg->body;
3894  pjsip_ctype_hdr *ctype_hdr = rdata->msg_info.ctype;
3895 
3896  if (body && ctype_hdr &&
3897  !pj_stricmp2(&ctype_hdr->media.type, "multipart") &&
3898  (!pj_stricmp2(&ctype_hdr->media.subtype, "mixed") ||
3899  !pj_stricmp2(&ctype_hdr->media.subtype, "alternative"))) {
3900  pjsip_multipart_part *part = pjsip_multipart_get_first_part(body);
3901  while (part != NULL) {
3903  return 1;
3904  }
3905  part = pjsip_multipart_get_next_part(body, part);
3906  }
3907  }
3908  return 0;
3909 }
static int check_content_disposition_in_multipart(pjsip_multipart_part *part)
#define NULL
Definition: resample.c:96

◆ check_content_disposition_in_multipart()

static int check_content_disposition_in_multipart ( pjsip_multipart_part *  part)
static

Definition at line 3867 of file res_pjsip_session.c.

References check_sdp_content_type_supported().

Referenced by check_content_disposition().

3868 {
3869  pjsip_hdr *hdr = part->hdr.next;
3870  static const pj_str_t str_handling_required = {"handling=required", 16};
3871 
3872  while (hdr != &part->hdr) {
3873  if (hdr->type == PJSIP_H_OTHER) {
3874  pjsip_generic_string_hdr *generic_hdr = (pjsip_generic_string_hdr*)hdr;
3875 
3876  if (!pj_stricmp2(&hdr->name, "Content-Disposition") &&
3877  pj_stristr(&generic_hdr->hvalue, &str_handling_required) &&
3878  !check_sdp_content_type_supported(&part->body->content_type)) {
3879  return 1;
3880  }
3881  }
3882  hdr = hdr->next;
3883  }
3884 
3885  return 0;
3886 }
static int check_sdp_content_type_supported(pjsip_media_type *content_type)

◆ check_delayed_requests()

static void check_delayed_requests ( struct ast_sip_session session,
int(*)(void *vsession)  cb 
)
static

Definition at line 1582 of file res_pjsip_session.c.

References ao2_ref, ast_sip_push_task(), and ast_sip_session::serializer.

Referenced by session_inv_on_tsx_state_changed().

1584 {
1585  ao2_ref(session, +1);
1586  if (ast_sip_push_task(session->serializer, cb, session)) {
1587  ao2_ref(session, -1);
1588  }
1589 }
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct ast_taskprocessor * serializer
int ast_sip_push_task(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Pushes a task to SIP servants.
Definition: res_pjsip.c:5138

◆ check_request_status()

static int check_request_status ( pjsip_inv_session *  inv,
pjsip_event *  e 
)
static

Definition at line 4560 of file res_pjsip_session.c.

References ast_sip_failover_request(), and ast_sip_session_send_request().

Referenced by session_inv_on_state_changed().

4561 {
4562  struct ast_sip_session *session = inv->mod_data[session_module.id];
4563  pjsip_transaction *tsx = e->body.tsx_state.tsx;
4564 
4565  if (tsx->status_code != 503 && tsx->status_code != 408) {
4566  return 0;
4567  }
4568 
4569  if (!ast_sip_failover_request(tsx->last_tx)) {
4570  return 0;
4571  }
4572 
4573  pjsip_inv_uac_restart(inv, PJ_FALSE);
4574  /*
4575  * Bump the ref since it will be on a new transaction and
4576  * we don't want it to go away along with the old transaction.
4577  */
4578  pjsip_tx_data_add_ref(tsx->last_tx);
4579  ast_sip_session_send_request(session, tsx->last_tx);
4580  return 1;
4581 }
A structure describing a SIP session.
int ast_sip_failover_request(pjsip_tx_data *tdata)
Set a request to use the next value in the list of resolved addresses.
Definition: res_pjsip.c:4871
static struct ast_mansession session
static pjsip_module session_module
void ast_sip_session_send_request(struct ast_sip_session *session, pjsip_tx_data *tdata)
Send a SIP request.

◆ check_sdp_content_type_supported()

static int check_sdp_content_type_supported ( pjsip_media_type *  content_type)
static

Definition at line 3855 of file res_pjsip_session.c.

Referenced by check_content_disposition_in_multipart().

3856 {
3857  pjsip_media_type app_sdp;
3858  pjsip_media_type_init2(&app_sdp, "application", "sdp");
3859 
3860  if (!pjsip_media_type_cmp(content_type, &app_sdp, 0)) {
3861  return 1;
3862  }
3863 
3864  return 0;
3865 }

◆ create_local_sdp()

static struct pjmedia_sdp_session * create_local_sdp ( pjsip_inv_session *  inv,
struct ast_sip_session session,
const pjmedia_sdp_session *  offer 
)
static

Definition at line 5081 of file res_pjsip_session.c.

References ast_sip_session::active_media_state, add_bundle_groups(), add_sdp_streams(), ast_sip_endpoint_media_configuration::address, ast_random(), ast_sip_get_host_ip_string(), ast_sip_session_get_name(), ast_sip_session_media_state_add(), ast_str_tmp, ast_stream_get_type(), ast_stream_to_str(), ast_stream_topology_clone(), ast_stream_topology_free(), ast_stream_topology_get_count(), ast_stream_topology_get_stream(), ast_strlen_zero, ast_trace, end, ast_sip_session::endpoint, ast_sip_media_rtp_configuration::ipv6, LOG_ERROR, ast_sip_endpoint::media, ast_sip_session_media::mid, NULL, ast_sip_session::pending_media_state, ast_sip_endpoint_media_configuration::rtp, S_COR, S_OR, SCOPE_ENTER, SCOPE_EXIT, SCOPE_EXIT_EXPR, SCOPE_EXIT_LOG_EXPR, SCOPE_EXIT_LOG_RTN_VALUE, SCOPE_EXIT_RTN_VALUE, ast_sip_endpoint_media_configuration::sdpowner, ast_sip_endpoint_media_configuration::sdpsession, ast_sip_session_media_state::topology, and ast_sip_endpoint_media_configuration::topology.

Referenced by ast_sip_session_create_invite(), ast_sip_session_regenerate_answer(), generate_session_refresh_sdp(), new_invite(), session_inv_on_create_offer(), and session_inv_on_rx_offer().

5082 {
5083  static const pj_str_t STR_IN = { "IN", 2 };
5084  static const pj_str_t STR_IP4 = { "IP4", 3 };
5085  static const pj_str_t STR_IP6 = { "IP6", 3 };
5086  pjmedia_sdp_session *local;
5087  int i;
5088  int stream;
5089  SCOPE_ENTER(3, "%s\n", ast_sip_session_get_name(session));
5090 
5091  if (inv->state == PJSIP_INV_STATE_DISCONNECTED) {
5092  SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR, "%s: Failed to create session SDP. Session has been already disconnected\n",
5093  ast_sip_session_get_name(session));
5094  }
5095 
5096  if (!inv->pool_prov || !(local = PJ_POOL_ZALLOC_T(inv->pool_prov, pjmedia_sdp_session))) {
5097  SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR, "%s: Pool allocation failure\n", ast_sip_session_get_name(session));
5098  }
5099 
5100  if (!offer) {
5101  local->origin.version = local->origin.id = (pj_uint32_t)(ast_random());
5102  } else {
5103  local->origin.version = offer->origin.version + 1;
5104  local->origin.id = offer->origin.id;
5105  }
5106 
5107  pj_strdup2(inv->pool_prov, &local->origin.user, session->endpoint->media.sdpowner);
5108  pj_strdup2(inv->pool_prov, &local->name, session->endpoint->media.sdpsession);
5109 
5111  /* We've encountered a situation where we have been told to create a local SDP but noone has given us any indication
5112  * of what kind of stream topology they would like. We try to not alter the current state of the SDP negotiation
5113  * by using what is currently negotiated. If this is unavailable we fall back to what is configured on the endpoint.
5114  */
5116  if (session->active_media_state->topology) {
5118  } else {
5120  }
5121  if (!session->pending_media_state->topology) {
5122  SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR, "%s: No pending media state topology\n", ast_sip_session_get_name(session));
5123  }
5124  }
5125 
5126  ast_trace(-1, "%s: Processing streams\n", ast_sip_session_get_name(session));
5127 
5128  for (i = 0; i < ast_stream_topology_get_count(session->pending_media_state->topology); ++i) {
5129  struct ast_sip_session_media *session_media;
5131  unsigned int streams = local->media_count;
5132  SCOPE_ENTER(4, "%s: Processing stream %s\n", ast_sip_session_get_name(session),
5133  ast_str_tmp(128, ast_stream_to_str(stream, &STR_TMP)));
5134 
5135  /* This code does not enforce any maximum stream count limitations as that is done on either
5136  * the handling of an incoming SDP offer or on the handling of a session refresh.
5137  */
5138 
5139  session_media = ast_sip_session_media_state_add(session, session->pending_media_state, ast_stream_get_type(stream), i);
5140  if (!session_media) {
5141  local = NULL;
5142  SCOPE_EXIT_LOG_EXPR(goto end, LOG_ERROR, "%s: Couldn't alloc/add session media for stream %s\n",
5143  ast_sip_session_get_name(session), ast_str_tmp(128, ast_stream_to_str(stream, &STR_TMP)));
5144  }
5145 
5146  if (add_sdp_streams(session_media, session, local, offer, stream)) {
5147  local = NULL;
5148  SCOPE_EXIT_LOG_EXPR(goto end, LOG_ERROR, "%s: Couldn't add sdp streams for stream %s\n",
5149  ast_sip_session_get_name(session), ast_str_tmp(128, ast_stream_to_str(stream, &STR_TMP)));
5150  }
5151 
5152  /* If a stream was actually added then add any additional details */
5153  if (streams != local->media_count) {
5154  pjmedia_sdp_media *media = local->media[streams];
5155  pj_str_t stmp;
5156  pjmedia_sdp_attr *attr;
5157 
5158  /* Add the media identifier if present */
5159  if (!ast_strlen_zero(session_media->mid)) {
5160  attr = pjmedia_sdp_attr_create(inv->pool_prov, "mid", pj_cstr(&stmp, session_media->mid));
5161  pjmedia_sdp_attr_add(&media->attr_count, media->attr, attr);
5162  }
5163 
5164  ast_trace(-1, "%s: Stream %s added%s%s\n", ast_sip_session_get_name(session),
5165  ast_str_tmp(128, ast_stream_to_str(stream, &STR_TMP)),
5166  S_COR(!ast_strlen_zero(session_media->mid), " with mid ", ""), S_OR(session_media->mid, ""));
5167 
5168  }
5169 
5170  /* Ensure that we never exceed the maximum number of streams PJMEDIA will allow. */
5171  if (local->media_count == PJMEDIA_MAX_SDP_MEDIA) {
5172  SCOPE_EXIT_EXPR(break, "%s: Stream %s exceeded max pjmedia count of %d\n",
5173  ast_sip_session_get_name(session), ast_str_tmp(128, ast_stream_to_str(stream, &STR_TMP)),
5174  PJMEDIA_MAX_SDP_MEDIA);
5175  }
5176 
5177  SCOPE_EXIT("%s: Done with %s\n", ast_sip_session_get_name(session),
5178  ast_str_tmp(128, ast_stream_to_str(stream, &STR_TMP)));
5179 
5180  }
5181 
5182  /* Add any bundle groups that are present on the media state */
5183  ast_trace(-1, "%s: Adding bundle groups (if available)\n", ast_sip_session_get_name(session));
5184  if (add_bundle_groups(session, inv->pool_prov, local)) {
5185  SCOPE_EXIT_LOG_RTN_VALUE(NULL, LOG_ERROR, "%s: Couldn't add bundle groups\n", ast_sip_session_get_name(session));
5186  }
5187 
5188  /* Use the connection details of an available media if possible for SDP level */
5189  ast_trace(-1, "%s: Copying connection details\n", ast_sip_session_get_name(session));
5190 
5191  for (stream = 0; stream < local->media_count; stream++) {
5192  SCOPE_ENTER(4, "%s: Processing media %d\n", ast_sip_session_get_name(session), stream);
5193  if (!local->media[stream]->conn) {
5194  SCOPE_EXIT_EXPR(continue, "%s: Media %d has no connection info\n", ast_sip_session_get_name(session), stream);
5195  }
5196 
5197  if (local->conn) {
5198  if (!pj_strcmp(&local->conn->net_type, &local->media[stream]->conn->net_type) &&
5199  !pj_strcmp(&local->conn->addr_type, &local->media[stream]->conn->addr_type) &&
5200  !pj_strcmp(&local->conn->addr, &local->media[stream]->conn->addr)) {
5201  local->media[stream]->conn = NULL;
5202  }
5203  SCOPE_EXIT_EXPR(continue, "%s: Media %d has good existing connection info\n", ast_sip_session_get_name(session), stream);
5204  }
5205 
5206  /* This stream's connection info will serve as the connection details for SDP level */
5207  local->conn = local->media[stream]->conn;
5208  local->media[stream]->conn = NULL;
5209 
5210  SCOPE_EXIT_EXPR(continue, "%s: Media %d reset\n", ast_sip_session_get_name(session), stream);
5211  }
5212 
5213  /* If no SDP level connection details are present then create some */
5214  if (!local->conn) {
5215  ast_trace(-1, "%s: Creating connection details\n", ast_sip_session_get_name(session));
5216 
5217  local->conn = pj_pool_zalloc(inv->pool_prov, sizeof(struct pjmedia_sdp_conn));
5218  local->conn->net_type = STR_IN;
5219  local->conn->addr_type = session->endpoint->media.rtp.ipv6 ? STR_IP6 : STR_IP4;
5220 
5221  if (!ast_strlen_zero(session->endpoint->media.address)) {
5222  pj_strdup2(inv->pool_prov, &local->conn->addr, session->endpoint->media.address);
5223  } else {
5224  pj_strdup2(inv->pool_prov, &local->conn->addr, ast_sip_get_host_ip_string(session->endpoint->media.rtp.ipv6 ? pj_AF_INET6() : pj_AF_INET()));
5225  }
5226  }
5227 
5228  pj_strassign(&local->origin.net_type, &local->conn->net_type);
5229  pj_strassign(&local->origin.addr_type, &local->conn->addr_type);
5230  pj_strassign(&local->origin.addr, &local->conn->addr);
5231 
5232 end:
5233  SCOPE_EXIT_RTN_VALUE(local, "%s\n", ast_sip_session_get_name(session));
5234 }
#define SCOPE_EXIT_LOG_RTN_VALUE(__value, __log_level,...)
Definition: logger.h:940
struct ast_sip_endpoint * endpoint
const char * ast_stream_to_str(const struct ast_stream *stream, struct ast_str **buf)
Get a string representing the stream for debugging/display purposes.
Definition: stream.c:337
struct ast_sip_session_media_state * pending_media_state
enum ast_media_type ast_stream_get_type(const struct ast_stream *stream)
Get the media type of a stream.
Definition: stream.c:316
char * mid
Media identifier for this stream (may be shared across multiple streams)
const ast_string_field sdpsession
Definition: res_pjsip.h:762
#define ast_trace(level,...)
Print a basic trace message.
Definition: logger.h:692
const ast_string_field address
Definition: res_pjsip.h:758
struct ast_stream * ast_stream_topology_get_stream(const struct ast_stream_topology *topology, unsigned int position)
Get a specific stream from the topology.
Definition: stream.c:788
#define NULL
Definition: resample.c:96
#define SCOPE_EXIT_LOG_EXPR(__expr, __log_level,...)
Definition: logger.h:946
char * end
Definition: eagi_proxy.c:73
#define ast_strlen_zero(foo)
Definition: strings.h:52
struct ast_sip_session_media_state * active_media_state
const char * ast_sip_get_host_ip_string(int af)
Retrieve the local host address in string form.
Definition: res_pjsip.c:5473
struct ast_sip_endpoint_media_configuration media
Definition: res_pjsip.h:841
const ast_string_field sdpowner
Definition: res_pjsip.h:760
#define ast_str_tmp(init_len, __expr)
Definition: strings.h:1136
struct ast_sip_media_rtp_configuration rtp
Definition: res_pjsip.h:764
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:85
long int ast_random(void)
Definition: main/utils.c:2064
#define SCOPE_EXIT(...)
Scope Exit.
Definition: logger.h:805
#define SCOPE_EXIT_EXPR(__expr,...)
Definition: logger.h:834
static int add_sdp_streams(struct ast_sip_session_media *session_media, struct ast_sip_session *session, pjmedia_sdp_session *answer, const struct pjmedia_sdp_session *remote, struct ast_stream *stream)
#define LOG_ERROR
Definition: logger.h:285
struct ast_sip_session_media * ast_sip_session_media_state_add(struct ast_sip_session *session, struct ast_sip_session_media_state *media_state, enum ast_media_type type, int position)
Allocate an ast_session_media and add it to the media state&#39;s vector.
static int add_bundle_groups(struct ast_sip_session *session, pj_pool_t *pool, pjmedia_sdp_session *answer)
#define SCOPE_ENTER(level,...)
Non RAII_VAR Scope Trace macros The advantage of these macros is that the EXITs will have the actual ...
Definition: logger.h:780
const char * ast_sip_session_get_name(const struct ast_sip_session *session)
Get the channel or endpoint name associated with the session.
int ast_stream_topology_get_count(const struct ast_stream_topology *topology)
Get the number of streams in a topology.
Definition: stream.c:765
A structure containing SIP session media information.
struct ast_stream_topology * ast_stream_topology_clone(const struct ast_stream_topology *topology)
Create a deep clone of an existing stream topology.
Definition: stream.c:667
#define SCOPE_EXIT_RTN_VALUE(__return_value,...)
Scope Exit with return value.
Definition: logger.h:875
struct ast_stream_topology * topology
Definition: res_pjsip.h:772
struct ast_stream_topology * topology
The media stream topology.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
void ast_stream_topology_free(struct ast_stream_topology *topology)
Unreference and destroy a stream topology.
Definition: stream.c:743

◆ datastore_cmp()

static int datastore_cmp ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 2888 of file res_pjsip_session.c.

References ast_assert, CMP_MATCH, CMP_STOP, NULL, OBJ_KEY, and ast_datastore::uid.

Referenced by ast_sip_session_alloc().

2889 {
2890  const struct ast_datastore *datastore1 = obj;
2891  const struct ast_datastore *datastore2 = arg;
2892  const char *uid2 = flags & OBJ_KEY ? arg : datastore2->uid;
2893 
2894  ast_assert(datastore1->uid != NULL);
2895  ast_assert(uid2 != NULL);
2896 
2897  return strcmp(datastore1->uid, uid2) ? 0 : CMP_MATCH | CMP_STOP;
2898 }
#define OBJ_KEY
Definition: astobj2.h:1155
#define ast_assert(a)
Definition: utils.h:695
Structure for a data store object.
Definition: datastore.h:68
#define NULL
Definition: resample.c:96
const char * uid
Definition: datastore.h:69

◆ datastore_hash()

static int datastore_hash ( const void *  obj,
int  flags 
)
static

Definition at line 2878 of file res_pjsip_session.c.

References ast_assert, ast_str_hash(), NULL, OBJ_KEY, and ast_datastore::uid.

Referenced by ast_sip_session_alloc().

2879 {
2880  const struct ast_datastore *datastore = obj;
2881  const char *uid = flags & OBJ_KEY ? obj : datastore->uid;
2882 
2883  ast_assert(uid != NULL);
2884 
2885  return ast_str_hash(uid);
2886 }
#define OBJ_KEY
Definition: astobj2.h:1155
#define ast_assert(a)
Definition: utils.h:695
Structure for a data store object.
Definition: datastore.h:68
#define NULL
Definition: resample.c:96
const char * uid
Definition: datastore.h:69
static force_inline int attribute_pure ast_str_hash(const char *str)
Compute a hash value on a string.
Definition: strings.h:1206

◆ delay_request()

static int delay_request ( struct ast_sip_session session,
ast_sip_session_request_creation_cb  on_request,
ast_sip_session_sdp_creation_cb  on_sdp_creation,
ast_sip_session_response_cb  on_response,
int  generate_new_sdp,
enum delayed_method  method,
struct ast_sip_session_media_state pending_media_state,
struct ast_sip_session_media_state active_media_state,
int  queue_head 
)
static

Definition at line 1591 of file res_pjsip_session.c.

References AST_LIST_INSERT_HEAD, AST_LIST_INSERT_TAIL, ast_sip_session_get_name(), ast_sip_session_media_state_free(), DELAYED_METHOD_BYE, delayed_request_alloc(), ast_sip_session::delayed_requests, LOG_ERROR, ast_sip_session_delayed_request::next, SCOPE_ENTER, SCOPE_EXIT_LOG_RTN_VALUE, and SCOPE_EXIT_RTN_VALUE.

Referenced by ast_sip_session_terminate(), reschedule_reinvite(), and sip_session_refresh().

1600 {
1602  on_request, on_sdp_creation, on_response, generate_new_sdp, pending_media_state,
1603  active_media_state);
1604  SCOPE_ENTER(3, "%s\n", ast_sip_session_get_name(session));
1605 
1606  if (!delay) {
1607  ast_sip_session_media_state_free(pending_media_state);
1608  ast_sip_session_media_state_free(active_media_state);
1609  SCOPE_EXIT_LOG_RTN_VALUE(-1, LOG_ERROR, "Unable to allocate delay request\n");
1610  }
1611 
1612  if (method == DELAYED_METHOD_BYE || queue_head) {
1613  /* Send BYE as early as possible */
1614  AST_LIST_INSERT_HEAD(&session->delayed_requests, delay, next);
1615  } else {
1616  AST_LIST_INSERT_TAIL(&session->delayed_requests, delay, next);
1617  }
1619 }
#define SCOPE_EXIT_LOG_RTN_VALUE(__value, __log_level,...)
Definition: logger.h:940
ast_sip_session_sdp_creation_cb on_sdp_creation
void ast_sip_session_media_state_free(struct ast_sip_session_media_state *media_state)
Free a session media state structure.
struct ast_sip_session_delayed_request * next
const char * method
Definition: res_pjsip.c:4335
#define LOG_ERROR
Definition: logger.h:285
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:730
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:710
static struct ast_sip_session_delayed_request * delayed_request_alloc(enum delayed_method method, ast_sip_session_request_creation_cb on_request_creation, ast_sip_session_sdp_creation_cb on_sdp_creation, ast_sip_session_response_cb on_response, int generate_new_sdp, struct ast_sip_session_media_state *pending_media_state, struct ast_sip_session_media_state *active_media_state)
Structure used for sending delayed requests.
#define SCOPE_ENTER(level,...)
Non RAII_VAR Scope Trace macros The advantage of these macros is that the EXITs will have the actual ...
Definition: logger.h:780
const char * ast_sip_session_get_name(const struct ast_sip_session *session)
Get the channel or endpoint name associated with the session.
ast_sip_session_response_cb on_response
struct ast_sip_session::@309 delayed_requests
#define SCOPE_EXIT_RTN_VALUE(__return_value,...)
Scope Exit with return value.
Definition: logger.h:875

◆ delayed_method2str()

static const char* delayed_method2str ( enum delayed_method  method)
static

Definition at line 1310 of file res_pjsip_session.c.

References DELAYED_METHOD_BYE, DELAYED_METHOD_INVITE, DELAYED_METHOD_UPDATE, and str.

Referenced by invite_proceeding(), invite_terminated(), and send_delayed_request().

1311 {
1312  const char *str = "<unknown>";
1313 
1314  switch (method) {
1315  case DELAYED_METHOD_INVITE:
1316  str = "INVITE";
1317  break;
1318  case DELAYED_METHOD_UPDATE:
1319  str = "UPDATE";
1320  break;
1321  case DELAYED_METHOD_BYE:
1322  str = "BYE";
1323  break;
1324  }
1325 
1326  return str;
1327 }
const char * str
Definition: app_jack.c:147
const char * method
Definition: res_pjsip.c:4335

◆ delayed_request_alloc()

static struct ast_sip_session_delayed_request* delayed_request_alloc ( enum delayed_method  method,
ast_sip_session_request_creation_cb  on_request_creation,
ast_sip_session_sdp_creation_cb  on_sdp_creation,
ast_sip_session_response_cb  on_response,
int  generate_new_sdp,
struct ast_sip_session_media_state pending_media_state,
struct ast_sip_session_media_state active_media_state 
)
static

Definition at line 1355 of file res_pjsip_session.c.

References ast_sip_session_delayed_request::active_media_state, ast_calloc, ast_sip_session_delayed_request::generate_new_sdp, ast_sip_session_delayed_request::method, method, NULL, ast_sip_session_delayed_request::on_request_creation, ast_sip_session_delayed_request::on_response, ast_sip_session_delayed_request::on_sdp_creation, and ast_sip_session_delayed_request::pending_media_state.

Referenced by delay_request().

1363 {
1364  struct ast_sip_session_delayed_request *delay = ast_calloc(1, sizeof(*delay));
1365 
1366  if (!delay) {
1367  return NULL;
1368  }
1369  delay->method = method;
1372  delay->on_response = on_response;
1376  return delay;
1377 }
ast_sip_session_sdp_creation_cb on_sdp_creation
struct ast_sip_session_media_state * pending_media_state
ast_sip_session_request_creation_cb on_request_creation
#define NULL
Definition: resample.c:96
struct ast_sip_session_media_state * active_media_state
const char * method
Definition: res_pjsip.c:4335
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
Structure used for sending delayed requests.
ast_sip_session_response_cb on_response

◆ delayed_request_free()

static void delayed_request_free ( struct ast_sip_session_delayed_request delay)
static

Definition at line 1379 of file res_pjsip_session.c.

References ast_sip_session_delayed_request::active_media_state, ast_free, ast_sip_session_media_state_free(), and ast_sip_session_delayed_request::pending_media_state.

Referenced by ast_sip_session_terminate(), invite_proceeding(), invite_terminated(), and session_destructor().

1380 {
1383  ast_free(delay);
1384 }
struct ast_sip_session_media_state * pending_media_state
void ast_sip_session_media_state_free(struct ast_sip_session_media_state *media_state)
Free a session media state structure.
struct ast_sip_session_media_state * active_media_state
#define ast_free(a)
Definition: astmm.h:182

◆ does_method_match()

static pj_bool_t does_method_match ( const pj_str_t *  message_method,
const char *  supplement_method 
)
static

Definition at line 4129 of file res_pjsip_session.c.

References ast_strlen_zero, and method.

Referenced by handle_incoming_request(), handle_incoming_response(), handle_outgoing_request(), handle_outgoing_response(), and has_supplement().

4130 {
4131  pj_str_t method;
4132 
4133  if (ast_strlen_zero(supplement_method)) {
4134  return PJ_TRUE;
4135  }
4136 
4137  pj_cstr(&method, supplement_method);
4138 
4139  return pj_stristr(&method, message_method) ? PJ_TRUE : PJ_FALSE;
4140 }
static const pjsip_method message_method
Definition: res_pjsip.c:4332
#define ast_strlen_zero(foo)
Definition: strings.h:52
const char * method
Definition: res_pjsip.c:4335

◆ generate_session_refresh_sdp()

static pjmedia_sdp_session* generate_session_refresh_sdp ( struct ast_sip_session session)
static

Definition at line 1621 of file res_pjsip_session.c.

References ast_sip_session_get_name(), create_local_sdp(), ast_sip_session::inv_session, NULL, SCOPE_ENTER, and SCOPE_EXIT_RTN_VALUE.

Referenced by sip_session_refresh().

1622 {
1623  pjsip_inv_session *inv_session = session->inv_session;
1624  const pjmedia_sdp_session *previous_sdp = NULL;
1625  SCOPE_ENTER(3, "%s\n", ast_sip_session_get_name(session));
1626 
1627  if (inv_session->neg) {
1628  if (pjmedia_sdp_neg_was_answer_remote(inv_session->neg)) {
1629  pjmedia_sdp_neg_get_active_remote(inv_session->neg, &previous_sdp);
1630  } else {
1631  pjmedia_sdp_neg_get_active_local(inv_session->neg, &previous_sdp);
1632  }
1633  }
1634  SCOPE_EXIT_RTN_VALUE(create_local_sdp(inv_session, session, previous_sdp));
1635 }
#define NULL
Definition: resample.c:96
struct pjsip_inv_session * inv_session
#define SCOPE_ENTER(level,...)
Non RAII_VAR Scope Trace macros The advantage of these macros is that the EXITs will have the actual ...
Definition: logger.h:780
const char * ast_sip_session_get_name(const struct ast_sip_session *session)
Get the channel or endpoint name associated with the session.
#define SCOPE_EXIT_RTN_VALUE(__return_value,...)
Scope Exit with return value.
Definition: logger.h:875
static struct pjmedia_sdp_session * create_local_sdp(pjsip_inv_session *inv, struct ast_sip_session *session, const pjmedia_sdp_session *offer)

◆ get_destination()

static enum sip_get_destination_result get_destination ( struct ast_sip_session session,
pjsip_rx_data *  rdata 
)
static

Determine where in the dialplan a call should go.

This uses the username in the request URI to try to match an extension in the endpoint's configured context in order to route the call.

Parameters
sessionThe inbound SIP session
rdataThe SIP INVITE

Definition at line 3666 of file res_pjsip_session.c.

References ast_sip_endpoint::allow_overlap, ao2_ref, ast_canmatch_extension(), ast_copy_pj_str(), ast_exists_extension(), ast_get_chan_features_pickup_config(), ast_log, ast_sip_session_get_name(), AST_SIP_USER_OPTIONS_TRUNCATE_CHECK, ast_strdupa, ast_sip_endpoint::context, ast_sip_session::endpoint, ast_sip_session::exten, ast_sip_session::inv_session, LOG_ERROR, NULL, ast_features_pickup_config::pickupexten, ast_sip_session::request_uri, SIP_GET_DEST_EXTEN_FOUND, SIP_GET_DEST_EXTEN_NOT_FOUND, SIP_GET_DEST_EXTEN_PARTIAL, and SIP_GET_DEST_UNSUPPORTED_URI.

Referenced by new_invite().

3667 {
3668  pjsip_uri *ruri = rdata->msg_info.msg->line.req.uri;
3669  pjsip_sip_uri *sip_ruri;
3670  struct ast_features_pickup_config *pickup_cfg;
3671  const char *pickupexten;
3672 
3673  if (!PJSIP_URI_SCHEME_IS_SIP(ruri) && !PJSIP_URI_SCHEME_IS_SIPS(ruri)) {
3675  }
3676 
3677  sip_ruri = pjsip_uri_get_uri(ruri);
3678  ast_copy_pj_str(session->exten, &sip_ruri->user, sizeof(session->exten));
3679 
3680  /*
3681  * We may want to match in the dialplan without any user
3682  * options getting in the way.
3683  */
3685 
3686  pickup_cfg = ast_get_chan_features_pickup_config(NULL); /* session->channel doesn't exist yet, using NULL */
3687  if (!pickup_cfg) {
3688  ast_log(LOG_ERROR, "%s: Unable to retrieve pickup configuration options. Unable to detect call pickup extension\n",
3689  ast_sip_session_get_name(session));
3690  pickupexten = "";
3691  } else {
3692  pickupexten = ast_strdupa(pickup_cfg->pickupexten);
3693  ao2_ref(pickup_cfg, -1);
3694  }
3695 
3696  if (!strcmp(session->exten, pickupexten) ||
3697  ast_exists_extension(NULL, session->endpoint->context, session->exten, 1, NULL)) {
3698  /*
3699  * Save off the INVITE Request-URI in case it is
3700  * needed: CHANNEL(pjsip,request_uri)
3701  */
3702  session->request_uri = pjsip_uri_clone(session->inv_session->pool, ruri);
3703 
3704  return SIP_GET_DEST_EXTEN_FOUND;
3705  }
3706 
3707  /*
3708  * Check for partial match via overlap dialling (if enabled)
3709  */
3710  if (session->endpoint->allow_overlap && (
3711  !strncmp(session->exten, pickupexten, strlen(session->exten)) ||
3712  ast_canmatch_extension(NULL, session->endpoint->context, session->exten, 1, NULL))) {
3713  /* Overlap partial match */
3715  }
3716 
3718 }
struct ast_sip_endpoint * endpoint
#define AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(str)
Truncate the URI user field options string if enabled.
Definition: res_pjsip.h:3036
struct ast_features_pickup_config * ast_get_chan_features_pickup_config(struct ast_channel *chan)
Get the pickup configuration options for a channel.
pjsip_uri * request_uri
const ast_string_field context
Definition: res_pjsip.h:815
void ast_copy_pj_str(char *dest, const pj_str_t *src, size_t size)
Copy a pj_str_t into a standard character buffer.
Definition: res_pjsip.c:5240
char exten[AST_MAX_EXTENSION]
#define NULL
Definition: resample.c:96
struct pjsip_inv_session * inv_session
int ast_canmatch_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Looks for a valid matching extension.
Definition: pbx.c:4194
#define ast_log
Definition: astobj2.c:42
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
Definition: pbx.c:4179
#define LOG_ERROR
Definition: logger.h:285
const char * ast_sip_session_get_name(const struct ast_sip_session *session)
Get the channel or endpoint name associated with the session.
unsigned int allow_overlap
Definition: res_pjsip.h:893
Configuration relating to call pickup.

◆ get_mid_bundle_group()

static int get_mid_bundle_group ( const pjmedia_sdp_session *  sdp,
const char *  mid 
)
static

Definition at line 612 of file res_pjsip_session.c.

References ast_copy_pj_str(), ast_sip_session_media::bundle_group, strsep(), and value.

Referenced by set_mid_and_bundle_group().

613 {
614  int bundle_group = 0;
615  int index;
616 
617  for (index = 0; index < sdp->attr_count; ++index) {
618  pjmedia_sdp_attr *attr = sdp->attr[index];
619  char value[pj_strlen(&attr->value) + 1], *mids = value, *attr_mid;
620 
621  if (pj_strcmp2(&attr->name, "group") || pj_strncmp2(&attr->value, "BUNDLE", 6)) {
622  continue;
623  }
624 
625  ast_copy_pj_str(value, &attr->value, sizeof(value));
626 
627  /* Skip the BUNDLE at the front */
628  mids += 7;
629 
630  while ((attr_mid = strsep(&mids, " "))) {
631  if (!strcmp(attr_mid, mid)) {
632  /* The ordering of attributes determines our internal identification of the bundle group based on number,
633  * with -1 being not in a bundle group. Since this is only exposed internally for response purposes it's
634  * actually even fine if things move around.
635  */
636  return bundle_group;
637  }
638  }
639 
640  bundle_group++;
641  }
642 
643  return -1;
644 }
void ast_copy_pj_str(char *dest, const pj_str_t *src, size_t size)
Copy a pj_str_t into a standard character buffer.
Definition: res_pjsip.c:5240
int value
Definition: syslog.c:37
char * strsep(char **str, const char *delims)

◆ handle_incoming()

static int handle_incoming ( struct ast_sip_session<