Asterisk - The Open Source Telephony Project GIT-master-57e2743
Loading...
Searching...
No Matches
Data Structures | Macros | Functions | Variables
chan_pjsip.c File Reference

PSJIP SIP Channel Driver. More...

#include "asterisk.h"
#include <pjsip.h>
#include <pjsip_ua.h>
#include <pjlib.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/rtp_engine.h"
#include "asterisk/acl.h"
#include "asterisk/callerid.h"
#include "asterisk/file.h"
#include "asterisk/cli.h"
#include "asterisk/app.h"
#include "asterisk/musiconhold.h"
#include "asterisk/causes.h"
#include "asterisk/taskprocessor.h"
#include "asterisk/dsp.h"
#include "asterisk/stasis_endpoints.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/indications.h"
#include "asterisk/format_cache.h"
#include "asterisk/translate.h"
#include "asterisk/threadstorage.h"
#include "asterisk/features_config.h"
#include "asterisk/pickup.h"
#include "asterisk/test.h"
#include "asterisk/message.h"
#include "asterisk/res_pjsip.h"
#include "asterisk/res_pjsip_session.h"
#include "asterisk/stream.h"
#include "pjsip/include/chan_pjsip.h"
#include "pjsip/include/channel_info.h"
#include "pjsip/include/dialplan_functions.h"
#include "pjsip/include/cli_functions.h"
Include dependency graph for chan_pjsip.c:

Go to the source code of this file.

Data Structures

struct  answer_data
 
struct  hangup_data
 
struct  indicate_data
 
struct  info_dtmf_data
 
struct  request_data
 
struct  rtp_direct_media_data
 
struct  sendtext_data
 
struct  topology_change_refresh_data
 
struct  transfer_data
 

Macros

#define UNIQUEID_BUFSIZE   256
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
static int answer (void *data)
 
struct ast_module * AST_MODULE_SELF_SYM (void)
 
 AST_THREADSTORAGE_CUSTOM_SCOPE (uniqueid_threadbuf, NULL, ast_free_ptr, static)
 
static int call (void *data)
 
static int call_pickup_incoming_request (struct ast_sip_session *session, pjsip_rx_data *rdata)
 
static int chan_pjsip_add_hold (const char *chan_uid)
 Add a channel ID to the list of PJSIP channels on hold.
 
static int chan_pjsip_answer (struct ast_channel *ast)
 Function called by core when we should answer a PJSIP session.
 
static int chan_pjsip_call (struct ast_channel *ast, const char *dest, int timeout)
 Function called by core to actually start calling a remote party.
 
static struct ast_frame * chan_pjsip_cng_tone_detected (struct ast_channel *ast, struct ast_sip_session *session, struct ast_frame *f)
 Internal helper function called when CNG tone is detected.
 
static int chan_pjsip_devicestate (const char *data)
 Function called to get the device state of an endpoint.
 
static int chan_pjsip_digit_begin (struct ast_channel *chan, char digit)
 Function called by core to start a DTMF digit.
 
static int chan_pjsip_digit_end (struct ast_channel *ast, char digit, unsigned int duration)
 Function called by core to stop a DTMF digit.
 
static int chan_pjsip_fixup (struct ast_channel *oldchan, struct ast_channel *newchan)
 Function called by core to change the underlying owner channel.
 
static void chan_pjsip_get_codec (struct ast_channel *chan, struct ast_format_cap *result)
 Function called by RTP engine to get peer capabilities.
 
static int chan_pjsip_get_hold (const char *chan_uid)
 Determine whether a channel ID is in the list of PJSIP channels on hold.
 
static enum ast_rtp_glue_result chan_pjsip_get_rtp_peer (struct ast_channel *chan, struct ast_rtp_instance **instance)
 Function called by RTP engine to get local audio RTP peer.
 
static const char * chan_pjsip_get_uniqueid (struct ast_channel *ast)
 
static enum ast_rtp_glue_result chan_pjsip_get_vrtp_peer (struct ast_channel *chan, struct ast_rtp_instance **instance)
 Function called by RTP engine to get local video RTP peer.
 
static int chan_pjsip_hangup (struct ast_channel *ast)
 Function called by core to hang up a PJSIP session.
 
static int chan_pjsip_incoming_ack (struct ast_sip_session *session, struct pjsip_rx_data *rdata)
 
static int chan_pjsip_incoming_prack (struct ast_sip_session *session, struct pjsip_rx_data *rdata)
 
static int chan_pjsip_incoming_request (struct ast_sip_session *session, struct pjsip_rx_data *rdata)
 Function called when a request is received on the session.
 
static void chan_pjsip_incoming_response (struct ast_sip_session *session, struct pjsip_rx_data *rdata)
 Function called when a response is received on the session.
 
static void chan_pjsip_incoming_response_update_cause (struct ast_sip_session *session, struct pjsip_rx_data *rdata)
 Function called when a response is received on the session.
 
static int chan_pjsip_indicate (struct ast_channel *ast, int condition, const void *data, size_t datalen)
 Function called by core to ask the channel to indicate some sort of condition.
 
static struct ast_channel * chan_pjsip_new (struct ast_sip_session *session, int state, const char *exten, const char *title, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *cid_name)
 Function called to create a new PJSIP Asterisk channel.
 
static void chan_pjsip_pvt_dtor (void *obj)
 
static int chan_pjsip_queryoption (struct ast_channel *ast, int option, void *data, int *datalen)
 Function called to query options on a channel.
 
static struct ast_frame * chan_pjsip_read_stream (struct ast_channel *ast)
 Function called by core to read any waiting frames.
 
static void chan_pjsip_remove_hold (const char *chan_uid)
 Remove a channel ID from the list of PJSIP channels on hold.
 
static struct ast_channel * chan_pjsip_request (const char *type, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *data, int *cause)
 Asterisk core interaction functions.
 
static struct ast_channel * chan_pjsip_request_with_stream_topology (const char *type, struct ast_stream_topology *topology, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *data, int *cause)
 Function called by core to create a new outgoing PJSIP session.
 
static int chan_pjsip_sendtext (struct ast_channel *ast, const char *text)
 
static int chan_pjsip_sendtext_data (struct ast_channel *ast, struct ast_msg_data *msg)
 Function called by core to send text on PJSIP session.
 
static void chan_pjsip_session_begin (struct ast_sip_session *session)
 SIP session interaction functions.
 
static void chan_pjsip_session_end (struct ast_sip_session *session)
 Function called when the session ends.
 
static int chan_pjsip_set_rtp_peer (struct ast_channel *chan, struct ast_rtp_instance *rtp, struct ast_rtp_instance *vrtp, struct ast_rtp_instance *tpeer, const struct ast_format_cap *cap, int nat_active)
 Function called by RTP engine to change where the remote party should send media.
 
static int chan_pjsip_transfer (struct ast_channel *chan, const char *target)
 Function called by core for Asterisk initiated transfer.
 
static int chan_pjsip_write (struct ast_channel *ast, struct ast_frame *f)
 
static int chan_pjsip_write_stream (struct ast_channel *ast, int stream_num, struct ast_frame *f)
 
static int check_for_rtp_changes (struct ast_channel *chan, struct ast_rtp_instance *rtp, struct ast_sip_session_media *media, struct ast_sip_session *session)
 
static void clear_session_and_channel (struct ast_sip_session *session, struct ast_channel *ast)
 Clear a channel from a session along with its PVT.
 
static void clear_session_and_channel_locked (struct ast_sip_session *session, struct ast_channel *ast)
 Clear a channel from a session along with its PVT (channel lock held)
 
static int compatible_formats_exist (struct ast_stream_topology *top, struct ast_format_cap *cap)
 Determine if a topology is compatible with format capabilities.
 
static int direct_media_mitigate_glare (struct ast_sip_session *session)
 
static int handle_topology_request_change (struct ast_sip_session *session, const struct ast_stream_topology *proposed)
 
static int hangup (void *data)
 
static int hangup_cause2sip (int cause)
 Internal function which translates from Asterisk cause codes to SIP response codes.
 
static struct hangup_data * hangup_data_alloc (int cause, struct ast_channel *chan)
 
static void hangup_data_destroy (void *obj)
 
static int indicate (void *data)
 
static struct indicate_data * indicate_data_alloc (struct ast_sip_session *session, int condition, int response_code, const void *frame_data, size_t datalen)
 
static void indicate_data_destroy (void *obj)
 
static struct info_dtmf_data * info_dtmf_data_alloc (struct ast_sip_session *session, char digit, unsigned int duration)
 
static void info_dtmf_data_destroy (void *obj)
 
static int is_colp_update_allowed (struct ast_sip_session *session)
 
static int is_compatible_format (struct ast_sip_session *session, struct ast_frame *f)
 Determine if the given frame is in a format we've negotiated.
 
static int load_module (void)
 Load the module.
 
static int on_topology_change_response (struct ast_sip_session *session, pjsip_rx_data *rdata)
 
static int pbx_start_incoming_request (struct ast_sip_session *session, pjsip_rx_data *rdata)
 
static int remote_send_hold (void *data)
 Update local hold state to be held.
 
static int remote_send_hold_refresh (struct ast_sip_session *session, unsigned int held)
 Update local hold state and send a re-INVITE with the new SDP.
 
static int remote_send_unhold (void *data)
 Update local hold state to be unheld.
 
static int request (void *obj)
 
static struct rtp_direct_media_data * rtp_direct_media_data_create (struct ast_channel *chan, struct ast_rtp_instance *rtp, struct ast_rtp_instance *vrtp, const struct ast_format_cap *cap, struct ast_sip_session *session)
 
static void rtp_direct_media_data_destroy (void *data)
 
static int rtp_find_rtcp_fd_position (struct ast_sip_session *session, struct ast_rtp_instance *rtp)
 Helper function to find the position for RTCP.
 
static int send_direct_media_request (void *data)
 
static int send_topology_change_refresh (void *data)
 
static int sendtext (void *obj)
 
static struct sendtext_data * sendtext_data_create (struct ast_channel *chan, struct ast_msg_data *msg)
 
static void sendtext_data_destroy (void *obj)
 
static void set_channel_on_rtp_instance (const struct ast_sip_session *session, const char *channel_id)
 
static void set_sipdomain_variable (struct ast_sip_session *session)
 
static int set_transport_info_local_addr (struct pjsip_tx_data *tdata, pj_sockaddr *local_addr)
 Determine the local signaling address used for an outgoing request.
 
static struct topology_change_refresh_data * topology_change_refresh_data_alloc (struct ast_sip_session *session, const struct ast_stream_topology *topology)
 
static void topology_change_refresh_data_free (struct topology_change_refresh_data *refresh_data)
 
static int transfer (void *data)
 
static struct transfer_data * transfer_data_alloc (struct ast_sip_session *session, const char *target)
 
static void transfer_data_destroy (void *obj)
 
static void transfer_redirect (struct ast_sip_session *session, const char *target)
 
static void transfer_refer (struct ast_sip_session *session, const char *target)
 
static int transmit_info_dtmf (void *data)
 
static int transmit_info_with_vidupdate (void *data)
 Send SIP INFO with video update request.
 
static void transport_info_destroy (void *obj)
 Destructor function for transport_info_data.
 
static pj_status_t transport_info_on_tx_request (pjsip_tx_data *tdata)
 Store transport information for outgoing PJSIP session requests.
 
static int uid_hold_hash_fn (const void *obj, const int flags)
 
static int uid_hold_sort_fn (const void *obj_left, const void *obj_right, const int flags)
 
static int unload_module (void)
 Unload the PJSIP channel from Asterisk.
 
static int update_connected_line_information (void *data)
 Update connected line information.
 
static int update_devstate (void *obj, void *arg, int flags)
 
static void update_initial_connected_line (struct ast_sip_session *session)
 
static void xfer_client_on_evsub_state (pjsip_evsub *sub, pjsip_event *event)
 Callback function to report status of implicit REFER-NOTIFY subscription.
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "PJSIP Channel Driver" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_CHANNEL_DRIVER, .requires = "res_pjsip,res_pjsip_session,res_pjsip_pubsub", }
 
static char * app_pjsip_hangup = "PJSIPHangup"
 
static const struct ast_module_info * ast_module_info = &__mod_info
 
static struct ast_sip_session_supplement call_pickup_supplement
 
static unsigned int chan_idx
 
static struct ast_sip_session_supplement chan_pjsip_ack_supplement
 
static struct ast_custom_function chan_pjsip_dial_contacts_function
 
static pjsip_module chan_pjsip_module
 General PJSIP module for chan_pjsip, currently used for REFER subscription data and outgoing request callbacks.
 
static struct ast_custom_function chan_pjsip_parse_uri_from_function
 
static struct ast_custom_function chan_pjsip_parse_uri_function
 
static struct ast_sip_session_supplement chan_pjsip_prack_supplement
 
static struct ast_rtp_glue chan_pjsip_rtp_glue
 Local glue for interacting with the RTP engine core.
 
static struct ast_sip_session_supplement chan_pjsip_supplement
 SIP session supplement structure.
 
static struct ast_sip_session_supplement chan_pjsip_supplement_response
 SIP session supplement structure just for responses.
 
struct ast_channel_tech chan_pjsip_tech
 PBX interface structure for channel registration.
 
static const char channel_type [] = "PJSIP"
 
static struct ast_datastore_info direct_media_mitigation_info = { }
 
static struct ast_custom_function dtmf_mode_function
 
static struct ast_custom_function media_offer_function
 
static struct ast_custom_function moh_passthrough_function
 
static struct ast_sip_session_supplement pbx_start_supplement
 
static struct ao2_container * pjsip_uids_onhold
 
static struct ast_custom_function session_refresh_function
 
static struct ast_custom_function transfer_handling_function
 
static struct ast_datastore_info transport_info
 Datastore used to store local/remote addresses for the INVITE request that created the PJSIP channel.
 

Detailed Description

PSJIP SIP Channel Driver.

Author
Joshua Colp jcolp.nosp@m.@dig.nosp@m.ium.c.nosp@m.om

Definition in file chan_pjsip.c.

Macro Definition Documentation

◆ UNIQUEID_BUFSIZE

#define UNIQUEID_BUFSIZE   256

Definition at line 77 of file chan_pjsip.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 3717 of file chan_pjsip.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 3717 of file chan_pjsip.c.

◆ answer()

static int answer ( void *  data)
static

Definition at line 793 of file chan_pjsip.c.

794{
795 struct answer_data *ans_data = data;
796 pj_status_t status = PJ_SUCCESS;
797 pjsip_tx_data *packet = NULL;
798 struct ast_sip_session *session = ans_data->session;
800
801 if (session->inv_session->state == PJSIP_INV_STATE_DISCONNECTED) {
802 ast_log(LOG_ERROR, "Session already DISCONNECTED [reason=%d (%s)]\n",
803 session->inv_session->cause,
804 pjsip_get_status_text(session->inv_session->cause)->ptr);
805 SCOPE_EXIT_RTN_VALUE(0, "Disconnected\n");
806 }
807
808 pjsip_dlg_inc_lock(session->inv_session->dlg);
809 if (session->inv_session->invite_tsx) {
810 status = pjsip_inv_answer(session->inv_session, 200, NULL, NULL, &packet);
811 } else {
812 ast_log(LOG_ERROR,"Cannot answer '%s' because there is no associated SIP transaction\n",
813 ast_channel_name(session->channel));
814 }
815 pjsip_dlg_dec_lock(session->inv_session->dlg);
816
817 if (status == PJ_SUCCESS && packet) {
819 }
820
821 if (status != PJ_SUCCESS) {
822 char err[PJ_ERR_MSG_SIZE];
823
824 pj_strerror(status, err, sizeof(err));
825 ast_log(LOG_WARNING,"Cannot answer '%s': %s\n",
826 ast_channel_name(session->channel), err);
827 /*
828 * Return this value so we can distinguish between this
829 * failure and the taskpool synchronous push failing.
830 */
831 SCOPE_EXIT_RTN_VALUE(-2, "pjproject failure\n");
832 }
834}
jack_status_t status
Definition app_jack.c:149
static struct ast_mansession session
#define ast_log
Definition astobj2.c:42
const char * ast_channel_name(const struct ast_channel *chan)
#define SCOPE_EXIT_RTN_VALUE(__return_value,...)
#define SCOPE_ENTER_TASK(level, indent,...)
#define LOG_ERROR
#define LOG_WARNING
const char * ast_sip_session_get_name(const struct ast_sip_session *session)
Get the channel or endpoint name associated with the session.
void ast_sip_session_send_response(struct ast_sip_session *session, pjsip_tx_data *tdata)
Send a SIP response.
#define NULL
Definition resample.c:96
struct ast_sip_session * session
Definition chan_pjsip.c:789
unsigned long indent
Definition chan_pjsip.c:790
A structure describing a SIP session.

References ast_channel_name(), ast_log, ast_sip_session_get_name(), ast_sip_session_send_response(), answer_data::indent, LOG_ERROR, LOG_WARNING, NULL, SCOPE_ENTER_TASK, SCOPE_EXIT_RTN_VALUE, answer_data::session, session, and status.

Referenced by add_bundle_groups(), add_sdp_streams(), ast_dns_resolver_set_result(), ast_raw_answer_with_stream_topology(), ast_search_dns(), ast_stun_request(), ast_unreal_answer(), chan_pjsip_answer(), dns_parse_answer(), dns_parse_answer_ex(), dump_answer(), ebl_callback(), enum_callback(), parse_naptr(), parse_srv(), pbx_builtin_incomplete(), session_inv_on_rx_offer(), srv_callback(), stun_monitor_request(), tds_log(), txt_callback(), verify_mock_cdr_record(), and zapateller_exec().

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 3717 of file chan_pjsip.c.

◆ AST_THREADSTORAGE_CUSTOM_SCOPE()

AST_THREADSTORAGE_CUSTOM_SCOPE ( uniqueid_threadbuf  ,
NULL  ,
ast_free_ptr  ,
static   
)

◆ call()

static int call ( void *  data)
static

Definition at line 2510 of file chan_pjsip.c.

2511{
2512 struct ast_sip_session *session = data;
2513 pjsip_tx_data *tdata;
2514 int res = 0;
2515 SCOPE_ENTER(1, "%s Topology: %s\n",
2517 ast_str_tmp(256, ast_stream_topology_to_str(session->pending_media_state->topology, &STR_TMP))
2518 );
2519
2520
2522
2523 if (res) {
2524 ast_set_hangupsource(session->channel, ast_channel_name(session->channel), 0);
2525 ast_queue_hangup(session->channel);
2526 } else {
2530 }
2531 SCOPE_EXIT_RTN_VALUE(res, "RC: %d\n", res);
2532}
static void update_initial_connected_line(struct ast_sip_session *session)
static void set_channel_on_rtp_instance(const struct ast_sip_session *session, const char *channel_id)
Definition chan_pjsip.c:592
int ast_queue_hangup(struct ast_channel *chan)
Queue a hangup frame.
Definition channel.c:1182
const char * ast_channel_uniqueid(const struct ast_channel *chan)
void ast_set_hangupsource(struct ast_channel *chan, const char *source, int force)
Set the source of the hangup in this channel and it's bridge.
Definition channel.c:2498
#define SCOPE_ENTER(level,...)
void ast_sip_session_send_request(struct ast_sip_session *session, pjsip_tx_data *tdata)
Send a SIP request.
int ast_sip_session_create_invite(struct ast_sip_session *session, pjsip_tx_data **tdata)
Creates an INVITE request.
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:939
#define ast_str_tmp(init_len, __expr)
Provides a temporary ast_str and returns a copy of its buffer.
Definition strings.h:1189

References ast_channel_name(), ast_channel_uniqueid(), ast_queue_hangup(), ast_set_hangupsource(), ast_sip_session_create_invite(), ast_sip_session_get_name(), ast_sip_session_send_request(), ast_str_tmp, ast_stream_topology_to_str(), SCOPE_ENTER, SCOPE_EXIT_RTN_VALUE, session, set_channel_on_rtp_instance(), and update_initial_connected_line().

Referenced by ast_call(), can_ring_entry(), chan_pjsip_call(), close_rtp_connection(), close_udptl_connection(), configure_local_rtp(), find_call(), native_start(), onAlerting(), onCallCleared(), onCallEstablished(), onModeChanged(), onNewCallCreated(), onOutgoingCall(), onProgress(), ooh323_onReceivedDigit(), ooh323_onReceivedSetup(), ooh323_set_read_format(), ooh323_set_write_format(), ooh323c_set_capability_for_call(), ooh323c_start_call_thread(), ooh323c_start_receive_channel(), ooh323c_start_transmit_channel(), ooh323c_start_transmit_datachannel(), ooh323c_stop_call_thread(), ooh323c_stop_transmit_channel(), ooh323c_stop_transmit_datachannel(), setup_rtp_connection(), setup_rtp_remote(), setup_udptl_connection(), and update_our_aliases().

◆ call_pickup_incoming_request()

static int call_pickup_incoming_request ( struct ast_sip_session *  session,
pjsip_rx_data *  rdata 
)
static

Definition at line 3278 of file chan_pjsip.c.

3279{
3280 struct ast_features_pickup_config *pickup_cfg;
3281 struct ast_channel *chan;
3282
3283 /* Check for a to-tag to determine if this is a reinvite */
3284 if (rdata->msg_info.to->tag.slen) {
3285 /* We don't care about reinvites */
3286 return 0;
3287 }
3288
3289 pickup_cfg = ast_get_chan_features_pickup_config(session->channel);
3290 if (!pickup_cfg) {
3291 ast_log(LOG_ERROR, "Unable to retrieve pickup configuration options. Unable to detect call pickup extension.\n");
3292 return 0;
3293 }
3294
3295 if (strcmp(session->exten, pickup_cfg->pickupexten)) {
3296 ao2_ref(pickup_cfg, -1);
3297 return 0;
3298 }
3299 ao2_ref(pickup_cfg, -1);
3300
3301 /* We can't directly use session->channel because the pickup operation will cause a masquerade to occur,
3302 * changing the channel pointer in session to a different channel. To ensure we work on the right channel
3303 * we store a pointer locally before we begin and keep a reference so it remains valid no matter what.
3304 */
3305 chan = ast_channel_ref(session->channel);
3306 if (ast_pickup_call(chan)) {
3308 } else {
3310 }
3311 /* A hangup always occurs because the pickup operation will have either failed resulting in the call
3312 * needing to be hung up OR the pickup operation was a success and the channel we now have is actually
3313 * the channel that was replaced, which should be hung up since it is literally in limbo not connected
3314 * to anything at all.
3315 */
3316 ast_hangup(chan);
3317 ast_channel_unref(chan);
3318
3319 return 1;
3320}
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition astobj2.h:459
#define AST_CAUSE_CALL_REJECTED
Definition causes.h:111
#define AST_CAUSE_NORMAL_CLEARING
Definition causes.h:106
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition channel.c:2540
#define ast_channel_ref(c)
Increase channel reference count.
Definition channel.h:3008
#define ast_channel_unref(c)
Decrease channel reference count.
Definition channel.h:3019
void ast_channel_hangupcause_set(struct ast_channel *chan, int value)
struct ast_features_pickup_config * ast_get_chan_features_pickup_config(struct ast_channel *chan)
Get the pickup configuration options for a channel.
int ast_pickup_call(struct ast_channel *chan)
Pickup a call.
Definition pickup.c:202
Main Channel structure associated with a channel.
Configuration relating to call pickup.

References ao2_ref, AST_CAUSE_CALL_REJECTED, AST_CAUSE_NORMAL_CLEARING, ast_channel_hangupcause_set(), ast_channel_ref, ast_channel_unref, ast_get_chan_features_pickup_config(), ast_hangup(), ast_log, ast_pickup_call(), LOG_ERROR, ast_features_pickup_config::pickupexten, and session.

◆ chan_pjsip_add_hold()

static int chan_pjsip_add_hold ( const char *  chan_uid)
static

Add a channel ID to the list of PJSIP channels on hold.

Parameters
chan_uid- Unique ID of the channel being put into the hold list
Return values
0Channel has been added to or was already in the hold list
-1Failed to add channel to the hold list

Definition at line 1228 of file chan_pjsip.c.

1229{
1230 RAII_VAR(char *, hold_uid, NULL, ao2_cleanup);
1231
1232 hold_uid = ao2_find(pjsip_uids_onhold, chan_uid, OBJ_SEARCH_KEY);
1233 if (hold_uid) {
1234 /* Device is already on hold. Nothing to do. */
1235 return 0;
1236 }
1237
1238 /* Device wasn't in hold list already. Create a new one. */
1239 hold_uid = ao2_alloc_options(strlen(chan_uid) + 1, NULL,
1241 if (!hold_uid) {
1242 return -1;
1243 }
1244
1245 ast_copy_string(hold_uid, chan_uid, strlen(chan_uid) + 1);
1246
1247 if (ao2_link(pjsip_uids_onhold, hold_uid) == 0) {
1248 return -1;
1249 }
1250
1251 return 0;
1252}
#define ao2_link(container, obj)
Add an object to a container.
Definition astobj2.h:1532
@ AO2_ALLOC_OPT_LOCK_NOLOCK
Definition astobj2.h:367
#define ao2_cleanup(obj)
Definition astobj2.h:1934
#define ao2_find(container, arg, flags)
Definition astobj2.h:1736
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition astobj2.h:404
@ OBJ_SEARCH_KEY
The arg parameter is a search key, but is not an object.
Definition astobj2.h:1101
static struct ao2_container * pjsip_uids_onhold
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition strings.h:425
#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:981

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_alloc_options, ao2_cleanup, ao2_find, ao2_link, ast_copy_string(), NULL, OBJ_SEARCH_KEY, pjsip_uids_onhold, and RAII_VAR.

Referenced by chan_pjsip_indicate().

◆ chan_pjsip_answer()

static int chan_pjsip_answer ( struct ast_channel *  ast)
static

Function called by core when we should answer a PJSIP session.

Definition at line 837 of file chan_pjsip.c.

838{
839 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(ast);
840 struct ast_sip_session *session;
841 struct answer_data ans_data = { 0, };
842 int res;
843 SCOPE_ENTER(1, "%s\n", ast_channel_name(ast));
844
845 if (ast_channel_state(ast) == AST_STATE_UP) {
846 SCOPE_EXIT_RTN_VALUE(0, "Already up\n");
847 return 0;
848 }
849
851 session = ao2_bump(channel->session);
852
853 /* the answer task needs to be pushed synchronously otherwise a race condition
854 can occur between this thread and bridging (specifically when native bridging
855 attempts to do direct media) */
857 ans_data.session = session;
858 ans_data.indent = ast_trace_get_indent();
859 res = ast_sip_push_task_wait_serializer(session->serializer, answer, &ans_data);
860 if (res) {
861 if (res == -1) {
862 ast_log(LOG_ERROR,"Cannot answer '%s': Unable to push answer task to the taskpool.\n",
863 ast_channel_name(session->channel));
864 }
865 ao2_ref(session, -1);
866 ast_channel_lock(ast);
867 SCOPE_EXIT_RTN_VALUE(-1, "Couldn't push task\n");
868 }
869 ao2_ref(session, -1);
870 ast_channel_lock(ast);
871
873}
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition astobj2.h:480
static int answer(void *data)
Definition chan_pjsip.c:793
void * ast_channel_tech_pvt(const struct ast_channel *chan)
#define ast_channel_lock(chan)
Definition channel.h:2983
#define ast_channel_unlock(chan)
Definition channel.h:2984
ast_channel_state
ast_channel states
@ AST_STATE_UP
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
Definition channel.c:7422
#define ast_trace_get_indent()
#define ast_sip_push_task_wait_serializer(serializer, sip_task, task_data)
Definition res_pjsip.h:2221
A structure which contains a channel implementation and session.
struct ast_sip_session * session
Pointer to session.

References answer(), ao2_bump, ao2_ref, ast_channel_lock, ast_channel_name(), ast_channel_tech_pvt(), ast_channel_unlock, ast_log, ast_setstate(), ast_sip_push_task_wait_serializer, AST_STATE_UP, ast_trace_get_indent, answer_data::indent, LOG_ERROR, SCOPE_ENTER, SCOPE_EXIT_RTN_VALUE, answer_data::session, ast_sip_channel_pvt::session, and session.

◆ chan_pjsip_call()

static int chan_pjsip_call ( struct ast_channel *  ast,
const char *  dest,
int  timeout 
)
static

Function called by core to actually start calling a remote party.

Definition at line 2535 of file chan_pjsip.c.

2536{
2537 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(ast);
2538 struct ast_sip_session *session = ao2_bump(channel->session);
2539
2540 SCOPE_ENTER(1, "%s Topology: %s\n", ast_sip_session_get_name(session),
2541 ast_str_tmp(256, ast_stream_topology_to_str(session->pending_media_state->topology, &STR_TMP)));
2542
2543 ast_channel_unlock(ast);
2544
2545 /* The creation of the INVITE needs to be pushed synchronously to prevent a race condition
2546 with bridging on attended transfers that can result in a loss of set Caller ID. */
2548 ast_log(LOG_WARNING, "Error attempting to place outbound call to '%s'\n", dest);
2549 ao2_ref(session, -1);
2550 ast_channel_lock(ast);
2551 SCOPE_EXIT_RTN_VALUE(-1, "Couldn't push task\n");
2552 }
2553
2554 ao2_ref(session, -1);
2555 ast_channel_lock(ast);
2556 SCOPE_EXIT_RTN_VALUE(0, "'call' task pushed\n");
2557}
static int call(void *data)
struct ast_channel * channel

References ao2_bump, ao2_ref, ast_channel_lock, ast_channel_tech_pvt(), ast_channel_unlock, ast_log, ast_sip_push_task_wait_serializer, ast_sip_session_get_name(), ast_str_tmp, ast_stream_topology_to_str(), call(), ast_sip_session::channel, LOG_WARNING, SCOPE_ENTER, SCOPE_EXIT_RTN_VALUE, and session.

◆ chan_pjsip_cng_tone_detected()

static struct ast_frame * chan_pjsip_cng_tone_detected ( struct ast_channel *  ast,
struct ast_sip_session *  session,
struct ast_frame *  f 
)
static

Internal helper function called when CNG tone is detected.

Definition at line 876 of file chan_pjsip.c.

878{
879 const char *target_context;
880 int exists;
881 int dsp_features;
882
883 dsp_features = ast_dsp_get_features(session->dsp);
884 dsp_features &= ~DSP_FEATURE_FAX_DETECT;
885 if (dsp_features) {
886 ast_dsp_set_features(session->dsp, dsp_features);
887 } else {
888 ast_dsp_free(session->dsp);
889 session->dsp = NULL;
890 }
891
892 /* If already executing in the fax extension don't do anything */
893 if (!strcmp(ast_channel_exten(ast), "fax")) {
894 return f;
895 }
896
897 target_context = ast_channel_context(ast);
898
899 /*
900 * We need to unlock the channel here because ast_exists_extension has the
901 * potential to start and stop an autoservice on the channel. Such action
902 * is prone to deadlock if the channel is locked.
903 *
904 * ast_async_goto() has its own restriction on not holding the channel lock.
905 */
907 ast_frfree(f);
908 f = &ast_null_frame;
909 exists = ast_exists_extension(ast, target_context, "fax", 1,
910 S_COR(ast_channel_caller(ast)->id.number.valid,
911 ast_channel_caller(ast)->id.number.str, NULL));
912 if (exists) {
913 ast_verb(2, "Redirecting '%s' to fax extension due to CNG detection\n",
914 ast_channel_name(ast));
915 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast_channel_exten(ast));
916 if (ast_async_goto(ast, target_context, "fax", 1)) {
917 ast_log(LOG_ERROR, "Failed to async goto '%s' into fax extension in '%s'\n",
918 ast_channel_name(ast), target_context);
919 }
920 } else {
921 ast_log(LOG_NOTICE, "FAX CNG detected on '%s' but no fax extension in '%s'\n",
922 ast_channel_name(ast), target_context);
923 }
924
925 /* It's possible for a masquerade to have occurred when doing the ast_async_goto resulting in
926 * the channel on the session having changed. Since we need to return with the original channel
927 * locked we lock the channel that was passed in and not session->channel.
928 */
929 ast_channel_lock(ast);
930
931 return f;
932}
const char * ast_channel_context(const struct ast_channel *chan)
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
const char * ast_channel_exten(const struct ast_channel *chan)
void ast_dsp_free(struct ast_dsp *dsp)
Definition dsp.c:1968
int ast_dsp_get_features(struct ast_dsp *dsp)
Get features.
Definition dsp.c:1962
void ast_dsp_set_features(struct ast_dsp *dsp, int features)
Select feature set.
Definition dsp.c:1953
static int exists(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition func_logic.c:185
#define ast_frfree(fr)
struct ast_frame ast_null_frame
Definition main/frame.c:79
#define ast_verb(level,...)
#define LOG_NOTICE
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
Definition pbx.c:2735
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name.
int ast_async_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
Set the channel to next execute the specified dialplan location.
Definition pbx.c:5251
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition strings.h:87
Number structure.

References ast_async_goto(), ast_channel_caller(), ast_channel_context(), ast_channel_exten(), ast_channel_lock, ast_channel_name(), ast_channel_unlock, ast_dsp_free(), ast_dsp_get_features(), ast_dsp_set_features(), ast_exists_extension(), ast_frfree, ast_log, ast_null_frame, ast_verb, exists(), LOG_ERROR, LOG_NOTICE, NULL, pbx_builtin_setvar_helper(), S_COR, and session.

Referenced by chan_pjsip_read_stream().

◆ chan_pjsip_devicestate()

static int chan_pjsip_devicestate ( const char *  data)
static

Function called to get the device state of an endpoint.

Definition at line 1285 of file chan_pjsip.c.

1286{
1287 RAII_VAR(struct ast_sip_endpoint *, endpoint, ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", data), ao2_cleanup);
1289 RAII_VAR(struct ast_endpoint_snapshot *, endpoint_snapshot, NULL, ao2_cleanup);
1290 struct ast_devstate_aggregate aggregate;
1291 int num, inuse = 0;
1292
1293 if (!endpoint) {
1294 return AST_DEVICE_INVALID;
1295 }
1296
1297 endpoint_snapshot = ast_endpoint_get_snapshot(endpoint->persistent);
1298 if (!endpoint_snapshot) {
1299 return AST_DEVICE_INVALID;
1300 }
1301
1302 if (endpoint_snapshot->state == AST_ENDPOINT_OFFLINE) {
1304 } else if (endpoint_snapshot->state == AST_ENDPOINT_ONLINE) {
1306 }
1307
1308 if (!endpoint_snapshot->num_channels) {
1309 return state;
1310 }
1311
1312 ast_devstate_aggregate_init(&aggregate);
1313
1314 for (num = 0; num < endpoint_snapshot->num_channels; num++) {
1315 struct ast_channel_snapshot *snapshot;
1316
1317 snapshot = ast_channel_snapshot_get_latest(endpoint_snapshot->channel_ids[num]);
1318 if (!snapshot) {
1319 continue;
1320 }
1321
1322 if (chan_pjsip_get_hold(snapshot->base->uniqueid)) {
1324 } else {
1325 ast_devstate_aggregate_add(&aggregate, ast_state_chan2dev(snapshot->state));
1326 }
1327
1328 if (snapshot->state != AST_STATE_DOWN && snapshot->state != AST_STATE_RESERVED) {
1329 inuse++;
1330 }
1331
1332 ao2_ref(snapshot, -1);
1333 }
1334
1335 if (endpoint->devicestate_busy_at && (inuse >= endpoint->devicestate_busy_at)) {
1337 } else if (ast_devstate_aggregate_result(&aggregate) != AST_DEVICE_INVALID) {
1339 }
1340
1341 return state;
1342}
static int chan_pjsip_get_hold(const char *chan_uid)
Determine whether a channel ID is in the list of PJSIP channels on hold.
@ AST_STATE_DOWN
@ AST_STATE_RESERVED
void ast_devstate_aggregate_add(struct ast_devstate_aggregate *agg, enum ast_device_state state)
Add a device state to the aggregate device state.
void ast_devstate_aggregate_init(struct ast_devstate_aggregate *agg)
Initialize aggregate device state.
enum ast_device_state ast_devstate_aggregate_result(struct ast_devstate_aggregate *agg)
Get the aggregate device state result.
enum ast_device_state ast_state_chan2dev(enum ast_channel_state chanstate)
Convert channel state to devicestate.
ast_device_state
Device States.
Definition devicestate.h:52
@ AST_DEVICE_UNKNOWN
Definition devicestate.h:53
@ AST_DEVICE_ONHOLD
Definition devicestate.h:61
@ AST_DEVICE_INVALID
Definition devicestate.h:57
@ AST_DEVICE_BUSY
Definition devicestate.h:56
@ AST_DEVICE_NOT_INUSE
Definition devicestate.h:54
@ AST_DEVICE_UNAVAILABLE
Definition devicestate.h:58
@ AST_ENDPOINT_OFFLINE
Definition endpoints.h:55
@ AST_ENDPOINT_ONLINE
Definition endpoints.h:57
struct ast_endpoint_snapshot * ast_endpoint_get_snapshot(struct ast_endpoint *endpoint)
Gets the latest snapshot of the given endpoint.
struct ast_channel_snapshot * ast_channel_snapshot_get_latest(const char *uniqueid)
Obtain the latest ast_channel_snapshot from the Stasis Message Bus API cache. This is an ao2 object,...
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
void * ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
Retrieve an object using its unique identifier.
Definition sorcery.c:1917
const ast_string_field uniqueid
Structure representing a snapshot of channel state.
struct ast_channel_snapshot_base * base
enum ast_channel_state state
You shouldn't care about the contents of this struct.
enum ast_device_state state
A snapshot of an endpoint's state.
An entity with which Asterisk communicates.
Definition res_pjsip.h:1067

References ao2_cleanup, ao2_ref, ast_channel_snapshot_get_latest(), AST_DEVICE_BUSY, AST_DEVICE_INVALID, AST_DEVICE_NOT_INUSE, AST_DEVICE_ONHOLD, AST_DEVICE_UNAVAILABLE, AST_DEVICE_UNKNOWN, ast_devstate_aggregate_add(), ast_devstate_aggregate_init(), ast_devstate_aggregate_result(), ast_endpoint_get_snapshot(), AST_ENDPOINT_OFFLINE, AST_ENDPOINT_ONLINE, ast_sip_get_sorcery(), ast_sorcery_retrieve_by_id(), ast_state_chan2dev(), AST_STATE_DOWN, AST_STATE_RESERVED, ast_channel_snapshot::base, chan_pjsip_get_hold(), ast_devstate_aggregate::inuse, NULL, RAII_VAR, ast_devstate_aggregate::state, ast_channel_snapshot::state, and ast_channel_snapshot_base::uniqueid.

◆ chan_pjsip_digit_begin()

static int chan_pjsip_digit_begin ( struct ast_channel *  ast,
char  digit 
)
static

Function called by core to start a DTMF digit.

Definition at line 2302 of file chan_pjsip.c.

2303{
2304 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(chan);
2305 struct ast_sip_session_media *media;
2306
2308
2309 switch (channel->session->dtmf) {
2311 if (!media || !media->rtp) {
2312 return 0;
2313 }
2314
2316 break;
2317 case AST_SIP_DTMF_AUTO:
2318 if (!media || !media->rtp) {
2319 return 0;
2320 }
2321
2323 return -1;
2324 }
2325
2327 break;
2329 if (!media || !media->rtp || (ast_rtp_instance_dtmf_mode_get(media->rtp) == AST_RTP_DTMF_MODE_NONE)) {
2330 return 0;
2331 }
2333 break;
2334 case AST_SIP_DTMF_NONE:
2335 break;
2337 return -1;
2338 default:
2339 break;
2340 }
2341
2342 return 0;
2343}
char digit
@ AST_MEDIA_TYPE_AUDIO
Definition codec.h:32
@ AST_SIP_DTMF_NONE
Definition res_pjsip.h:549
@ AST_SIP_DTMF_AUTO_INFO
Definition res_pjsip.h:560
@ AST_SIP_DTMF_AUTO
Definition res_pjsip.h:558
@ AST_SIP_DTMF_INBAND
Definition res_pjsip.h:554
@ AST_SIP_DTMF_RFC_4733
Definition res_pjsip.h:552
enum ast_rtp_dtmf_mode ast_rtp_instance_dtmf_mode_get(struct ast_rtp_instance *instance)
Get the DTMF mode of an RTP instance.
@ AST_RTP_DTMF_MODE_INBAND
Definition rtp_engine.h:157
@ AST_RTP_DTMF_MODE_NONE
Definition rtp_engine.h:153
int ast_rtp_instance_dtmf_begin(struct ast_rtp_instance *instance, char digit)
Begin sending a DTMF digit.
struct ast_sip_session_media * default_session[AST_MEDIA_TYPE_END]
Default media sessions for each type.
A structure containing SIP session media information.
struct ast_rtp_instance * rtp
RTP instance itself.
struct ast_sip_session_media_state * active_media_state
enum ast_sip_dtmf_mode dtmf

References ast_sip_session::active_media_state, ast_channel_tech_pvt(), AST_MEDIA_TYPE_AUDIO, AST_RTP_DTMF_MODE_INBAND, AST_RTP_DTMF_MODE_NONE, ast_rtp_instance_dtmf_begin(), ast_rtp_instance_dtmf_mode_get(), AST_SIP_DTMF_AUTO, AST_SIP_DTMF_AUTO_INFO, AST_SIP_DTMF_INBAND, AST_SIP_DTMF_NONE, AST_SIP_DTMF_RFC_4733, ast_sip_session_media_state::default_session, digit, ast_sip_session::dtmf, ast_sip_session_media::rtp, and ast_sip_channel_pvt::session.

◆ chan_pjsip_digit_end()

static int chan_pjsip_digit_end ( struct ast_channel *  ast,
char  digit,
unsigned int  duration 
)
static

Function called by core to stop a DTMF digit.

Definition at line 2414 of file chan_pjsip.c.

2415{
2416 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(ast);
2417 struct ast_sip_session_media *media;
2418
2419 if (!channel || !channel->session) {
2420 /* This happens when the channel is hungup while a DTMF digit is playing. See ASTERISK-28086 */
2421 ast_debug(3, "Channel %s disappeared while calling digit_end\n", ast_channel_name(ast));
2422 return -1;
2423 }
2424
2426
2427 switch (channel->session->dtmf) {
2429 {
2430 if (!media || !media->rtp) {
2431 return 0;
2432 }
2433
2435 ast_debug(3, "Told to send end of digit on Auto-Info channel %s RFC4733 negotiated so using it.\n", ast_channel_name(ast));
2437 break;
2438 }
2439 /* If RFC_4733 was not negotiated, fail through to the DTMF_INFO processing */
2440 ast_debug(3, "Told to send end of digit on Auto-Info channel %s RFC4733 NOT negotiated using INFO instead.\n", ast_channel_name(ast));
2441 }
2442
2443 case AST_SIP_DTMF_INFO:
2444 {
2445 struct info_dtmf_data *dtmf_data = info_dtmf_data_alloc(channel->session, digit, duration);
2446
2447 if (!dtmf_data) {
2448 return -1;
2449 }
2450
2451 if (ast_sip_push_task(channel->session->serializer, transmit_info_dtmf, dtmf_data)) {
2452 ast_log(LOG_WARNING, "Error sending DTMF via INFO.\n");
2453 ao2_cleanup(dtmf_data);
2454 return -1;
2455 }
2456 break;
2457 }
2459 if (!media || !media->rtp) {
2460 return 0;
2461 }
2462
2464 break;
2465 case AST_SIP_DTMF_AUTO:
2466 if (!media || !media->rtp) {
2467 return 0;
2468 }
2469
2471 return -1;
2472 }
2473
2475 break;
2476 case AST_SIP_DTMF_NONE:
2477 break;
2479 return -1;
2480 }
2481
2482 return 0;
2483}
static int transmit_info_dtmf(void *data)
static struct info_dtmf_data * info_dtmf_data_alloc(struct ast_sip_session *session, char digit, unsigned int duration)
#define ast_sip_push_task(serializer, sip_task, task_data)
Definition res_pjsip.h:2126
#define ast_debug(level,...)
Log a DEBUG message.
@ AST_SIP_DTMF_INFO
Definition res_pjsip.h:556
int ast_rtp_instance_dtmf_end_with_duration(struct ast_rtp_instance *instance, char digit, unsigned int duration)
struct ast_taskprocessor * serializer
unsigned int duration

References ast_sip_session::active_media_state, ao2_cleanup, ast_channel_name(), ast_channel_tech_pvt(), ast_debug, ast_log, AST_MEDIA_TYPE_AUDIO, AST_RTP_DTMF_MODE_INBAND, AST_RTP_DTMF_MODE_NONE, ast_rtp_instance_dtmf_end_with_duration(), ast_rtp_instance_dtmf_mode_get(), AST_SIP_DTMF_AUTO, AST_SIP_DTMF_AUTO_INFO, AST_SIP_DTMF_INBAND, AST_SIP_DTMF_INFO, AST_SIP_DTMF_NONE, AST_SIP_DTMF_RFC_4733, ast_sip_push_task, ast_sip_session_media_state::default_session, digit, ast_sip_session::dtmf, info_dtmf_data::duration, info_dtmf_data_alloc(), LOG_WARNING, ast_sip_session_media::rtp, ast_sip_session::serializer, ast_sip_channel_pvt::session, and transmit_info_dtmf().

◆ chan_pjsip_fixup()

static int chan_pjsip_fixup ( struct ast_channel *  oldchan,
struct ast_channel *  newchan 
)
static

Function called by core to change the underlying owner channel.

Definition at line 1156 of file chan_pjsip.c.

1157{
1158 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(newchan);
1159
1160 if (channel->session->channel != oldchan) {
1161 return -1;
1162 }
1163
1164 /*
1165 * The masquerade has suspended the channel's session
1166 * serializer so we can safely change it outside of
1167 * the serializer thread.
1168 */
1169 channel->session->channel = newchan;
1170
1172
1173 return 0;
1174}

References ast_channel_tech_pvt(), ast_channel_uniqueid(), ast_sip_session::channel, ast_sip_channel_pvt::session, and set_channel_on_rtp_instance().

◆ chan_pjsip_get_codec()

static void chan_pjsip_get_codec ( struct ast_channel *  chan,
struct ast_format_cap *  result 
)
static

Function called by RTP engine to get peer capabilities.

Definition at line 253 of file chan_pjsip.c.

254{
255 SCOPE_ENTER(1, "%s Native formats %s\n", ast_channel_name(chan),
259}
static PGresult * result
Definition cel_pgsql.c:84
struct ast_format_cap * ast_channel_nativeformats(const struct ast_channel *chan)
@ AST_MEDIA_TYPE_UNKNOWN
Definition codec.h:31
#define AST_FORMAT_CAP_NAMES_LEN
Definition format_cap.h:324
int ast_format_cap_append_from_cap(struct ast_format_cap *dst, const struct ast_format_cap *src, enum ast_media_type type)
Append the formats of provided type in src to dst.
Definition format_cap.c:269
const char * ast_format_cap_get_names(const struct ast_format_cap *cap, struct ast_str **buf)
Get the names of codecs of a set of formats.
Definition format_cap.c:742
#define SCOPE_EXIT_RTN(...)

References ast_channel_name(), ast_channel_nativeformats(), ast_format_cap_append_from_cap(), ast_format_cap_get_names(), AST_FORMAT_CAP_NAMES_LEN, AST_MEDIA_TYPE_UNKNOWN, ast_str_tmp, result, SCOPE_ENTER, and SCOPE_EXIT_RTN.

◆ chan_pjsip_get_hold()

static int chan_pjsip_get_hold ( const char *  chan_uid)
static

Determine whether a channel ID is in the list of PJSIP channels on hold.

Parameters
chan_uid- Channel being checked
Return values
0The channel is not in the hold list
1The channel is in the hold list

Definition at line 1272 of file chan_pjsip.c.

1273{
1274 RAII_VAR(char *, hold_uid, NULL, ao2_cleanup);
1275
1276 hold_uid = ao2_find(pjsip_uids_onhold, chan_uid, OBJ_SEARCH_KEY);
1277 if (!hold_uid) {
1278 return 0;
1279 }
1280
1281 return 1;
1282}

References ao2_cleanup, ao2_find, NULL, OBJ_SEARCH_KEY, pjsip_uids_onhold, and RAII_VAR.

Referenced by chan_pjsip_devicestate().

◆ chan_pjsip_get_rtp_peer()

static enum ast_rtp_glue_result chan_pjsip_get_rtp_peer ( struct ast_channel *  chan,
struct ast_rtp_instance **  instance 
)
static

Function called by RTP engine to get local audio RTP peer.

Definition at line 180 of file chan_pjsip.c.

181{
182 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(chan);
183 struct ast_sip_endpoint *endpoint;
184 struct ast_datastore *datastore;
185 struct ast_sip_session_media *media;
186
187 if (!channel || !channel->session) {
189 }
190
191 /* XXX Getting the first RTP instance for direct media related stuff seems just
192 * absolutely wrong. But the native RTP bridge knows no other method than single-stream
193 * for direct media. So this is the best we can do.
194 */
196 if (!media || !media->rtp) {
198 }
199
200 datastore = ast_sip_session_get_datastore(channel->session, "t38");
201 if (datastore) {
202 ao2_ref(datastore, -1);
204 }
205
206 endpoint = channel->session->endpoint;
207
208 *instance = media->rtp;
209 ao2_ref(*instance, +1);
210
211 ast_assert(endpoint != NULL);
214 }
215
216 if (endpoint->media.direct_media.enabled) {
218 }
219
221}
@ AST_SIP_MEDIA_ENCRYPT_NONE
Definition res_pjsip.h:739
struct ast_datastore * ast_sip_session_get_datastore(struct ast_sip_session *session, const char *name)
Retrieve a session datastore.
@ AST_RTP_GLUE_RESULT_LOCAL
Definition rtp_engine.h:167
@ AST_RTP_GLUE_RESULT_REMOTE
Definition rtp_engine.h:165
@ AST_RTP_GLUE_RESULT_FORBID
Definition rtp_engine.h:163
Structure for a data store object.
Definition datastore.h:64
struct ast_sip_media_rtp_configuration rtp
Definition res_pjsip.h:1019
struct ast_sip_direct_media_configuration direct_media
Definition res_pjsip.h:1021
struct ast_sip_endpoint_media_configuration media
Definition res_pjsip.h:1100
enum ast_sip_session_media_encryption encryption
Definition res_pjsip.h:958
struct ast_sip_endpoint * endpoint
#define ast_assert(a)
Definition utils.h:779

References ast_sip_session::active_media_state, ao2_ref, ast_assert, ast_channel_tech_pvt(), AST_MEDIA_TYPE_AUDIO, AST_RTP_GLUE_RESULT_FORBID, AST_RTP_GLUE_RESULT_LOCAL, AST_RTP_GLUE_RESULT_REMOTE, AST_SIP_MEDIA_ENCRYPT_NONE, ast_sip_session_get_datastore(), ast_sip_session_media_state::default_session, ast_sip_endpoint_media_configuration::direct_media, ast_sip_direct_media_configuration::enabled, ast_sip_media_rtp_configuration::encryption, ast_sip_session::endpoint, ast_sip_endpoint::media, NULL, ast_sip_endpoint_media_configuration::rtp, ast_sip_session_media::rtp, and ast_sip_channel_pvt::session.

◆ chan_pjsip_get_uniqueid()

static const char * chan_pjsip_get_uniqueid ( struct ast_channel *  ast)
static

Definition at line 1386 of file chan_pjsip.c.

1387{
1388 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(ast);
1389 char *uniqueid = ast_threadstorage_get(&uniqueid_threadbuf, UNIQUEID_BUFSIZE);
1390
1391 if (!channel || !uniqueid) {
1392 return "";
1393 }
1394
1395 ast_copy_pj_str(uniqueid, &channel->session->inv_session->dlg->call_id->id, UNIQUEID_BUFSIZE);
1396
1397 return uniqueid;
1398}
#define UNIQUEID_BUFSIZE
Definition chan_pjsip.c:77
void ast_copy_pj_str(char *dest, const pj_str_t *src, size_t size)
Copy a pj_str_t into a standard character buffer.
Definition res_pjsip.c:2221
struct pjsip_inv_session * inv_session
void * ast_threadstorage_get(struct ast_threadstorage *ts, size_t init_size)
Retrieve thread storage.

References ast_channel_tech_pvt(), ast_copy_pj_str(), ast_threadstorage_get(), ast_sip_session::inv_session, ast_sip_channel_pvt::session, and UNIQUEID_BUFSIZE.

◆ chan_pjsip_get_vrtp_peer()

static enum ast_rtp_glue_result chan_pjsip_get_vrtp_peer ( struct ast_channel *  chan,
struct ast_rtp_instance **  instance 
)
static

Function called by RTP engine to get local video RTP peer.

Definition at line 224 of file chan_pjsip.c.

225{
226 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(chan);
227 struct ast_sip_endpoint *endpoint;
228 struct ast_sip_session_media *media;
229
230 if (!channel || !channel->session) {
232 }
233
235 if (!media || !media->rtp) {
237 }
238
239 endpoint = channel->session->endpoint;
240
241 *instance = media->rtp;
242 ao2_ref(*instance, +1);
243
244 ast_assert(endpoint != NULL);
247 }
248
250}
@ AST_MEDIA_TYPE_VIDEO
Definition codec.h:33

References ast_sip_session::active_media_state, ao2_ref, ast_assert, ast_channel_tech_pvt(), AST_MEDIA_TYPE_VIDEO, AST_RTP_GLUE_RESULT_FORBID, AST_RTP_GLUE_RESULT_LOCAL, AST_SIP_MEDIA_ENCRYPT_NONE, ast_sip_session_media_state::default_session, ast_sip_media_rtp_configuration::encryption, ast_sip_session::endpoint, ast_sip_endpoint::media, NULL, ast_sip_endpoint_media_configuration::rtp, ast_sip_session_media::rtp, and ast_sip_channel_pvt::session.

◆ chan_pjsip_hangup()

static int chan_pjsip_hangup ( struct ast_channel *  ast)
static

Function called by core to hang up a PJSIP session.

Definition at line 2695 of file chan_pjsip.c.

2696{
2697 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(ast);
2698 int cause;
2699 int tech_cause;
2700 int original_tech_cause;
2701 struct hangup_data *h_data;
2702 SCOPE_ENTER(1, "%s\n", ast_channel_name(ast));
2703
2704 if (!channel || !channel->session) {
2705 SCOPE_EXIT_RTN_VALUE(-1, "%s: No channel or session\n", ast_channel_name(ast));
2706 }
2707
2709 tech_cause = hangup_cause2sip(cause);
2710 original_tech_cause = ast_channel_tech_hangupcause(channel->session->channel);
2711 if (!original_tech_cause) {
2712 ast_channel_tech_hangupcause_set(channel->session->channel, tech_cause);
2713 }
2714
2715 h_data = hangup_data_alloc(tech_cause, ast);
2716 if (!h_data) {
2717 goto failure;
2718 }
2719
2720 if (ast_sip_push_task(channel->session->serializer, hangup, h_data)) {
2721 ast_log(LOG_WARNING, "Unable to push hangup task to the taskpool. Expect bad things\n");
2722 goto failure;
2723 }
2724
2725 SCOPE_EXIT_RTN_VALUE(0, "%s: Cause: %d Tech Cause: %d\n", ast_channel_name(ast),
2726 cause, tech_cause);
2727
2728failure:
2729 /* Go ahead and do our cleanup of the session and channel even if we're not going
2730 * to be able to send our SIP request/response
2731 */
2733 ao2_cleanup(channel);
2734 ao2_cleanup(h_data);
2735
2736 SCOPE_EXIT_RTN_VALUE(-1, "%s: Cause: %d\n", ast_channel_name(ast), cause);
2737}
static int hangup_cause2sip(int cause)
Internal function which translates from Asterisk cause codes to SIP response codes.
static void clear_session_and_channel_locked(struct ast_sip_session *session, struct ast_channel *ast)
Clear a channel from a session along with its PVT (channel lock held)
static int hangup(void *data)
static struct hangup_data * hangup_data_alloc(int cause, struct ast_channel *chan)
int ast_channel_tech_hangupcause(const struct ast_channel *chan)
void ast_channel_tech_hangupcause_set(struct ast_channel *chan, int value)
int ast_channel_hangupcause(const struct ast_channel *chan)

References ao2_cleanup, ast_channel_hangupcause(), ast_channel_name(), ast_channel_tech_hangupcause(), ast_channel_tech_hangupcause_set(), ast_channel_tech_pvt(), ast_log, ast_sip_push_task, hangup_data::cause, ast_sip_session::channel, clear_session_and_channel_locked(), hangup(), hangup_cause2sip(), hangup_data_alloc(), LOG_WARNING, SCOPE_ENTER, SCOPE_EXIT_RTN_VALUE, ast_sip_session::serializer, and ast_sip_channel_pvt::session.

◆ chan_pjsip_incoming_ack()

static int chan_pjsip_incoming_ack ( struct ast_sip_session *  session,
struct pjsip_rx_data *  rdata 
)
static

Definition at line 3464 of file chan_pjsip.c.

3465{
3467
3468 if (rdata->msg_info.msg->line.req.method.id == PJSIP_ACK_METHOD) {
3469 if (session->endpoint->media.direct_media.enabled && session->channel) {
3470 ast_trace(-1, "%s: Queueing SRCCHANGE\n", ast_sip_session_get_name(session));
3472 }
3473 }
3475}
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame without payload.
Definition channel.c:1289
#define ast_trace(level,...)
@ AST_CONTROL_SRCCHANGE

References AST_CONTROL_SRCCHANGE, ast_queue_control(), ast_sip_session_get_name(), ast_trace, SCOPE_ENTER, SCOPE_EXIT_RTN_VALUE, and session.

◆ chan_pjsip_incoming_prack()

static int chan_pjsip_incoming_prack ( struct ast_sip_session *  session,
struct pjsip_rx_data *  rdata 
)
static

Definition at line 3477 of file chan_pjsip.c.

3478{
3480
3481 if (pj_strcmp2(&rdata->msg_info.msg->line.req.method.name, "PRACK") == 0 &&
3482 pjmedia_sdp_neg_get_state(session->inv_session->neg) == PJMEDIA_SDP_NEG_STATE_DONE) {
3483
3484 session->early_confirmed = 1;
3485 }
3487}

References ast_sip_session_get_name(), SCOPE_ENTER, SCOPE_EXIT_RTN_VALUE, and session.

◆ chan_pjsip_incoming_request()

static int chan_pjsip_incoming_request ( struct ast_sip_session *  session,
struct pjsip_rx_data *  rdata 
)
static

Function called when a request is received on the session.

Definition at line 3220 of file chan_pjsip.c.

3221{
3222 RAII_VAR(struct ast_datastore *, datastore, NULL, ao2_cleanup);
3223 struct transport_info_data *transport_data;
3224 pjsip_tx_data *packet = NULL;
3226
3227 if (session->channel) {
3228 SCOPE_EXIT_RTN_VALUE(0, "%s: No channel\n", ast_sip_session_get_name(session));
3229 }
3230
3231 /* Check for a to-tag to determine if this is a reinvite */
3232 if (rdata->msg_info.to->tag.slen) {
3233 /* Weird case. We've received a reinvite but we don't have a channel. The most
3234 * typical case for this happening is that a blind transfer fails, and so the
3235 * transferer attempts to reinvite himself back into the call. We already got
3236 * rid of that channel, and the other side of the call is unrecoverable.
3237 *
3238 * We treat this as a failure, so our best bet is to just hang this call
3239 * up and not create a new channel. Clearing defer_terminate here ensures that
3240 * calling ast_sip_session_terminate() can result in a BYE being sent ASAP.
3241 */
3242 session->defer_terminate = 0;
3244 SCOPE_EXIT_RTN_VALUE(-1, "%s: We have a To tag but no channel. Terminating session\n", ast_sip_session_get_name(session));
3245 }
3246
3247 datastore = ast_sip_session_alloc_datastore(&transport_info, "transport_info");
3248 if (!datastore) {
3249 SCOPE_EXIT_LOG_RTN_VALUE(-1, LOG_ERROR, "%s: Couldn't alloc transport_info datastore\n", ast_sip_session_get_name(session));
3250 }
3251
3252 transport_data = ast_calloc(1, sizeof(*transport_data));
3253 if (!transport_data) {
3254 SCOPE_EXIT_LOG_RTN_VALUE(-1, LOG_ERROR, "%s: Couldn't alloc transport_info\n", ast_sip_session_get_name(session));
3255 }
3256 pj_sockaddr_cp(&transport_data->local_addr, &rdata->tp_info.transport->local_addr);
3257 pj_sockaddr_cp(&transport_data->remote_addr, &rdata->pkt_info.src_addr);
3258 datastore->data = transport_data;
3260
3261 if (!(session->channel = chan_pjsip_new(session, AST_STATE_RING, session->exten, NULL, NULL, NULL, NULL))) {
3262 if (pjsip_inv_end_session(session->inv_session, 503, NULL, &packet) == PJ_SUCCESS
3263 && packet) {
3265 }
3266
3267 SCOPE_EXIT_LOG_RTN_VALUE(-1, LOG_ERROR, "%s: Failed to allocate new PJSIP channel on incoming SIP INVITE\n",
3269 }
3270
3272
3273 /* channel gets created on incoming request, but we wait to call start
3274 so other supplements have a chance to run */
3276}
#define ast_calloc(num, len)
A wrapper for calloc()
Definition astmm.h:202
static struct ast_datastore_info transport_info
Datastore used to store local/remote addresses for the INVITE request that created the PJSIP channel.
Definition chan_pjsip.c:270
static void set_sipdomain_variable(struct ast_sip_session *session)
static struct ast_channel * chan_pjsip_new(struct ast_sip_session *session, int state, const char *exten, const char *title, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *cid_name)
Function called to create a new PJSIP Asterisk channel.
Definition chan_pjsip.c:645
@ AST_STATE_RING
#define SCOPE_EXIT_LOG_RTN_VALUE(__value, __log_level,...)
int ast_sip_session_add_datastore(struct ast_sip_session *session, struct ast_datastore *datastore)
Add a datastore to a SIP session.
struct ast_datastore * ast_sip_session_alloc_datastore(const struct ast_datastore_info *info, const char *uid)
Alternative for ast_datastore_alloc()
void ast_sip_session_terminate(struct ast_sip_session *session, int response)
Terminate a session and, if possible, send the provided response code.
Transport information stored in transport_info datastore.
Definition chan_pjsip.h:30
pj_sockaddr local_addr
Our address that received the request.
Definition chan_pjsip.h:34
pj_sockaddr remote_addr
The address that sent the request.
Definition chan_pjsip.h:32

References ao2_cleanup, ast_calloc, ast_sip_session_add_datastore(), ast_sip_session_alloc_datastore(), ast_sip_session_get_name(), ast_sip_session_send_response(), ast_sip_session_terminate(), AST_STATE_RING, chan_pjsip_new(), transport_info_data::local_addr, LOG_ERROR, NULL, RAII_VAR, transport_info_data::remote_addr, SCOPE_ENTER, SCOPE_EXIT_LOG_RTN_VALUE, SCOPE_EXIT_RTN_VALUE, session, set_sipdomain_variable(), and transport_info.

◆ chan_pjsip_incoming_response()

static void chan_pjsip_incoming_response ( struct ast_sip_session *  session,
struct pjsip_rx_data *  rdata 
)
static

Function called when a response is received on the session.

Definition at line 3407 of file chan_pjsip.c.

3408{
3409 struct pjsip_status_line status = rdata->msg_info.msg->line.status;
3410 SCOPE_ENTER(3, "%s: Status: %d\n", ast_sip_session_get_name(session), status.code);
3411
3412 if (!session->channel) {
3413 SCOPE_EXIT_RTN("%s: No channel\n", ast_sip_session_get_name(session));
3414 }
3415
3416 switch (status.code) {
3417 case 180: {
3418 pjsip_rdata_sdp_info *sdp = pjsip_rdata_get_sdp_info(rdata);
3419 if (sdp && sdp->body.ptr) {
3420 ast_trace(-1, "%s: Queueing PROGRESS\n", ast_sip_session_get_name(session));
3421 session->early_confirmed = pjsip_100rel_is_reliable(rdata) == PJ_TRUE;
3423 } else {
3424 ast_trace(-1, "%s: Queueing RINGING\n", ast_sip_session_get_name(session));
3426 }
3427
3428 ast_channel_lock(session->channel);
3429 if (ast_channel_state(session->channel) != AST_STATE_UP) {
3431 }
3432 ast_channel_unlock(session->channel);
3433 break;
3434 }
3435 case 183:
3436 if (session->endpoint->ignore_183_without_sdp) {
3437 pjsip_rdata_sdp_info *sdp = pjsip_rdata_get_sdp_info(rdata);
3438 if (sdp && sdp->body.ptr) {
3439 ast_trace(-1, "%s: Queueing PROGRESS\n", ast_sip_session_get_name(session));
3440 ast_trace(1, "%s Method: %.*s Status: %d Queueing PROGRESS with SDP\n", ast_sip_session_get_name(session),
3441 (int)rdata->msg_info.cseq->method.name.slen, rdata->msg_info.cseq->method.name.ptr, status.code);
3442 session->early_confirmed = pjsip_100rel_is_reliable(rdata) == PJ_TRUE;
3444 }
3445 } else {
3446 ast_trace(-1, "%s: Queueing PROGRESS\n", ast_sip_session_get_name(session));
3447 ast_trace(1, "%s Method: %.*s Status: %d Queueing PROGRESS without SDP\n", ast_sip_session_get_name(session),
3448 (int)rdata->msg_info.cseq->method.name.slen, rdata->msg_info.cseq->method.name.ptr, status.code);
3450 }
3451 break;
3452 case 200:
3453 ast_trace(-1, "%s: Queueing ANSWER\n", ast_sip_session_get_name(session));
3455 break;
3456 default:
3457 ast_trace(-1, "%s: Not queueing anything\n", ast_sip_session_get_name(session));
3458 break;
3459 }
3460
3462}
@ AST_STATE_RINGING
@ AST_CONTROL_PROGRESS
@ AST_CONTROL_ANSWER
@ AST_CONTROL_RINGING

References ast_channel_lock, ast_channel_unlock, AST_CONTROL_ANSWER, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, ast_queue_control(), ast_setstate(), ast_sip_session_get_name(), AST_STATE_RINGING, AST_STATE_UP, ast_trace, SCOPE_ENTER, SCOPE_EXIT_RTN, session, and status.

◆ chan_pjsip_incoming_response_update_cause()

static void chan_pjsip_incoming_response_update_cause ( struct ast_sip_session *  session,
struct pjsip_rx_data *  rdata 
)
static

Function called when a response is received on the session.

Definition at line 3369 of file chan_pjsip.c.

3370{
3371 struct pjsip_status_line status = rdata->msg_info.msg->line.status;
3372 struct ast_control_pvt_cause_code *cause_code;
3373 int data_size = sizeof(*cause_code);
3374 SCOPE_ENTER(3, "%s: Status: %d\n", ast_sip_session_get_name(session), status.code);
3375
3376 if (!session->channel) {
3377 SCOPE_EXIT_RTN("%s: No channel\n", ast_sip_session_get_name(session));
3378 }
3379
3380 /* Build and send the tech-specific cause information */
3381 /* size of the string making up the cause code is "SIP " number + " " + reason length */
3382 data_size += 4 + 4 + pj_strlen(&status.reason);
3383 cause_code = ast_alloca(data_size);
3384 memset(cause_code, 0, data_size);
3385
3387
3388 /*
3389 * The cause code string is built in the format "SIP <status code> <reason phrase>".
3390 * Unfortunately, the ast_control_pvt_cause_code structure doesn't have a separate
3391 * field for the numeric code and adding it would break ABI so we'll have to parse
3392 * this string in chan_pjsip_session_end() later. If the string needs to be
3393 * changed, make sure the parsing in chan_pjsip_session_end() is adjusted as well.
3394 */
3395 snprintf(cause_code->code, data_size - sizeof(*cause_code) + 1, "SIP %d %.*s", status.code,
3396 (int) pj_strlen(&status.reason), pj_strbuf(&status.reason));
3397
3398 cause_code->ast_cause = ast_sip_hangup_sip2cause(status.code);
3399 ast_queue_control_data(session->channel, AST_CONTROL_PVT_CAUSE_CODE, cause_code, data_size);
3400 ast_channel_hangupcause_hash_set(session->channel, cause_code, data_size);
3401
3402 SCOPE_EXIT_RTN("%s: ast_cause: %d tech_cause: %s\n", ast_sip_session_get_name(session),
3403 cause_code->ast_cause, cause_code->code);
3404}
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition astmm.h:288
int ast_queue_control_data(struct ast_channel *chan, enum ast_control_frame_type control, const void *data, size_t datalen)
Queue a control frame with payload.
Definition channel.c:1296
void ast_channel_hangupcause_hash_set(struct ast_channel *chan, const struct ast_control_pvt_cause_code *cause_code, int datalen)
Sets the HANGUPCAUSE hash and optionally the SIP_CAUSE hash on the given channel.
Definition channel.c:4368
#define AST_CHANNEL_NAME
Definition channel.h:173
@ AST_CONTROL_PVT_CAUSE_CODE
const int ast_sip_hangup_sip2cause(int cause)
Convert SIP hangup causes to Asterisk hangup causes.
Definition res_pjsip.c:3570

References ast_alloca, ast_control_pvt_cause_code::ast_cause, ast_channel_hangupcause_hash_set(), AST_CHANNEL_NAME, ast_channel_name(), AST_CONTROL_PVT_CAUSE_CODE, ast_copy_string(), ast_queue_control_data(), ast_sip_hangup_sip2cause(), ast_sip_session_get_name(), ast_control_pvt_cause_code::chan_name, ast_control_pvt_cause_code::code, SCOPE_ENTER, SCOPE_EXIT_RTN, session, and status.

◆ chan_pjsip_indicate()

static int chan_pjsip_indicate ( struct ast_channel *  ast,
int  condition,
const void *  data,
size_t  datalen 
)
static

Function called by core to ask the channel to indicate some sort of condition.

Definition at line 1728 of file chan_pjsip.c.

1729{
1730 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(ast);
1731 struct ast_sip_session_media *media;
1732 int response_code = 0;
1733 int res = 0;
1734 char *device_buf;
1735 size_t device_buf_size;
1736 int i;
1737 const struct ast_stream_topology *topology;
1738 struct ast_frame f = {
1740 .subclass = {
1741 .integer = condition
1742 },
1743 .datalen = datalen,
1744 .data.ptr = (void *)data,
1745 };
1746 char condition_name[256];
1747 unsigned int duration;
1748 char digit;
1749 struct info_dtmf_data *dtmf_data;
1750
1751 SCOPE_ENTER(3, "%s: Indicated %s\n", ast_channel_name(ast),
1752 ast_frame_subclass2str(&f, condition_name, sizeof(condition_name), NULL, 0));
1753
1754 switch (condition) {
1756 if (ast_channel_state(ast) == AST_STATE_RING) {
1757 if (channel->session->endpoint->inband_progress ||
1758 (channel->session->inv_session && channel->session->inv_session->neg &&
1759 pjmedia_sdp_neg_get_state(channel->session->inv_session->neg) == PJMEDIA_SDP_NEG_STATE_DONE)) {
1760 res = -1;
1762 response_code = 180;
1763 } else {
1764 response_code = 183;
1765 }
1766 } else {
1767 response_code = 180;
1768 }
1769 } else {
1770 res = -1;
1771 }
1773 break;
1774 case AST_CONTROL_BUSY:
1775 if (ast_channel_state(ast) != AST_STATE_UP) {
1776 response_code = 486;
1777 } else {
1778 res = -1;
1779 }
1780 break;
1782 if (ast_channel_state(ast) != AST_STATE_UP) {
1783 response_code = 503;
1784 } else {
1785 res = -1;
1786 }
1787 break;
1789 if (ast_channel_state(ast) != AST_STATE_UP) {
1790 response_code = 484;
1791 } else {
1792 res = -1;
1793 }
1794 break;
1796 if (ast_channel_state(ast) != AST_STATE_UP) {
1797 response_code = 100;
1798 } else {
1799 res = -1;
1800 }
1801 break;
1803 if (ast_channel_state(ast) != AST_STATE_UP) {
1804 response_code = 183;
1805 } else {
1806 res = -1;
1807 }
1809 break;
1810 case AST_CONTROL_FLASH:
1811 duration = 300;
1812 digit = '!';
1813 dtmf_data = info_dtmf_data_alloc(channel->session, digit, duration);
1814
1815 if (!dtmf_data) {
1816 res = -1;
1817 break;
1818 }
1819
1820 if (ast_sip_push_task(channel->session->serializer, transmit_info_dtmf, dtmf_data)) {
1821 ast_log(LOG_WARNING, "Error sending FLASH via INFO on channel %s\n", ast_channel_name(ast));
1822 ao2_ref(dtmf_data, -1); /* dtmf_data can't be null here */
1823 res = -1;
1824 }
1825 break;
1827 for (i = 0; i < AST_VECTOR_SIZE(&channel->session->active_media_state->sessions); ++i) {
1828 media = AST_VECTOR_GET(&channel->session->active_media_state->sessions, i);
1829 if (!media || media->type != AST_MEDIA_TYPE_VIDEO) {
1830 continue;
1831 }
1832 if (media->rtp) {
1833 /* FIXME: Only use this for VP8. Additional work would have to be done to
1834 * fully support other video codecs */
1835
1840 /* FIXME Fake RTP write, this will be sent as an RTCP packet. Ideally the
1841 * RTP engine would provide a way to externally write/schedule RTCP
1842 * packets */
1843 struct ast_frame fr;
1845 fr.subclass.integer = AST_CONTROL_VIDUPDATE;
1846 res = ast_rtp_instance_write(media->rtp, &fr);
1847 } else {
1848 ao2_ref(channel->session, +1);
1850 ao2_cleanup(channel->session);
1851 }
1852 }
1853 ast_test_suite_event_notify("AST_CONTROL_VIDUPDATE", "Result: Success");
1854 } else {
1855 ast_test_suite_event_notify("AST_CONTROL_VIDUPDATE", "Result: Failure");
1856 res = -1;
1857 }
1858 }
1859 /* XXX If there were no video streams, then this should set
1860 * res to -1
1861 */
1862 break;
1864 ao2_ref(channel->session, +1);
1866 ao2_cleanup(channel->session);
1867 }
1868 break;
1870 break;
1872 res = -1;
1873 break;
1875 ast_assert(datalen == sizeof(int));
1876 if (*(int *) data) {
1877 /*
1878 * Masquerade is beginning:
1879 * Wait for session serializer to get suspended.
1880 */
1881 ast_channel_unlock(ast);
1883 ast_channel_lock(ast);
1884 } else {
1885 /*
1886 * Masquerade is complete:
1887 * Unsuspend the session serializer.
1888 */
1890 }
1891 break;
1892 case AST_CONTROL_HOLD:
1894 device_buf_size = strlen(ast_channel_name(ast)) + 1;
1895 device_buf = alloca(device_buf_size);
1896 ast_channel_get_device_name(ast, device_buf, device_buf_size);
1898 if (!channel->session->moh_passthrough) {
1899 ast_moh_start(ast, data, NULL);
1900 } else {
1902 ast_log(LOG_WARNING, "Could not queue task to remotely put session '%s' on hold with endpoint '%s'\n",
1904 ao2_ref(channel->session, -1);
1905 }
1906 }
1907 break;
1908 case AST_CONTROL_UNHOLD:
1910 device_buf_size = strlen(ast_channel_name(ast)) + 1;
1911 device_buf = alloca(device_buf_size);
1912 ast_channel_get_device_name(ast, device_buf, device_buf_size);
1914 if (!channel->session->moh_passthrough) {
1915 ast_moh_stop(ast);
1916 } else {
1918 ast_log(LOG_WARNING, "Could not queue task to remotely take session '%s' off hold with endpoint '%s'\n",
1920 ao2_ref(channel->session, -1);
1921 }
1922 }
1923 break;
1925 break;
1927 if (!channel->session->endpoint->media.bundle) {
1928 /* Generate a new SSRC due to media source change and RTP timestamp reset.
1929 Ensures RFC 3550 compliance and avoids SBC interoperability issues (Sonus/Ribbon)*/
1930 for (i = 0; i < AST_VECTOR_SIZE(&channel->session->active_media_state->sessions); ++i) {
1931 media = AST_VECTOR_GET(&channel->session->active_media_state->sessions, i);
1932 if (media && media->rtp) {
1934 }
1935 }
1936 }
1937 break;
1939 if (ast_channel_state(ast) != AST_STATE_UP) {
1940 response_code = 181;
1941 } else {
1942 res = -1;
1943 }
1944 break;
1946 res = 0;
1947
1948 if (channel->session->t38state == T38_PEER_REINVITE) {
1949 const struct ast_control_t38_parameters *parameters = data;
1950
1951 if (parameters->request_response == AST_T38_REQUEST_PARMS) {
1953 }
1954 }
1955
1956 break;
1958 topology = data;
1959 ast_trace(-1, "%s: New topology: %s\n", ast_channel_name(ast),
1960 ast_str_tmp(256, ast_stream_topology_to_str(topology, &STR_TMP)));
1961 res = handle_topology_request_change(channel->session, topology);
1962 break;
1964 break;
1966 break;
1968 break;
1969 case -1:
1970 res = -1;
1971 break;
1972 default:
1973 ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", condition);
1974 res = -1;
1975 break;
1976 }
1977
1978 if (response_code) {
1979 struct indicate_data *ind_data = indicate_data_alloc(channel->session, condition, response_code, data, datalen);
1980
1981 if (!ind_data) {
1982 SCOPE_EXIT_LOG_RTN_VALUE(-1, LOG_ERROR, "%s: Couldn't alloc indicate data\n", ast_channel_name(ast));
1983 }
1984
1985 if (ast_sip_push_task(channel->session->serializer, indicate, ind_data)) {
1986 ast_log(LOG_ERROR, "%s: Cannot send response code %d to endpoint %s. Could not queue task properly\n",
1988 ao2_cleanup(ind_data);
1989 res = -1;
1990 }
1991 }
1992
1993 SCOPE_EXIT_RTN_VALUE(res, "%s\n", ast_channel_name(ast));
1994}
static int update_connected_line_information(void *data)
Update connected line information.
static int remote_send_unhold(void *data)
Update local hold state to be unheld.
static int handle_topology_request_change(struct ast_sip_session *session, const struct ast_stream_topology *proposed)
static int indicate(void *data)
static int remote_send_hold(void *data)
Update local hold state to be held.
static struct indicate_data * indicate_data_alloc(struct ast_sip_session *session, int condition, int response_code, const void *frame_data, size_t datalen)
static void chan_pjsip_remove_hold(const char *chan_uid)
Remove a channel ID from the list of PJSIP channels on hold.
static int transmit_info_with_vidupdate(void *data)
Send SIP INFO with video update request.
static int chan_pjsip_add_hold(const char *chan_uid)
Add a channel ID to the list of PJSIP channels on hold.
int ast_channel_get_device_name(struct ast_channel *chan, char *device_name, size_t name_buffer_length)
Get a device name given its channel structure.
Definition channel.c:10676
@ AST_DEVSTATE_CACHABLE
Definition devicestate.h:70
int ast_devstate_changed(enum ast_device_state state, enum ast_devstate_cache cachable, const char *fmt,...)
Tells Asterisk the State for Device is changed.
int ast_devstate_changed_literal(enum ast_device_state state, enum ast_devstate_cache cachable, const char *device)
Tells Asterisk the State for Device is changed.
@ AST_FORMAT_CMP_NOT_EQUAL
Definition format.h:38
struct ast_format * ast_format_h264
Built-in cached h264 format.
struct ast_format * ast_format_h265
Built-in cached h265 format.
struct ast_format * ast_format_vp9
Built-in cached vp9 format.
struct ast_format * ast_format_vp8
Built-in cached vp8 format.
enum ast_format_cmp_res ast_format_cap_iscompatible_format(const struct ast_format_cap *cap, const struct ast_format *format)
Find if ast_format is within the capabilities of the ast_format_cap object.
Definition format_cap.c:589
@ AST_T38_REQUEST_PARMS
char * ast_frame_subclass2str(struct ast_frame *f, char *subclass, size_t slen, char *moreinfo, size_t mlen)
Copy the discription of a frame's subclass into the provided string.
Definition main/frame.c:406
@ AST_FRAME_CONTROL
@ AST_CONTROL_SRCUPDATE
@ AST_CONTROL_STREAM_TOPOLOGY_SOURCE_CHANGED
@ AST_CONTROL_UNHOLD
@ AST_CONTROL_VIDUPDATE
@ AST_CONTROL_STREAM_TOPOLOGY_REQUEST_CHANGE
@ AST_CONTROL_PROCEEDING
@ AST_CONTROL_REDIRECTING
@ AST_CONTROL_T38_PARAMETERS
@ AST_CONTROL_CONGESTION
@ AST_CONTROL_STREAM_TOPOLOGY_CHANGED
@ AST_CONTROL_CONNECTED_LINE
@ AST_CONTROL_TRANSFER
@ AST_CONTROL_FLASH
@ AST_CONTROL_INCOMPLETE
@ AST_CONTROL_MASQUERADE_NOTIFY
@ AST_CONTROL_UPDATE_RTP_PEER
int ast_moh_start(struct ast_channel *chan, const char *mclass, const char *interpclass)
Turn on music on hold on a given channel.
Definition channel.c:7802
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition channel.c:7812
unsigned int ast_sip_get_allow_sending_180_after_183(void)
Retrieve the global setting 'allow_sending_180_after_183'.
@ T38_PEER_REINVITE
void ast_sip_session_unsuspend(struct ast_sip_session *session)
Request the session serializer be unsuspended.
void ast_sip_session_suspend(struct ast_sip_session *session)
Request and wait for the session serializer to be suspended.
int ast_rtp_instance_write(struct ast_rtp_instance *instance, struct ast_frame *frame)
Send a frame out over RTP.
Definition rtp_engine.c:619
void ast_rtp_instance_change_source(struct ast_rtp_instance *instance)
Indicate a new source of audio has dropped in and the ssrc should change.
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition sorcery.c:2381
enum ast_control_t38 request_response
Data structure associated with a single frame of data.
enum ast_frame_type frametype
union ast_frame::@237 data
unsigned int inband_progress
Definition res_pjsip.h:1122
struct ast_sip_session_media_state::@280 sessions
Mapping of stream to media sessions.
enum ast_media_type type
Media type of this session media.
enum ast_sip_session_t38state t38state
unsigned int moh_passthrough
#define ast_test_suite_event_notify(s, f,...)
Definition test.h:189
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition vector.h:637
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition vector.h:708

References ast_sip_session::active_media_state, ao2_bump, ao2_cleanup, ao2_ref, ast_assert, ast_channel_get_device_name(), ast_channel_lock, ast_channel_name(), ast_channel_nativeformats(), ast_channel_tech_pvt(), ast_channel_uniqueid(), ast_channel_unlock, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_CONNECTED_LINE, AST_CONTROL_FLASH, AST_CONTROL_HOLD, AST_CONTROL_INCOMPLETE, AST_CONTROL_MASQUERADE_NOTIFY, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_PVT_CAUSE_CODE, AST_CONTROL_REDIRECTING, AST_CONTROL_RINGING, AST_CONTROL_SRCCHANGE, AST_CONTROL_SRCUPDATE, AST_CONTROL_STREAM_TOPOLOGY_CHANGED, AST_CONTROL_STREAM_TOPOLOGY_REQUEST_CHANGE, AST_CONTROL_STREAM_TOPOLOGY_SOURCE_CHANGED, AST_CONTROL_T38_PARAMETERS, AST_CONTROL_TRANSFER, AST_CONTROL_UNHOLD, AST_CONTROL_UPDATE_RTP_PEER, AST_CONTROL_VIDUPDATE, AST_DEVICE_UNKNOWN, AST_DEVSTATE_CACHABLE, ast_devstate_changed(), ast_devstate_changed_literal(), ast_format_cap_iscompatible_format(), AST_FORMAT_CMP_NOT_EQUAL, ast_format_h264, ast_format_h265, ast_format_vp8, ast_format_vp9, AST_FRAME_CONTROL, ast_frame_subclass2str(), ast_log, AST_MEDIA_TYPE_VIDEO, ast_moh_start(), ast_moh_stop(), ast_rtp_instance_change_source(), ast_rtp_instance_write(), ast_sip_get_allow_sending_180_after_183(), ast_sip_push_task, ast_sip_session_suspend(), ast_sip_session_unsuspend(), ast_sorcery_object_get_id(), AST_STATE_RING, AST_STATE_UP, ast_str_tmp, ast_stream_topology_to_str(), AST_T38_REQUEST_PARMS, ast_test_suite_event_notify, ast_trace, AST_VECTOR_GET, AST_VECTOR_SIZE, ast_sip_endpoint_media_configuration::bundle, chan_pjsip_add_hold(), chan_pjsip_remove_hold(), indicate_data::condition, ast_frame::data, indicate_data::datalen, ast_frame::datalen, digit, info_dtmf_data::duration, ast_sip_session::endpoint, ast_frame::frametype, handle_topology_request_change(), ast_sip_endpoint::inband_progress, indicate(), indicate_data_alloc(), info_dtmf_data_alloc(), ast_frame_subclass::integer, ast_sip_session::inv_session, LOG_ERROR, LOG_WARNING, ast_sip_endpoint::media, ast_sip_session::moh_passthrough, NULL, remote_send_hold(), remote_send_unhold(), ast_control_t38_parameters::request_response, indicate_data::response_code, ast_sip_session_media::rtp, SCOPE_ENTER, SCOPE_EXIT_LOG_RTN_VALUE, SCOPE_EXIT_RTN_VALUE, ast_sip_session::serializer, ast_sip_channel_pvt::session, ast_sip_session_media_state::sessions, ast_frame::subclass, T38_PEER_REINVITE, ast_sip_session::t38state, transmit_info_dtmf(), transmit_info_with_vidupdate(), ast_sip_session_media::type, and update_connected_line_information().

◆ chan_pjsip_new()

static struct ast_channel * chan_pjsip_new ( struct ast_sip_session *  session,
int  state,
const char *  exten,
const char *  title,
const struct ast_assigned_ids *  assignedids,
const struct ast_channel *  requestor,
const char *  cid_name 
)
static

Function called to create a new PJSIP Asterisk channel.

Definition at line 645 of file chan_pjsip.c.

646{
647 struct ast_channel *chan;
648 struct ast_format_cap *caps;
649 RAII_VAR(struct chan_pjsip_pvt *, pvt, NULL, ao2_cleanup);
650 struct ast_sip_channel_pvt *channel;
651 struct ast_variable *var;
652 struct ast_stream_topology *topology;
653 struct ast_channel_initializers initializers = {
655 .tenantid = session->endpoint->tenantid,
656 };
658
660 SCOPE_EXIT_RTN_VALUE(NULL, "Couldn't create pvt\n");
661 }
662
664 S_COR(session->id.number.valid, session->id.number.str, ""),
665 S_COR(session->id.name.valid, session->id.name.str, ""),
666 session->endpoint->accountcode,
667 exten, session->endpoint->context,
668 assignedids, requestor, 0,
669 session->endpoint->persistent, &initializers, "PJSIP/%s-%08x",
671 (unsigned) ast_atomic_fetchadd_int((int *) &chan_idx, +1));
672 if (!chan) {
673 SCOPE_EXIT_RTN_VALUE(NULL, "Couldn't create channel\n");
674 }
675
677
678 if (!(channel = ast_sip_channel_pvt_alloc(pvt, session))) {
679 ast_channel_unlock(chan);
680 ast_hangup(chan);
681 SCOPE_EXIT_RTN_VALUE(NULL, "Couldn't create pvt channel\n");
682 }
683
684 ast_channel_tech_pvt_set(chan, channel);
686 /* Keep technology hangup from accessing the not yet attached session. */
688 ao2_cleanup(channel);
689 ast_channel_unlock(chan);
690 ast_hangup(chan);
691 SCOPE_EXIT_RTN_VALUE(NULL, "Couldn't create PJSIP channel state\n");
692 }
693
694 if (!ast_stream_topology_get_count(session->pending_media_state->topology) ||
695 !compatible_formats_exist(session->pending_media_state->topology, session->endpoint->media.codecs)) {
697 if (!caps) {
698 ast_channel_unlock(chan);
699 ast_hangup(chan);
700 SCOPE_EXIT_RTN_VALUE(NULL, "Couldn't create caps\n");
701 }
702 ast_format_cap_append_from_cap(caps, session->endpoint->media.codecs, AST_MEDIA_TYPE_UNKNOWN);
703 topology = ast_stream_topology_clone(session->endpoint->media.topology);
704 } else {
705 caps = ast_stream_topology_get_formats(session->pending_media_state->topology);
706 topology = ast_stream_topology_clone(session->pending_media_state->topology);
707 }
708
709 if (!topology || !caps) {
710 ao2_cleanup(caps);
711 ast_stream_topology_free(topology);
712 ast_channel_unlock(chan);
713 ast_hangup(chan);
714 SCOPE_EXIT_RTN_VALUE(NULL, "Couldn't get caps or clone topology\n");
715 }
716
718
720 ast_channel_set_stream_topology(chan, topology);
721
722 if (!ast_format_cap_empty(caps)) {
723 struct ast_format *fmt;
724
726 if (!fmt) {
727 /* Since our capabilities aren't empty, this will succeed */
728 fmt = ast_format_cap_get_format(caps, 0);
729 }
734 ao2_ref(fmt, -1);
735 }
736
737 ao2_ref(caps, -1);
738
739 if (state == AST_STATE_RING) {
740 ast_channel_rings_set(chan, 1);
741 }
742
744
747 ast_channel_caller(chan)->ani2 = session->ani2;
748
749 if (!ast_strlen_zero(exten)) {
750 /* Set provided DNID on the new channel. */
751 ast_channel_dialed(chan)->number.str = ast_strdup(exten);
752 }
753
755
756 ast_channel_callgroup_set(chan, session->endpoint->pickup.callgroup);
757 ast_channel_pickupgroup_set(chan, session->endpoint->pickup.pickupgroup);
758
759 ast_channel_named_callgroups_set(chan, session->endpoint->pickup.named_callgroups);
760 ast_channel_named_pickupgroups_set(chan, session->endpoint->pickup.named_pickupgroups);
761
762 if (!ast_strlen_zero(session->endpoint->language)) {
763 ast_channel_language_set(chan, session->endpoint->language);
764 }
765
766 if (!ast_strlen_zero(session->endpoint->zone)) {
767 struct ast_tone_zone *zone = ast_get_indication_zone(session->endpoint->zone);
768 if (!zone) {
769 ast_log(LOG_ERROR, "Unknown country code '%s' for tonezone. Check indications.conf for available country codes.\n", session->endpoint->zone);
770 }
771 ast_channel_zone_set(chan, zone);
772 }
773
775 ast_channel_unlock(chan);
776
777 for (var = session->endpoint->channel_vars; var; var = var->next) {
778 char buf[512];
780 var->value, buf, sizeof(buf)));
781 }
782
784
786}
#define var
Definition ast_expr2f.c:605
#define ast_strdup(str)
A wrapper for strdup()
Definition astmm.h:241
static void chan_pjsip_pvt_dtor(void *obj)
Definition chan_pjsip.c:83
struct ast_channel_tech chan_pjsip_tech
PBX interface structure for channel registration.
Definition chan_pjsip.c:110
static int compatible_formats_exist(struct ast_stream_topology *top, struct ast_format_cap *cap)
Determine if a topology is compatible with format capabilities.
Definition chan_pjsip.c:624
static unsigned int chan_idx
Definition chan_pjsip.c:81
void ast_channel_rings_set(struct ast_channel *chan, int value)
void ast_channel_named_pickupgroups_set(struct ast_channel *chan, struct ast_namedgroups *value)
struct ast_stream_topology * ast_channel_set_stream_topology(struct ast_channel *chan, struct ast_stream_topology *topology)
Set the topology of streams on a channel.
void ast_channel_nativeformats_set(struct ast_channel *chan, struct ast_format_cap *value)
@ AST_ADSI_UNAVAILABLE
Definition channel.h:891
#define AST_CHANNEL_INITIALIZERS_VERSION
struct ABI version
Definition channel.h:620
void ast_channel_set_rawreadformat(struct ast_channel *chan, struct ast_format *format)
void ast_channel_tech_pvt_set(struct ast_channel *chan, void *value)
void ast_channel_callgroup_set(struct ast_channel *chan, ast_group_t value)
void ast_channel_set_rawwriteformat(struct ast_channel *chan, struct ast_format *format)
struct ast_party_dialed * ast_channel_dialed(struct ast_channel *chan)
#define ast_channel_alloc_with_initializers(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag, endpoint, initializers,...)
Definition channel.h:1307
void ast_channel_named_callgroups_set(struct ast_channel *chan, struct ast_namedgroups *value)
void ast_channel_set_readformat(struct ast_channel *chan, struct ast_format *format)
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:1752
void ast_channel_zone_set(struct ast_channel *chan, struct ast_tone_zone *value)
void ast_channel_priority_set(struct ast_channel *chan, int value)
void ast_channel_pickupgroup_set(struct ast_channel *chan, ast_group_t value)
void ast_channel_adsicpe_set(struct ast_channel *chan, enum ast_channel_adsicpe value)
void ast_channel_tech_set(struct ast_channel *chan, const struct ast_channel_tech *value)
void ast_channel_set_writeformat(struct ast_channel *chan, struct ast_format *format)
int pjsip_channel_info_create(struct ast_channel *chan, struct ast_sip_session *session)
Create channel-owned PJSIP information before channel publication.
char buf[BUFSIZE]
Definition eagi_proxy.c:66
int ast_format_cap_empty(const struct ast_format_cap *cap)
Determine if a format cap has no formats in it.
Definition format_cap.c:752
struct ast_format * ast_format_cap_get_format(const struct ast_format_cap *cap, int position)
Get the format at a specific index.
Definition format_cap.c:408
struct ast_format * ast_format_cap_get_best_by_type(const struct ast_format_cap *cap, enum ast_media_type type)
Get the most preferred format for a particular media type.
Definition format_cap.c:425
@ 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
void ast_channel_stage_snapshot_done(struct ast_channel *chan)
Clear flag to indicate channel snapshot is being staged, and publish snapshot.
void ast_channel_stage_snapshot(struct ast_channel *chan)
Set flag to indicate channel snapshot is being staged.
char * ast_get_encoded_str(const char *stream, char *result, size_t result_len)
Decode a stream of encoded control or extended ASCII characters.
Definition main/app.c:3163
struct ast_tone_zone * ast_get_indication_zone(const char *country)
locate ast_tone_zone
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition lock.h:764
struct ast_sip_channel_pvt * ast_sip_channel_pvt_alloc(void *pvt, struct ast_sip_session *session)
Allocate a new SIP channel pvt structure.
int ast_stream_topology_get_count(const struct ast_stream_topology *topology)
Get the number of streams in a topology.
Definition stream.c:768
void ast_stream_topology_free(struct ast_stream_topology *topology)
Unreference and destroy a stream topology.
Definition stream.c:746
struct ast_format_cap * ast_stream_topology_get_formats(struct ast_stream_topology *topology)
Create a format capabilities structure representing the topology.
Definition stream.c:933
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:670
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition strings.h:65
Helper struct for initializing additional channel information on channel creation.
Definition channel.h:615
uint32_t version
struct ABI version
Definition channel.h:625
Format capabilities structure, holds formats + preference order + etc.
Definition format_cap.c:54
Definition of a media format.
Definition format.c:43
int ani2
Automatic Number Identification 2 (Info Digits)
Definition channel.h:435
struct ast_party_dialed::@218 number
Dialed/Called number.
char * str
Subscriber phone number (Malloced)
Definition channel.h:388
A set of tones for a given locale.
Definition indications.h:74
Structure for variables, used for configurations and for channel variables.
The PJSIP channel driver pvt, stored in the ast_sip_channel_pvt data structure.
Definition chan_pjsip.h:42

References ast_party_caller::ani2, AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_alloc_options, ao2_cleanup, ao2_ref, AST_ADSI_UNAVAILABLE, ast_atomic_fetchadd_int(), ast_channel_adsicpe_set(), ast_channel_alloc_with_initializers, ast_channel_caller(), ast_channel_callgroup_set(), ast_channel_dialed(), AST_CHANNEL_INITIALIZERS_VERSION, ast_channel_named_callgroups_set(), ast_channel_named_pickupgroups_set(), ast_channel_nativeformats_set(), ast_channel_pickupgroup_set(), ast_channel_priority_set(), ast_channel_rings_set(), ast_channel_set_rawreadformat(), ast_channel_set_rawwriteformat(), ast_channel_set_readformat(), ast_channel_set_stream_topology(), ast_channel_set_writeformat(), ast_channel_stage_snapshot(), ast_channel_stage_snapshot_done(), ast_channel_tech_pvt_set(), ast_channel_tech_set(), ast_channel_uniqueid(), ast_channel_unlock, ast_channel_zone_set(), ast_format_cap_alloc, ast_format_cap_append_from_cap(), ast_format_cap_empty(), AST_FORMAT_CAP_FLAG_DEFAULT, ast_format_cap_get_best_by_type(), ast_format_cap_get_format(), ast_get_encoded_str(), ast_get_indication_zone(), ast_hangup(), ast_log, AST_MEDIA_TYPE_AUDIO, AST_MEDIA_TYPE_UNKNOWN, ast_party_id_copy(), ast_sip_channel_pvt_alloc(), ast_sip_session_get_name(), ast_sorcery_object_get_id(), AST_STATE_RING, ast_strdup, ast_stream_topology_clone(), ast_stream_topology_free(), ast_stream_topology_get_count(), ast_stream_topology_get_formats(), ast_strlen_zero(), buf, chan_idx, chan_pjsip_pvt_dtor(), chan_pjsip_tech, compatible_formats_exist(), LOG_ERROR, NULL, ast_party_dialed::number, pbx_builtin_setvar_helper(), pjsip_channel_info_create(), RAII_VAR, S_COR, SCOPE_ENTER, SCOPE_EXIT_RTN_VALUE, session, set_channel_on_rtp_instance(), ast_party_dialed::str, var, and ast_channel_initializers::version.

Referenced by chan_pjsip_incoming_request(), and chan_pjsip_request_with_stream_topology().

◆ chan_pjsip_pvt_dtor()

static void chan_pjsip_pvt_dtor ( void *  obj)
static

Definition at line 83 of file chan_pjsip.c.

84{
85}

Referenced by chan_pjsip_new().

◆ chan_pjsip_queryoption()

static int chan_pjsip_queryoption ( struct ast_channel *  ast,
int  option,
void *  data,
int *  datalen 
)
static

Function called to query options on a channel.

Definition at line 1345 of file chan_pjsip.c.

1346{
1347 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(ast);
1348 int res = -1;
1350
1351 if (!channel) {
1352 return -1;
1353 }
1354
1355 switch (option) {
1357 if (channel->session->endpoint->media.t38.enabled) {
1358 switch (channel->session->t38state) {
1359 case T38_LOCAL_REINVITE:
1360 case T38_PEER_REINVITE:
1362 break;
1363 case T38_ENABLED:
1365 break;
1366 case T38_REJECTED:
1368 break;
1369 default:
1371 break;
1372 }
1373 }
1374
1375 *((enum ast_t38_state *) data) = state;
1376 res = 0;
1377
1378 break;
1379 default:
1380 break;
1381 }
1382
1383 return res;
1384}
#define T38_ENABLED
ast_t38_state
Possible T38 states on channels.
Definition channel.h:898
@ T38_STATE_UNAVAILABLE
Definition channel.h:899
@ T38_STATE_UNKNOWN
Definition channel.h:900
@ T38_STATE_REJECTED
Definition channel.h:902
@ T38_STATE_NEGOTIATED
Definition channel.h:903
@ T38_STATE_NEGOTIATING
Definition channel.h:901
#define AST_OPTION_T38_STATE
@ T38_LOCAL_REINVITE
@ T38_REJECTED
struct ast_sip_t38_configuration t38
Definition res_pjsip.h:1023

References ast_channel_tech_pvt(), AST_OPTION_T38_STATE, ast_sip_t38_configuration::enabled, ast_sip_session::endpoint, ast_sip_endpoint::media, ast_sip_channel_pvt::session, ast_sip_endpoint_media_configuration::t38, T38_ENABLED, T38_LOCAL_REINVITE, T38_PEER_REINVITE, T38_REJECTED, T38_STATE_NEGOTIATED, T38_STATE_NEGOTIATING, T38_STATE_REJECTED, T38_STATE_UNAVAILABLE, T38_STATE_UNKNOWN, and ast_sip_session::t38state.

◆ chan_pjsip_read_stream()

static struct ast_frame * chan_pjsip_read_stream ( struct ast_channel *  ast)
static

Function called by core to read any waiting frames.

Note
The channel is already locked.

Definition at line 949 of file chan_pjsip.c.

950{
951 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(ast);
952 struct ast_sip_session *session = channel->session;
953 struct ast_sip_session_media_read_callback_state *callback_state;
954 struct ast_frame *f;
955 int fdno = ast_channel_fdno(ast) - AST_EXTENDED_FDS;
956 struct ast_frame *cur;
957
958 if (fdno >= AST_VECTOR_SIZE(&session->active_media_state->read_callbacks)) {
959 return &ast_null_frame;
960 }
961
962 callback_state = AST_VECTOR_GET_ADDR(&session->active_media_state->read_callbacks, fdno);
963 f = callback_state->read_callback(session, callback_state->session);
964
965 if (!f) {
966 return f;
967 }
968
969 for (cur = f; cur; cur = AST_LIST_NEXT(cur, frame_list)) {
970 if (cur->frametype == AST_FRAME_VOICE) {
971 break;
972 }
973 }
974
975 if (!cur || callback_state->session != session->active_media_state->default_session[callback_state->session->type]) {
976 return f;
977 }
978
979 session = channel->session;
980
981 /*
982 * Asymmetric RTP only has one native format set at a time.
983 * Therefore we need to update the native format to the current
984 * raw read format BEFORE the native format check
985 */
986 if (!session->endpoint->asymmetric_rtp_codec &&
989 struct ast_format_cap *caps;
990
991 /* For maximum compatibility we ensure that the formats match that of the received media */
992 ast_debug(1, "Oooh, got a frame with format of %s on channel '%s' when we're sending '%s', switching to match\n",
995
997 if (caps) {
1000 ast_format_cap_append(caps, cur->subclass.format, 0);
1002 ao2_ref(caps, -1);
1003 }
1004
1007
1008 if (ast_channel_is_bridged(ast)) {
1010 }
1011 }
1012
1015 ast_debug(1, "Oooh, got a frame with format of %s on channel '%s' when it has not been negotiated\n",
1017 ast_frfree(f);
1018 return &ast_null_frame;
1019 }
1020
1021 if (session->dsp) {
1022 int dsp_features;
1023
1024 dsp_features = ast_dsp_get_features(session->dsp);
1025 if ((dsp_features & DSP_FEATURE_FAX_DETECT)
1026 && session->endpoint->faxdetect_timeout
1027 && session->endpoint->faxdetect_timeout <= ast_channel_get_up_time(ast)) {
1028 dsp_features &= ~DSP_FEATURE_FAX_DETECT;
1029 if (dsp_features) {
1030 ast_dsp_set_features(session->dsp, dsp_features);
1031 } else {
1032 ast_dsp_free(session->dsp);
1033 session->dsp = NULL;
1034 }
1035 ast_debug(3, "Channel driver fax CNG detection timeout on %s\n",
1036 ast_channel_name(ast));
1037 }
1038 }
1039 if (session->dsp) {
1040 f = ast_dsp_process(ast, session->dsp, f);
1041 if (f && (f->frametype == AST_FRAME_DTMF)) {
1042 if (f->subclass.integer == 'f') {
1043 ast_debug(3, "Channel driver fax CNG detected on %s\n",
1044 ast_channel_name(ast));
1046 /* When chan_pjsip_cng_tone_detected returns it is possible for the
1047 * channel pointed to by ast and by session->channel to differ due to a
1048 * masquerade. It's best not to touch things after this.
1049 */
1050 } else {
1051 ast_debug(3, "* Detected inband DTMF '%c' on '%s'\n", f->subclass.integer,
1052 ast_channel_name(ast));
1053 }
1054 }
1055 }
1056
1057 return f;
1058}
static int is_compatible_format(struct ast_sip_session *session, struct ast_frame *f)
Determine if the given frame is in a format we've negotiated.
Definition chan_pjsip.c:935
static struct ast_frame * chan_pjsip_cng_tone_detected(struct ast_channel *ast, struct ast_sip_session *session, struct ast_frame *f)
Internal helper function called when CNG tone is detected.
Definition chan_pjsip.c:876
#define AST_EXTENDED_FDS
Definition channel.h:197
void ast_channel_set_unbridged_nolock(struct ast_channel *chan, int value)
Variant of ast_channel_set_unbridged. Use this if the channel is already locked prior to calling.
int ast_set_read_format_path(struct ast_channel *chan, struct ast_format *raw_format, struct ast_format *core_format)
Set specific read path on channel.
Definition channel.c:5511
int ast_channel_fdno(const struct ast_channel *chan)
struct ast_format * ast_channel_rawwriteformat(struct ast_channel *chan)
int ast_channel_is_bridged(const struct ast_channel *chan)
Determine if a channel is in a bridge.
Definition channel.c:10725
struct ast_format * ast_channel_writeformat(struct ast_channel *chan)
int ast_channel_get_up_time(struct ast_channel *chan)
Obtain how long it has been since the channel was answered.
Definition channel.c:2845
int ast_set_write_format_path(struct ast_channel *chan, struct ast_format *core_format, struct ast_format *raw_format)
Set specific write path on channel.
Definition channel.c:5547
struct ast_format * ast_channel_readformat(struct ast_channel *chan)
struct ast_frame * ast_dsp_process(struct ast_channel *chan, struct ast_dsp *dsp, struct ast_frame *inf)
Return AST_FRAME_NULL frames when there is silence, AST_FRAME_BUSY on busies, and call progress,...
Definition dsp.c:1683
#define DSP_FEATURE_FAX_DETECT
Definition dsp.h:29
enum ast_format_cmp_res ast_format_cmp(const struct ast_format *format1, const struct ast_format *format2)
Compare two formats.
Definition format.c:201
const char * ast_format_get_name(const struct ast_format *format)
Get the name associated with a format.
Definition format.c:334
void ast_format_cap_remove_by_type(struct ast_format_cap *cap, enum ast_media_type type)
Remove all formats matching a specific format type.
Definition format_cap.c:531
#define ast_format_cap_append(cap, format, framing)
Add format capability to capabilities structure.
Definition format_cap.h:99
#define AST_FRAME_DTMF
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
struct ast_format * format
struct ast_frame_subclass subclass
Structure which contains read callback information.
ast_sip_session_media_read_cb read_callback
The callback to invoke.
struct ast_sip_session_media * session
The media session.
#define AST_VECTOR_GET_ADDR(vec, idx)
Get an address of element in a vector.
Definition vector.h:696

References ao2_ref, ast_channel_fdno(), ast_channel_get_up_time(), ast_channel_is_bridged(), ast_channel_name(), ast_channel_nativeformats(), ast_channel_nativeformats_set(), ast_channel_rawwriteformat(), ast_channel_readformat(), ast_channel_set_unbridged_nolock(), ast_channel_tech_pvt(), ast_channel_writeformat(), ast_debug, ast_dsp_free(), ast_dsp_get_features(), ast_dsp_process(), ast_dsp_set_features(), AST_EXTENDED_FDS, ast_format_cap_alloc, ast_format_cap_append, ast_format_cap_append_from_cap(), AST_FORMAT_CAP_FLAG_DEFAULT, ast_format_cap_iscompatible_format(), ast_format_cap_remove_by_type(), ast_format_cmp(), AST_FORMAT_CMP_NOT_EQUAL, ast_format_get_name(), AST_FRAME_DTMF, AST_FRAME_VOICE, ast_frfree, AST_LIST_NEXT, AST_MEDIA_TYPE_AUDIO, AST_MEDIA_TYPE_UNKNOWN, ast_null_frame, ast_set_read_format_path(), ast_set_write_format_path(), AST_VECTOR_GET_ADDR, AST_VECTOR_SIZE, chan_pjsip_cng_tone_detected(), ast_sip_session::channel, DSP_FEATURE_FAX_DETECT, ast_frame_subclass::format, ast_frame::frametype, ast_frame_subclass::integer, is_compatible_format(), NULL, ast_sip_session_media_read_callback_state::read_callback, ast_sip_session_media_read_callback_state::session, ast_sip_channel_pvt::session, session, ast_frame::subclass, and ast_sip_session_media::type.

◆ chan_pjsip_remove_hold()

static void chan_pjsip_remove_hold ( const char *  chan_uid)
static

Remove a channel ID from the list of PJSIP channels on hold.

Parameters
chan_uid- Unique ID of the channel being taken out of the hold list

Definition at line 1259 of file chan_pjsip.c.

1260{
1262}
@ OBJ_NODATA
Definition astobj2.h:1044
@ OBJ_UNLINK
Definition astobj2.h:1039

References ao2_find, OBJ_NODATA, OBJ_SEARCH_KEY, OBJ_UNLINK, and pjsip_uids_onhold.

Referenced by chan_pjsip_indicate(), and chan_pjsip_session_end().

◆ chan_pjsip_request()

static struct ast_channel * chan_pjsip_request ( const char *  type,
struct ast_format_cap *  cap,
const struct ast_assigned_ids *  assignedids,
const struct ast_channel *  requestor,
const char *  data,
int *  cause 
)
static

Asterisk core interaction functions.

Definition at line 2881 of file chan_pjsip.c.

2882{
2883 struct ast_stream_topology *topology;
2884 struct ast_channel *chan;
2885
2887 if (!topology) {
2888 return NULL;
2889 }
2890
2891 chan = chan_pjsip_request_with_stream_topology(type, topology, assignedids, requestor, data, cause);
2892
2893 ast_stream_topology_free(topology);
2894
2895 return chan;
2896}
static const char type[]
static struct ast_channel * chan_pjsip_request_with_stream_topology(const char *type, struct ast_stream_topology *topology, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *data, int *cause)
Function called by core to create a new outgoing PJSIP session.
struct ast_stream_topology * ast_stream_topology_create_from_format_cap(struct ast_format_cap *cap)
A helper function that, given a format capabilities structure, creates a topology and separates the m...
Definition stream.c:851
const char * data

References ast_stream_topology_create_from_format_cap(), ast_stream_topology_free(), chan_pjsip_request_with_stream_topology(), ast_channel::data, NULL, and type.

◆ chan_pjsip_request_with_stream_topology()

static struct ast_channel * chan_pjsip_request_with_stream_topology ( const char *  type,
struct ast_stream_topology *  topology,
const struct ast_assigned_ids *  assignedids,
const struct ast_channel *  requestor,
const char *  data,
int *  cause 
)
static

Function called by core to create a new outgoing PJSIP session.

Definition at line 2854 of file chan_pjsip.c.

2855{
2856 struct request_data req_data;
2858 SCOPE_ENTER(1, "%s Topology: %s\n", data,
2860
2861 req_data.topology = topology;
2862 req_data.dest = data;
2863 /* Default failure value in case ast_sip_push_task_wait_servant() itself fails. */
2864 req_data.cause = AST_CAUSE_FAILURE;
2865
2866 if (ast_sip_push_task_wait_servant(NULL, request, &req_data)) {
2867 *cause = req_data.cause;
2868 SCOPE_EXIT_RTN_VALUE(NULL, "Couldn't push task\n");
2869 }
2870
2871 session = req_data.session;
2872
2873 if (!(session->channel = chan_pjsip_new(session, AST_STATE_DOWN, NULL, NULL, assignedids, requestor, NULL))) {
2874 /* Session needs to be terminated prematurely */
2875 SCOPE_EXIT_RTN_VALUE(NULL, "Couldn't create channel\n");
2876 }
2877
2878 SCOPE_EXIT_RTN_VALUE(session->channel, "Channel: %s\n", ast_channel_name(session->channel));
2879}
#define AST_CAUSE_FAILURE
Definition causes.h:150
static int request(void *obj)
#define ast_sip_push_task_wait_servant(serializer, sip_task, task_data)
Definition res_pjsip.h:2165
struct ast_stream_topology * topology

References ao2_cleanup, AST_CAUSE_FAILURE, ast_channel_name(), ast_sip_push_task_wait_servant, AST_STATE_DOWN, ast_str_tmp, ast_stream_topology_to_str(), request_data::cause, chan_pjsip_new(), request_data::dest, NULL, RAII_VAR, request(), SCOPE_ENTER, SCOPE_EXIT_RTN_VALUE, request_data::session, session, and request_data::topology.

Referenced by chan_pjsip_request().

◆ chan_pjsip_sendtext()

static int chan_pjsip_sendtext ( struct ast_channel *  ast,
const char *  text 
)
static

Definition at line 3025 of file chan_pjsip.c.

3026{
3027 struct ast_msg_data *msg;
3028 int rc;
3029 struct ast_msg_data_attribute attrs[] =
3030 {
3031 {
3033 .value = (char *)text,
3034 }
3035 };
3036
3038 if (!msg) {
3039 return -1;
3040 }
3041 rc = chan_pjsip_sendtext_data(ast, msg);
3042 ast_free(msg);
3043
3044 return rc;
3045}
#define ast_free(a)
Definition astmm.h:180
static int chan_pjsip_sendtext_data(struct ast_channel *ast, struct ast_msg_data *msg)
Function called by core to send text on PJSIP session.
struct ast_msg_data * ast_msg_data_alloc(enum ast_msg_data_source_type source, struct ast_msg_data_attribute attributes[], size_t count)
Allocates an ast_msg_data structure.
@ AST_MSG_DATA_ATTR_BODY
Definition message.h:458
@ AST_MSG_DATA_SOURCE_TYPE_UNKNOWN
Definition message.h:447
enum ast_msg_data_attribute_type type
Definition message.h:463
Structure used to transport a message through the frame core.
#define ARRAY_LEN(a)
Definition utils.h:706

References ARRAY_LEN, ast_free, ast_msg_data_alloc(), AST_MSG_DATA_ATTR_BODY, AST_MSG_DATA_SOURCE_TYPE_UNKNOWN, chan_pjsip_sendtext_data(), text, and ast_msg_data_attribute::type.

◆ chan_pjsip_sendtext_data()

static int chan_pjsip_sendtext_data ( struct ast_channel *  ast,
struct ast_msg_data *  msg 
)
static

Function called by core to send text on PJSIP session.

Definition at line 3003 of file chan_pjsip.c.

3004{
3005 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(ast);
3006 struct sendtext_data *data = sendtext_data_create(ast, msg);
3007
3008 ast_debug(1, "Sending MESSAGE from '%s' to '%s:%s': %s\n",
3011 ast_channel_name(ast),
3013
3014 if (!data) {
3015 return -1;
3016 }
3017
3018 if (ast_sip_push_task(channel->session->serializer, sendtext, data)) {
3019 ao2_ref(data, -1);
3020 return -1;
3021 }
3022 return 0;
3023}
static int sendtext(void *obj)
static struct sendtext_data * sendtext_data_create(struct ast_channel *chan, struct ast_msg_data *msg)
const char * ast_msg_data_get_attribute(struct ast_msg_data *msg, enum ast_msg_data_attribute_type attribute_type)
Get attribute from ast_msg_data.
@ AST_MSG_DATA_ATTR_TO
Definition message.h:455
@ AST_MSG_DATA_ATTR_FROM
Definition message.h:456
struct ast_msg_data * msg

References ao2_ref, ast_channel_name(), ast_channel_tech_pvt(), ast_debug, AST_MSG_DATA_ATTR_BODY, AST_MSG_DATA_ATTR_FROM, AST_MSG_DATA_ATTR_TO, ast_msg_data_get_attribute(), ast_sip_push_task, sendtext_data::msg, sendtext(), sendtext_data_create(), ast_sip_session::serializer, and ast_sip_channel_pvt::session.

Referenced by chan_pjsip_sendtext().

◆ chan_pjsip_session_begin()

static void chan_pjsip_session_begin ( struct ast_sip_session *  session)
static

SIP session interaction functions.

Definition at line 3047 of file chan_pjsip.c.

3048{
3049 RAII_VAR(struct ast_datastore *, datastore, NULL, ao2_cleanup);
3051
3052 if (session->endpoint->media.direct_media.glare_mitigation ==
3054 SCOPE_EXIT_RTN("Direct media no glare mitigation\n");
3055 }
3056
3058 "direct_media_glare_mitigation");
3059
3060 if (!datastore) {
3061 SCOPE_EXIT_RTN("Couldn't create datastore\n");
3062 }
3063
3066}
static struct ast_datastore_info direct_media_mitigation_info
Definition chan_pjsip.c:371
@ AST_SIP_DIRECT_MEDIA_GLARE_MITIGATION_NONE
Definition res_pjsip.h:724

References ao2_cleanup, AST_SIP_DIRECT_MEDIA_GLARE_MITIGATION_NONE, ast_sip_session_add_datastore(), ast_sip_session_alloc_datastore(), ast_sip_session_get_name(), direct_media_mitigation_info, NULL, RAII_VAR, SCOPE_ENTER, SCOPE_EXIT_RTN, and session.

◆ chan_pjsip_session_end()

static void chan_pjsip_session_end ( struct ast_sip_session *  session)
static

Function called when the session ends.

Definition at line 3069 of file chan_pjsip.c.

3070{
3071 int existing_cause = 0;
3072 int existing_tech_cause = 0;
3073 int new_cause = 0;
3074 int new_tech_cause = 0;
3076
3077 if (session->inv_session) {
3078 ast_trace(-1, "%s: inv_session->cause: %d\n", ast_sip_session_get_name(session),
3079 session->inv_session->cause);
3080 }
3081
3082 if (!session->channel) {
3083 SCOPE_EXIT_RTN("%s: No channel\n", ast_sip_session_get_name(session));
3084 }
3085
3086 if (session->active_media_state &&
3087 session->active_media_state->default_session[AST_MEDIA_TYPE_AUDIO]) {
3088 struct ast_sip_session_media *media =
3089 session->active_media_state->default_session[AST_MEDIA_TYPE_AUDIO];
3090 if (media->rtp) {
3092 }
3093 }
3094
3096 ast_set_hangupsource(session->channel, ast_channel_name(session->channel), 0);
3097
3098 existing_cause = ast_channel_hangupcause(session->channel);
3099 new_cause = existing_cause;
3100 existing_tech_cause = ast_channel_tech_hangupcause(session->channel);
3101 new_tech_cause = existing_tech_cause;
3102
3103 ast_trace(-1, "%s: existing ast_cause: %d tech_cause: %d\n", ast_sip_session_get_name(session),
3104 existing_cause, existing_tech_cause);
3105
3106 if (session->inv_session) {
3107 struct ao2_iterator dialed_causes_iterator = ast_channel_dialed_causes_iterator(session->channel);
3108 struct ast_control_pvt_cause_code *pvt_cause;
3109 int tech_cause = 0;
3110
3111 /*
3112 * The dialed causes represent the results of each channel dialed but we are only
3113 * interested in the cause codes for _this_ channel. For example, in a redirect
3114 * scenario, if this channel is the redirecting channel (it responded with a 302),
3115 * then chan_pjsip_incoming_response_update_cause() will have been called with the
3116 * 302 and it would have been added to the dialed causes for this channel. When this
3117 * session ends however, the inv_session->cause will probably be something like
3118 * "487 Request terminated" which is just a generic "the session ended" code and
3119 * not really informative.
3120 *
3121 * We'll iterate over the dialed causes to find the one for this channel and if we
3122 * find one with a non-2xx SIP response code, we'll use that cause code for the
3123 * channel hangup cause instead of the generic 487 cause code that results from
3124 * the session termination.
3125 */
3126 while ((pvt_cause = ao2_iterator_next(&dialed_causes_iterator))) {
3127 if (ast_strings_equal(pvt_cause->chan_name, ast_channel_name(session->channel))) {
3128 /*
3129 * The "SIP <code> <reason>" format for pvt_cause->code is set in
3130 * chan_pjsip_incoming_response_update_cause but only for PJSIP channels.
3131 * However, since we've just checked that the chan_name matches our channel,
3132 * we can be confident that this format is correct and attempt to parse out the
3133 * tech cause from it. If for some reason it doesn't match this format,
3134 * we'll just log a trace/debug and skip using this cause code.
3135 */
3136 int count = sscanf(pvt_cause->code, "SIP %d ", &tech_cause);
3137 if (count != 1) {
3138 ast_trace(-1, "%s: Unable to parse tech_cause from code '%s'\n",
3140 continue;
3141 }
3142 /* We only want to use non-2XX SIP response codes */
3143 if (tech_cause / 100 > 2) {
3144 new_tech_cause = tech_cause;
3145 if (!existing_cause) {
3146 new_cause = pvt_cause->ast_cause;
3147 }
3148 ast_trace(-1, "%s: %s dialed ast_cause: %d tech_cause: %d used\n", ast_sip_session_get_name(session),
3149 pvt_cause->chan_name, new_cause, new_tech_cause);
3150 } else {
3151 ast_trace(-1, "%s: %s dialed ast_cause: %d tech_cause: %s. Skipped 2XX code.\n",
3153 pvt_cause->ast_cause, pvt_cause->code);
3154 }
3155 } else {
3156 ast_trace(-1, "%s: %s dialed ast_cause: %d tech_cause: %s. Skipped other channel.\n",
3158 pvt_cause->ast_cause, pvt_cause->code);
3159 }
3160 ao2_cleanup(pvt_cause);
3161 }
3162 ao2_iterator_destroy(&dialed_causes_iterator);
3163
3164 /*
3165 * We have a chicken and egg thing going here. We can derive the tech_cause
3166 * from the ast cause but we can also derive the ast cause from the tech cause.
3167 */
3168
3169 /* We only want to use non 2XX response codes for tech cause. */
3170 if (new_tech_cause == 0 && session->inv_session->cause / 100 > 2) {
3171 new_tech_cause = session->inv_session->cause;
3172 ast_trace(-1, "%s: Using tech_cause %d from invite session\n",
3173 ast_sip_session_get_name(session), session->inv_session->cause);
3174 }
3175
3176 if (new_cause == 0 && new_tech_cause > 0) {
3177 new_cause = ast_sip_hangup_sip2cause(new_tech_cause);
3178 ast_trace(-1, "%s: Using ast_cause %d derived from tech_cause %d\n",
3179 ast_sip_session_get_name(session), new_cause, new_tech_cause);
3180 }
3181
3182 if (new_cause != existing_cause) {
3183 ast_trace(-1, "%s: Setting ast_cause %d\n",
3184 ast_sip_session_get_name(session), new_cause);
3185 ast_channel_hangupcause_set(session->channel, new_cause);
3186 }
3187
3188 if (new_tech_cause == 0) {
3189 new_tech_cause = hangup_cause2sip(new_cause);
3190 ast_trace(-1, "%s: Using tech_cause cause %d derived from ast_cause %d\n",
3191 ast_sip_session_get_name(session), new_tech_cause, new_cause);
3192 }
3193
3194 if (new_tech_cause != existing_tech_cause && new_tech_cause / 100 > 2) {
3195 ast_trace(-1, "%s: Setting tech_cause %d\n",
3196 ast_sip_session_get_name(session), new_tech_cause);
3197 ast_channel_tech_hangupcause_set(session->channel, new_tech_cause);
3198 }
3199 }
3200
3201 ast_queue_hangup(session->channel);
3202
3203 SCOPE_EXIT_RTN("%s: ast_cause: %d tech_cause: %d\n", ast_sip_session_get_name(session),
3204 new_cause, new_tech_cause);
3205}
#define ao2_iterator_next(iter)
Definition astobj2.h:1911
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
struct ao2_iterator ast_channel_dialed_causes_iterator(const struct ast_channel *chan)
Retrieve an iterator for dialed cause information.
void ast_rtp_instance_set_stats_vars(struct ast_channel *chan, struct ast_rtp_instance *instance)
Set standard statistics from an RTP instance on a channel.
int ast_strings_equal(const char *str1, const char *str2)
Compare strings for equality checking for NULL.
Definition strings.c:238
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition astobj2.h:1821

References ao2_cleanup, ao2_iterator_destroy(), ao2_iterator_next, ast_control_pvt_cause_code::ast_cause, ast_channel_dialed_causes_iterator(), ast_channel_hangupcause(), ast_channel_hangupcause_set(), ast_channel_name(), ast_channel_tech_hangupcause(), ast_channel_tech_hangupcause_set(), ast_channel_uniqueid(), AST_MEDIA_TYPE_AUDIO, ast_queue_hangup(), ast_rtp_instance_set_stats_vars(), ast_set_hangupsource(), ast_sip_hangup_sip2cause(), ast_sip_session_get_name(), ast_strings_equal(), ast_trace, ast_control_pvt_cause_code::chan_name, chan_pjsip_remove_hold(), ast_control_pvt_cause_code::code, hangup_cause2sip(), ast_sip_session_media::rtp, SCOPE_ENTER, SCOPE_EXIT_RTN, and session.

◆ chan_pjsip_set_rtp_peer()

static int chan_pjsip_set_rtp_peer ( struct ast_channel *  chan,
struct ast_rtp_instance *  rtp,
struct ast_rtp_instance *  vrtp,
struct ast_rtp_instance *  tpeer,
const struct ast_format_cap *  cap,
int  nat_active 
)
static

Function called by RTP engine to change where the remote party should send media.

Definition at line 546 of file chan_pjsip.c.

552{
553 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(chan);
554 struct ast_sip_session *session = channel->session;
556 SCOPE_ENTER(1, "%s %s\n", ast_channel_name(chan),
558
559 /* Don't try to do any direct media shenanigans on early bridges */
560 if ((rtp || vrtp || tpeer) && !ast_channel_is_bridged(chan)) {
561 ast_debug(4, "Disregarding setting RTP on %s: channel is not bridged\n", ast_channel_name(chan));
562 SCOPE_EXIT_RTN_VALUE(0, "Channel not bridged\n");
563 }
564
565 if (nat_active && session->endpoint->media.direct_media.disable_on_nat) {
566 ast_debug(4, "Disregarding setting RTP on %s: NAT is active\n", ast_channel_name(chan));
567 SCOPE_EXIT_RTN_VALUE(0, "NAT is active\n");
568 }
569
571 if (!cdata) {
573 }
574
576 ast_log(LOG_ERROR, "Unable to send direct media request for channel %s\n", ast_channel_name(chan));
577 ao2_ref(cdata, -1);
578 }
579
581}
static struct rtp_direct_media_data * rtp_direct_media_data_create(struct ast_channel *chan, struct ast_rtp_instance *rtp, struct ast_rtp_instance *vrtp, const struct ast_format_cap *cap, struct ast_sip_session *session)
Definition chan_pjsip.c:474
static int send_direct_media_request(void *data)
Definition chan_pjsip.c:493
static int cdata(void *userdata, int state, const char *cdata, size_t len)
struct ast_rtp_instance * vrtp
Definition chan_pjsip.c:458
struct ast_channel * chan
Definition chan_pjsip.c:456
struct ast_rtp_instance * rtp
Definition chan_pjsip.c:457
struct ast_format_cap * cap
Definition chan_pjsip.c:459

References ao2_ref, ast_channel_is_bridged(), ast_channel_name(), ast_channel_tech_pvt(), ast_debug, ast_format_cap_get_names(), AST_FORMAT_CAP_NAMES_LEN, ast_log, ast_sip_push_task, ast_str_tmp, rtp_direct_media_data::cap, cdata(), rtp_direct_media_data::chan, ast_sip_session::channel, LOG_ERROR, rtp_direct_media_data::rtp, rtp_direct_media_data_create(), SCOPE_ENTER, SCOPE_EXIT_RTN_VALUE, send_direct_media_request(), session, and rtp_direct_media_data::vrtp.

◆ chan_pjsip_transfer()

static int chan_pjsip_transfer ( struct ast_channel *  ast,
const char *  target 
)
static

Function called by core for Asterisk initiated transfer.

Definition at line 2283 of file chan_pjsip.c.

2284{
2285 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(chan);
2286 struct transfer_data *trnf_data = transfer_data_alloc(channel->session, target);
2287
2288 if (!trnf_data) {
2289 return -1;
2290 }
2291
2292 if (ast_sip_push_task(channel->session->serializer, transfer, trnf_data)) {
2293 ast_log(LOG_WARNING, "Error requesting transfer\n");
2294 ao2_cleanup(trnf_data);
2295 return -1;
2296 }
2297
2298 return 0;
2299}
static int transfer(void *data)
static struct transfer_data * transfer_data_alloc(struct ast_sip_session *session, const char *target)

References ao2_cleanup, ast_channel_tech_pvt(), ast_log, ast_sip_push_task, LOG_WARNING, ast_sip_session::serializer, ast_sip_channel_pvt::session, transfer_data::target, transfer(), and transfer_data_alloc().

◆ chan_pjsip_write()

static int chan_pjsip_write ( struct ast_channel *  ast,
struct ast_frame *  f 
)
static

Definition at line 1150 of file chan_pjsip.c.

1151{
1152 return chan_pjsip_write_stream(ast, -1, frame);
1153}
static int chan_pjsip_write_stream(struct ast_channel *ast, int stream_num, struct ast_frame *f)

References chan_pjsip_write_stream().

◆ chan_pjsip_write_stream()

static int chan_pjsip_write_stream ( struct ast_channel *  ast,
int  stream_num,
struct ast_frame *  f 
)
static

Definition at line 1060 of file chan_pjsip.c.

1061{
1062 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(ast);
1063 struct ast_sip_session *session = channel->session;
1064 struct ast_sip_session_media *media = NULL;
1065 int res = 0;
1066
1067 /* The core provides a guarantee that the stream will exist when we are called if stream_num is provided */
1068 if (stream_num >= 0) {
1069 /* What is not guaranteed is that a media session will exist */
1072 }
1073 }
1074
1075 switch (frame->frametype) {
1076 case AST_FRAME_VOICE:
1077 if (!media) {
1078 return 0;
1079 } else if (media->type != AST_MEDIA_TYPE_AUDIO) {
1080 ast_debug(3, "Channel %s stream %d is of type '%s', not audio!\n",
1082 return 0;
1083 } else if (media == channel->session->active_media_state->default_session[AST_MEDIA_TYPE_AUDIO] &&
1086 struct ast_str *write_transpath = ast_str_alloca(256);
1087 struct ast_str *read_transpath = ast_str_alloca(256);
1088
1090 "Channel %s asked to send %s frame when native formats are %s (rd:%s->%s;%s wr:%s->%s;%s)\n",
1091 ast_channel_name(ast),
1092 ast_format_get_name(frame->subclass.format),
1096 ast_translate_path_to_str(ast_channel_readtrans(ast), &read_transpath),
1099 ast_translate_path_to_str(ast_channel_writetrans(ast), &write_transpath));
1100 return 0;
1101 } else if (media->write_callback) {
1102 res = media->write_callback(session, media, frame);
1103
1104 }
1105 break;
1106 case AST_FRAME_VIDEO:
1107 if (!media) {
1108 return 0;
1109 } else if (media->type != AST_MEDIA_TYPE_VIDEO) {
1110 ast_debug(3, "Channel %s stream %d is of type '%s', not video!\n",
1111 ast_channel_name(ast), stream_num, ast_codec_media_type2str(media->type));
1112 return 0;
1113 } else if (media->write_callback) {
1114 res = media->write_callback(session, media, frame);
1115 }
1116 break;
1117 case AST_FRAME_MODEM:
1118 if (!media) {
1119 return 0;
1120 } else if (media->type != AST_MEDIA_TYPE_IMAGE) {
1121 ast_debug(3, "Channel %s stream %d is of type '%s', not image!\n",
1122 ast_channel_name(ast), stream_num, ast_codec_media_type2str(media->type));
1123 return 0;
1124 } else if (media->write_callback) {
1125 res = media->write_callback(session, media, frame);
1126 }
1127 break;
1128 case AST_FRAME_CNG:
1129 break;
1130 case AST_FRAME_RTCP:
1131 /* We only support writing out feedback */
1132 if (frame->subclass.integer != AST_RTP_RTCP_PSFB || !media) {
1133 return 0;
1134 } else if (media->type != AST_MEDIA_TYPE_VIDEO) {
1135 ast_debug(3, "Channel %s stream %d is of type '%s', not video! Unable to write RTCP feedback.\n",
1136 ast_channel_name(ast), stream_num, ast_codec_media_type2str(media->type));
1137 return 0;
1138 } else if (media->write_callback) {
1139 res = media->write_callback(session, media, frame);
1140 }
1141 break;
1142 default:
1143 ast_log(LOG_WARNING, "Can't send %u type frames with PJSIP\n", frame->frametype);
1144 break;
1145 }
1146
1147 return res;
1148}
struct ast_format * ast_channel_rawreadformat(struct ast_channel *chan)
struct ast_trans_pvt * ast_channel_readtrans(const struct ast_channel *chan)
struct ast_trans_pvt * ast_channel_writetrans(const struct ast_channel *chan)
@ AST_MEDIA_TYPE_IMAGE
Definition codec.h:34
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:348
#define AST_RTP_RTCP_PSFB
Definition rtp_engine.h:329
#define ast_str_alloca(init_len)
Definition strings.h:848
ast_sip_session_media_write_cb write_callback
The write callback when writing frames.
int stream_num
The stream number to place into any resulting frames.
Support for dynamic strings.
Definition strings.h:623
const char * ast_translate_path_to_str(struct ast_trans_pvt *t, struct ast_str **str)
Puts a string representation of the translation path into outbuf.
Definition translate.c:1145

References ast_sip_session::active_media_state, ast_channel_name(), ast_channel_nativeformats(), ast_channel_rawreadformat(), ast_channel_rawwriteformat(), ast_channel_readformat(), ast_channel_readtrans(), ast_channel_tech_pvt(), ast_channel_writeformat(), ast_channel_writetrans(), ast_codec_media_type2str(), ast_debug, ast_format_cap_get_names(), ast_format_cap_iscompatible_format(), AST_FORMAT_CAP_NAMES_LEN, AST_FORMAT_CMP_NOT_EQUAL, ast_format_get_name(), AST_FRAME_CNG, AST_FRAME_MODEM, AST_FRAME_RTCP, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_log, AST_MEDIA_TYPE_AUDIO, AST_MEDIA_TYPE_IMAGE, AST_MEDIA_TYPE_VIDEO, AST_RTP_RTCP_PSFB, ast_str_alloca, ast_translate_path_to_str(), AST_VECTOR_GET, AST_VECTOR_SIZE, ast_sip_session::channel, ast_sip_session_media_state::default_session, ast_frame_subclass::format, ast_frame::frametype, ast_frame_subclass::integer, LOG_WARNING, NULL, ast_sip_channel_pvt::session, session, ast_sip_session_media_state::sessions, ast_sip_session_media::stream_num, ast_frame::subclass, ast_sip_session_media::type, and ast_sip_session_media::write_callback.

Referenced by chan_pjsip_write().

◆ check_for_rtp_changes()

static int check_for_rtp_changes ( struct ast_channel *  chan,
struct ast_rtp_instance *  rtp,
struct ast_sip_session_media *  media,
struct ast_sip_session *  session 
)
static
Precondition
chan is locked

Definition at line 424 of file chan_pjsip.c.

426{
427 int changed = 0, position = -1;
428
429 if (media->rtp) {
430 position = rtp_find_rtcp_fd_position(session, media->rtp);
431 }
432
433 if (rtp) {
435 if (media->rtp) {
436 if (position != -1) {
437 ast_channel_set_fd(chan, position + AST_EXTENDED_FDS, -1);
438 }
440 }
441 } else if (!ast_sockaddr_isnull(&media->direct_media_addr)){
443 changed = 1;
444 if (media->rtp) {
446 if (position != -1) {
447 ast_channel_set_fd(chan, position + AST_EXTENDED_FDS, ast_rtp_instance_fd(media->rtp, 1));
448 }
449 }
450 }
451
452 return changed;
453}
static int rtp_find_rtcp_fd_position(struct ast_sip_session *session, struct ast_rtp_instance *rtp)
Helper function to find the position for RTCP.
Definition chan_pjsip.c:403
void ast_channel_set_fd(struct ast_channel *chan, int which, int fd)
Definition channel.c:2417
static int ast_sockaddr_isnull(const struct ast_sockaddr *addr)
Checks if the ast_sockaddr is null. "null" in this sense essentially means uninitialized,...
Definition netsock2.h:127
static void ast_sockaddr_setnull(struct ast_sockaddr *addr)
Sets address addr to null.
Definition netsock2.h:138
#define ast_rtp_instance_get_and_cmp_remote_address(instance, address)
Get the address of the remote endpoint that we are sending RTP to, comparing its address to another.
void ast_rtp_instance_set_prop(struct ast_rtp_instance *instance, enum ast_rtp_property property, int value)
Set the value of an RTP instance property.
Definition rtp_engine.c:756
@ AST_RTP_PROPERTY_RTCP
Definition rtp_engine.h:126
int ast_rtp_instance_fd(struct ast_rtp_instance *instance, int rtcp)
Get the file descriptor for an RTP session (or RTCP)
struct ast_sockaddr direct_media_addr
Direct media address.

References ast_channel_set_fd(), AST_EXTENDED_FDS, ast_rtp_instance_fd(), ast_rtp_instance_get_and_cmp_remote_address, ast_rtp_instance_set_prop(), AST_RTP_PROPERTY_RTCP, ast_sockaddr_isnull(), ast_sockaddr_setnull(), ast_sip_session_media::direct_media_addr, ast_sip_session_media::rtp, rtp_find_rtcp_fd_position(), and session.

Referenced by send_direct_media_request().

◆ clear_session_and_channel()

static void clear_session_and_channel ( struct ast_sip_session *  session,
struct ast_channel *  ast 
)
static

Clear a channel from a session along with its PVT.

Definition at line 2645 of file chan_pjsip.c.

2646{
2647 /* Serialize detachment with channel-locked readers of the session. */
2648 ast_channel_lock(ast);
2650 ast_channel_unlock(ast);
2651}

References ast_channel_lock, ast_channel_unlock, clear_session_and_channel_locked(), and session.

Referenced by hangup().

◆ clear_session_and_channel_locked()

static void clear_session_and_channel_locked ( struct ast_sip_session *  session,
struct ast_channel *  ast 
)
static

Clear a channel from a session along with its PVT (channel lock held)

Definition at line 2636 of file chan_pjsip.c.

2638{
2639 session->channel = NULL;
2642}

References ast_channel_tech_pvt_set(), NULL, session, and set_channel_on_rtp_instance().

Referenced by chan_pjsip_hangup(), and clear_session_and_channel().

◆ compatible_formats_exist()

static int compatible_formats_exist ( struct ast_stream_topology *  top,
struct ast_format_cap *  cap 
)
static

Determine if a topology is compatible with format capabilities.

This will return true if ANY formats in the topology are compatible with the format capabilities.

XXX When supporting true multistream, we will need to be sure to mark which streams from top1 are compatible with which streams from top2. Then the ones that are not compatible will need to be marked as "removed" so that they are negotiated as expected.

Parameters
topTopology
capFormat capabilities
Return values
1The topology has at least one compatible format
0The topology has no compatible formats or an error occurred.

Definition at line 624 of file chan_pjsip.c.

625{
626 struct ast_format_cap *cap_from_top;
627 int res;
628 SCOPE_ENTER(1, "Topology: %s Formats: %s\n",
631
632 cap_from_top = ast_stream_topology_get_formats(top);
633
634 if (!cap_from_top) {
635 SCOPE_EXIT_RTN_VALUE(0, "Topology had no formats\n");
636 }
637
638 res = ast_format_cap_iscompatible(cap_from_top, cap);
639 ao2_ref(cap_from_top, -1);
640
641 SCOPE_EXIT_RTN_VALUE(res, "Compatible? %s\n", res ? "yes" : "no");
642}
int ast_format_cap_iscompatible(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2)
Determine if any joint capabilities exist between two capabilities structures.
Definition format_cap.c:661

References ao2_ref, ast_format_cap_get_names(), ast_format_cap_iscompatible(), AST_FORMAT_CAP_NAMES_LEN, ast_str_tmp, ast_stream_topology_get_formats(), ast_stream_topology_to_str(), SCOPE_ENTER, and SCOPE_EXIT_RTN_VALUE.

Referenced by chan_pjsip_new().

◆ direct_media_mitigate_glare()

static int direct_media_mitigate_glare ( struct ast_sip_session *  session)
static

Definition at line 373 of file chan_pjsip.c.

374{
375 RAII_VAR(struct ast_datastore *, datastore, NULL, ao2_cleanup);
376
377 if (session->endpoint->media.direct_media.glare_mitigation ==
379 return 0;
380 }
381
382 datastore = ast_sip_session_get_datastore(session, "direct_media_glare_mitigation");
383 if (!datastore) {
384 return 0;
385 }
386
387 /* Removing the datastore ensures we won't try to mitigate glare on subsequent reinvites */
388 ast_sip_session_remove_datastore(session, "direct_media_glare_mitigation");
389
390 if ((session->endpoint->media.direct_media.glare_mitigation ==
392 session->inv_session->role == PJSIP_ROLE_UAC) ||
393 (session->endpoint->media.direct_media.glare_mitigation ==
395 session->inv_session->role == PJSIP_ROLE_UAS)) {
396 return 1;
397 }
398
399 return 0;
400}
@ AST_SIP_DIRECT_MEDIA_GLARE_MITIGATION_INCOMING
Definition res_pjsip.h:732
@ AST_SIP_DIRECT_MEDIA_GLARE_MITIGATION_OUTGOING
Definition res_pjsip.h:728
void ast_sip_session_remove_datastore(struct ast_sip_session *session, const char *name)
Remove a session datastore from the session.

References ao2_cleanup, AST_SIP_DIRECT_MEDIA_GLARE_MITIGATION_INCOMING, AST_SIP_DIRECT_MEDIA_GLARE_MITIGATION_NONE, AST_SIP_DIRECT_MEDIA_GLARE_MITIGATION_OUTGOING, ast_sip_session_get_datastore(), ast_sip_session_remove_datastore(), NULL, RAII_VAR, and session.

Referenced by send_direct_media_request().

◆ handle_topology_request_change()

static int handle_topology_request_change ( struct ast_sip_session *  session,
const struct ast_stream_topology *  proposed 
)
static

Definition at line 1704 of file chan_pjsip.c.

1706{
1708 int res;
1709 SCOPE_ENTER(1);
1710
1712 if (!refresh_data) {
1713 SCOPE_EXIT_RTN_VALUE(-1, "Couldn't create refresh_data\n");
1714 }
1715
1717 if (res) {
1719 }
1720 SCOPE_EXIT_RTN_VALUE(res, "RC: %d\n", res);
1721}
static struct topology_change_refresh_data * topology_change_refresh_data_alloc(struct ast_sip_session *session, const struct ast_stream_topology *topology)
static int send_topology_change_refresh(void *data)
static void topology_change_refresh_data_free(struct topology_change_refresh_data *refresh_data)

References ast_sip_push_task, SCOPE_ENTER, SCOPE_EXIT_RTN_VALUE, send_topology_change_refresh(), session, topology_change_refresh_data_alloc(), and topology_change_refresh_data_free().

Referenced by chan_pjsip_indicate().

◆ hangup()

static int hangup ( void *  data)
static

Definition at line 2653 of file chan_pjsip.c.

2654{
2655 struct hangup_data *h_data = data;
2656 struct ast_channel *ast = h_data->chan;
2657 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(ast);
2658 SCOPE_ENTER(1, "%s\n", ast_channel_name(ast));
2659
2660 /*
2661 * Before cleaning we have to ensure that channel or its session is not NULL
2662 * we have seen rare case when taskprocessor calls hangup but channel is NULL
2663 * due to SIP session timeout and answer happening at the same time
2664 */
2665 if (channel) {
2666 struct ast_sip_session *session = channel->session;
2667 if (session) {
2668 int cause = h_data->cause;
2669
2670 if (channel->session->active_media_state &&
2671 channel->session->active_media_state->default_session[AST_MEDIA_TYPE_AUDIO]) {
2672 struct ast_sip_session_media *media =
2674 if (media->rtp) {
2676 }
2677 }
2678
2679 /*
2680 * It's possible that session_terminate might cause the session to be destroyed
2681 * immediately so we need to keep a reference to it so we can NULL session->channel
2682 * afterwards.
2683 */
2687 }
2688 ao2_cleanup(channel);
2689 }
2690 ao2_cleanup(h_data);
2692}
static void clear_session_and_channel(struct ast_sip_session *session, struct ast_channel *ast)
Clear a channel from a session along with its PVT.
struct ast_channel * chan

References ast_sip_session::active_media_state, ao2_bump, ao2_cleanup, ast_channel_name(), ast_channel_tech_pvt(), AST_MEDIA_TYPE_AUDIO, ast_rtp_instance_set_stats_vars(), ast_sip_session_terminate(), hangup_data::cause, hangup_data::chan, ast_sip_session::channel, clear_session_and_channel(), ast_sip_session_media_state::default_session, ast_sip_session_media::rtp, SCOPE_ENTER, SCOPE_EXIT_RTN_VALUE, ast_sip_channel_pvt::session, and session.

Referenced by ast_audiosocket_receive_frame_with_hangup(), ast_hangup(), audiosocket_read(), audiosocket_run(), chan_pjsip_hangup(), destroy_conference_bridge(), hangup_data_destroy(), hangup_data_init(), hangup_playback(), manage_calls(), play_on_channel(), playback_final_update(), and sla_stop_ringing_station().

◆ hangup_cause2sip()

static int hangup_cause2sip ( int  cause)
static

Internal function which translates from Asterisk cause codes to SIP response codes.

Definition at line 2560 of file chan_pjsip.c.

2561{
2562 switch (cause) {
2564 return 302;
2565 case AST_CAUSE_UNALLOCATED: /* 1 */
2566 case AST_CAUSE_NO_ROUTE_DESTINATION: /* 3 IAX2: Can't find extension in context */
2567 case AST_CAUSE_NO_ROUTE_TRANSIT_NET: /* 2 */
2568 return 404;
2569 case AST_CAUSE_CONGESTION: /* 34 */
2570 case AST_CAUSE_SWITCH_CONGESTION: /* 42 */
2571 return 503;
2572 case AST_CAUSE_NO_USER_RESPONSE: /* 18 */
2573 return 408;
2574 case AST_CAUSE_NO_ANSWER: /* 19 */
2575 case AST_CAUSE_UNREGISTERED: /* 20 */
2576 return 480;
2577 case AST_CAUSE_CALL_REJECTED: /* 21 */
2578 return 403;
2579 case AST_CAUSE_NUMBER_CHANGED: /* 22 */
2580 return 410;
2581 case AST_CAUSE_NORMAL_UNSPECIFIED: /* 31 */
2582 return 480;
2584 return 484;
2586 return 486;
2587 case AST_CAUSE_FAILURE:
2588 return 500;
2589 case AST_CAUSE_FACILITY_REJECTED: /* 29 */
2590 return 501;
2592 return 503;
2594 return 502;
2595 case AST_CAUSE_BEARERCAPABILITY_NOTAVAIL: /* Can't find codec to connect to host */
2596 return 488;
2597 case AST_CAUSE_INTERWORKING: /* Unspecified Interworking issues */
2598 return 500;
2600 default:
2601 ast_debug(1, "AST hangup cause %d (no match found in PJSIP)\n", cause);
2602 return 0;
2603 }
2604
2605 /* Never reached */
2606 return 0;
2607}
#define AST_CAUSE_SWITCH_CONGESTION
Definition causes.h:123
#define AST_CAUSE_CONGESTION
Definition causes.h:153
#define AST_CAUSE_UNALLOCATED
Definition causes.h:98
#define AST_CAUSE_INTERWORKING
Definition causes.h:146
#define AST_CAUSE_NUMBER_CHANGED
Definition causes.h:112
#define AST_CAUSE_BEARERCAPABILITY_NOTAVAIL
Definition causes.h:130
#define AST_CAUSE_INVALID_NUMBER_FORMAT
Definition causes.h:116
#define AST_CAUSE_CHAN_NOT_IMPLEMENTED
Definition causes.h:132
#define AST_CAUSE_DESTINATION_OUT_OF_ORDER
Definition causes.h:115
#define AST_CAUSE_NO_USER_RESPONSE
Definition causes.h:108
#define AST_CAUSE_REDIRECTED_TO_NEW_DESTINATION
Definition causes.h:113
#define AST_CAUSE_NOTDEFINED
Definition causes.h:155
#define AST_CAUSE_FACILITY_REJECTED
Definition causes.h:117
#define AST_CAUSE_NORMAL_UNSPECIFIED
Definition causes.h:119
#define AST_CAUSE_NO_ROUTE_TRANSIT_NET
Definition causes.h:99
#define AST_CAUSE_NO_ROUTE_DESTINATION
Definition causes.h:100
#define AST_CAUSE_UNREGISTERED
Definition causes.h:154
#define AST_CAUSE_NO_ANSWER
Definition causes.h:109
#define AST_CAUSE_USER_BUSY
Definition causes.h:107

References AST_CAUSE_BEARERCAPABILITY_NOTAVAIL, AST_CAUSE_CALL_REJECTED, AST_CAUSE_CHAN_NOT_IMPLEMENTED, AST_CAUSE_CONGESTION, AST_CAUSE_DESTINATION_OUT_OF_ORDER, AST_CAUSE_FACILITY_REJECTED, AST_CAUSE_FAILURE, AST_CAUSE_INTERWORKING, AST_CAUSE_INVALID_NUMBER_FORMAT, AST_CAUSE_NO_ANSWER, AST_CAUSE_NO_ROUTE_DESTINATION, AST_CAUSE_NO_ROUTE_TRANSIT_NET, AST_CAUSE_NO_USER_RESPONSE, AST_CAUSE_NORMAL_UNSPECIFIED, AST_CAUSE_NOTDEFINED, AST_CAUSE_NUMBER_CHANGED, AST_CAUSE_REDIRECTED_TO_NEW_DESTINATION, AST_CAUSE_SWITCH_CONGESTION, AST_CAUSE_UNALLOCATED, AST_CAUSE_UNREGISTERED, AST_CAUSE_USER_BUSY, and ast_debug.

Referenced by chan_pjsip_hangup(), and chan_pjsip_session_end().

◆ hangup_data_alloc()

static struct hangup_data * hangup_data_alloc ( int  cause,
struct ast_channel *  chan 
)
static

Definition at line 2621 of file chan_pjsip.c.

2622{
2623 struct hangup_data *h_data = ao2_alloc(sizeof(*h_data), hangup_data_destroy);
2624
2625 if (!h_data) {
2626 return NULL;
2627 }
2628
2629 h_data->cause = cause;
2630 h_data->chan = ast_channel_ref(chan);
2631
2632 return h_data;
2633}
#define ao2_alloc(data_size, destructor_fn)
Definition astobj2.h:409
static void hangup_data_destroy(void *obj)

References ao2_alloc, ast_channel_ref, hangup_data::cause, hangup_data::chan, hangup_data_destroy(), and NULL.

Referenced by chan_pjsip_hangup().

◆ hangup_data_destroy()

static void hangup_data_destroy ( void *  obj)
static

Definition at line 2614 of file chan_pjsip.c.

2615{
2616 struct hangup_data *h_data = obj;
2617
2618 h_data->chan = ast_channel_unref(h_data->chan);
2619}

References ast_channel_unref, and hangup_data::chan.

Referenced by hangup_data_alloc().

◆ indicate()

static int indicate ( void *  data)
static

Definition at line 1441 of file chan_pjsip.c.

1442{
1443 pjsip_tx_data *packet = NULL;
1444 struct indicate_data *ind_data = data;
1445 struct ast_sip_session *session = ind_data->session;
1446 int response_code = ind_data->response_code;
1447
1448 if ((session->inv_session->state != PJSIP_INV_STATE_DISCONNECTED) &&
1449 (pjsip_inv_answer(session->inv_session, response_code, NULL, NULL, &packet) == PJ_SUCCESS)) {
1451 }
1452
1453 ao2_ref(ind_data, -1);
1454
1455 return 0;
1456}
struct ast_sip_session * session

References ao2_ref, ast_sip_session_send_response(), NULL, indicate_data::response_code, indicate_data::session, and session.

Referenced by ast_channel_request_stream_topology_change(), ast_channel_stream_topology_changed(), chan_pjsip_indicate(), and indicate_data_internal().

◆ indicate_data_alloc()

static struct indicate_data * indicate_data_alloc ( struct ast_sip_session *  session,
int  condition,
int  response_code,
const void *  frame_data,
size_t  datalen 
)
static

Definition at line 1416 of file chan_pjsip.c.

1418{
1419 struct indicate_data *ind_data = ao2_alloc(sizeof(*ind_data), indicate_data_destroy);
1420
1421 if (!ind_data) {
1422 return NULL;
1423 }
1424
1425 ind_data->frame_data = ast_malloc(datalen);
1426 if (!ind_data->frame_data) {
1427 ao2_ref(ind_data, -1);
1428 return NULL;
1429 }
1430
1431 memcpy(ind_data->frame_data, frame_data, datalen);
1432 ind_data->datalen = datalen;
1433 ind_data->condition = condition;
1434 ind_data->response_code = response_code;
1435 ao2_ref(session, +1);
1436 ind_data->session = session;
1437
1438 return ind_data;
1439}
#define ast_malloc(len)
A wrapper for malloc()
Definition astmm.h:191
static void indicate_data_destroy(void *obj)
void * frame_data

References ao2_alloc, ao2_ref, ast_malloc, indicate_data::condition, indicate_data::datalen, indicate_data::frame_data, indicate_data_destroy(), NULL, indicate_data::response_code, indicate_data::session, and session.

Referenced by chan_pjsip_indicate().

◆ indicate_data_destroy()

static void indicate_data_destroy ( void *  obj)
static

Definition at line 1408 of file chan_pjsip.c.

1409{
1410 struct indicate_data *ind_data = obj;
1411
1412 ast_free(ind_data->frame_data);
1413 ao2_ref(ind_data->session, -1);
1414}

References ao2_ref, ast_free, indicate_data::frame_data, and indicate_data::session.

Referenced by indicate_data_alloc().

◆ info_dtmf_data_alloc()

static struct info_dtmf_data * info_dtmf_data_alloc ( struct ast_sip_session *  session,
char  digit,
unsigned int  duration 
)
static

Definition at line 2357 of file chan_pjsip.c.

2358{
2359 struct info_dtmf_data *dtmf_data = ao2_alloc(sizeof(*dtmf_data), info_dtmf_data_destroy);
2360 if (!dtmf_data) {
2361 return NULL;
2362 }
2363 ao2_ref(session, +1);
2364 dtmf_data->session = session;
2365 dtmf_data->digit = digit;
2366 dtmf_data->duration = duration;
2367 return dtmf_data;
2368}
static void info_dtmf_data_destroy(void *obj)
struct ast_sip_session * session

References ao2_alloc, ao2_ref, digit, info_dtmf_data::digit, info_dtmf_data::duration, info_dtmf_data_destroy(), NULL, info_dtmf_data::session, and session.

Referenced by chan_pjsip_digit_end(), and chan_pjsip_indicate().

◆ info_dtmf_data_destroy()

static void info_dtmf_data_destroy ( void *  obj)
static

Definition at line 2351 of file chan_pjsip.c.

2352{
2353 struct info_dtmf_data *dtmf_data = obj;
2354 ao2_ref(dtmf_data->session, -1);
2355}

References ao2_ref, and info_dtmf_data::session.

Referenced by info_dtmf_data_alloc().

◆ is_colp_update_allowed()

static int is_colp_update_allowed ( struct ast_sip_session *  session)
static

Definition at line 1510 of file chan_pjsip.c.

1511{
1512 struct ast_party_id connected_id;
1513 int update_allowed = 0;
1514
1515 if (!session->endpoint->id.send_connected_line
1516 || (!session->endpoint->id.send_pai && !session->endpoint->id.send_rpid)) {
1517 return 0;
1518 }
1519
1520 /*
1521 * Check if privacy allows the update. Check while the channel
1522 * is locked so we can work with the shallow connected_id copy.
1523 */
1524 ast_channel_lock(session->channel);
1525 connected_id = ast_channel_connected_effective_id(session->channel);
1526 if (connected_id.number.valid
1527 && (session->endpoint->id.trust_outbound
1529 update_allowed = 1;
1530 }
1531 ast_channel_unlock(session->channel);
1532
1533 return update_allowed;
1534}
#define AST_PRES_ALLOWED
Definition callerid.h:432
#define AST_PRES_RESTRICTION
Definition callerid.h:431
int ast_party_id_presentation(const struct ast_party_id *id)
Determine the overall presentation value for the given party.
Definition channel.c:1808
struct ast_party_id ast_channel_connected_effective_id(struct ast_channel *chan)
Information needed to identify an endpoint in a call.
Definition channel.h:340

References ast_channel_connected_effective_id(), ast_channel_lock, ast_channel_unlock, ast_party_id_presentation(), AST_PRES_ALLOWED, AST_PRES_RESTRICTION, ast_party_id::number, session, and ast_party_number::valid.

Referenced by update_connected_line_information().

◆ is_compatible_format()

static int is_compatible_format ( struct ast_sip_session *  session,
struct ast_frame *  f 
)
static

Determine if the given frame is in a format we've negotiated.

Definition at line 935 of file chan_pjsip.c.

936{
937 struct ast_stream_topology *topology = session->active_media_state->topology;
938 struct ast_stream *stream = ast_stream_topology_get_stream(topology, f->stream_num);
939 const struct ast_format_cap *cap = ast_stream_get_formats(stream);
940
942}
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:791
const struct ast_format_cap * ast_stream_get_formats(const struct ast_stream *stream)
Get the current negotiated formats of a stream.
Definition stream.c:330

References ast_format_cap_iscompatible_format(), AST_FORMAT_CMP_NOT_EQUAL, ast_stream_get_formats(), ast_stream_topology_get_stream(), ast_frame_subclass::format, session, ast_frame::stream_num, and ast_frame::subclass.

Referenced by chan_pjsip_read_stream().

◆ load_module()

static int load_module ( void  )
static

Load the module.

Module loading including tests for configuration or dependencies. This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE, or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails tests return AST_MODULE_LOAD_FAILURE. If the module can not load the configuration file or other non-critical problem return AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.

Definition at line 3551 of file chan_pjsip.c.

3552{
3553 struct ao2_container *endpoints;
3554
3557 }
3558
3560
3563
3565 ast_log(LOG_ERROR, "Unable to register channel class %s\n", channel_type);
3566 goto end;
3567 }
3568
3570 ast_log(LOG_ERROR, "Unable to register PJSIP_DIAL_CONTACTS dialplan function\n");
3571 goto end;
3572 }
3573
3575 ast_log(LOG_ERROR, "Unable to register PJSIP_PARSE_URI dialplan function\n");
3576 goto end;
3577 }
3578
3580 ast_log(LOG_ERROR, "Unable to register PJSIP_PARSE_URI_FROM dialplan function\n");
3581 goto end;
3582 }
3583
3585 ast_log(LOG_WARNING, "Unable to register PJSIP_MEDIA_OFFER dialplan function\n");
3586 goto end;
3587 }
3588
3590 ast_log(LOG_WARNING, "Unable to register PJSIP_DTMF_MODE dialplan function\n");
3591 goto end;
3592 }
3593
3595 ast_log(LOG_WARNING, "Unable to register PJSIP_MOH_PASSTHROUGH dialplan function\n");
3596 goto end;
3597 }
3598
3600 ast_log(LOG_WARNING, "Unable to register PJSIP_SEND_SESSION_REFRESH dialplan function\n");
3601 goto end;
3602 }
3603
3605 ast_log(LOG_WARNING, "Unable to register PJSIP_TRANSFER_HANDLING dialplan function\n");
3606 goto end;
3607 }
3608
3610 ast_log(LOG_WARNING, "Unable to register PJSIPHangup dialplan application\n");
3611 goto end;
3612 }
3614
3615
3617
3620
3624 ast_log(LOG_ERROR, "Unable to create held channels container\n");
3625 goto end;
3626 }
3627
3632
3634 ast_log(LOG_ERROR, "Unable to register PJSIP Channel CLI\n");
3635 goto end;
3636 }
3637
3638 /* since endpoints are loaded before the channel driver their device
3639 states get set to 'invalid', so they need to be updated */
3640 if ((endpoints = ast_sip_get_endpoints())) {
3642 ao2_ref(endpoints, -1);
3643 }
3644
3645 return 0;
3646
3647end:
3668
3671
3673}
@ AO2_ALLOC_OPT_LOCK_RWLOCK
Definition astobj2.h:365
#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
#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
@ AO2_CONTAINER_ALLOC_OPT_DUPS_REJECT
Reject objects with duplicate keys in container.
Definition astobj2.h:1188
static int uid_hold_sort_fn(const void *obj_left, const void *obj_right, const int flags)
static pjsip_module chan_pjsip_module
General PJSIP module for chan_pjsip, currently used for REFER subscription data and outgoing request ...
static char * app_pjsip_hangup
static int update_devstate(void *obj, void *arg, int flags)
static struct ast_sip_session_supplement chan_pjsip_supplement
SIP session supplement structure.
Definition chan_pjsip.c:144
static struct ast_custom_function chan_pjsip_dial_contacts_function
static int uid_hold_hash_fn(const void *obj, const int flags)
static struct ast_sip_session_supplement pbx_start_supplement
static struct ast_custom_function chan_pjsip_parse_uri_from_function
static struct ast_sip_session_supplement chan_pjsip_prack_supplement
Definition chan_pjsip.c:173
static struct ast_rtp_glue chan_pjsip_rtp_glue
Local glue for interacting with the RTP engine core.
Definition chan_pjsip.c:584
static const char channel_type[]
Definition chan_pjsip.c:79
static struct ast_custom_function moh_passthrough_function
static struct ast_custom_function media_offer_function
static struct ast_sip_session_supplement chan_pjsip_ack_supplement
Definition chan_pjsip.c:165
static struct ast_custom_function transfer_handling_function
static struct ast_custom_function chan_pjsip_parse_uri_function
static struct ast_custom_function session_refresh_function
static struct ast_sip_session_supplement chan_pjsip_supplement_response
SIP session supplement structure just for responses.
Definition chan_pjsip.c:156
static struct ast_sip_session_supplement call_pickup_supplement
static struct ast_custom_function dtmf_mode_function
void ast_channel_unregister(const struct ast_channel_tech *tech)
Unregister a channel technology.
Definition channel.c:571
int ast_channel_register(const struct ast_channel_tech *tech)
Register a channel technology (a new channel driver) Called by a channel module to register the kind ...
Definition channel.c:540
void pjsip_channel_info_register(void)
Register the channel information session supplement.
void pjsip_channel_info_unregister(void)
Unregister the channel information session supplement.
int pjsip_channel_cli_register(void)
Registers the channel cli commands.
int pjsip_app_hangup(struct ast_channel *chan, const char *data)
PJSIPHangup Dialplan App.
int pjsip_action_hangup(struct mansession *s, const struct message *m)
PJSIPHangup Manager Action.
char * end
Definition eagi_proxy.c:73
int ast_format_cap_append_by_type(struct ast_format_cap *cap, enum ast_media_type type)
Add all codecs Asterisk knows about for a specific type to the capabilities structure.
Definition format_cap.c:216
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition manager.c:7782
static struct ao2_container * endpoints
#define EVENT_FLAG_SYSTEM
Definition manager.h:75
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition manager.h:193
#define EVENT_FLAG_CALL
Definition manager.h:76
int ast_unregister_application(const char *app)
Unregister an application.
Definition pbx_app.c:404
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition module.h:78
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition module.h:640
#define ast_custom_function_register(acf)
Register a custom function.
Definition pbx.h:1563
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
void ast_sip_unregister_service(pjsip_module *module)
Definition res_pjsip.c:127
struct ao2_container * ast_sip_get_endpoints(void)
Retrieve any endpoints available to sorcery.
int ast_sip_register_service(pjsip_module *module)
Register a SIP service in Asterisk.
Definition res_pjsip.c:111
#define ast_sip_session_register_supplement(supplement)
void ast_sip_session_unregister_supplement(struct ast_sip_session_supplement *supplement)
Unregister a an supplement to SIP session processing.
#define ast_rtp_glue_register(glue)
Definition rtp_engine.h:905
int ast_rtp_glue_unregister(struct ast_rtp_glue *glue)
Unregister RTP glue.
Definition rtp_engine.c:418
Generic container type.
struct ast_format_cap * capabilities
Definition channel.h:652

References AO2_ALLOC_OPT_LOCK_RWLOCK, ao2_callback, ao2_cleanup, ao2_container_alloc_hash, AO2_CONTAINER_ALLOC_OPT_DUPS_REJECT, ao2_ref, app_pjsip_hangup, ast_channel_register(), ast_channel_unregister(), ast_custom_function_register, ast_custom_function_unregister(), ast_format_cap_alloc, ast_format_cap_append_by_type(), AST_FORMAT_CAP_FLAG_DEFAULT, ast_log, ast_manager_register_xml, ast_manager_unregister(), AST_MEDIA_TYPE_AUDIO, AST_MODULE_LOAD_DECLINE, ast_register_application_xml, ast_rtp_glue_register, ast_rtp_glue_unregister(), ast_sip_get_endpoints(), ast_sip_register_service(), ast_sip_session_register_supplement, ast_sip_session_unregister_supplement(), ast_sip_unregister_service(), ast_unregister_application(), call_pickup_supplement, ast_channel_tech::capabilities, chan_pjsip_ack_supplement, chan_pjsip_dial_contacts_function, chan_pjsip_module, chan_pjsip_parse_uri_from_function, chan_pjsip_parse_uri_function, chan_pjsip_prack_supplement, chan_pjsip_rtp_glue, chan_pjsip_supplement, chan_pjsip_supplement_response, chan_pjsip_tech, channel_type, dtmf_mode_function, end, endpoints, EVENT_FLAG_CALL, EVENT_FLAG_SYSTEM, LOG_ERROR, LOG_WARNING, media_offer_function, moh_passthrough_function, NULL, OBJ_NODATA, pbx_start_supplement, pjsip_action_hangup(), pjsip_app_hangup(), pjsip_channel_cli_register(), pjsip_channel_info_register(), pjsip_channel_info_unregister(), pjsip_uids_onhold, session_refresh_function, transfer_handling_function, uid_hold_hash_fn(), uid_hold_sort_fn(), and update_devstate().

◆ on_topology_change_response()

static int on_topology_change_response ( struct ast_sip_session *  session,
pjsip_rx_data *  rdata 
)
static

Definition at line 1652 of file chan_pjsip.c.

1653{
1654 SCOPE_ENTER(3, "%s: Received response code %d. PT: %s AT: %s\n", ast_sip_session_get_name(session),
1655 rdata->msg_info.msg->line.status.code,
1656 ast_str_tmp(256, ast_stream_topology_to_str(session->pending_media_state->topology, &STR_TMP)),
1657 ast_str_tmp(256, ast_stream_topology_to_str(session->active_media_state->topology, &STR_TMP)));
1658
1659
1660 if (PJSIP_IS_STATUS_IN_CLASS(rdata->msg_info.msg->line.status.code, 200)) {
1661 /* The topology was changed to something new so give notice to what requested
1662 * it so it queries the channel and updates accordingly.
1663 */
1664 if (session->channel) {
1666 SCOPE_EXIT_RTN_VALUE(0, "%s: Queued topology change frame\n", ast_sip_session_get_name(session));
1667 }
1668 SCOPE_EXIT_RTN_VALUE(0, "%s: No channel? Can't queue topology change frame\n", ast_sip_session_get_name(session));
1669 } else if (300 <= rdata->msg_info.msg->line.status.code) {
1670 /* The topology change failed, so drop the current pending media state */
1671 ast_sip_session_media_state_reset(session->pending_media_state);
1672 SCOPE_EXIT_RTN_VALUE(0, "%s: response code > 300. Resetting pending media state\n", ast_sip_session_get_name(session));
1673 }
1674
1675 SCOPE_EXIT_RTN_VALUE(0, "%s: Nothing to do\n", ast_sip_session_get_name(session));
1676}
void ast_sip_session_media_state_reset(struct ast_sip_session_media_state *media_state)
Reset a media state to a clean state.

References AST_CONTROL_STREAM_TOPOLOGY_CHANGED, ast_queue_control(), ast_sip_session_get_name(), ast_sip_session_media_state_reset(), ast_str_tmp, ast_stream_topology_to_str(), SCOPE_ENTER, SCOPE_EXIT_RTN_VALUE, and session.

Referenced by send_topology_change_refresh().

◆ pbx_start_incoming_request()

static int pbx_start_incoming_request ( struct ast_sip_session *  session,
pjsip_rx_data *  rdata 
)
static

Definition at line 3328 of file chan_pjsip.c.

3329{
3330 int res;
3332
3333 /* Check for a to-tag to determine if this is a reinvite */
3334 if (rdata->msg_info.to->tag.slen) {
3335 /* We don't care about reinvites */
3336 SCOPE_EXIT_RTN_VALUE(0, "Reinvite\n");
3337 }
3338
3339 res = ast_pbx_start(session->channel);
3340
3341 switch (res) {
3342 case AST_PBX_FAILED:
3343 ast_log(LOG_WARNING, "Failed to start PBX ;(\n");
3345 ast_hangup(session->channel);
3346 break;
3347 case AST_PBX_CALL_LIMIT:
3348 ast_log(LOG_WARNING, "Failed to start PBX (call limit reached) \n");
3350 ast_hangup(session->channel);
3351 break;
3352 case AST_PBX_SUCCESS:
3353 default:
3354 break;
3355 }
3356
3357 ast_debug(3, "Started PBX on new PJSIP channel %s\n", ast_channel_name(session->channel));
3358
3359 SCOPE_EXIT_RTN_VALUE((res == AST_PBX_SUCCESS) ? 0 : -1, "RC: %d\n", res);
3360}
@ AST_PBX_FAILED
Definition pbx.h:374
@ AST_PBX_CALL_LIMIT
Definition pbx.h:375
@ AST_PBX_SUCCESS
Definition pbx.h:373
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
Definition pbx.c:3268

References AST_CAUSE_SWITCH_CONGESTION, ast_channel_hangupcause_set(), ast_channel_name(), ast_debug, ast_hangup(), ast_log, AST_PBX_CALL_LIMIT, AST_PBX_FAILED, ast_pbx_start(), AST_PBX_SUCCESS, ast_sip_session_get_name(), LOG_WARNING, SCOPE_ENTER, SCOPE_EXIT_RTN_VALUE, and session.

◆ remote_send_hold()

static int remote_send_hold ( void *  data)
static

Update local hold state to be held.

Definition at line 1603 of file chan_pjsip.c.

1604{
1605 return remote_send_hold_refresh(data, 1);
1606}
static int remote_send_hold_refresh(struct ast_sip_session *session, unsigned int held)
Update local hold state and send a re-INVITE with the new SDP.

References remote_send_hold_refresh().

Referenced by chan_pjsip_indicate().

◆ remote_send_hold_refresh()

static int remote_send_hold_refresh ( struct ast_sip_session *  session,
unsigned int  held 
)
static

Update local hold state and send a re-INVITE with the new SDP.

Definition at line 1590 of file chan_pjsip.c.

1591{
1592 struct ast_sip_session_media *session_media = session->active_media_state->default_session[AST_MEDIA_TYPE_AUDIO];
1593 if (session_media) {
1594 session_media->locally_held = held;
1595 }
1597 ao2_ref(session, -1);
1598
1599 return 0;
1600}
@ AST_SIP_SESSION_REFRESH_METHOD_INVITE
Definition res_pjsip.h:717
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.
unsigned int locally_held
Stream is on hold by local side.

References ao2_ref, AST_MEDIA_TYPE_AUDIO, ast_sip_session_refresh(), AST_SIP_SESSION_REFRESH_METHOD_INVITE, ast_sip_session_media::locally_held, NULL, and session.

Referenced by remote_send_hold(), and remote_send_unhold().

◆ remote_send_unhold()

static int remote_send_unhold ( void *  data)
static

Update local hold state to be unheld.

Definition at line 1609 of file chan_pjsip.c.

1610{
1611 return remote_send_hold_refresh(data, 0);
1612}

References remote_send_hold_refresh().

Referenced by chan_pjsip_indicate().

◆ request()

static int request ( void *  obj)
static

Definition at line 2746 of file chan_pjsip.c.

2747{
2748 struct request_data *req_data = obj;
2749 struct ast_sip_session *session = NULL;
2750 char *tmp = ast_strdupa(req_data->dest), *endpoint_name = NULL, *request_user = NULL;
2751 struct ast_sip_endpoint *endpoint;
2752
2754 AST_APP_ARG(endpoint);
2755 AST_APP_ARG(aor);
2756 );
2757 SCOPE_ENTER(1, "%s\n",tmp);
2758
2759 if (ast_strlen_zero(tmp)) {
2760 ast_log(LOG_ERROR, "Unable to create PJSIP channel with empty destination\n");
2762 SCOPE_EXIT_RTN_VALUE(-1, "Empty destination\n");
2763 }
2764
2765 AST_NONSTANDARD_APP_ARGS(args, tmp, '/');
2766
2768 /* If a request user has been specified extract it from the endpoint name portion */
2769 if ((endpoint_name = strchr(args.endpoint, '@'))) {
2770 request_user = args.endpoint;
2771 *endpoint_name++ = '\0';
2772 } else {
2773 endpoint_name = args.endpoint;
2774 }
2775
2776 if (ast_strlen_zero(endpoint_name)) {
2777 if (request_user) {
2778 ast_log(LOG_ERROR, "Unable to create PJSIP channel with empty endpoint name: %s@<endpoint-name>\n",
2779 request_user);
2780 } else {
2781 ast_log(LOG_ERROR, "Unable to create PJSIP channel with empty endpoint name\n");
2782 }
2784 SCOPE_EXIT_RTN_VALUE(-1, "Empty endpoint name\n");
2785 }
2786 endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint",
2787 endpoint_name);
2788 if (!endpoint) {
2789 ast_log(LOG_ERROR, "Unable to create PJSIP channel - endpoint '%s' was not found\n", endpoint_name);
2791 SCOPE_EXIT_RTN_VALUE(-1, "Endpoint not found\n");
2792 }
2793 } else {
2794 /* First try to find an exact endpoint match, for single (user) or multi-domain (user@domain) */
2795 endpoint_name = args.endpoint;
2796 if (ast_strlen_zero(endpoint_name)) {
2797 ast_log(LOG_ERROR, "Unable to create PJSIP channel with empty endpoint name\n");
2799 SCOPE_EXIT_RTN_VALUE(-1, "Empty endpoint name\n");
2800 }
2801 endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint",
2802 endpoint_name);
2803 if (!endpoint) {
2804 /* It seems it's not a multi-domain endpoint or single endpoint exact match,
2805 * it's possible that it's a SIP trunk with a specified user (user@trunkname),
2806 * so extract the user before @ sign.
2807 */
2808 endpoint_name = strchr(args.endpoint, '@');
2809 if (!endpoint_name) {
2810 /*
2811 * Couldn't find an '@' so it had to be an endpoint
2812 * name that doesn't exist.
2813 */
2814 ast_log(LOG_ERROR, "Unable to create PJSIP channel - endpoint '%s' was not found\n",
2815 args.endpoint);
2817 SCOPE_EXIT_RTN_VALUE(-1, "Endpoint not found\n");
2818 }
2819 request_user = args.endpoint;
2820 *endpoint_name++ = '\0';
2821
2822 if (ast_strlen_zero(endpoint_name)) {
2823 ast_log(LOG_ERROR, "Unable to create PJSIP channel with empty endpoint name: %s@<endpoint-name>\n",
2824 request_user);
2826 SCOPE_EXIT_RTN_VALUE(-1, "Empty endpoint name\n");
2827 }
2828
2829 endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint",
2830 endpoint_name);
2831 if (!endpoint) {
2832 ast_log(LOG_ERROR, "Unable to create PJSIP channel - endpoint '%s' was not found\n", endpoint_name);
2834 SCOPE_EXIT_RTN_VALUE(-1, "Endpoint not found\n");
2835 }
2836 }
2837 }
2838
2839 session = ast_sip_session_create_outgoing(endpoint, NULL, args.aor, request_user,
2840 req_data->topology);
2841 ao2_ref(endpoint, -1);
2842 if (!session) {
2843 ast_log(LOG_ERROR, "Failed to create outgoing session to endpoint '%s'\n", endpoint_name);
2845 SCOPE_EXIT_RTN_VALUE(-1, "Couldn't create session\n");
2846 }
2847
2848 req_data->session = session;
2849
2851}
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition astmm.h:298
#define AST_CAUSE_CHANNEL_UNACCEPTABLE
Definition causes.h:102
#define AST_APP_ARG(name)
Define an application argument.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_NONSTANDARD_APP_ARGS(args, parse, sep)
Performs the 'nonstandard' argument separation process for an application.
unsigned int ast_sip_get_disable_multi_domain(void)
Retrieve the system setting 'disable multi domain'.
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.
static struct @523 args
struct ast_sip_session * session
const char * dest

References ao2_ref, args, AST_APP_ARG, AST_CAUSE_CHANNEL_UNACCEPTABLE, AST_CAUSE_NO_ROUTE_DESTINATION, AST_DECLARE_APP_ARGS, ast_log, AST_NONSTANDARD_APP_ARGS, ast_sip_get_disable_multi_domain(), ast_sip_get_sorcery(), ast_sip_session_create_outgoing(), ast_sorcery_retrieve_by_id(), ast_strdupa, ast_strlen_zero(), request_data::cause, request_data::dest, LOG_ERROR, NULL, SCOPE_ENTER, SCOPE_EXIT_RTN_VALUE, request_data::session, session, and request_data::topology.

Referenced by ari_websocket_process_request(), ast_bridge_channel_merge_inhibit(), ast_bridge_merge_inhibit(), ast_http_body_discard(), ast_http_body_read_status(), ast_http_get_contents(), ast_http_request_close_on_completion(), ast_http_send(), ast_parse_digest(), AST_TEST_DEFINE(), bridge_manager_destroy(), bridge_manager_service_req(), bridge_manager_thread(), bridge_merge_inhibit_nolock(), chan_pjsip_request_with_stream_topology(), ewscal_write_event(), get_ewscal_ids_for(), http_request_tracking_init(), http_request_tracking_setup(), httpd_process_request(), parse_ewscal_id(), parse_rest_request_msg(), request_destroy(), run_agi(), send_ews_request_and_parse(), send_rest_response(), setup_env(), xmpp_pubsub_build_node_request(), xmpp_pubsub_build_publish_skeleton(), xmpp_pubsub_delete_node(), xmpp_pubsub_handle_error(), xmpp_pubsub_iq_create(), xmpp_pubsub_publish_device_state(), xmpp_pubsub_publish_mwi(), xmpp_pubsub_purge_nodes(), xmpp_pubsub_request_nodes(), xmpp_pubsub_subscribe(), and xmpp_pubsub_unsubscribe().

◆ rtp_direct_media_data_create()

static struct rtp_direct_media_data * rtp_direct_media_data_create ( struct ast_channel *  chan,
struct ast_rtp_instance *  rtp,
struct ast_rtp_instance *  vrtp,
const struct ast_format_cap *  cap,
struct ast_sip_session *  session 
)
static

Definition at line 474 of file chan_pjsip.c.

477{
479
480 if (!cdata) {
481 return NULL;
482 }
483
484 cdata->chan = ao2_bump(chan);
485 cdata->rtp = ao2_bump(rtp);
486 cdata->vrtp = ao2_bump(vrtp);
487 cdata->cap = ao2_bump((struct ast_format_cap *)cap);
488 cdata->session = ao2_bump(session);
489
490 return cdata;
491}
static void rtp_direct_media_data_destroy(void *data)
Definition chan_pjsip.c:463

References ao2_alloc, ao2_bump, rtp_direct_media_data::cap, cdata(), rtp_direct_media_data::chan, NULL, rtp_direct_media_data::rtp, rtp_direct_media_data_destroy(), session, and rtp_direct_media_data::vrtp.

Referenced by chan_pjsip_set_rtp_peer().

◆ rtp_direct_media_data_destroy()

static void rtp_direct_media_data_destroy ( void *  data)
static

Definition at line 463 of file chan_pjsip.c.

464{
465 struct rtp_direct_media_data *cdata = data;
466
467 ao2_cleanup(cdata->session);
468 ao2_cleanup(cdata->cap);
469 ao2_cleanup(cdata->vrtp);
470 ao2_cleanup(cdata->rtp);
471 ao2_cleanup(cdata->chan);
472}

References ao2_cleanup, and cdata().

Referenced by rtp_direct_media_data_create().

◆ rtp_find_rtcp_fd_position()

static int rtp_find_rtcp_fd_position ( struct ast_sip_session *  session,
struct ast_rtp_instance *  rtp 
)
static

Helper function to find the position for RTCP.

Definition at line 403 of file chan_pjsip.c.

404{
405 int index;
406
407 for (index = 0; index < AST_VECTOR_SIZE(&session->active_media_state->read_callbacks); ++index) {
408 struct ast_sip_session_media_read_callback_state *callback_state =
409 AST_VECTOR_GET_ADDR(&session->active_media_state->read_callbacks, index);
410
411 if (callback_state->fd != ast_rtp_instance_fd(rtp, 1)) {
412 continue;
413 }
414
415 return index;
416 }
417
418 return -1;
419}

References ast_rtp_instance_fd(), AST_VECTOR_GET_ADDR, AST_VECTOR_SIZE, ast_sip_session_media_read_callback_state::fd, and session.

Referenced by check_for_rtp_changes().

◆ send_direct_media_request()

static int send_direct_media_request ( void *  data)
static

Definition at line 493 of file chan_pjsip.c.

494{
495 struct rtp_direct_media_data *cdata = data;
496 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(cdata->chan);
497 struct ast_sip_session *session;
498 int changed = 0;
499 int res = 0;
500
501 /* XXX In an ideal world each media stream would be direct, but for now preserve behavior
502 * and connect only the default media sessions for audio and video.
503 */
504
505 /* The channel needs to be locked when checking for RTP changes.
506 * Otherwise, we could end up destroying an underlying RTCP structure
507 * at the same time that the channel thread is attempting to read RTCP
508 */
509 ast_channel_lock(cdata->chan);
510 session = channel->session;
511 if (session->active_media_state->default_session[AST_MEDIA_TYPE_AUDIO]) {
512 changed |= check_for_rtp_changes(
513 cdata->chan, cdata->rtp, session->active_media_state->default_session[AST_MEDIA_TYPE_AUDIO], session);
514 }
515 if (session->active_media_state->default_session[AST_MEDIA_TYPE_VIDEO]) {
516 changed |= check_for_rtp_changes(
517 cdata->chan, cdata->vrtp, session->active_media_state->default_session[AST_MEDIA_TYPE_VIDEO], session);
518 }
521
522 if (direct_media_mitigate_glare(cdata->session)) {
523 ast_debug(4, "Disregarding setting RTP on %s: mitigating re-INVITE glare\n", ast_channel_name(cdata->chan));
524 ao2_ref(cdata, -1);
525 return 0;
526 }
527
528 if (cdata->cap && ast_format_cap_count(cdata->cap) &&
529 !ast_format_cap_identical(cdata->session->direct_media_cap, cdata->cap)) {
531 ast_format_cap_append_from_cap(cdata->session->direct_media_cap, cdata->cap, AST_MEDIA_TYPE_UNKNOWN);
532 changed = 1;
533 }
534
535 if (changed) {
536 ast_debug(4, "RTP changed on %s; initiating direct media update\n", ast_channel_name(cdata->chan));
537 res = ast_sip_session_refresh(cdata->session, NULL, NULL, NULL,
538 cdata->session->endpoint->media.direct_media.method, 1, NULL);
539 }
540
541 ao2_ref(cdata, -1);
542 return res;
543}
static int check_for_rtp_changes(struct ast_channel *chan, struct ast_rtp_instance *rtp, struct ast_sip_session_media *media, struct ast_sip_session *session)
Definition chan_pjsip.c:424
static int direct_media_mitigate_glare(struct ast_sip_session *session)
Definition chan_pjsip.c:373
void pjsip_channel_info_update(struct ast_sip_session *session)
Refresh channel information under the channel lock.
int ast_format_cap_identical(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2)
Determine if two capabilities structures are identical.
Definition format_cap.c:695
size_t ast_format_cap_count(const struct ast_format_cap *cap)
Get the number of formats present within the capabilities structure.
Definition format_cap.c:403

References ao2_ref, ast_channel_lock, ast_channel_name(), ast_channel_tech_pvt(), ast_channel_unlock, ast_debug, ast_format_cap_append_from_cap(), ast_format_cap_count(), ast_format_cap_identical(), ast_format_cap_remove_by_type(), AST_MEDIA_TYPE_AUDIO, AST_MEDIA_TYPE_UNKNOWN, AST_MEDIA_TYPE_VIDEO, ast_sip_session_refresh(), cdata(), ast_sip_session::channel, check_for_rtp_changes(), direct_media_mitigate_glare(), NULL, pjsip_channel_info_update(), and session.

Referenced by chan_pjsip_set_rtp_peer().

◆ send_topology_change_refresh()

static int send_topology_change_refresh ( void *  data)
static

Definition at line 1678 of file chan_pjsip.c.

1679{
1684 int ret;
1686 ast_str_tmp(256, ast_stream_topology_to_str(refresh_data->media_state->topology, &STR_TMP)));
1687
1688 /* See RFC 6337, especially section 3.2: If the early media SDP was sent reliably, we are allowed
1689 * to send UPDATEs. Only relevant for AST_STATE_RINGING and AST_STATE_RING - if the channel is UP,
1690 * re-INVITES can be sent.
1691 */
1692 if (session->early_confirmed && (state == AST_STATE_RINGING || state == AST_STATE_RING)) {
1694 }
1695
1697 method, 1, refresh_data->media_state);
1698 refresh_data->media_state = NULL;
1700
1702}
static int on_topology_change_response(struct ast_sip_session *session, pjsip_rx_data *rdata)
const char * method
Definition res_pjsip.c:1277
ast_sip_session_refresh_method
Definition res_pjsip.h:715
@ AST_SIP_SESSION_REFRESH_METHOD_UPDATE
Definition res_pjsip.h:719
struct ast_sip_session * session

References ast_sip_session_get_name(), ast_sip_session_refresh(), AST_SIP_SESSION_REFRESH_METHOD_INVITE, AST_SIP_SESSION_REFRESH_METHOD_UPDATE, AST_STATE_RING, AST_STATE_RINGING, ast_str_tmp, ast_stream_topology_to_str(), method, NULL, on_topology_change_response(), SCOPE_ENTER, SCOPE_EXIT_RTN_VALUE, refresh_data::session, session, and topology_change_refresh_data_free().

Referenced by handle_topology_request_change().

◆ sendtext()

static int sendtext ( void *  obj)
static

Definition at line 2931 of file chan_pjsip.c.

2932{
2933 struct sendtext_data *data = obj;
2934 pjsip_tx_data *tdata;
2935 const char *body_text = ast_msg_data_get_attribute(data->msg, AST_MSG_DATA_ATTR_BODY);
2936 const char *content_type = ast_msg_data_get_attribute(data->msg, AST_MSG_DATA_ATTR_CONTENT_TYPE);
2937 char *sep;
2938 struct ast_sip_body body = {
2939 .type = "text",
2940 .subtype = "plain",
2941 .body_text = body_text,
2942 };
2943
2944 if (!ast_strlen_zero(content_type)) {
2945 char *content_type_copy = ast_strdupa(content_type);
2946 sep = strchr(content_type_copy, '/');
2947 if (sep) {
2948 *sep = '\0';
2949 body.type = content_type_copy;
2950 body.subtype = ++sep;
2951 }
2952 }
2953
2954 if (data->session->inv_session->state == PJSIP_INV_STATE_DISCONNECTED) {
2955 ast_log(LOG_ERROR, "Session already DISCONNECTED [reason=%d (%s)]\n",
2956 data->session->inv_session->cause,
2957 pjsip_get_status_text(data->session->inv_session->cause)->ptr);
2958 } else {
2959 pjsip_from_hdr *hdr;
2960 pjsip_name_addr *name_addr;
2961 const char *from = ast_msg_data_get_attribute(data->msg, AST_MSG_DATA_ATTR_FROM);
2962 const char *to = ast_msg_data_get_attribute(data->msg, AST_MSG_DATA_ATTR_TO);
2963 int invalidate_tdata = 0;
2964
2965 ast_sip_create_request("MESSAGE", data->session->inv_session->dlg, data->session->endpoint, NULL, NULL, &tdata);
2966 ast_sip_add_body(tdata, &body);
2967
2968 /*
2969 * If we have a 'from' in the msg, set the display name in the From
2970 * header to it.
2971 */
2972 if (!ast_strlen_zero(from)) {
2973 hdr = PJSIP_MSG_FROM_HDR(tdata->msg);
2974 name_addr = (pjsip_name_addr *) hdr->uri;
2975 pj_strdup2(tdata->pool, &name_addr->display, from);
2976 invalidate_tdata = 1;
2977 }
2978
2979 /*
2980 * If we have a 'to' in the msg, set the display name in the To
2981 * header to it.
2982 */
2983 if (!ast_strlen_zero(to)) {
2984 hdr = PJSIP_MSG_TO_HDR(tdata->msg);
2985 name_addr = (pjsip_name_addr *) hdr->uri;
2986 pj_strdup2(tdata->pool, &name_addr->display, to);
2987 invalidate_tdata = 1;
2988 }
2989
2990 if (invalidate_tdata) {
2991 pjsip_tx_data_invalidate_msg(tdata);
2992 }
2993
2994 ast_sip_send_request(tdata, data->session->inv_session->dlg, data->session->endpoint, NULL, NULL);
2995 }
2996
2997 ao2_cleanup(data);
2998
2999 return 0;
3000}
@ AST_MSG_DATA_ATTR_CONTENT_TYPE
Definition message.h:457
int ast_sip_send_request(pjsip_tx_data *tdata, struct pjsip_dialog *dlg, struct ast_sip_endpoint *endpoint, void *token, void(*callback)(void *token, pjsip_event *e))
General purpose method for sending a SIP request.
Definition res_pjsip.c:2022
int ast_sip_add_body(pjsip_tx_data *tdata, const struct ast_sip_body *body)
Add a body to an outbound SIP message.
Definition res_pjsip.c:2095
int ast_sip_create_request(const char *method, struct pjsip_dialog *dlg, struct ast_sip_endpoint *endpoint, const char *uri, struct ast_sip_contact *contact, pjsip_tx_data **tdata)
General purpose method for creating a SIP request.
Definition res_pjsip.c:1433
SIP body description.
Definition res_pjsip.h:2501
const char * type
Definition res_pjsip.h:2503
const char * body_text
Definition res_pjsip.h:2507
const char * subtype
Definition res_pjsip.h:2505
struct ast_sip_session * session

References ao2_cleanup, ast_log, AST_MSG_DATA_ATTR_BODY, AST_MSG_DATA_ATTR_CONTENT_TYPE, AST_MSG_DATA_ATTR_FROM, AST_MSG_DATA_ATTR_TO, ast_msg_data_get_attribute(), ast_sip_add_body(), ast_sip_create_request(), ast_sip_send_request(), ast_strdupa, ast_strlen_zero(), ast_sip_body::body_text, ast_sip_session::endpoint, ast_sip_session::inv_session, LOG_ERROR, sendtext_data::msg, NULL, sendtext_data::session, ast_sip_body::subtype, and ast_sip_body::type.

Referenced by chan_pjsip_sendtext_data().

◆ sendtext_data_create()

static struct sendtext_data * sendtext_data_create ( struct ast_channel *  chan,
struct ast_msg_data *  msg 
)
static

Definition at line 2910 of file chan_pjsip.c.

2912{
2913 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(chan);
2914 struct sendtext_data *data = ao2_alloc(sizeof(*data), sendtext_data_destroy);
2915
2916 if (!data) {
2917 return NULL;
2918 }
2919
2920 data->msg = ast_msg_data_dup(msg);
2921 if (!data->msg) {
2922 ao2_cleanup(data);
2923 return NULL;
2924 }
2925 data->session = channel->session;
2926 ao2_ref(data->session, +1);
2927
2928 return data;
2929}
static void sendtext_data_destroy(void *obj)
struct ast_msg_data * ast_msg_data_dup(struct ast_msg_data *msg)
Clone an ast_msg_data structure.

References ao2_alloc, ao2_cleanup, ao2_ref, ast_channel_tech_pvt(), ast_msg_data_dup(), sendtext_data::msg, NULL, sendtext_data_destroy(), sendtext_data::session, and ast_sip_channel_pvt::session.

Referenced by chan_pjsip_sendtext_data().

◆ sendtext_data_destroy()

static void sendtext_data_destroy ( void *  obj)
static

Definition at line 2903 of file chan_pjsip.c.

2904{
2905 struct sendtext_data *data = obj;
2906 ao2_cleanup(data->session);
2907 ast_free(data->msg);
2908}

References ao2_cleanup, ast_free, sendtext_data::msg, and sendtext_data::session.

Referenced by sendtext_data_create().

◆ set_channel_on_rtp_instance()

static void set_channel_on_rtp_instance ( const struct ast_sip_session *  session,
const char *  channel_id 
)
static

Definition at line 592 of file chan_pjsip.c.

594{
595 int i;
596
597 for (i = 0; i < AST_VECTOR_SIZE(&session->active_media_state->sessions); ++i) {
598 struct ast_sip_session_media *session_media;
599
600 session_media = AST_VECTOR_GET(&session->active_media_state->sessions, i);
601 if (!session_media || !session_media->rtp) {
602 continue;
603 }
604
605 ast_rtp_instance_set_channel_id(session_media->rtp, channel_id);
606 }
607}
void ast_rtp_instance_set_channel_id(struct ast_rtp_instance *instance, const char *uniqueid)
Set the channel that owns this RTP instance.
Definition rtp_engine.c:604

References ast_rtp_instance_set_channel_id(), AST_VECTOR_GET, AST_VECTOR_SIZE, ast_sip_session_media::rtp, and session.

Referenced by call(), chan_pjsip_fixup(), chan_pjsip_new(), and clear_session_and_channel_locked().

◆ set_sipdomain_variable()

static void set_sipdomain_variable ( struct ast_sip_session *  session)
static

Definition at line 3207 of file chan_pjsip.c.

3208{
3209 const pj_str_t *host = ast_sip_pjsip_uri_get_hostname(session->request_uri);
3210 size_t size = pj_strlen(host) + 1;
3211 char *domain = ast_alloca(size);
3212
3213 ast_copy_pj_str(domain, host, size);
3214
3215 pbx_builtin_setvar_helper(session->channel, "SIPDOMAIN", domain);
3216 return;
3217}
const pj_str_t * ast_sip_pjsip_uri_get_hostname(pjsip_uri *uri)
Get the host portion of the pjsip_uri.
Definition res_pjsip.c:3516

References ast_alloca, ast_copy_pj_str(), ast_sip_pjsip_uri_get_hostname(), pbx_builtin_setvar_helper(), and session.

Referenced by chan_pjsip_incoming_request().

◆ set_transport_info_local_addr()

static int set_transport_info_local_addr ( struct pjsip_tx_data *  tdata,
pj_sockaddr *  local_addr 
)
static

Determine the local signaling address used for an outgoing request.

For unreliable transports, the transport local address may be a wildcard address. Ask the PJSIP transport manager for the local interface selected for the request destination, then fall back to the transport local address if needed.

Definition at line 284 of file chan_pjsip.c.

285{
286 if (!(tdata->tp_info.transport->flag & PJSIP_TRANSPORT_RELIABLE)) {
287 pjsip_tpmgr_fla2_param prm;
288
289 pjsip_tpmgr_fla2_param_default(&prm);
290 prm.tp_type = tdata->tp_info.transport->key.type;
291 pj_strset2(&prm.dst_host, tdata->tp_info.dst_name);
292 prm.local_if = PJ_TRUE;
293
294 if (pjsip_tpmgr_find_local_addr2(pjsip_endpt_get_tpmgr(ast_sip_get_pjsip_endpoint()),
295 tdata->pool, &prm) == PJ_SUCCESS) {
296 int af = prm.tp_type & PJSIP_TRANSPORT_IPV6 ? pj_AF_INET6() : pj_AF_INET();
297
298 if (prm.tp_type == PJSIP_TRANSPORT_UDP || prm.tp_type == PJSIP_TRANSPORT_UDP6) {
299 prm.ret_port = tdata->tp_info.transport->local_name.port;
300 }
301
302 if (pj_sockaddr_init(af, local_addr, &prm.ret_addr, prm.ret_port) == PJ_SUCCESS) {
303 return 0;
304 }
305 }
306 }
307
308 pj_sockaddr_cp(local_addr, &tdata->tp_info.transport->local_addr);
309 return pj_sockaddr_has_addr(local_addr) ? 0 : -1;
310}
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
Definition res_pjsip.c:518

References ast_sip_get_pjsip_endpoint().

Referenced by transport_info_on_tx_request().

◆ topology_change_refresh_data_alloc()

static struct topology_change_refresh_data * topology_change_refresh_data_alloc ( struct ast_sip_session *  session,
const struct ast_stream_topology *  topology 
)
static

Definition at line 1627 of file chan_pjsip.c.

1629{
1631
1632 refresh_data = ast_calloc(1, sizeof(*refresh_data));
1633 if (!refresh_data) {
1634 return NULL;
1635 }
1636
1639 if (!refresh_data->media_state) {
1641 return NULL;
1642 }
1643 refresh_data->media_state->topology = ast_stream_topology_clone(topology);
1644 if (!refresh_data->media_state->topology) {
1646 return NULL;
1647 }
1648
1649 return refresh_data;
1650}
struct ast_sip_session_media_state * ast_sip_session_media_state_alloc(void)
Allocate a session media state structure.

References ao2_bump, ast_calloc, ast_sip_session_media_state_alloc(), ast_stream_topology_clone(), NULL, refresh_data::session, session, and topology_change_refresh_data_free().

Referenced by handle_topology_request_change().

◆ topology_change_refresh_data_free()

static void topology_change_refresh_data_free ( struct topology_change_refresh_data *  refresh_data)
static

Definition at line 1619 of file chan_pjsip.c.

1620{
1622
1625}
void ast_sip_session_media_state_free(struct ast_sip_session_media_state *media_state)
Free a session media state structure.

References ao2_cleanup, ast_free, ast_sip_session_media_state_free(), and refresh_data::session.

Referenced by handle_topology_request_change(), send_topology_change_refresh(), and topology_change_refresh_data_alloc().

◆ transfer()

static int transfer ( void *  data)
static

Definition at line 2248 of file chan_pjsip.c.

2249{
2250 struct transfer_data *trnf_data = data;
2251 struct ast_sip_endpoint *endpoint = NULL;
2252 struct ast_sip_contact *contact = NULL;
2253 const char *target = trnf_data->target;
2254
2255 if (trnf_data->session->inv_session->state == PJSIP_INV_STATE_DISCONNECTED) {
2256 ast_log(LOG_ERROR, "Session already DISCONNECTED [reason=%d (%s)]\n",
2257 trnf_data->session->inv_session->cause,
2258 pjsip_get_status_text(trnf_data->session->inv_session->cause)->ptr);
2259 } else {
2260 /* See if we have an endpoint; if so, use its contact */
2262 if (endpoint) {
2264 if (contact && !ast_strlen_zero(contact->uri)) {
2265 target = contact->uri;
2266 }
2267 }
2268
2269 if (ast_channel_state(trnf_data->session->channel) == AST_STATE_RING) {
2270 transfer_redirect(trnf_data->session, target);
2271 } else {
2272 transfer_refer(trnf_data->session, target);
2273 }
2274 }
2275
2276 ao2_ref(trnf_data, -1);
2278 ao2_cleanup(contact);
2279 return 0;
2280}
static void transfer_redirect(struct ast_sip_session *session, const char *target)
static void transfer_refer(struct ast_sip_session *session, const char *target)
struct ast_sip_contact * ast_sip_location_retrieve_contact_from_aor_list(const char *aor_list)
Retrieve the first bound contact from a list of AORs.
Definition location.c:304
Contact associated with an address of record.
Definition res_pjsip.h:392
const ast_string_field uri
Definition res_pjsip.h:414
struct ast_sip_endpoint * endpoint
Definition res_pjsip.h:424
const ast_string_field aors
Definition res_pjsip.h:1096
struct ast_sip_session * session

References ao2_cleanup, ao2_ref, ast_sip_endpoint::aors, ast_log, ast_sip_get_sorcery(), ast_sip_location_retrieve_contact_from_aor_list(), ast_sorcery_retrieve_by_id(), AST_STATE_RING, ast_strlen_zero(), ast_sip_session::channel, ast_sip_contact::endpoint, ast_sip_session::inv_session, LOG_ERROR, NULL, transfer_data::session, transfer_data::target, transfer_redirect(), transfer_refer(), and ast_sip_contact::uri.

Referenced by __send_command(), ast_transfer_protocol(), chan_pjsip_transfer(), iax2_send(), leave_voicemail(), send_packet(), and transfer_exec().

◆ transfer_data_alloc()

static struct transfer_data * transfer_data_alloc ( struct ast_sip_session *  session,
const char *  target 
)
static

Definition at line 2009 of file chan_pjsip.c.

2010{
2011 struct transfer_data *trnf_data = ao2_alloc(sizeof(*trnf_data), transfer_data_destroy);
2012
2013 if (!trnf_data) {
2014 return NULL;
2015 }
2016
2017 if (!(trnf_data->target = ast_strdup(target))) {
2018 ao2_ref(trnf_data, -1);
2019 return NULL;
2020 }
2021
2022 ao2_ref(session, +1);
2023 trnf_data->session = session;
2024
2025 return trnf_data;
2026}
static void transfer_data_destroy(void *obj)

References ao2_alloc, ao2_ref, ast_strdup, NULL, transfer_data::session, session, transfer_data::target, and transfer_data_destroy().

Referenced by chan_pjsip_transfer().

◆ transfer_data_destroy()

static void transfer_data_destroy ( void *  obj)
static

Definition at line 2001 of file chan_pjsip.c.

2002{
2003 struct transfer_data *trnf_data = obj;
2004
2005 ast_free(trnf_data->target);
2006 ao2_cleanup(trnf_data->session);
2007}

References ao2_cleanup, ast_free, transfer_data::session, and transfer_data::target.

Referenced by transfer_data_alloc().

◆ transfer_redirect()

static void transfer_redirect ( struct ast_sip_session *  session,
const char *  target 
)
static

Definition at line 2028 of file chan_pjsip.c.

2029{
2030 pjsip_tx_data *packet;
2032 pjsip_contact_hdr *contact;
2033 pj_str_t tmp;
2034
2035 if (pjsip_inv_end_session(session->inv_session, 302, NULL, &packet) != PJ_SUCCESS
2036 || !packet) {
2037 ast_log(LOG_WARNING, "Failed to redirect PJSIP session for channel %s\n",
2038 ast_channel_name(session->channel));
2041
2042 return;
2043 }
2044
2045 if (!(contact = pjsip_msg_find_hdr(packet->msg, PJSIP_H_CONTACT, NULL))) {
2046 contact = pjsip_contact_hdr_create(packet->pool);
2047 }
2048
2049 pj_strdup2_with_null(packet->pool, &tmp, target);
2050 if (!(contact->uri = pjsip_parse_uri(packet->pool, tmp.ptr, tmp.slen, PJSIP_PARSE_URI_AS_NAMEADDR))) {
2051 ast_log(LOG_WARNING, "Failed to parse destination URI '%s' for channel %s\n",
2052 target, ast_channel_name(session->channel));
2055 pjsip_tx_data_dec_ref(packet);
2056
2057 return;
2058 }
2059 pjsip_msg_add_hdr(packet->msg, (pjsip_hdr *) contact);
2060
2063}
@ AST_TRANSFER_FAILED
@ AST_TRANSFER_SUCCESS

References ast_channel_name(), AST_CONTROL_TRANSFER, ast_log, ast_queue_control_data(), ast_sip_session_send_response(), AST_TRANSFER_FAILED, AST_TRANSFER_SUCCESS, LOG_WARNING, NULL, session, and transfer_data::target.

Referenced by transfer().

◆ transfer_refer()

static void transfer_refer ( struct ast_sip_session *  session,
const char *  target 
)
static

Definition at line 2196 of file chan_pjsip.c.

2197{
2198 pjsip_evsub *sub;
2200 pj_str_t tmp;
2201 pjsip_tx_data *packet;
2202 const char *ref_by_val;
2203 char local_info[pj_strlen(&session->inv_session->dlg->local.info_str) + 1];
2204 struct pjsip_evsub_user xfer_cb;
2205 struct ast_channel *chan = session->channel;
2206
2207 pj_bzero(&xfer_cb, sizeof(xfer_cb));
2208 xfer_cb.on_evsub_state = &xfer_client_on_evsub_state;
2209
2210 if (pjsip_xfer_create_uac(session->inv_session->dlg, &xfer_cb, &sub) != PJ_SUCCESS) {
2213
2214 return;
2215 }
2216
2217 /* chan_pjsip_module requires a reference to chan
2218 * which will be released in xfer_client_on_evsub_state()
2219 * when the implicit REFER subscription terminates */
2220 pjsip_evsub_set_mod_data(sub, chan_pjsip_module.id, chan);
2221 ao2_ref(chan, +1);
2222
2223 if (pjsip_xfer_initiate(sub, pj_cstr(&tmp, target), &packet) != PJ_SUCCESS) {
2224 goto failure;
2225 }
2226
2227 ref_by_val = pbx_builtin_getvar_helper(chan, "SIPREFERREDBYHDR");
2228 if (!ast_strlen_zero(ref_by_val)) {
2229 ast_sip_add_header(packet, "Referred-By", ref_by_val);
2230 } else {
2231 ast_copy_pj_str(local_info, &session->inv_session->dlg->local.info_str, sizeof(local_info));
2232 ast_sip_add_header(packet, "Referred-By", local_info);
2233 }
2234
2235 if (pjsip_xfer_send_request(sub, packet) == PJ_SUCCESS) {
2236 return;
2237 }
2238
2239failure:
2242 pjsip_evsub_set_mod_data(sub, chan_pjsip_module.id, NULL);
2243 pjsip_evsub_terminate(sub, PJ_FALSE);
2244
2245 ao2_ref(chan, -1);
2246}
static void xfer_client_on_evsub_state(pjsip_evsub *sub, pjsip_event *event)
Callback function to report status of implicit REFER-NOTIFY subscription.
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
static struct stasis_subscription * sub
Statsd channel stats. Exmaple of how to subscribe to Stasis events.
int ast_sip_add_header(pjsip_tx_data *tdata, const char *name, const char *value)
Add a header to an outbound SIP message.
Definition res_pjsip.c:2051

References ao2_ref, AST_CONTROL_TRANSFER, ast_copy_pj_str(), ast_queue_control_data(), ast_sip_add_header(), ast_strlen_zero(), AST_TRANSFER_FAILED, AST_TRANSFER_SUCCESS, chan_pjsip_module, NULL, pbx_builtin_getvar_helper(), session, sub, and xfer_client_on_evsub_state().

Referenced by transfer().

◆ transmit_info_dtmf()

static int transmit_info_dtmf ( void *  data)
static

Definition at line 2370 of file chan_pjsip.c.

2371{
2372 RAII_VAR(struct info_dtmf_data *, dtmf_data, data, ao2_cleanup);
2373
2374 struct ast_sip_session *session = dtmf_data->session;
2375 struct pjsip_tx_data *tdata;
2376
2377 RAII_VAR(struct ast_str *, body_text, NULL, ast_free_ptr);
2378
2379 struct ast_sip_body body = {
2380 .type = "application",
2381 .subtype = "dtmf-relay",
2382 };
2383
2384 if (session->inv_session->state == PJSIP_INV_STATE_DISCONNECTED) {
2385 ast_log(LOG_ERROR, "Session already DISCONNECTED [reason=%d (%s)]\n",
2386 session->inv_session->cause,
2387 pjsip_get_status_text(session->inv_session->cause)->ptr);
2388 return -1;
2389 }
2390
2391 if (!(body_text = ast_str_create(32))) {
2392 ast_log(LOG_ERROR, "Could not allocate buffer for INFO DTMF.\n");
2393 return -1;
2394 }
2395 ast_str_set(&body_text, 0, "Signal=%c\r\nDuration=%u\r\n", dtmf_data->digit, dtmf_data->duration);
2396
2398
2399 if (ast_sip_create_request("INFO", session->inv_session->dlg, session->endpoint, NULL, NULL, &tdata)) {
2400 ast_log(LOG_ERROR, "Could not create DTMF INFO request\n");
2401 return -1;
2402 }
2403 if (ast_sip_add_body(tdata, &body)) {
2404 ast_log(LOG_ERROR, "Could not add body to DTMF INFO request\n");
2405 pjsip_tx_data_dec_ref(tdata);
2406 return -1;
2407 }
2409
2410 return 0;
2411}
void ast_free_ptr(void *ptr)
free() wrapper
Definition astmm.c:1739
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition strings.h:659
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition strings.h:1113
char *attribute_pure ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition strings.h:761

References ao2_cleanup, ast_free_ptr(), ast_log, ast_sip_add_body(), ast_sip_create_request(), ast_sip_session_send_request(), ast_str_buffer(), ast_str_create, ast_str_set(), ast_sip_body::body_text, LOG_ERROR, NULL, RAII_VAR, session, and ast_sip_body::type.

Referenced by chan_pjsip_digit_end(), and chan_pjsip_indicate().

◆ transmit_info_with_vidupdate()

static int transmit_info_with_vidupdate ( void *  data)
static

Send SIP INFO with video update request.

Definition at line 1459 of file chan_pjsip.c.

1460{
1461 const char * xml =
1462 "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\r\n"
1463 " <media_control>\r\n"
1464 " <vc_primitive>\r\n"
1465 " <to_encoder>\r\n"
1466 " <picture_fast_update/>\r\n"
1467 " </to_encoder>\r\n"
1468 " </vc_primitive>\r\n"
1469 " </media_control>\r\n";
1470
1471 const struct ast_sip_body body = {
1472 .type = "application",
1473 .subtype = "media_control+xml",
1474 .body_text = xml
1475 };
1476
1477 RAII_VAR(struct ast_sip_session *, session, data, ao2_cleanup);
1478 struct pjsip_tx_data *tdata;
1479
1480 if (session->inv_session->state == PJSIP_INV_STATE_DISCONNECTED) {
1481 ast_log(LOG_ERROR, "Session already DISCONNECTED [reason=%d (%s)]\n",
1482 session->inv_session->cause,
1483 pjsip_get_status_text(session->inv_session->cause)->ptr);
1484 return -1;
1485 }
1486
1487 if (ast_sip_create_request("INFO", session->inv_session->dlg, session->endpoint, NULL, NULL, &tdata)) {
1488 ast_log(LOG_ERROR, "Could not create text video update INFO request\n");
1489 return -1;
1490 }
1491 if (ast_sip_add_body(tdata, &body)) {
1492 ast_log(LOG_ERROR, "Could not add body to text video update INFO request\n");
1493 return -1;
1494 }
1496
1497 return 0;
1498}

References ao2_cleanup, ast_log, ast_sip_add_body(), ast_sip_create_request(), ast_sip_session_send_request(), LOG_ERROR, NULL, RAII_VAR, session, and ast_sip_body::type.

Referenced by chan_pjsip_indicate().

◆ transport_info_destroy()

static void transport_info_destroy ( void *  obj)
static

Destructor function for transport_info_data.

Definition at line 262 of file chan_pjsip.c.

263{
264 struct transport_info_data *data = obj;
265 ast_free(data);
266}

References ast_free.

◆ transport_info_on_tx_request()

static pj_status_t transport_info_on_tx_request ( pjsip_tx_data *  tdata)
static

Store transport information for outgoing PJSIP session requests.

Incoming PJSIP channels get their transport information from the received request. Outgoing channels may not have this information available through the channel datastore, so store the selected transport addresses once the outgoing request has been created and a destination is known.

Definition at line 320 of file chan_pjsip.c.

321{
323 RAII_VAR(struct ast_datastore *, datastore, NULL, ao2_cleanup);
324 struct transport_info_data *transport_data;
325 pjsip_dialog *dlg;
326
327 if (!tdata->tp_info.transport
328 || !pj_sockaddr_has_addr(&tdata->tp_info.dst_addr)) {
329 return PJ_SUCCESS;
330 }
331
332 dlg = pjsip_tdata_get_dlg(tdata);
333 if (!dlg) {
334 return PJ_SUCCESS;
335 }
336
338 if (!session
339 || !session->inv_session
340 || session->inv_session->role != PJSIP_ROLE_UAC) {
341 return PJ_SUCCESS;
342 }
343
344 datastore = ast_sip_session_get_datastore(session, "transport_info");
345 if (datastore) {
346 return PJ_SUCCESS;
347 }
348
349 datastore = ast_sip_session_alloc_datastore(&transport_info, "transport_info");
350 if (!datastore) {
351 return PJ_SUCCESS;
352 }
353
354 transport_data = ast_calloc(1, sizeof(*transport_data));
355 if (!transport_data) {
356 return PJ_SUCCESS;
357 }
358
359 if (set_transport_info_local_addr(tdata, &transport_data->local_addr)) {
360 ast_free(transport_data);
361 return PJ_SUCCESS;
362 }
363 pj_sockaddr_cp(&transport_data->remote_addr, &tdata->tp_info.dst_addr);
364
365 datastore->data = transport_data;
367
368 return PJ_SUCCESS;
369}
static int set_transport_info_local_addr(struct pjsip_tx_data *tdata, pj_sockaddr *local_addr)
Determine the local signaling address used for an outgoing request.
Definition chan_pjsip.c:284
struct ast_sip_session * ast_sip_dialog_get_session(pjsip_dialog *dlg)
Retrieves a session from a dialog.

References ao2_cleanup, ast_calloc, ast_free, ast_sip_dialog_get_session(), ast_sip_session_add_datastore(), ast_sip_session_alloc_datastore(), ast_sip_session_get_datastore(), transport_info_data::local_addr, NULL, RAII_VAR, transport_info_data::remote_addr, session, set_transport_info_local_addr(), and transport_info.

◆ uid_hold_hash_fn()

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

AO2 hash function for on hold UIDs

Definition at line 1177 of file chan_pjsip.c.

1178{
1179 const char *key = obj;
1180
1181 switch (flags & OBJ_SEARCH_MASK) {
1182 case OBJ_SEARCH_KEY:
1183 break;
1184 case OBJ_SEARCH_OBJECT:
1185 break;
1186 default:
1187 /* Hash can only work on something with a full key. */
1188 ast_assert(0);
1189 return 0;
1190 }
1191 return ast_str_hash(key);
1192}
@ OBJ_SEARCH_OBJECT
The arg parameter is an object of the same type.
Definition astobj2.h:1087
@ OBJ_SEARCH_MASK
Search option field mask.
Definition astobj2.h:1072
static force_inline int attribute_pure ast_str_hash(const char *str)
Compute a hash value on a string.
Definition strings.h:1259

References ast_assert, ast_str_hash(), OBJ_SEARCH_KEY, OBJ_SEARCH_MASK, and OBJ_SEARCH_OBJECT.

Referenced by load_module().

◆ uid_hold_sort_fn()

static int uid_hold_sort_fn ( const void *  obj_left,
const void *  obj_right,
const int  flags 
)
static

AO2 sort function for on hold UIDs

Definition at line 1195 of file chan_pjsip.c.

1196{
1197 const char *left = obj_left;
1198 const char *right = obj_right;
1199 int cmp;
1200
1201 switch (flags & OBJ_SEARCH_MASK) {
1202 case OBJ_SEARCH_OBJECT:
1203 case OBJ_SEARCH_KEY:
1204 cmp = strcmp(left, right);
1205 break;
1207 cmp = strncmp(left, right, strlen(right));
1208 break;
1209 default:
1210 /* Sort can only work on something with a full or partial key. */
1211 ast_assert(0);
1212 cmp = 0;
1213 break;
1214 }
1215 return cmp;
1216}
@ OBJ_SEARCH_PARTIAL_KEY
The arg parameter is a partial search key similar to OBJ_SEARCH_KEY.
Definition astobj2.h:1116

References ast_assert, OBJ_SEARCH_KEY, OBJ_SEARCH_MASK, OBJ_SEARCH_OBJECT, and OBJ_SEARCH_PARTIAL_KEY.

Referenced by load_module().

◆ unload_module()

static int unload_module ( void  )
static

Unload the PJSIP channel from Asterisk.

Definition at line 3676 of file chan_pjsip.c.

3677{
3681
3683
3690
3692
3703
3707
3708 return 0;
3709}
void pjsip_channel_cli_unregister(void)
Unregisters the channel cli commands.

References ao2_cleanup, ao2_ref, app_pjsip_hangup, ast_channel_unregister(), ast_custom_function_unregister(), ast_manager_unregister(), ast_rtp_glue_unregister(), ast_sip_session_unregister_supplement(), ast_sip_unregister_service(), ast_unregister_application(), call_pickup_supplement, ast_channel_tech::capabilities, chan_pjsip_ack_supplement, chan_pjsip_dial_contacts_function, chan_pjsip_module, chan_pjsip_parse_uri_from_function, chan_pjsip_parse_uri_function, chan_pjsip_prack_supplement, chan_pjsip_rtp_glue, chan_pjsip_supplement, chan_pjsip_supplement_response, chan_pjsip_tech, dtmf_mode_function, media_offer_function, moh_passthrough_function, NULL, pbx_start_supplement, pjsip_channel_cli_unregister(), pjsip_channel_info_unregister(), pjsip_uids_onhold, session_refresh_function, and transfer_handling_function.

◆ update_connected_line_information()

static int update_connected_line_information ( void *  data)
static

Update connected line information.

Definition at line 1537 of file chan_pjsip.c.

1538{
1539 struct ast_sip_session *session = data;
1540
1541 if (session->inv_session->state == PJSIP_INV_STATE_DISCONNECTED) {
1542 ast_log(LOG_ERROR, "Session already DISCONNECTED [reason=%d (%s)]\n",
1543 session->inv_session->cause,
1544 pjsip_get_status_text(session->inv_session->cause)->ptr);
1545 ao2_ref(session, -1);
1546 return -1;
1547 }
1548
1549 if (ast_channel_state(session->channel) == AST_STATE_UP
1550 || session->inv_session->role == PJSIP_ROLE_UAC) {
1553 int generate_new_sdp;
1554
1555 method = session->endpoint->id.refresh_method;
1556 if (session->inv_session->options & PJSIP_INV_SUPPORT_UPDATE) {
1558 }
1559
1560 /* Only the INVITE method actually needs SDP, UPDATE can do without */
1561 generate_new_sdp = (method == AST_SIP_SESSION_REFRESH_METHOD_INVITE);
1562
1563 ast_sip_session_refresh(session, NULL, NULL, NULL, method, generate_new_sdp, NULL);
1564 }
1565 } else if (session->endpoint->id.rpid_immediate
1566 && session->inv_session->state != PJSIP_INV_STATE_DISCONNECTED
1568 int response_code = 0;
1569
1570 if (ast_channel_state(session->channel) == AST_STATE_RING) {
1571 response_code = !session->endpoint->inband_progress ? 180 : 183;
1572 } else if (ast_channel_state(session->channel) == AST_STATE_RINGING) {
1573 response_code = 183;
1574 }
1575
1576 if (response_code) {
1577 struct pjsip_tx_data *packet = NULL;
1578
1579 if (pjsip_inv_answer(session->inv_session, response_code, NULL, NULL, &packet) == PJ_SUCCESS) {
1581 }
1582 }
1583 }
1584
1585 ao2_ref(session, -1);
1586 return 0;
1587}
static int is_colp_update_allowed(struct ast_sip_session *session)

References ao2_ref, ast_log, ast_sip_session_refresh(), AST_SIP_SESSION_REFRESH_METHOD_INVITE, AST_SIP_SESSION_REFRESH_METHOD_UPDATE, ast_sip_session_send_response(), AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, is_colp_update_allowed(), LOG_ERROR, method, NULL, and session.

Referenced by chan_pjsip_indicate().

◆ update_devstate()

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

◆ update_initial_connected_line()

static void update_initial_connected_line ( struct ast_sip_session *  session)
static

Definition at line 2485 of file chan_pjsip.c.

2486{
2488
2489 /*
2490 * Use the channel CALLERID() as the initial connected line data.
2491 * The core or a predial handler may have supplied missing values
2492 * from the session->endpoint->id.self about who we are calling.
2493 */
2494 ast_channel_lock(session->channel);
2496 ast_channel_unlock(session->channel);
2497
2498 /* Supply initial connected line information if available. */
2499 if (!session->id.number.valid && !session->id.name.valid) {
2500 return;
2501 }
2502
2504 connected.id = session->id;
2506
2508}
@ AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER
Definition callerid.h:554
static int connected
Definition cdr_pgsql.c:73
void ast_party_connected_line_init(struct ast_party_connected_line *init)
Initialize the given connected line structure.
Definition channel.c:2009
void ast_channel_queue_connected_line_update(struct ast_channel *chan, const struct ast_party_connected_line *connected, const struct ast_set_party_connected_line *update)
Queue a connected line update frame on a channel.
Definition channel.c:9282
struct ast_party_id id
Caller party ID.
Definition channel.h:422
Connected Line/Party information.
Definition channel.h:458

References ast_channel_caller(), ast_channel_lock, ast_channel_queue_connected_line_update(), ast_channel_unlock, AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER, ast_party_connected_line_init(), ast_party_id_copy(), connected, ast_party_caller::id, NULL, and session.

Referenced by call().

◆ xfer_client_on_evsub_state()

static void xfer_client_on_evsub_state ( pjsip_evsub *  sub,
pjsip_event *  event 
)
static

Callback function to report status of implicit REFER-NOTIFY subscription.

This function will be called on any state change in the REFER-NOTIFY subscription. Its primary purpose is to report SUCCESS/FAILURE of a transfer initiated via transfer_refer as well as to terminate the subscription, if necessary.

Definition at line 2079 of file chan_pjsip.c.

2080{
2081 struct ast_channel *chan;
2083 int res = 0;
2084
2085 if (!event) {
2086 return;
2087 }
2088
2089 chan = pjsip_evsub_get_mod_data(sub, chan_pjsip_module.id);
2090 if (!chan) {
2091 return;
2092 }
2093
2094 if (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_ACCEPTED) {
2095 /* Check if subscription is suppressed and terminate and send completion code, if so. */
2096 pjsip_rx_data *rdata;
2097 pjsip_generic_string_hdr *refer_sub;
2098 const pj_str_t REFER_SUB = { "Refer-Sub", 9 };
2099
2100 ast_debug(3, "Transfer accepted on channel %s\n", ast_channel_name(chan));
2101
2102 /* Check if response message */
2103 if (event->type == PJSIP_EVENT_TSX_STATE && event->body.tsx_state.type == PJSIP_EVENT_RX_MSG) {
2104 rdata = event->body.tsx_state.src.rdata;
2105
2106 /* Find Refer-Sub header */
2107 refer_sub = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &REFER_SUB, NULL);
2108
2109 /* Check if subscription is suppressed. If it is, the far end will not terminate it,
2110 * and the subscription will remain active until it times out. Terminating it here
2111 * eliminates the unnecessary timeout.
2112 */
2113 if (refer_sub && !pj_stricmp2(&refer_sub->hvalue, "false")) {
2114 /* Since no subscription is desired, assume that call has been transferred successfully. */
2115 /* Channel reference will be released at end of function */
2116 /* Terminate subscription. */
2117 pjsip_evsub_set_mod_data(sub, chan_pjsip_module.id, NULL);
2118 pjsip_evsub_terminate(sub, PJ_TRUE);
2119 res = -1;
2120 }
2121 }
2122 } else if (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_ACTIVE ||
2123 pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_TERMINATED) {
2124 /* Check for NOTIFY complete or error. */
2125 pjsip_msg *msg;
2126 pjsip_msg_body *body;
2127 pjsip_status_line status_line = { .code = 0 };
2128 pj_bool_t is_last;
2129 pj_status_t status;
2130
2131 if (event->type == PJSIP_EVENT_TSX_STATE && event->body.tsx_state.type == PJSIP_EVENT_RX_MSG) {
2132 pjsip_rx_data *rdata;
2133
2134 rdata = event->body.tsx_state.src.rdata;
2135 msg = rdata->msg_info.msg;
2136
2137 if (msg->type == PJSIP_REQUEST_MSG) {
2138 if (!pjsip_method_cmp(&msg->line.req.method, pjsip_get_notify_method())) {
2139 body = msg->body;
2140 if (body && !pj_stricmp2(&body->content_type.type, "message")
2141 && !pj_stricmp2(&body->content_type.subtype, "sipfrag")) {
2142 pjsip_parse_status_line((char *)body->data, body->len, &status_line);
2143 }
2144 }
2145 } else {
2146 status_line.code = msg->line.status.code;
2147 status_line.reason = msg->line.status.reason;
2148 }
2149 } else {
2150 status_line.code = 500;
2151 status_line.reason = *pjsip_get_status_text(500);
2152 }
2153
2154 is_last = (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_TERMINATED);
2155 /* If the status code is >= 200, the subscription is finished. */
2156 if (status_line.code >= 200 || is_last) {
2157 res = -1;
2158
2159 /* If the subscription has terminated, return AST_TRANSFER_SUCCESS for 2XX.
2160 * Return AST_TRANSFER_FAILED for any code < 200.
2161 * Otherwise, return the status code.
2162 * The subscription should not terminate for any code < 200,
2163 * but if it does, that constitutes a failure. */
2164 if (status_line.code < 200) {
2166 } else if (status_line.code >= 300) {
2167 message = status_line.code;
2168 }
2169
2170 /* If subscription not terminated and subscription is finished (status code >= 200)
2171 * terminate it */
2172 if (!is_last) {
2173 pjsip_tx_data *tdata;
2174
2175 status = pjsip_evsub_initiate(sub, pjsip_get_subscribe_method(), 0, &tdata);
2176 if (status == PJ_SUCCESS) {
2177 pjsip_evsub_send_request(sub, tdata);
2178 }
2179 }
2180 /* Finished. Remove session from subscription */
2181 pjsip_evsub_set_mod_data(sub, chan_pjsip_module.id, NULL);
2182 ast_debug(3, "Transfer channel %s completed: %d %.*s (%s)\n",
2183 ast_channel_name(chan),
2184 status_line.code,
2185 (int)status_line.reason.slen, status_line.reason.ptr,
2186 (message == AST_TRANSFER_SUCCESS) ? "Success" : "Failure");
2187 }
2188 }
2189
2190 if (res) {
2192 ao2_ref(chan, -1);
2193 }
2194}

References ao2_ref, ast_channel_name(), AST_CONTROL_TRANSFER, ast_debug, ast_queue_control_data(), AST_TRANSFER_FAILED, AST_TRANSFER_SUCCESS, chan_pjsip_module, NULL, status, and sub.

Referenced by transfer_refer().

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "PJSIP Channel Driver" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_CHANNEL_DRIVER, .requires = "res_pjsip,res_pjsip_session,res_pjsip_pubsub", }
static

Definition at line 3717 of file chan_pjsip.c.

◆ app_pjsip_hangup

char* app_pjsip_hangup = "PJSIPHangup"
static

Definition at line 3539 of file chan_pjsip.c.

Referenced by load_module(), and unload_module().

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 3717 of file chan_pjsip.c.

◆ call_pickup_supplement

struct ast_sip_session_supplement call_pickup_supplement
static
Initial value:
= {
.method = "INVITE",
.incoming_request = call_pickup_incoming_request,
}
static int call_pickup_incoming_request(struct ast_sip_session *session, pjsip_rx_data *rdata)
@ AST_SIP_SUPPLEMENT_PRIORITY_LAST
Definition res_pjsip.h:3415

Definition at line 3322 of file chan_pjsip.c.

3322 {
3323 .method = "INVITE",
3324 .priority = AST_SIP_SUPPLEMENT_PRIORITY_LAST - 1,
3325 .incoming_request = call_pickup_incoming_request,
3326};

Referenced by load_module(), and unload_module().

◆ chan_idx

unsigned int chan_idx
static

Definition at line 81 of file chan_pjsip.c.

Referenced by chan_pjsip_new().

◆ chan_pjsip_ack_supplement

struct ast_sip_session_supplement chan_pjsip_ack_supplement
static
Initial value:
= {
.method = "ACK",
.incoming_request = chan_pjsip_incoming_ack,
}
static int chan_pjsip_incoming_ack(struct ast_sip_session *session, struct pjsip_rx_data *rdata)
@ AST_SIP_SUPPLEMENT_PRIORITY_CHANNEL
Definition res_pjsip.h:3413

Definition at line 165 of file chan_pjsip.c.

165 {
166 .method = "ACK",
168 .incoming_request = chan_pjsip_incoming_ack,
169};

Referenced by load_module(), and unload_module().

◆ chan_pjsip_dial_contacts_function

struct ast_custom_function chan_pjsip_dial_contacts_function
static
Initial value:
= {
.name = "PJSIP_DIAL_CONTACTS",
}
int pjsip_acf_dial_contacts_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
PJSIP_DIAL_CONTACTS function read callback.

Definition at line 3496 of file chan_pjsip.c.

3496 {
3497 .name = "PJSIP_DIAL_CONTACTS",
3499};

Referenced by load_module(), and unload_module().

◆ chan_pjsip_module

pjsip_module chan_pjsip_module
static
Initial value:
= {
.name = { "chan_pjsip", 10 },
.id = -1,
.on_tx_request = transport_info_on_tx_request,
}
static pj_status_t transport_info_on_tx_request(pjsip_tx_data *tdata)
Store transport information for outgoing PJSIP session requests.
Definition chan_pjsip.c:320

General PJSIP module for chan_pjsip, currently used for REFER subscription data and outgoing request callbacks.

Definition at line 2066 of file chan_pjsip.c.

2066 {
2067 .name = { "chan_pjsip", 10 },
2068 .id = -1,
2069 .on_tx_request = transport_info_on_tx_request,
2070};

Referenced by load_module(), transfer_refer(), unload_module(), and xfer_client_on_evsub_state().

◆ chan_pjsip_parse_uri_from_function

struct ast_custom_function chan_pjsip_parse_uri_from_function
static
Initial value:
= {
.name = "PJSIP_PARSE_URI_FROM",
}
int pjsip_acf_parse_uri_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
PJSIP_PARSE_URI function read callback.

Definition at line 3506 of file chan_pjsip.c.

3506 {
3507 .name = "PJSIP_PARSE_URI_FROM",
3509};

Referenced by load_module(), and unload_module().

◆ chan_pjsip_parse_uri_function

struct ast_custom_function chan_pjsip_parse_uri_function
static
Initial value:
= {
.name = "PJSIP_PARSE_URI",
}

Definition at line 3501 of file chan_pjsip.c.

3501 {
3502 .name = "PJSIP_PARSE_URI",
3504};

Referenced by load_module(), and unload_module().

◆ chan_pjsip_prack_supplement

struct ast_sip_session_supplement chan_pjsip_prack_supplement
static
Initial value:
= {
.method = "PRACK",
.incoming_request = chan_pjsip_incoming_prack,
}
static int chan_pjsip_incoming_prack(struct ast_sip_session *session, struct pjsip_rx_data *rdata)

Definition at line 173 of file chan_pjsip.c.

173 {
174 .method = "PRACK",
176 .incoming_request = chan_pjsip_incoming_prack,
177};

Referenced by load_module(), and unload_module().

◆ chan_pjsip_rtp_glue

struct ast_rtp_glue chan_pjsip_rtp_glue
static

Local glue for interacting with the RTP engine core.

Definition at line 584 of file chan_pjsip.c.

584 {
585 .type = "PJSIP",
586 .get_rtp_info = chan_pjsip_get_rtp_peer,
587 .get_vrtp_info = chan_pjsip_get_vrtp_peer,
588 .get_codec = chan_pjsip_get_codec,
589 .update_peer = chan_pjsip_set_rtp_peer,
590};
static void chan_pjsip_get_codec(struct ast_channel *chan, struct ast_format_cap *result)
Function called by RTP engine to get peer capabilities.
Definition chan_pjsip.c:253
static int chan_pjsip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *rtp, struct ast_rtp_instance *vrtp, struct ast_rtp_instance *tpeer, const struct ast_format_cap *cap, int nat_active)
Function called by RTP engine to change where the remote party should send media.
Definition chan_pjsip.c:546
static enum ast_rtp_glue_result chan_pjsip_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **instance)
Function called by RTP engine to get local audio RTP peer.
Definition chan_pjsip.c:180
static enum ast_rtp_glue_result chan_pjsip_get_vrtp_peer(struct ast_channel *chan, struct ast_rtp_instance **instance)
Function called by RTP engine to get local video RTP peer.
Definition chan_pjsip.c:224

Referenced by load_module(), and unload_module().

◆ chan_pjsip_supplement

struct ast_sip_session_supplement chan_pjsip_supplement
static

SIP session supplement structure.

Definition at line 144 of file chan_pjsip.c.

144 {
145 .method = "INVITE",
147 .session_begin = chan_pjsip_session_begin,
148 .session_end = chan_pjsip_session_end,
149 .incoming_request = chan_pjsip_incoming_request,
150 .incoming_response = chan_pjsip_incoming_response,
151 /* It is important that this supplement runs after media has been negotiated */
152 .response_priority = AST_SIP_SESSION_AFTER_MEDIA,
153};
static void chan_pjsip_session_end(struct ast_sip_session *session)
Function called when the session ends.
static int chan_pjsip_incoming_request(struct ast_sip_session *session, struct pjsip_rx_data *rdata)
Function called when a request is received on the session.
static void chan_pjsip_session_begin(struct ast_sip_session *session)
SIP session interaction functions.
static void chan_pjsip_incoming_response(struct ast_sip_session *session, struct pjsip_rx_data *rdata)
Function called when a response is received on the session.
@ AST_SIP_SESSION_AFTER_MEDIA

Referenced by load_module(), and unload_module().

◆ chan_pjsip_supplement_response

struct ast_sip_session_supplement chan_pjsip_supplement_response
static

SIP session supplement structure just for responses.

Definition at line 156 of file chan_pjsip.c.

156 {
157 .method = "INVITE",
161};
static void chan_pjsip_incoming_response_update_cause(struct ast_sip_session *session, struct pjsip_rx_data *rdata)
Function called when a response is received on the session.
@ AST_SIP_SESSION_BEFORE_MEDIA

Referenced by load_module(), and unload_module().

◆ chan_pjsip_tech

struct ast_channel_tech chan_pjsip_tech

PBX interface structure for channel registration.

Definition at line 110 of file chan_pjsip.c.

110 {
111 .type = channel_type,
112 .description = "PJSIP Channel Driver",
113 .requester = chan_pjsip_request,
114 .requester_with_stream_topology = chan_pjsip_request_with_stream_topology,
115 .send_text = chan_pjsip_sendtext,
116 .send_text_data = chan_pjsip_sendtext_data,
117 .send_digit_begin = chan_pjsip_digit_begin,
118 .send_digit_end = chan_pjsip_digit_end,
119 .call = chan_pjsip_call,
120 .hangup = chan_pjsip_hangup,
121 .answer = chan_pjsip_answer,
122 .read_stream = chan_pjsip_read_stream,
123 .write = chan_pjsip_write,
124 .write_stream = chan_pjsip_write_stream,
125 .exception = chan_pjsip_read_stream,
126 .indicate = chan_pjsip_indicate,
127 .transfer = chan_pjsip_transfer,
128 .fixup = chan_pjsip_fixup,
129 .devicestate = chan_pjsip_devicestate,
130 .queryoption = chan_pjsip_queryoption,
131 .func_channel_read = pjsip_acf_channel_read,
132 .get_pvt_uniqueid = chan_pjsip_get_uniqueid,
134};
static int chan_pjsip_devicestate(const char *data)
Function called to get the device state of an endpoint.
static int chan_pjsip_transfer(struct ast_channel *ast, const char *target)
Function called by core for Asterisk initiated transfer.
static int chan_pjsip_call(struct ast_channel *ast, const char *dest, int timeout)
Function called by core to actually start calling a remote party.
static int chan_pjsip_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen)
Function called by core to ask the channel to indicate some sort of condition.
static int chan_pjsip_hangup(struct ast_channel *ast)
Function called by core to hang up a PJSIP session.
static struct ast_channel * chan_pjsip_request(const char *type, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *data, int *cause)
Asterisk core interaction functions.
static int chan_pjsip_queryoption(struct ast_channel *ast, int option, void *data, int *datalen)
Function called to query options on a channel.
static int chan_pjsip_digit_begin(struct ast_channel *ast, char digit)
Function called by core to start a DTMF digit.
static int chan_pjsip_write(struct ast_channel *ast, struct ast_frame *f)
static int chan_pjsip_sendtext(struct ast_channel *ast, const char *text)
static const char * chan_pjsip_get_uniqueid(struct ast_channel *ast)
static int chan_pjsip_answer(struct ast_channel *ast)
Function called by core when we should answer a PJSIP session.
Definition chan_pjsip.c:837
static int chan_pjsip_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
Function called by core to stop a DTMF digit.
static struct ast_frame * chan_pjsip_read_stream(struct ast_channel *ast)
Function called by core to read any waiting frames.
Definition chan_pjsip.c:949
static int chan_pjsip_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
Function called by core to change the underlying owner channel.
@ AST_CHAN_TP_SEND_TEXT_DATA
Channels have this property if they implement send_text_data.
Definition channel.h:995
@ AST_CHAN_TP_WANTSJITTER
Channels have this property if they can accept input with jitter; i.e. most VoIP channels.
Definition channel.h:980
@ AST_CHAN_TP_CREATESJITTER
Channels have this property if they can create jitter; i.e. most VoIP channels.
Definition channel.h:985
int pjsip_acf_channel_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
CHANNEL function read callback.

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

◆ channel_type

const char channel_type[] = "PJSIP"
static

Definition at line 79 of file chan_pjsip.c.

Referenced by load_module().

◆ direct_media_mitigation_info

struct ast_datastore_info direct_media_mitigation_info = { }
static

Definition at line 371 of file chan_pjsip.c.

371{ };

Referenced by chan_pjsip_session_begin().

◆ dtmf_mode_function

struct ast_custom_function dtmf_mode_function
static
Initial value:
= {
.name = "PJSIP_DTMF_MODE",
}
int pjsip_acf_dtmf_mode_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
PJSIP_DTMF_MODE function write callback.
int pjsip_acf_dtmf_mode_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
PJSIP_DTMF_MODE function read callback.

Definition at line 3517 of file chan_pjsip.c.

3517 {
3518 .name = "PJSIP_DTMF_MODE",
3521};

Referenced by load_module(), and unload_module().

◆ media_offer_function

struct ast_custom_function media_offer_function
static
Initial value:
= {
.name = "PJSIP_MEDIA_OFFER",
}
int pjsip_acf_media_offer_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
PJSIP_MEDIA_OFFER function read callback.
int pjsip_acf_media_offer_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
PJSIP_MEDIA_OFFER function write callback.

Definition at line 3511 of file chan_pjsip.c.

3511 {
3512 .name = "PJSIP_MEDIA_OFFER",
3515};

Referenced by load_module(), and unload_module().

◆ moh_passthrough_function

struct ast_custom_function moh_passthrough_function
static
Initial value:
= {
.name = "PJSIP_MOH_PASSTHROUGH",
}
int pjsip_acf_moh_passthrough_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
PJSIP_MOH_PASSTHROUGH function read callback.
int pjsip_acf_moh_passthrough_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
PJSIP_MOH_PASSTHROUGH function write callback.

Definition at line 3523 of file chan_pjsip.c.

3523 {
3524 .name = "PJSIP_MOH_PASSTHROUGH",
3527};

Referenced by load_module(), and unload_module().

◆ pbx_start_supplement

struct ast_sip_session_supplement pbx_start_supplement
static
Initial value:
= {
.method = "INVITE",
.incoming_request = pbx_start_incoming_request,
}
static int pbx_start_incoming_request(struct ast_sip_session *session, pjsip_rx_data *rdata)

Definition at line 3362 of file chan_pjsip.c.

3362 {
3363 .method = "INVITE",
3365 .incoming_request = pbx_start_incoming_request,
3366};

Referenced by load_module(), and unload_module().

◆ pjsip_uids_onhold

struct ao2_container* pjsip_uids_onhold
static

◆ session_refresh_function

struct ast_custom_function session_refresh_function
static
Initial value:
= {
.name = "PJSIP_SEND_SESSION_REFRESH",
}
int pjsip_acf_session_refresh_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
PJSIP_SEND_SESSION_REFRESH function write callback.

Definition at line 3529 of file chan_pjsip.c.

3529 {
3530 .name = "PJSIP_SEND_SESSION_REFRESH",
3532};

Referenced by load_module(), and unload_module().

◆ transfer_handling_function

struct ast_custom_function transfer_handling_function
static
Initial value:
= {
.name = "PJSIP_TRANSFER_HANDLING",
}
int pjsip_transfer_handling_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
PJSIP_TRANSFER_HANDLING function write callback.

Definition at line 3534 of file chan_pjsip.c.

3534 {
3535 .name = "PJSIP_TRANSFER_HANDLING",
3537};

Referenced by load_module(), and unload_module().

◆ transport_info

struct ast_datastore_info transport_info
static
Initial value:
= {
.type = "chan_pjsip_transport_info",
}
static void transport_info_destroy(void *obj)
Destructor function for transport_info_data.
Definition chan_pjsip.c:262

Datastore used to store local/remote addresses for the INVITE request that created the PJSIP channel.

Definition at line 270 of file chan_pjsip.c.

270 {
271 .type = "chan_pjsip_transport_info",
272 .destroy = transport_info_destroy,
273};

Referenced by chan_pjsip_incoming_request(), and transport_info_on_tx_request().