Asterisk - The Open Source Telephony Project  18.5.0
Data Structures | Macros | Typedefs | Enumerations | Functions
res_pjsip_session.h File Reference
#include <pjlib.h>
#include "asterisk/linkedlists.h"
#include "asterisk/channel.h"
#include "asterisk/netsock2.h"
#include "asterisk/sdp_srtp.h"
#include "asterisk/codec.h"
#include <pjsip_ua.h>
Include dependency graph for res_pjsip_session.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  ast_sip_channel_pvt
 A structure which contains a channel implementation and session. More...
 
struct  ast_sip_session
 A structure describing a SIP session. More...
 
struct  ast_sip_session_media
 A structure containing SIP session media information. More...
 
struct  ast_sip_session_media_read_callback_state
 Structure which contains read callback information. More...
 
struct  ast_sip_session_media_state
 Structure which contains media state information (streams, sessions) More...
 
struct  ast_sip_session_sdp_handler
 A handler for SDPs in SIP sessions. More...
 
struct  ast_sip_session_supplement
 A supplement to SIP message processing. More...
 

Macros

#define ast_sip_session_register_supplement(supplement)   ast_sip_session_register_supplement_with_module(AST_MODULE_SELF, supplement)
 

Typedefs

typedef struct ast_frame *(* ast_sip_session_media_read_cb) (struct ast_sip_session *session, struct ast_sip_session_media *session_media)
 
typedef int(* ast_sip_session_media_write_cb) (struct ast_sip_session *session, struct ast_sip_session_media *session_media, struct ast_frame *frame)
 
typedef int(* ast_sip_session_request_creation_cb) (struct ast_sip_session *session, pjsip_tx_data *tdata)
 
typedef int(* ast_sip_session_response_cb) (struct ast_sip_session *session, pjsip_rx_data *rdata)
 
typedef int(* ast_sip_session_sdp_creation_cb) (struct ast_sip_session *session, pjmedia_sdp_session *sdp)
 

Enumerations

enum  ast_sip_session_call_direction { AST_SIP_SESSION_INCOMING_CALL = 0, AST_SIP_SESSION_OUTGOING_CALL }
 Indicates the call direction respective to Asterisk. More...
 
enum  ast_sip_session_response_priority { AST_SIP_SESSION_BEFORE_REDIRECTING = (1 << 0), AST_SIP_SESSION_BEFORE_MEDIA = (1 << 1), AST_SIP_SESSION_AFTER_MEDIA = (1 << 2) }
 Describes when a supplement should be called into on incoming responses. More...
 
enum  ast_sip_session_sdp_stream_defer { AST_SIP_SESSION_SDP_DEFER_NOT_HANDLED, AST_SIP_SESSION_SDP_DEFER_ERROR, AST_SIP_SESSION_SDP_DEFER_NOT_NEEDED, AST_SIP_SESSION_SDP_DEFER_NEEDED }
 
enum  ast_sip_session_t38state {
  T38_DISABLED = 0, T38_LOCAL_REINVITE, T38_PEER_REINVITE, T38_ENABLED,
  T38_REJECTED, T38_MAX_ENUM
}
 T.38 states for a session. More...
 

Functions

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...
 
int ast_sip_session_add_supplements (struct ast_sip_session *session)
 Add supplements 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, 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_register_supplement_with_module (struct ast_module *module, struct ast_sip_session_supplement *supplement)
 Register a supplement to SIP session processing. 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_remove_supplements (struct ast_sip_session *session)
 Remove supplements from a SIP 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_unregister_supplement (struct ast_sip_session_supplement *supplement)
 Unregister a an supplement to SIP session processing. More...
 
void ast_sip_session_unsuspend (struct ast_sip_session *session)
 Request the session serializer be unsuspended. More...
 

Macro Definition Documentation

◆ ast_sip_session_register_supplement

#define ast_sip_session_register_supplement (   supplement)    ast_sip_session_register_supplement_with_module(AST_MODULE_SELF, supplement)

Definition at line 616 of file res_pjsip_session.h.

Referenced by ast_res_pjsip_init_message_filter(), and load_module().

Typedef Documentation

◆ ast_sip_session_media_read_cb

typedef struct ast_frame*(* ast_sip_session_media_read_cb) (struct ast_sip_session *session, struct ast_sip_session_media *session_media)

Definition at line 68 of file res_pjsip_session.h.

◆ ast_sip_session_media_write_cb

typedef int(* ast_sip_session_media_write_cb) (struct ast_sip_session *session, struct ast_sip_session_media *session_media, struct ast_frame *frame)

Definition at line 69 of file res_pjsip_session.h.

◆ ast_sip_session_request_creation_cb

typedef int(* ast_sip_session_request_creation_cb) (struct ast_sip_session *session, pjsip_tx_data *tdata)

Definition at line 246 of file res_pjsip_session.h.

◆ ast_sip_session_response_cb

typedef int(* ast_sip_session_response_cb) (struct ast_sip_session *session, pjsip_rx_data *rdata)

Definition at line 247 of file res_pjsip_session.h.

◆ ast_sip_session_sdp_creation_cb

typedef int(* ast_sip_session_sdp_creation_cb) (struct ast_sip_session *session, pjmedia_sdp_session *sdp)

Definition at line 248 of file res_pjsip_session.h.

Enumeration Type Documentation

◆ ast_sip_session_call_direction

Indicates the call direction respective to Asterisk.

Enumerator
AST_SIP_SESSION_INCOMING_CALL 
AST_SIP_SESSION_OUTGOING_CALL 

Definition at line 166 of file res_pjsip_session.h.

◆ ast_sip_session_response_priority

Describes when a supplement should be called into on incoming responses.

In most cases, session supplements will not need to worry about this because in most cases, the correct value will be automatically applied. However, there are rare circumstances when a supplement will want to specify when it should be called.

The values below are listed in chronological order.

Enumerator
AST_SIP_SESSION_BEFORE_REDIRECTING 

When processing 3XX responses, the supplement is called into before the redirecting information is processed.

AST_SIP_SESSION_BEFORE_MEDIA 

For responses to INVITE transactions, the supplement is called into before media is negotiated.

This priority is applied by default to any session supplement that does not specify a response priority.

AST_SIP_SESSION_AFTER_MEDIA 

For INVITE transactions, the supplement is called into after media is negotiated.

Definition at line 259 of file res_pjsip_session.h.

259  {
260  /*!
261  * When processing 3XX responses, the supplement is called into before
262  * the redirecting information is processed.
263  */
265  /*!
266  * For responses to INVITE transactions, the supplement is called into
267  * before media is negotiated.
268  *
269  * This priority is applied by default to any session supplement that
270  * does not specify a response priority.
271  */
272  AST_SIP_SESSION_BEFORE_MEDIA = (1 << 1),
273  /*!
274  * For INVITE transactions, the supplement is called into after media
275  * is negotiated.
276  */
277  AST_SIP_SESSION_AFTER_MEDIA = (1 << 2),
278 };

◆ ast_sip_session_sdp_stream_defer

Enumerator
AST_SIP_SESSION_SDP_DEFER_NOT_HANDLED 

The stream was not handled by this handler. If there are other registered handlers for this stream type, they will be called.

AST_SIP_SESSION_SDP_DEFER_ERROR 

There was an error encountered. No further operations will take place and the current negotiation will be abandoned.

AST_SIP_SESSION_SDP_DEFER_NOT_NEEDED 

Re-invite is not needed

AST_SIP_SESSION_SDP_DEFER_NEEDED 

Re-invite should be deferred and will be resumed later. No further operations will take place.

Definition at line 363 of file res_pjsip_session.h.

363  {
364  /*! The stream was not handled by this handler. If there are other registered handlers for this stream type, they will be called. */
366  /*! There was an error encountered. No further operations will take place and the current negotiation will be abandoned. */
368  /*! Re-invite is not needed */
370  /*! Re-invite should be deferred and will be resumed later. No further operations will take place. */
372 };

◆ ast_sip_session_t38state

T.38 states for a session.

Enumerator
T38_DISABLED 

Not enabled

T38_LOCAL_REINVITE 

Offered from local - REINVITE

T38_PEER_REINVITE 

Offered from peer - REINVITE

T38_ENABLED 

Negotiated (enabled)

T38_REJECTED 

Refused

T38_MAX_ENUM 

Not an actual state; used as max value in the enum

Definition at line 54 of file res_pjsip_session.h.

54  {
55  T38_DISABLED = 0, /*!< Not enabled */
56  T38_LOCAL_REINVITE, /*!< Offered from local - REINVITE */
57  T38_PEER_REINVITE, /*!< Offered from peer - REINVITE */
58  T38_ENABLED, /*!< Negotiated (enabled) */
59  T38_REJECTED, /*!< Refused */
60  T38_MAX_ENUM, /*!< Not an actual state; used as max value in the enum */
61 };

Function Documentation

◆ 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_add_supplements()

int ast_sip_session_add_supplements ( struct ast_sip_session session)

Add supplements to a SIP session.

Parameters
sessionThe session to initialize

Definition at line 90 of file pjsip_session.c.

References AST_LIST_INSERT_TAIL, ast_module_ref, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, copy(), lock, ast_sip_session_supplement::module, ast_sip_session_supplement::next, SCOPED_LOCK, supplement_dup(), and ast_sip_session::supplements.

Referenced by ast_sip_session_alloc().

91 {
92  struct ast_sip_session_supplement *iter;
94 
97 
98  if (!copy) {
99  return -1;
100  }
101 
102  /* referenced session created. increasing module reference. */
103  ast_module_ref(copy->module);
104 
105  AST_LIST_INSERT_TAIL(&session->supplements, copy, next);
106  }
107 
108  return 0;
109 }
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
static int copy(char *infile, char *outfile)
Utility function to copy a file.
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
ast_mutex_t lock
Definition: app_meetme.c:1091
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
#define SCOPED_LOCK(varname, lock, lockfunc, unlockfunc)
Scoped Locks.
Definition: lock.h:581
struct ast_module * module
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:730
struct ast_sip_session::@308 supplements
struct ast_sip_session_supplement * next
A supplement to SIP message processing.
static struct ast_sip_session_supplement * supplement_dup(const struct ast_sip_session_supplement *src)
Definition: pjsip_session.c:77
#define ast_module_ref(mod)
Hold a reference to the module.
Definition: module.h:443

◆ 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_register_supplement_with_module()

void ast_sip_session_register_supplement_with_module ( struct ast_module module,
struct ast_sip_session_supplement supplement 
)

Register a supplement to SIP session processing.

This allows for someone to insert themselves in the processing of SIP requests and responses. This, for example could allow for a module to set channel data based on headers in an incoming message. Similarly, a module could reject an incoming request if desired.

Parameters
moduleReferenced module(NULL safe)
supplementThe supplement to register

Definition at line 35 of file pjsip_session.c.

References ast_assert, AST_RWLIST_INSERT_BEFORE_CURRENT, AST_RWLIST_INSERT_TAIL, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, AST_SIP_SESSION_BEFORE_MEDIA, lock, ast_sip_session_supplement::module, ast_sip_session_supplement::next, NULL, ast_sip_session_supplement::priority, ast_sip_session_supplement::response_priority, and SCOPED_LOCK.

36 {
37  struct ast_sip_session_supplement *iter;
38  int inserted = 0;
40 
41  ast_assert(supplement != NULL);
42 
43  supplement->module = module;
44 
45  if (!supplement->response_priority) {
47  }
48 
50  if (iter->priority > supplement->priority) {
52  inserted = 1;
53  break;
54  }
55  }
57 
58  if (!inserted) {
60  }
61 }
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
#define ast_assert(a)
Definition: utils.h:695
#define NULL
Definition: resample.c:96
enum ast_sip_session_response_priority response_priority
ast_mutex_t lock
Definition: app_meetme.c:1091
#define SCOPED_LOCK(varname, lock, lockfunc, unlockfunc)
Scoped Locks.
Definition: lock.h:581
#define AST_RWLIST_INSERT_BEFORE_CURRENT
Definition: linkedlists.h:609
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
Definition: linkedlists.h:544
struct ast_module * module
enum ast_sip_supplement_priority priority
struct ast_sip_session_supplement * next
A supplement to SIP message processing.
#define AST_RWLIST_INSERT_TAIL
Definition: linkedlists.h:740
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:616

◆ 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_remove_supplements()

void ast_sip_session_remove_supplements ( struct ast_sip_session session)

Remove supplements from a SIP session.

Parameters
sessionThe session to remove

Definition at line 111 of file pjsip_session.c.

References ast_free, AST_LIST_REMOVE_HEAD, ast_module_unref, ast_sip_session_supplement::module, ast_sip_session_supplement::next, and ast_sip_session::supplements.

Referenced by session_destructor().

112 {
113  struct ast_sip_session_supplement *iter;
114 
115  if (!session) {
116  return;
117  }
118 
119  /* free the supplements */
120  while ((iter = AST_LIST_REMOVE_HEAD(&session->supplements, next))) {
121  if (iter->module) {
122  /* referenced session closed. decreasing modue reference. */
123  ast_module_unref(iter->module);
124  }
125 
126  ast_free(iter);
127  }
128 
129  return;
130 }
#define ast_module_unref(mod)
Release a reference to the module.
Definition: module.h:469
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
struct ast_module * module
#define ast_free(a)
Definition: astmm.h:182
struct ast_sip_session::@308 supplements
struct ast_sip_session_supplement * next
A supplement to SIP message processing.

◆ 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_unregister_supplement()

void ast_sip_session_unregister_supplement ( struct ast_sip_session_supplement supplement)

Unregister a an supplement to SIP session processing.

Parameters
supplementThe supplement to unregister

Definition at line 63 of file pjsip_session.c.

References AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, lock, ast_sip_session_supplement::next, and SCOPED_LOCK.

Referenced by ast_res_pjsip_cleanup_message_filter(), load_module(), and unload_module().

64 {
65  struct ast_sip_session_supplement *iter;
67 
69  if (supplement == iter) {
71  break;
72  }
73  }
75 }
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
ast_mutex_t lock
Definition: app_meetme.c:1091
#define AST_RWLIST_REMOVE_CURRENT
Definition: linkedlists.h:569
#define SCOPED_LOCK(varname, lock, lockfunc, unlockfunc)
Scoped Locks.
Definition: lock.h:581
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
Definition: linkedlists.h:544
struct ast_sip_session_supplement * next
A supplement to SIP message processing.
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:616

◆ 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