Asterisk - The Open Source Telephony Project  GIT-master-93d0901
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 612 of file res_pjsip_session.h.

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 1 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.

166  {
169 };
@ AST_SIP_SESSION_OUTGOING_CALL
@ AST_SIP_SESSION_INCOMING_CALL

◆ 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_BEFORE_REDIRECTING
@ AST_SIP_SESSION_AFTER_MEDIA
@ AST_SIP_SESSION_BEFORE_MEDIA

◆ 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_SDP_DEFER_NEEDED
@ AST_SIP_SESSION_SDP_DEFER_NOT_HANDLED
@ AST_SIP_SESSION_SDP_DEFER_NOT_NEEDED
@ AST_SIP_SESSION_SDP_DEFER_ERROR

◆ 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 };
@ T38_PEER_REINVITE
@ T38_LOCAL_REINVITE
@ T38_MAX_ENUM
@ T38_ENABLED
@ T38_REJECTED
@ T38_DISABLED

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 2975 of file res_pjsip_session.c.

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

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

Referenced by chan_pjsip_new().

◆ 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 3629 of file res_pjsip_session.c.

3630 {
3631  pjsip_inv_session *inv_session = pjsip_dlg_get_inv_session(dlg);
3632  struct ast_sip_session *session;
3633 
3634  if (!inv_session ||
3635  !(session = inv_session->mod_data[session_module.id])) {
3636  return NULL;
3637  }
3638 
3639  ao2_ref(session, +1);
3640 
3641  return session;
3642 }
static pjsip_module session_module
A structure describing a SIP session.
struct pjsip_inv_session * inv_session

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

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

◆ 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.

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 }
#define ao2_link(container, obj)
Add an object to a container.
Definition: astobj2.h:1532
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
const struct ast_datastore_info * info
Definition: datastore.h:67
const char * uid
Definition: datastore.h:65
#define ast_assert(a)
Definition: utils.h:734

References ao2_link, ast_assert, ast_strlen_zero(), ast_datastore::info, NULL, session, 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().

◆ 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.

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 }
ast_mutex_t lock
Definition: app_meetme.c:1093
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:78
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:151
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:494
#define SCOPED_LOCK(varname, lock, lockfunc, unlockfunc)
Scoped Locks.
Definition: lock.h:581
#define ast_module_ref(mod)
Hold a reference to the module.
Definition: module.h:443
static struct ast_sip_session_supplement * supplement_dup(const struct ast_sip_session_supplement *src)
Definition: pjsip_session.c:77
A supplement to SIP message processing.
struct ast_sip_session_supplement * next

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

Referenced by ast_sip_session_alloc().

◆ 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
invThe PJSIP INVITE session data
rdataINVITE request received (NULL if for outgoing allocation)

Definition at line 2991 of file res_pjsip_session.c.

2993 {
2995  struct ast_sip_session *ret_session;
2996  int dsp_features = 0;
2997 
2999  if (!session) {
3000  return NULL;
3001  }
3002 
3003  AST_LIST_HEAD_INIT(&session->supplements);
3004  AST_LIST_HEAD_INIT_NOLOCK(&session->delayed_requests);
3005  ast_party_id_init(&session->id);
3006 
3008  if (!session->direct_media_cap) {
3009  return NULL;
3010  }
3013  if (!session->datastores) {
3014  return NULL;
3015  }
3016  session->active_media_state = ast_sip_session_media_state_alloc();
3017  if (!session->active_media_state) {
3018  return NULL;
3019  }
3020  session->pending_media_state = ast_sip_session_media_state_alloc();
3021  if (!session->pending_media_state) {
3022  return NULL;
3023  }
3024  if (AST_VECTOR_INIT(&session->media_stats, 1) < 0) {
3025  return NULL;
3026  }
3027 
3029  dsp_features |= DSP_FEATURE_DIGIT_DETECT;
3030  }
3031  if (endpoint->faxdetect) {
3032  dsp_features |= DSP_FEATURE_FAX_DETECT;
3033  }
3034  if (dsp_features) {
3035  session->dsp = ast_dsp_new();
3036  if (!session->dsp) {
3037  return NULL;
3038  }
3039 
3040  ast_dsp_set_features(session->dsp, dsp_features);
3041  }
3042 
3043  session->endpoint = ao2_bump(endpoint);
3044 
3045  if (rdata) {
3046  /*
3047  * We must continue using the serializer that the original
3048  * INVITE came in on for the dialog. There may be
3049  * retransmissions already enqueued in the original
3050  * serializer that can result in reentrancy and message
3051  * sequencing problems.
3052  */
3053  session->serializer = ast_sip_get_distributor_serializer(rdata);
3054  } else {
3055  char tps_name[AST_TASKPROCESSOR_MAX_NAME + 1];
3056 
3057  /* Create name with seq number appended. */
3058  ast_taskprocessor_build_name(tps_name, sizeof(tps_name), "pjsip/outsess/%s",
3060 
3061  session->serializer = ast_sip_create_serializer(tps_name);
3062  }
3063  if (!session->serializer) {
3064  return NULL;
3065  }
3068 
3069  /* When a PJSIP INVITE session is created it is created with a reference
3070  * count of 1, with that reference being managed by the underlying state
3071  * of the INVITE session itself. When the INVITE session transitions to
3072  * a DISCONNECTED state that reference is released. This means we can not
3073  * rely on that reference to ensure the INVITE session remains for the
3074  * lifetime of our session. To ensure it does we add our own reference
3075  * and release it when our own session goes away, ensuring that the INVITE
3076  * session remains for the lifetime of session.
3077  */
3078 
3079 #ifdef HAVE_PJSIP_INV_SESSION_REF
3080  if (pjsip_inv_add_ref(inv_session) != PJ_SUCCESS) {
3081  ast_log(LOG_ERROR, "Can't increase the session reference counter\n");
3082  return NULL;
3083  }
3084 #endif
3085 
3086  pjsip_dlg_inc_session(inv_session->dlg, &session_module);
3087  inv_session->mod_data[session_module.id] = ao2_bump(session);
3088  session->contact = ao2_bump(contact);
3089  session->inv_session = inv_session;
3090 
3091  session->dtmf = endpoint->dtmf;
3092  session->moh_passthrough = endpoint->moh_passthrough;
3093 
3095  /* Release the ref held by session->inv_session */
3096  ao2_ref(session, -1);
3097  return NULL;
3098  }
3099 
3100  session->authentication_challenge_count = 0;
3101 
3102  /* Fire session begin handlers */
3104 
3105  /* Avoid unnecessary ref manipulation to return a session */
3106  ret_session = session;
3107  session = NULL;
3108  return ret_session;
3109 }
#define ast_log
Definition: astobj2.c:42
@ AO2_ALLOC_OPT_LOCK_MUTEX
Definition: astobj2.h:363
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Allocate and initialize a hash container with the desired number of buckets.
Definition: astobj2.h:1303
void ast_party_id_init(struct ast_party_id *init)
Initialize the given party id structure.
Definition: channel.c:1751
struct ast_dsp * ast_dsp_new(void)
Allocates a new dsp, assumes 8khz for internal sample rate.
Definition: dsp.c:1748
#define DSP_FEATURE_DIGIT_DETECT
Definition: dsp.h:28
#define DSP_FEATURE_FAX_DETECT
Definition: dsp.h:29
void ast_dsp_set_features(struct ast_dsp *dsp, int features)
Select feature set.
Definition: dsp.c:1758
@ AST_FORMAT_CAP_FLAG_DEFAULT
Definition: format_cap.h:38
#define ast_format_cap_alloc(flags)
Allocate a new ast_format_cap structure.
Definition: format_cap.h:49
struct ast_taskprocessor * ast_sip_get_distributor_serializer(pjsip_rx_data *rdata)
Determine the distributor serializer for the SIP message.
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.
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_taskprocessor * ast_sip_create_serializer(const char *name)
Create a new serializer for SIP tasks.
Definition: res_pjsip.c:5170
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
Definition: linkedlists.h:681
#define AST_LIST_HEAD_INIT(head)
Initializes a list head structure.
Definition: linkedlists.h:626
#define LOG_ERROR
Definition: logger.h:286
@ AST_SIP_DTMF_AUTO
Definition: res_pjsip.h:438
@ AST_SIP_DTMF_INBAND
Definition: res_pjsip.h:434
struct ast_sip_session_media_state * ast_sip_session_media_state_alloc(void)
Allocate a session media state structure.
static void handle_session_begin(struct ast_sip_session *session)
#define DATASTORE_BUCKETS
static void session_destructor(void *obj)
static int datastore_cmp(void *obj, void *arg, int flags)
static int datastore_hash(const void *obj, int flags)
int ast_sip_session_add_supplements(struct ast_sip_session *session)
Add supplements to a SIP session.
Definition: pjsip_session.c:90
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
unsigned int moh_passthrough
Definition: res_pjsip.h:923
enum ast_sip_dtmf_mode dtmf
Definition: res_pjsip.h:901
unsigned int faxdetect
Definition: res_pjsip.h:913
struct ast_sip_endpoint * endpoint
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 AST_TASKPROCESSOR_MAX_NAME
Suggested maximum taskprocessor name length (less null terminator).
Definition: taskprocessor.h:61
#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:936
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:113

References 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, DATASTORE_BUCKETS, datastore_cmp(), datastore_hash(), DSP_FEATURE_DIGIT_DETECT, DSP_FEATURE_FAX_DETECT, ast_sip_endpoint::dtmf, ast_sip_session::endpoint, ast_sip_endpoint::faxdetect, handle_session_begin(), ast_sip_session::inv_session, LOG_ERROR, ast_sip_endpoint::moh_passthrough, NULL, RAII_VAR, session, session_destructor(), and session_module.

Referenced by ast_sip_session_create_outgoing(), and handle_new_invite_request().

◆ 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.

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_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
def info(msg)
static void session_datastore_destroy(void *obj)
Structure for a data store object.
Definition: datastore.h:64
#define AST_UUID_STR_LEN
Definition: uuid.h:27
char * ast_uuid_generate_str(char *buf, size_t size)
Generate a UUID string.
Definition: uuid.c:141

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().

◆ 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 2848 of file res_pjsip_session.c.

2849 {
2850  pjmedia_sdp_session *offer;
2852 
2853  if (!(offer = create_local_sdp(session->inv_session, session, NULL))) {
2854  pjsip_inv_terminate(session->inv_session, 500, PJ_FALSE);
2855  SCOPE_EXIT_RTN_VALUE(-1, "Couldn't create offer\n");
2856  }
2857 
2858  pjsip_inv_set_local_sdp(session->inv_session, offer);
2859  pjmedia_sdp_neg_set_prefer_remote_codec_order(session->inv_session->neg, PJ_FALSE);
2860 #ifdef PJMEDIA_SDP_NEG_ANSWER_MULTIPLE_CODECS
2861  if (!session->endpoint->preferred_codec_only) {
2862  pjmedia_sdp_neg_set_answer_multiple_codecs(session->inv_session->neg, PJ_TRUE);
2863  }
2864 #endif
2865 
2866  /*
2867  * We MUST call set_from_header() before pjsip_inv_invite. If we don't, the
2868  * From in the initial INVITE will be wrong but the rest of the messages will be OK.
2869  */
2871 
2872  if (pjsip_inv_invite(session->inv_session, tdata) != PJ_SUCCESS) {
2873  SCOPE_EXIT_RTN_VALUE(-1, "pjsip_inv_invite failed\n");
2874  }
2875 
2877 }
#define SCOPE_EXIT_RTN_VALUE(__return_value,...)
Definition: logger.h:900
#define SCOPE_ENTER(level,...)
Definition: logger.h:881
static struct pjmedia_sdp_session * create_local_sdp(pjsip_inv_session *inv, struct ast_sip_session *session, const pjmedia_sdp_session *offer)
static void set_from_header(struct ast_sip_session *session)
const char * ast_sip_session_get_name(const struct ast_sip_session *session)
Get the channel or endpoint name associated with the session.

References ast_sip_session_get_name(), create_local_sdp(), NULL, SCOPE_ENTER, SCOPE_EXIT_RTN_VALUE, session, and set_from_header().

Referenced by call().

◆ 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 3318 of file res_pjsip_session.c.

3321 {
3322  const char *uri = NULL;
3323  RAII_VAR(struct ast_sip_aor *, found_aor, NULL, ao2_cleanup);
3324  RAII_VAR(struct ast_sip_contact *, found_contact, NULL, ao2_cleanup);
3325  pjsip_timer_setting timer;
3326  pjsip_dialog *dlg;
3327  struct pjsip_inv_session *inv_session;
3329  struct ast_sip_session *ret_session;
3330  SCOPE_ENTER(1, "%s %s Topology: %s\n", ast_sorcery_object_get_id(endpoint), request_user,
3331  ast_str_tmp(256, ast_stream_topology_to_str(req_topology, &STR_TMP)));
3332 
3333  /* If no location has been provided use the AOR list from the endpoint itself */
3334  if (location || !contact) {
3335  location = S_OR(location, endpoint->aors);
3336 
3338  &found_aor, &found_contact);
3339  if (!found_contact || ast_strlen_zero(found_contact->uri)) {
3340  uri = location;
3341  } else {
3342  uri = found_contact->uri;
3343  }
3344  } else {
3345  uri = contact->uri;
3346  }
3347 
3348  /* If we still have no URI to dial fail to create the session */
3349  if (ast_strlen_zero(uri)) {
3350  ast_log(LOG_ERROR, "Endpoint '%s': No URI available. Is endpoint registered?\n",
3352  SCOPE_EXIT_RTN_VALUE(NULL, "No URI\n");
3353  }
3354 
3355  if (!(dlg = ast_sip_create_dialog_uac(endpoint, uri, request_user))) {
3356  SCOPE_EXIT_RTN_VALUE(NULL, "Couldn't create dialog\n");
3357  }
3358 
3359  if (setup_outbound_invite_auth(dlg)) {
3360  pjsip_dlg_terminate(dlg);
3361  SCOPE_EXIT_RTN_VALUE(NULL, "Couldn't setup auth\n");
3362  }
3363 
3364  if (pjsip_inv_create_uac(dlg, NULL, endpoint->extensions.flags, &inv_session) != PJ_SUCCESS) {
3365  pjsip_dlg_terminate(dlg);
3366  SCOPE_EXIT_RTN_VALUE(NULL, "Couldn't create uac\n");
3367  }
3368 #if defined(HAVE_PJSIP_REPLACE_MEDIA_STREAM) || defined(PJMEDIA_SDP_NEG_ALLOW_MEDIA_CHANGE)
3369  inv_session->sdp_neg_flags = PJMEDIA_SDP_NEG_ALLOW_MEDIA_CHANGE;
3370 #endif
3371 
3372  pjsip_timer_setting_default(&timer);
3373  timer.min_se = endpoint->extensions.timer.min_se;
3374  timer.sess_expires = endpoint->extensions.timer.sess_expires;
3375  pjsip_timer_init_session(inv_session, &timer);
3376 
3377  session = ast_sip_session_alloc(endpoint, found_contact ? found_contact : contact,
3378  inv_session, NULL);
3379  if (!session) {
3380  pjsip_inv_terminate(inv_session, 500, PJ_FALSE);
3381  return NULL;
3382  }
3383  session->aor = ao2_bump(found_aor);
3384  session->call_direction = AST_SIP_SESSION_OUTGOING_CALL;
3385 
3387 
3388  if (ast_stream_topology_get_count(req_topology) > 0) {
3389  /* get joint caps between req_topology and endpoint topology */
3390  int i;
3391 
3392  for (i = 0; i < ast_stream_topology_get_count(req_topology); ++i) {
3393  struct ast_stream *req_stream;
3394  struct ast_stream *clone_stream;
3395 
3396  req_stream = ast_stream_topology_get_stream(req_topology, i);
3397 
3398  if (ast_stream_get_state(req_stream) == AST_STREAM_STATE_REMOVED) {
3399  continue;
3400  }
3401 
3402  clone_stream = ast_sip_session_create_joint_call_stream(session, req_stream);
3403  if (!clone_stream || ast_stream_get_format_count(clone_stream) == 0) {
3404  ast_stream_free(clone_stream);
3405  continue;
3406  }
3407 
3408  if (!session->pending_media_state->topology) {
3409  session->pending_media_state->topology = ast_stream_topology_alloc();
3410  if (!session->pending_media_state->topology) {
3411  pjsip_inv_terminate(inv_session, 500, PJ_FALSE);
3412  ao2_ref(session, -1);
3413  SCOPE_EXIT_RTN_VALUE(NULL, "Couldn't create topology\n");
3414  }
3415  }
3416 
3417  if (ast_stream_topology_append_stream(session->pending_media_state->topology, clone_stream) < 0) {
3418  ast_stream_free(clone_stream);
3419  continue;
3420  }
3421  }
3422  }
3423 
3424  if (!session->pending_media_state->topology) {
3425  /* Use the configured topology on the endpoint as the pending one */
3426  session->pending_media_state->topology = ast_stream_topology_clone(endpoint->media.topology);
3427  if (!session->pending_media_state->topology) {
3428  pjsip_inv_terminate(inv_session, 500, PJ_FALSE);
3429  ao2_ref(session, -1);
3430  SCOPE_EXIT_RTN_VALUE(NULL, "Couldn't clone topology\n");
3431  }
3432  }
3433 
3434  if (pjsip_dlg_add_usage(dlg, &session_module, NULL) != PJ_SUCCESS) {
3435  pjsip_inv_terminate(inv_session, 500, PJ_FALSE);
3436  /* Since we are not notifying ourselves that the INVITE session is being terminated
3437  * we need to manually drop its reference to session
3438  */
3439  ao2_ref(session, -1);
3440  SCOPE_EXIT_RTN_VALUE(NULL, "Couldn't add usage\n");
3441  }
3442 
3443  /* Avoid unnecessary ref manipulation to return a session */
3444  ret_session = session;
3445  session = NULL;
3446  SCOPE_EXIT_RTN_VALUE(ret_session);
3447 }
static struct ast_timer * timer
Definition: chan_iax2.c:357
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:1759
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:4065
@ AST_SIP_CONTACT_FILTER_REACHABLE
Return only reachable or unknown contacts.
Definition: res_pjsip.h:1087
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
static int setup_outbound_invite_auth(pjsip_dialog *dlg)
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.
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.
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
@ AST_STREAM_STATE_REMOVED
Set when the stream has been removed/declined.
Definition: stream.h:78
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
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
int ast_stream_topology_get_count(const struct ast_stream_topology *topology)
Get the number of streams in a topology.
Definition: stream.c:765
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
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_stream_topology_get_stream(const struct ast_stream_topology *topology, unsigned int position)
Get a specific stream from the topology.
Definition: stream.c:788
void ast_stream_free(struct ast_stream *stream)
Destroy a media stream representation.
Definition: stream.c:292
struct ast_stream_topology * ast_stream_topology_alloc(void)
Create a stream topology.
Definition: stream.c:650
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
#define ast_str_tmp(init_len, __expr)
Provides a temporary ast_str and returns a copy of its buffer.
Definition: strings.h:1165
A SIP address of record.
Definition: res_pjsip.h:376
Contact associated with an address of record.
Definition: res_pjsip.h:297
struct ast_sip_timer_options timer
Definition: res_pjsip.h:612
struct ast_party_id self
Definition: res_pjsip.h:663
struct ast_stream_topology * topology
Definition: res_pjsip.h:814
struct ast_sip_endpoint_id_configuration id
Definition: res_pjsip.h:891
const ast_string_field aors
Definition: res_pjsip.h:881
struct ast_sip_endpoint_extensions extensions
Definition: res_pjsip.h:883
struct ast_sip_endpoint_media_configuration media
Definition: res_pjsip.h:885
unsigned int sess_expires
Definition: res_pjsip.h:599
unsigned int min_se
Definition: res_pjsip.h:597

References ao2_bump, ao2_cleanup, ao2_ref, 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::endpoint, ast_sip_endpoint::extensions, ast_sip_endpoint_extensions::flags, ast_sip_endpoint::id, ast_sip_session::inv_session, LOG_ERROR, ast_sip_endpoint::media, ast_sip_timer_options::min_se, NULL, RAII_VAR, S_OR, SCOPE_ENTER, SCOPE_EXIT_RTN_VALUE, ast_sip_endpoint_id_configuration::self, ast_sip_timer_options::sess_expires, session, session_module, setup_outbound_invite_auth(), timer, ast_sip_endpoint_extensions::timer, and ast_sip_endpoint_media_configuration::topology.

Referenced by request().

◆ 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 3555 of file res_pjsip_session.c.

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

References ao2_ref, ast_assert, ast_sip_get_pjsip_endpoint(), session, and session_termination_cb().

Referenced by refer_incoming_attended_request(), and refer_incoming_blind_request().

◆ 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 3595 of file res_pjsip_session.c.

3596 {
3597  if (!session->defer_terminate) {
3598  /* Already canceled or timer fired. */
3599  return;
3600  }
3601 
3602  session->defer_terminate = 0;
3603 
3604  if (session->terminate_while_deferred) {
3605  /* Complete the termination started by the upper layer. */
3607  }
3608 
3609  /* Stop the termination timer if it is still running. */
3611 }
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.

References ast_sip_session_terminate(), session, and sip_session_defer_termination_stop_timer().

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

◆ 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 3613 of file res_pjsip_session.c.

3614 {
3615  if (!session->defer_end) {
3616  return;
3617  }
3618 
3619  session->defer_end = 0;
3620 
3621  if (session->ended_while_deferred) {
3622  /* Complete the session end started by the remote hangup. */
3623  ast_debug(3, "%s: Ending session after being deferred\n", ast_sip_session_get_name(session));
3624  session->ended_while_deferred = 0;
3626  }
3627 }
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:451
static int session_end(void *vsession)

References ast_debug, ast_sip_session_get_name(), session, 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().

◆ 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.

1286 {
1287  return ao2_find(session->datastores, name, OBJ_KEY);
1288 }
#define OBJ_KEY
Definition: astobj2.h:1151
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1736
static const char name[]
Definition: format_mp3.c:68

References ao2_find, name, OBJ_KEY, and session.

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

◆ 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.

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 }
const char * ast_channel_name(const struct ast_channel *chan)

References ast_channel_name(), ast_sorcery_object_get_id(), and session.

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(), 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().

◆ 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.

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) {
374  if (ast_stream_get_type(ast_stream_topology_get_stream(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 }
#define LOG_WARNING
Definition: logger.h:275
enum ast_media_type ast_stream_get_type(const struct ast_stream *stream)
Get the media type of a stream.
Definition: stream.c:316

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(), LOG_WARNING, and session.

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

◆ 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.

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 }
Structure which contains read callback information.
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256

References AST_VECTOR_APPEND, ast_sip_session_media_read_callback_state::fd, and session.

Referenced by apply_negotiated_sdp_stream().

◆ 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.

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 }
A structure containing SIP session media information.
int bundle_group
The bundle group the stream belongs to.
char * mid
Media identifier for this stream (may be shared across multiple streams)
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:609
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:680

References ast_strlen_zero(), AST_VECTOR_GET, AST_VECTOR_SIZE, ast_sip_session_media::bundle_group, ast_sip_session_media::mid, and session.

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

◆ 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.

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.

References ast_sip_session_media::write_callback.

Referenced by apply_negotiated_sdp_stream().

◆ 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.

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 }
#define ast_free(a)
Definition: astmm.h:180
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition: astmm.h:267
@ AO2_ALLOC_OPT_LOCK_NOLOCK
Definition: astobj2.h:367
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:404
static const char type[]
Definition: chan_ooh323.c:109
const char * ast_codec_media_type2str(enum ast_media_type type)
Conversion function to take a media type and turn it into a string.
Definition: codec.c:347
#define ast_trace(level,...)
Definition: logger.h:872
static void session_media_dtor(void *obj)
const char * ast_stream_get_name(const struct ast_stream *stream)
Get the name of a stream.
Definition: stream.c:309
struct ast_stream_topology * topology
The media stream topology.
struct ast_sip_session_media_state::@292 sessions
Mapping of stream to media sessions.
struct ast_sip_session_media * default_session[AST_MEDIA_TYPE_END]
Default media sessions for each type.
char * stream_name
Stream name.
unsigned int remote_ice
Does remote support ice.
enum ast_media_type type
Media type of this session media.
unsigned int remote_rtcp_mux
Does remote support rtcp_mux.
int timeout_sched_id
Scheduler ID for RTP timeout.
int stream_num
The stream number to place into any resulting frames.
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.
int keepalive_sched_id
Scheduler ID for RTP keepalive.
#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

References 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_session_media::bundle_group, ast_sip_session_media::bundled, ast_sip_session_media_state::default_session, ast_sip_session_media::encryption, ast_sip_session_media::keepalive_sched_id, ast_sip_session_media::mid, NULL, ast_sip_session_media::remote_ice, ast_sip_session_media::remote_rtcp_mux, SCOPE_ENTER, SCOPE_EXIT_RTN_VALUE, session, session_media_dtor(), ast_sip_session_media_state::sessions, 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, type, and ast_sip_session_media::type.

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

◆ 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.

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)

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().

◆ 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.

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) {
337 
339  }
340 
341  return cloned;
342 }
ast_media_type
Types of media.
Definition: codec.h:30
void ast_sip_session_media_state_free(struct ast_sip_session_media_state *media_state)
Free a session media state structure.
ast_sip_session_media_read_cb read_callback
The callback to invoke.
Structure which contains media state information (streams, sessions)
struct ast_sip_session_media_state::@293 read_callbacks
Added read callbacks - these are whole structs and not pointers.
#define AST_VECTOR_GET_ADDR(vec, idx)
Get an address of element in a vector.
Definition: vector.h:668

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::read_callbacks, ast_sip_session_media_state::sessions, 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().

◆ 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.

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 }
void ast_sip_session_media_state_reset(struct ast_sip_session_media_state *media_state)
Reset a media state to a clean state.
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition: vector.h:174

References ast_free, ast_sip_session_media_state_reset(), AST_VECTOR_FREE, ast_sip_session_media_state::read_callbacks, and ast_sip_session_media_state::sessions.

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

◆ 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.

279 {
280  int index;
281 
282  if (!media_state) {
283  return;
284  }
285 
286  AST_VECTOR_RESET(&media_state->sessions, ao2_cleanup);
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 }
@ AST_MEDIA_TYPE_END
Definition: codec.h:36
void ast_stream_topology_free(struct ast_stream_topology *topology)
Unreference and destroy a stream topology.
Definition: stream.c:743
#define AST_VECTOR_RESET(vec, cleanup)
Reset vector.
Definition: vector.h:625
#define AST_VECTOR_ELEM_CLEANUP_NOOP(elem)
Vector element cleanup that does nothing.
Definition: vector.h:571

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, ast_sip_session_media_state::read_callbacks, ast_sip_session_media_state::sessions, 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().

◆ 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
sip_sessionSession on which to save active media state for
media_stateThe media state to save

Definition at line 244 of file res_pjsip_session.c.

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 */
273 
274  AST_VECTOR_APPEND(&sip_session->media_stats, stats_tmp);
275  }
276 }
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
static int media_stats_local_ssrc_cmp(const struct ast_rtp_instance_stats *vec_elem, const struct ast_rtp_instance_stats *srch)
@ AST_RTP_INSTANCE_STAT_ALL
Definition: rtp_engine.h:182
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:2438
struct ast_rtp_instance * rtp
RTP instance itself.
struct ast_sip_session::@296 media_stats
#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

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, ast_sip_session::media_stats, media_stats_local_ssrc_cmp(), NULL, ast_sip_session_media::rtp, and ast_sip_session_media_state::sessions.

Referenced by ast_sip_session_terminate(), and handle_negotiated_sdp().

◆ 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 2525 of file res_pjsip_session.c.

2531 {
2532  return sip_session_refresh(session, on_request_creation, on_sdp_creation,
2533  on_response, method, generate_new_sdp, media_state, NULL, 0);
2534 }
const char * method
Definition: res_pjsip.c:4372
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)

References method, NULL, session, 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().

◆ 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
Return values
0Successfully updated the SDP answer
-1Failure to updated the SDP answer

Definition at line 2536 of file res_pjsip_session.c.

2538 {
2539  pjsip_inv_session *inv_session = session->inv_session;
2540  pjmedia_sdp_session *new_answer = NULL;
2541  const pjmedia_sdp_session *previous_offer = NULL;
2543 
2544  /* The SDP answer can only be regenerated if it is still pending to be sent */
2545  if (!inv_session->neg || (pjmedia_sdp_neg_get_state(inv_session->neg) != PJMEDIA_SDP_NEG_STATE_REMOTE_OFFER &&
2546  pjmedia_sdp_neg_get_state(inv_session->neg) != PJMEDIA_SDP_NEG_STATE_WAIT_NEGO)) {
2547  ast_log(LOG_WARNING, "Requested to regenerate local SDP answer for channel '%s' but negotiation in state '%s'\n",
2548  ast_channel_name(session->channel), pjmedia_sdp_neg_state_str(pjmedia_sdp_neg_get_state(inv_session->neg)));
2549  SCOPE_EXIT_RTN_VALUE(-1, "Bad negotiation state\n");
2550  }
2551 
2552  pjmedia_sdp_neg_get_neg_remote(inv_session->neg, &previous_offer);
2553  if (pjmedia_sdp_neg_get_state(inv_session->neg) == PJMEDIA_SDP_NEG_STATE_WAIT_NEGO) {
2554  /* Transition the SDP negotiator back to when it received the remote offer */
2555  pjmedia_sdp_neg_negotiate(inv_session->pool, inv_session->neg, 0);
2556  pjmedia_sdp_neg_set_remote_offer(inv_session->pool, inv_session->neg, previous_offer);
2557  }
2558 
2559  new_answer = create_local_sdp(inv_session, session, previous_offer);
2560  if (!new_answer) {
2561  ast_log(LOG_WARNING, "Could not create a new local SDP answer for channel '%s'\n",
2562  ast_channel_name(session->channel));
2563  SCOPE_EXIT_RTN_VALUE(-1, "Couldn't create new SDP\n");
2564  }
2565 
2566  if (on_sdp_creation) {
2567  if (on_sdp_creation(session, new_answer)) {
2568  SCOPE_EXIT_RTN_VALUE(-1, "Callback failed\n");
2569  }
2570  }
2571 
2572  pjsip_inv_set_sdp_answer(inv_session, new_answer);
2573 
2575 }

References ast_channel_name(), ast_log, ast_sip_session_get_name(), create_local_sdp(), LOG_WARNING, NULL, SCOPE_ENTER, SCOPE_EXIT_RTN_VALUE, and session.

Referenced by dtmf_mode_refresh_cb().

◆ 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.

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 AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
#define SCOPED_AO2LOCK(varname, obj)
scoped lock specialization for ao2 mutexes.
Definition: lock.h:602
static struct ao2_container * sdp_handlers
Registered SDP stream handlers.
A handler for SDPs in SIP sessions.
struct ast_sip_session_sdp_handler * next
static void handler(const char *name, int response_code, struct ast_variable *get_params, struct ast_variable *path_vars, struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
Definition: test_ari.c:59

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, handler(), ast_sip_session_sdp_handler::id, lock, LOG_WARNING, ast_sip_session_sdp_handler::next, NULL, OBJ_KEY, RAII_VAR, SCOPED_AO2LOCK, sdp_handlers, and sdp_handler_list::stream_type.

◆ 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.

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_TRAVERSE_SAFE_BEGIN
Definition: linkedlists.h:545
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:52
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:617
#define AST_RWLIST_INSERT_TAIL
Definition: linkedlists.h:741
#define AST_RWLIST_INSERT_BEFORE_CURRENT
Definition: linkedlists.h:610
enum ast_sip_session_response_priority response_priority
struct ast_module * module
enum ast_sip_supplement_priority priority

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.

◆ 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.

1291 {
1292  ao2_callback(session->datastores, OBJ_KEY | OBJ_UNLINK | OBJ_NODATA, NULL, (void *) name);
1293 }
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container,...
Definition: astobj2.h:1693
@ OBJ_NODATA
Definition: astobj2.h:1044
@ OBJ_UNLINK
Definition: astobj2.h:1039

References ao2_callback, name, NULL, OBJ_KEY, OBJ_NODATA, OBJ_UNLINK, and session.

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

◆ 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.

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 module reference. */
123  ast_module_unref(iter->module);
124  }
125 
126  ast_free(iter);
127  }
128 
129  return;
130 }
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833
#define ast_module_unref(mod)
Release a reference to the module.
Definition: module.h:469

References ast_free, AST_LIST_REMOVE_HEAD, ast_module_unref, ast_sip_session_supplement::module, ast_sip_session_supplement::next, and session.

Referenced by session_destructor().

◆ 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 2799 of file res_pjsip_session.c.

2800 {
2801  if (!session->deferred_reinvite) {
2802  return;
2803  }
2804 
2805  if (session->channel) {
2806  pjsip_endpt_process_rx_data(ast_sip_get_pjsip_endpoint(),
2807  session->deferred_reinvite, NULL, NULL);
2808  }
2809  pjsip_rx_data_free_cloned(session->deferred_reinvite);
2810  session->deferred_reinvite = NULL;
2811 }

References ast_sip_get_pjsip_endpoint(), NULL, and session.

Referenced by t38_automatic_reject(), and t38_interpret_parameters().

◆ 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 2843 of file res_pjsip_session.c.

2844 {
2846 }
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.

References ast_sip_session_send_request_with_cb(), NULL, and session.

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().

◆ 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 2819 of file res_pjsip_session.c.

2821 {
2822  pjsip_inv_session *inv_session = session->inv_session;
2823 
2824  /* For every request except BYE we disallow sending of the message when
2825  * the session has been disconnected. A BYE request is special though
2826  * because it can be sent again after the session is disconnected except
2827  * with credentials.
2828  */
2829  if (inv_session->state == PJSIP_INV_STATE_DISCONNECTED &&
2830  tdata->msg->line.req.method.id != PJSIP_BYE_METHOD) {
2831  return;
2832  }
2833 
2834  ast_sip_mod_data_set(tdata->pool, tdata->mod_data, session_module.id,
2835  MOD_DATA_ON_RESPONSE, on_response);
2836 
2838  pjsip_inv_send_msg(session->inv_session, tdata);
2839 
2840  return;
2841 }
#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:2750
#define MOD_DATA_ON_RESPONSE
static void handle_outgoing_request(struct ast_sip_session *session, pjsip_tx_data *tdata)

References ast_sip_mod_data_set, handle_outgoing_request(), MOD_DATA_ON_RESPONSE, session, and session_module.

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

◆ 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 2577 of file res_pjsip_session.c.

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

References handle_outgoing_response(), and session.

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().

◆ 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.

Definition at line 3156 of file res_pjsip_session.c.

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

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, session, sip_session_suspend_task(), sip_session_suspender_dtor(), and ast_sip_session_suspender::suspended.

Referenced by chan_pjsip_indicate().

◆ 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 3452 of file res_pjsip_session.c.

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

References 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(), delay_request(), DELAYED_METHOD_BYE, delayed_request_free(), ast_sip_session_delayed_request::next, NULL, SCOPE_ENTER, SCOPE_EXIT_RTN, session, session_end(), session_end_completion(), session_module, status, and SWAP.

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

◆ 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.

200 {
202 }
#define ao2_callback_data(container, flags, cb_fn, arg, data)
Definition: astobj2.h:1723
static int remove_handler(void *obj, void *arg, void *data, int flags)

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

Referenced by unload_module().

◆ 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.

64 {
65  struct ast_sip_session_supplement *iter;
67 
69  if (supplement == iter) {
71  break;
72  }
73  }
75 }
#define AST_RWLIST_REMOVE_CURRENT
Definition: linkedlists.h:570

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().

◆ 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.

Definition at line 3201 of file res_pjsip_session.c.

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

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, and session.

Referenced by chan_pjsip_indicate().