Asterisk - The Open Source Telephony Project GIT-master-27fb039
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/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_moduleAST_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_framechan_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_channelchan_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_framechan_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_channelchan_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_channelchan_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 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_datahangup_data_alloc (int cause, struct ast_channel *chan)
 
static void hangup_data_destroy (void *obj)
 
static int indicate (void *data)
 
static struct indicate_dataindicate_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_datainfo_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_datartp_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_datasendtext_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 struct topology_change_refresh_datatopology_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_datatransfer_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 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_infoast_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 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_containerpjsip_uids_onhold
 
static pjsip_module refer_callback_module
 REFER Callback module, used to attach session data structure to subscription.
 
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 76 of file chan_pjsip.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 3500 of file chan_pjsip.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 3500 of file chan_pjsip.c.

◆ answer()

static int answer ( void *  data)
static

Definition at line 687 of file chan_pjsip.c.

688{
689 struct answer_data *ans_data = data;
690 pj_status_t status = PJ_SUCCESS;
691 pjsip_tx_data *packet = NULL;
692 struct ast_sip_session *session = ans_data->session;
694
695 if (session->inv_session->state == PJSIP_INV_STATE_DISCONNECTED) {
696 ast_log(LOG_ERROR, "Session already DISCONNECTED [reason=%d (%s)]\n",
697 session->inv_session->cause,
698 pjsip_get_status_text(session->inv_session->cause)->ptr);
699 SCOPE_EXIT_RTN_VALUE(0, "Disconnected\n");
700 }
701
702 pjsip_dlg_inc_lock(session->inv_session->dlg);
703 if (session->inv_session->invite_tsx) {
704 status = pjsip_inv_answer(session->inv_session, 200, NULL, NULL, &packet);
705 } else {
706 ast_log(LOG_ERROR,"Cannot answer '%s' because there is no associated SIP transaction\n",
707 ast_channel_name(session->channel));
708 }
709 pjsip_dlg_dec_lock(session->inv_session->dlg);
710
711 if (status == PJ_SUCCESS && packet) {
713 }
714
715 if (status != PJ_SUCCESS) {
716 char err[PJ_ERR_MSG_SIZE];
717
718 pj_strerror(status, err, sizeof(err));
719 ast_log(LOG_WARNING,"Cannot answer '%s': %s\n",
720 ast_channel_name(session->channel), err);
721 /*
722 * Return this value so we can distinguish between this
723 * failure and the threadpool synchronous push failing.
724 */
725 SCOPE_EXIT_RTN_VALUE(-2, "pjproject failure\n");
726 }
728}
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:683
unsigned long indent
Definition chan_pjsip.c:684
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 3500 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 2405 of file chan_pjsip.c.

2406{
2407 struct ast_sip_session *session = data;
2408 pjsip_tx_data *tdata;
2409 int res = 0;
2410 SCOPE_ENTER(1, "%s Topology: %s\n",
2412 ast_str_tmp(256, ast_stream_topology_to_str(session->pending_media_state->topology, &STR_TMP))
2413 );
2414
2415
2417
2418 if (res) {
2419 ast_set_hangupsource(session->channel, ast_channel_name(session->channel), 0);
2420 ast_queue_hangup(session->channel);
2421 } else {
2425 }
2426 SCOPE_EXIT_RTN_VALUE(res, "RC: %d\n", res);
2427}
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:494
int ast_queue_hangup(struct ast_channel *chan)
Queue a hangup frame.
Definition channel.c:1181
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:2496
#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 3072 of file chan_pjsip.c.

3073{
3074 struct ast_features_pickup_config *pickup_cfg;
3075 struct ast_channel *chan;
3076
3077 /* Check for a to-tag to determine if this is a reinvite */
3078 if (rdata->msg_info.to->tag.slen) {
3079 /* We don't care about reinvites */
3080 return 0;
3081 }
3082
3083 pickup_cfg = ast_get_chan_features_pickup_config(session->channel);
3084 if (!pickup_cfg) {
3085 ast_log(LOG_ERROR, "Unable to retrieve pickup configuration options. Unable to detect call pickup extension.\n");
3086 return 0;
3087 }
3088
3089 if (strcmp(session->exten, pickup_cfg->pickupexten)) {
3090 ao2_ref(pickup_cfg, -1);
3091 return 0;
3092 }
3093 ao2_ref(pickup_cfg, -1);
3094
3095 /* We can't directly use session->channel because the pickup operation will cause a masquerade to occur,
3096 * changing the channel pointer in session to a different channel. To ensure we work on the right channel
3097 * we store a pointer locally before we begin and keep a reference so it remains valid no matter what.
3098 */
3099 chan = ast_channel_ref(session->channel);
3100 if (ast_pickup_call(chan)) {
3102 } else {
3104 }
3105 /* A hangup always occurs because the pickup operation will have either failed resulting in the call
3106 * needing to be hung up OR the pickup operation was a success and the channel we now have is actually
3107 * the channel that was replaced, which should be hung up since it is literally in limbo not connected
3108 * to anything at all.
3109 */
3110 ast_hangup(chan);
3111 ast_channel_unref(chan);
3112
3113 return 1;
3114}
#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:2538
#define ast_channel_ref(c)
Increase channel reference count.
Definition channel.h:3007
#define ast_channel_unref(c)
Decrease channel reference count.
Definition channel.h:3018
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 1122 of file chan_pjsip.c.

1123{
1124 RAII_VAR(char *, hold_uid, NULL, ao2_cleanup);
1125
1126 hold_uid = ao2_find(pjsip_uids_onhold, chan_uid, OBJ_SEARCH_KEY);
1127 if (hold_uid) {
1128 /* Device is already on hold. Nothing to do. */
1129 return 0;
1130 }
1131
1132 /* Device wasn't in hold list already. Create a new one. */
1133 hold_uid = ao2_alloc_options(strlen(chan_uid) + 1, NULL,
1135 if (!hold_uid) {
1136 return -1;
1137 }
1138
1139 ast_copy_string(hold_uid, chan_uid, strlen(chan_uid) + 1);
1140
1141 if (ao2_link(pjsip_uids_onhold, hold_uid) == 0) {
1142 return -1;
1143 }
1144
1145 return 0;
1146}
#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 731 of file chan_pjsip.c.

732{
733 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(ast);
734 struct ast_sip_session *session;
735 struct answer_data ans_data = { 0, };
736 int res;
737 SCOPE_ENTER(1, "%s\n", ast_channel_name(ast));
738
739 if (ast_channel_state(ast) == AST_STATE_UP) {
740 SCOPE_EXIT_RTN_VALUE(0, "Already up\n");
741 return 0;
742 }
743
745 session = ao2_bump(channel->session);
746
747 /* the answer task needs to be pushed synchronously otherwise a race condition
748 can occur between this thread and bridging (specifically when native bridging
749 attempts to do direct media) */
751 ans_data.session = session;
752 ans_data.indent = ast_trace_get_indent();
753 res = ast_sip_push_task_wait_serializer(session->serializer, answer, &ans_data);
754 if (res) {
755 if (res == -1) {
756 ast_log(LOG_ERROR,"Cannot answer '%s': Unable to push answer task to the threadpool.\n",
757 ast_channel_name(session->channel));
758 }
759 ao2_ref(session, -1);
760 ast_channel_lock(ast);
761 SCOPE_EXIT_RTN_VALUE(-1, "Couldn't push task\n");
762 }
763 ao2_ref(session, -1);
764 ast_channel_lock(ast);
765
767}
#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:687
void * ast_channel_tech_pvt(const struct ast_channel *chan)
#define ast_channel_lock(chan)
Definition channel.h:2982
#define ast_channel_unlock(chan)
Definition channel.h:2983
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:7398
#define ast_trace_get_indent()
int ast_sip_push_task_wait_serializer(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Push a task to the serializer and wait for it to complete.
Definition res_pjsip.c:2179
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 2430 of file chan_pjsip.c.

2431{
2432 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(ast);
2433 struct ast_sip_session *session = ao2_bump(channel->session);
2434
2435 SCOPE_ENTER(1, "%s Topology: %s\n", ast_sip_session_get_name(session),
2436 ast_str_tmp(256, ast_stream_topology_to_str(session->pending_media_state->topology, &STR_TMP)));
2437
2438 ast_channel_unlock(ast);
2439
2440 /* The creation of the INVITE needs to be pushed synchronously to prevent a race condition
2441 with bridging on attended transfers that can result in a loss of set Caller ID. */
2443 ast_log(LOG_WARNING, "Error attempting to place outbound call to '%s'\n", dest);
2444 ao2_ref(session, -1);
2445 ast_channel_lock(ast);
2446 SCOPE_EXIT_RTN_VALUE(-1, "Couldn't push task\n");
2447 }
2448
2449 ao2_ref(session, -1);
2450 ast_channel_lock(ast);
2451 SCOPE_EXIT_RTN_VALUE(0, "'call' task pushed\n");
2452}
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 770 of file chan_pjsip.c.

772{
773 const char *target_context;
774 int exists;
775 int dsp_features;
776
777 dsp_features = ast_dsp_get_features(session->dsp);
778 dsp_features &= ~DSP_FEATURE_FAX_DETECT;
779 if (dsp_features) {
780 ast_dsp_set_features(session->dsp, dsp_features);
781 } else {
782 ast_dsp_free(session->dsp);
783 session->dsp = NULL;
784 }
785
786 /* If already executing in the fax extension don't do anything */
787 if (!strcmp(ast_channel_exten(ast), "fax")) {
788 return f;
789 }
790
791 target_context = ast_channel_context(ast);
792
793 /*
794 * We need to unlock the channel here because ast_exists_extension has the
795 * potential to start and stop an autoservice on the channel. Such action
796 * is prone to deadlock if the channel is locked.
797 *
798 * ast_async_goto() has its own restriction on not holding the channel lock.
799 */
801 ast_frfree(f);
802 f = &ast_null_frame;
803 exists = ast_exists_extension(ast, target_context, "fax", 1,
804 S_COR(ast_channel_caller(ast)->id.number.valid,
805 ast_channel_caller(ast)->id.number.str, NULL));
806 if (exists) {
807 ast_verb(2, "Redirecting '%s' to fax extension due to CNG detection\n",
808 ast_channel_name(ast));
809 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast_channel_exten(ast));
810 if (ast_async_goto(ast, target_context, "fax", 1)) {
811 ast_log(LOG_ERROR, "Failed to async goto '%s' into fax extension in '%s'\n",
812 ast_channel_name(ast), target_context);
813 }
814 } else {
815 ast_log(LOG_NOTICE, "FAX CNG detected on '%s' but no fax extension in '%s'\n",
816 ast_channel_name(ast), target_context);
817 }
818
819 /* It's possible for a masquerade to have occurred when doing the ast_async_goto resulting in
820 * the channel on the session having changed. Since we need to return with the original channel
821 * locked we lock the channel that was passed in and not session->channel.
822 */
823 ast_channel_lock(ast);
824
825 return f;
826}
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:1787
int ast_dsp_get_features(struct ast_dsp *dsp)
Get features.
Definition dsp.c:1781
void ast_dsp_set_features(struct ast_dsp *dsp, int features)
Select feature set.
Definition dsp.c:1772
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:4196
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:6994
#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 1179 of file chan_pjsip.c.

1180{
1181 RAII_VAR(struct ast_sip_endpoint *, endpoint, ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", data), ao2_cleanup);
1183 RAII_VAR(struct ast_endpoint_snapshot *, endpoint_snapshot, NULL, ao2_cleanup);
1184 struct ast_devstate_aggregate aggregate;
1185 int num, inuse = 0;
1186
1187 if (!endpoint) {
1188 return AST_DEVICE_INVALID;
1189 }
1190
1191 endpoint_snapshot = ast_endpoint_latest_snapshot(ast_endpoint_get_tech(endpoint->persistent),
1192 ast_endpoint_get_resource(endpoint->persistent));
1193
1194 if (!endpoint_snapshot) {
1195 return AST_DEVICE_INVALID;
1196 }
1197
1198 if (endpoint_snapshot->state == AST_ENDPOINT_OFFLINE) {
1200 } else if (endpoint_snapshot->state == AST_ENDPOINT_ONLINE) {
1202 }
1203
1204 if (!endpoint_snapshot->num_channels) {
1205 return state;
1206 }
1207
1208 ast_devstate_aggregate_init(&aggregate);
1209
1210 for (num = 0; num < endpoint_snapshot->num_channels; num++) {
1211 struct ast_channel_snapshot *snapshot;
1212
1213 snapshot = ast_channel_snapshot_get_latest(endpoint_snapshot->channel_ids[num]);
1214 if (!snapshot) {
1215 continue;
1216 }
1217
1218 if (chan_pjsip_get_hold(snapshot->base->uniqueid)) {
1220 } else {
1221 ast_devstate_aggregate_add(&aggregate, ast_state_chan2dev(snapshot->state));
1222 }
1223
1224 if (snapshot->state != AST_STATE_DOWN && snapshot->state != AST_STATE_RESERVED) {
1225 inuse++;
1226 }
1227
1228 ao2_ref(snapshot, -1);
1229 }
1230
1231 if (endpoint->devicestate_busy_at && (inuse >= endpoint->devicestate_busy_at)) {
1233 } else if (ast_devstate_aggregate_result(&aggregate) != AST_DEVICE_INVALID) {
1235 }
1236
1237 return state;
1238}
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
const char * ast_endpoint_get_tech(const struct ast_endpoint *endpoint)
Gets the technology of the given endpoint.
const char * ast_endpoint_get_resource(const struct ast_endpoint *endpoint)
Gets the resource name 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_endpoint_snapshot * ast_endpoint_latest_snapshot(const char *tech, const char *resource)
Retrieve the most recent snapshot for the endpoint with the given name.
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:1051

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_resource(), ast_endpoint_get_tech(), ast_endpoint_latest_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 2197 of file chan_pjsip.c.

2198{
2199 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(chan);
2200 struct ast_sip_session_media *media;
2201
2203
2204 switch (channel->session->dtmf) {
2206 if (!media || !media->rtp) {
2207 return 0;
2208 }
2209
2211 break;
2212 case AST_SIP_DTMF_AUTO:
2213 if (!media || !media->rtp) {
2214 return 0;
2215 }
2216
2218 return -1;
2219 }
2220
2222 break;
2224 if (!media || !media->rtp || (ast_rtp_instance_dtmf_mode_get(media->rtp) == AST_RTP_DTMF_MODE_NONE)) {
2225 return 0;
2226 }
2228 break;
2229 case AST_SIP_DTMF_NONE:
2230 break;
2232 return -1;
2233 default:
2234 break;
2235 }
2236
2237 return 0;
2238}
char digit
@ AST_MEDIA_TYPE_AUDIO
Definition codec.h:32
@ AST_SIP_DTMF_NONE
Definition res_pjsip.h:547
@ AST_SIP_DTMF_AUTO_INFO
Definition res_pjsip.h:558
@ AST_SIP_DTMF_AUTO
Definition res_pjsip.h:556
@ AST_SIP_DTMF_INBAND
Definition res_pjsip.h:552
@ AST_SIP_DTMF_RFC_4733
Definition res_pjsip.h:550
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 2309 of file chan_pjsip.c.

2310{
2311 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(ast);
2312 struct ast_sip_session_media *media;
2313
2314 if (!channel || !channel->session) {
2315 /* This happens when the channel is hungup while a DTMF digit is playing. See ASTERISK-28086 */
2316 ast_debug(3, "Channel %s disappeared while calling digit_end\n", ast_channel_name(ast));
2317 return -1;
2318 }
2319
2321
2322 switch (channel->session->dtmf) {
2324 {
2325 if (!media || !media->rtp) {
2326 return 0;
2327 }
2328
2330 ast_debug(3, "Told to send end of digit on Auto-Info channel %s RFC4733 negotiated so using it.\n", ast_channel_name(ast));
2332 break;
2333 }
2334 /* If RFC_4733 was not negotiated, fail through to the DTMF_INFO processing */
2335 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));
2336 }
2337
2338 case AST_SIP_DTMF_INFO:
2339 {
2340 struct info_dtmf_data *dtmf_data = info_dtmf_data_alloc(channel->session, digit, duration);
2341
2342 if (!dtmf_data) {
2343 return -1;
2344 }
2345
2346 if (ast_sip_push_task(channel->session->serializer, transmit_info_dtmf, dtmf_data)) {
2347 ast_log(LOG_WARNING, "Error sending DTMF via INFO.\n");
2348 ao2_cleanup(dtmf_data);
2349 return -1;
2350 }
2351 break;
2352 }
2354 if (!media || !media->rtp) {
2355 return 0;
2356 }
2357
2359 break;
2360 case AST_SIP_DTMF_AUTO:
2361 if (!media || !media->rtp) {
2362 return 0;
2363 }
2364
2366 return -1;
2367 }
2368
2370 break;
2371 case AST_SIP_DTMF_NONE:
2372 break;
2374 return -1;
2375 }
2376
2377 return 0;
2378}
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)
int ast_sip_push_task(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Pushes a task to SIP servants.
Definition res_pjsip.c:2099
#define ast_debug(level,...)
Log a DEBUG message.
@ AST_SIP_DTMF_INFO
Definition res_pjsip.h:554
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 1050 of file chan_pjsip.c.

1051{
1052 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(newchan);
1053
1054 if (channel->session->channel != oldchan) {
1055 return -1;
1056 }
1057
1058 /*
1059 * The masquerade has suspended the channel's session
1060 * serializer so we can safely change it outside of
1061 * the serializer thread.
1062 */
1063 channel->session->channel = newchan;
1064
1066
1067 return 0;
1068}

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 252 of file chan_pjsip.c.

253{
254 SCOPE_ENTER(1, "%s Native formats %s\n", ast_channel_name(chan),
258}
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:734
#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 1166 of file chan_pjsip.c.

1167{
1168 RAII_VAR(char *, hold_uid, NULL, ao2_cleanup);
1169
1170 hold_uid = ao2_find(pjsip_uids_onhold, chan_uid, OBJ_SEARCH_KEY);
1171 if (!hold_uid) {
1172 return 0;
1173 }
1174
1175 return 1;
1176}

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 179 of file chan_pjsip.c.

180{
181 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(chan);
182 struct ast_sip_endpoint *endpoint;
183 struct ast_datastore *datastore;
184 struct ast_sip_session_media *media;
185
186 if (!channel || !channel->session) {
188 }
189
190 /* XXX Getting the first RTP instance for direct media related stuff seems just
191 * absolutely wrong. But the native RTP bridge knows no other method than single-stream
192 * for direct media. So this is the best we can do.
193 */
195 if (!media || !media->rtp) {
197 }
198
199 datastore = ast_sip_session_get_datastore(channel->session, "t38");
200 if (datastore) {
201 ao2_ref(datastore, -1);
203 }
204
205 endpoint = channel->session->endpoint;
206
207 *instance = media->rtp;
208 ao2_ref(*instance, +1);
209
210 ast_assert(endpoint != NULL);
213 }
214
215 if (endpoint->media.direct_media.enabled) {
217 }
218
220}
@ AST_SIP_MEDIA_ENCRYPT_NONE
Definition res_pjsip.h:737
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:1003
struct ast_sip_direct_media_configuration direct_media
Definition res_pjsip.h:1005
struct ast_sip_endpoint_media_configuration media
Definition res_pjsip.h:1084
enum ast_sip_session_media_encryption encryption
Definition res_pjsip.h:946
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 1282 of file chan_pjsip.c.

1283{
1284 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(ast);
1285 char *uniqueid = ast_threadstorage_get(&uniqueid_threadbuf, UNIQUEID_BUFSIZE);
1286
1287 if (!channel || !uniqueid) {
1288 return "";
1289 }
1290
1291 ast_copy_pj_str(uniqueid, &channel->session->inv_session->dlg->call_id->id, UNIQUEID_BUFSIZE);
1292
1293 return uniqueid;
1294}
#define UNIQUEID_BUFSIZE
Definition chan_pjsip.c:76
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:2201
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 223 of file chan_pjsip.c.

224{
225 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(chan);
226 struct ast_sip_endpoint *endpoint;
227 struct ast_sip_session_media *media;
228
229 if (!channel || !channel->session) {
231 }
232
234 if (!media || !media->rtp) {
236 }
237
238 endpoint = channel->session->endpoint;
239
240 *instance = media->rtp;
241 ao2_ref(*instance, +1);
242
243 ast_assert(endpoint != NULL);
246 }
247
249}
@ 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 2578 of file chan_pjsip.c.

2579{
2580 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(ast);
2581 int cause;
2582 int tech_cause;
2583 int original_tech_cause;
2584 struct hangup_data *h_data;
2585 SCOPE_ENTER(1, "%s\n", ast_channel_name(ast));
2586
2587 if (!channel || !channel->session) {
2588 SCOPE_EXIT_RTN_VALUE(-1, "%s: No channel or session\n", ast_channel_name(ast));
2589 }
2590
2592 tech_cause = hangup_cause2sip(cause);
2593 original_tech_cause = ast_channel_tech_hangupcause(channel->session->channel);
2594 if (!original_tech_cause) {
2595 ast_channel_tech_hangupcause_set(channel->session->channel, tech_cause);
2596 }
2597
2598 h_data = hangup_data_alloc(tech_cause, ast);
2599 if (!h_data) {
2600 goto failure;
2601 }
2602
2603 if (ast_sip_push_task(channel->session->serializer, hangup, h_data)) {
2604 ast_log(LOG_WARNING, "Unable to push hangup task to the threadpool. Expect bad things\n");
2605 goto failure;
2606 }
2607
2608 SCOPE_EXIT_RTN_VALUE(0, "%s: Cause: %d Tech Cause: %d\n", ast_channel_name(ast),
2609 cause, tech_cause);
2610
2611failure:
2612 /* Go ahead and do our cleanup of the session and channel even if we're not going
2613 * to be able to send our SIP request/response
2614 */
2615 clear_session_and_channel(channel->session, ast);
2616 ao2_cleanup(channel);
2617 ao2_cleanup(h_data);
2618
2619 SCOPE_EXIT_RTN_VALUE(-1, "%s: Cause: %d\n", ast_channel_name(ast), cause);
2620}
static int hangup_cause2sip(int cause)
Internal function which translates from Asterisk cause codes to SIP response codes.
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 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(), 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 3250 of file chan_pjsip.c.

3251{
3253
3254 if (rdata->msg_info.msg->line.req.method.id == PJSIP_ACK_METHOD) {
3255 if (session->endpoint->media.direct_media.enabled && session->channel) {
3256 ast_trace(-1, "%s: Queueing SRCCHANGE\n", ast_sip_session_get_name(session));
3258 }
3259 }
3261}
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame without payload.
Definition channel.c:1288
#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 3263 of file chan_pjsip.c.

3264{
3266
3267 if (pj_strcmp2(&rdata->msg_info.msg->line.req.method.name, "PRACK") == 0 &&
3268 pjmedia_sdp_neg_get_state(session->inv_session->neg) == PJMEDIA_SDP_NEG_STATE_DONE) {
3269
3270 session->early_confirmed = 1;
3271 }
3273}

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 3014 of file chan_pjsip.c.

3015{
3016 RAII_VAR(struct ast_datastore *, datastore, NULL, ao2_cleanup);
3017 struct transport_info_data *transport_data;
3018 pjsip_tx_data *packet = NULL;
3020
3021 if (session->channel) {
3022 SCOPE_EXIT_RTN_VALUE(0, "%s: No channel\n", ast_sip_session_get_name(session));
3023 }
3024
3025 /* Check for a to-tag to determine if this is a reinvite */
3026 if (rdata->msg_info.to->tag.slen) {
3027 /* Weird case. We've received a reinvite but we don't have a channel. The most
3028 * typical case for this happening is that a blind transfer fails, and so the
3029 * transferer attempts to reinvite himself back into the call. We already got
3030 * rid of that channel, and the other side of the call is unrecoverable.
3031 *
3032 * We treat this as a failure, so our best bet is to just hang this call
3033 * up and not create a new channel. Clearing defer_terminate here ensures that
3034 * calling ast_sip_session_terminate() can result in a BYE being sent ASAP.
3035 */
3036 session->defer_terminate = 0;
3038 SCOPE_EXIT_RTN_VALUE(-1, "%s: We have a To tag but no channel. Terminating session\n", ast_sip_session_get_name(session));
3039 }
3040
3041 datastore = ast_sip_session_alloc_datastore(&transport_info, "transport_info");
3042 if (!datastore) {
3043 SCOPE_EXIT_LOG_RTN_VALUE(-1, LOG_ERROR, "%s: Couldn't alloc transport_info datastore\n", ast_sip_session_get_name(session));
3044 }
3045
3046 transport_data = ast_calloc(1, sizeof(*transport_data));
3047 if (!transport_data) {
3048 SCOPE_EXIT_LOG_RTN_VALUE(-1, LOG_ERROR, "%s: Couldn't alloc transport_info\n", ast_sip_session_get_name(session));
3049 }
3050 pj_sockaddr_cp(&transport_data->local_addr, &rdata->tp_info.transport->local_addr);
3051 pj_sockaddr_cp(&transport_data->remote_addr, &rdata->pkt_info.src_addr);
3052 datastore->data = transport_data;
3054
3055 if (!(session->channel = chan_pjsip_new(session, AST_STATE_RING, session->exten, NULL, NULL, NULL, NULL))) {
3056 if (pjsip_inv_end_session(session->inv_session, 503, NULL, &packet) == PJ_SUCCESS
3057 && packet) {
3059 }
3060
3061 SCOPE_EXIT_LOG_RTN_VALUE(-1, LOG_ERROR, "%s: Failed to allocate new PJSIP channel on incoming SIP INVITE\n",
3063 }
3064
3066
3067 /* channel gets created on incoming request, but we wait to call start
3068 so other supplements have a chance to run */
3070}
#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:269
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:547
@ 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 3193 of file chan_pjsip.c.

3194{
3195 struct pjsip_status_line status = rdata->msg_info.msg->line.status;
3196 SCOPE_ENTER(3, "%s: Status: %d\n", ast_sip_session_get_name(session), status.code);
3197
3198 if (!session->channel) {
3199 SCOPE_EXIT_RTN("%s: No channel\n", ast_sip_session_get_name(session));
3200 }
3201
3202 switch (status.code) {
3203 case 180: {
3204 pjsip_rdata_sdp_info *sdp = pjsip_rdata_get_sdp_info(rdata);
3205 if (sdp && sdp->body.ptr) {
3206 ast_trace(-1, "%s: Queueing PROGRESS\n", ast_sip_session_get_name(session));
3207 session->early_confirmed = pjsip_100rel_is_reliable(rdata) == PJ_TRUE;
3209 } else {
3210 ast_trace(-1, "%s: Queueing RINGING\n", ast_sip_session_get_name(session));
3212 }
3213
3214 ast_channel_lock(session->channel);
3215 if (ast_channel_state(session->channel) != AST_STATE_UP) {
3217 }
3218 ast_channel_unlock(session->channel);
3219 break;
3220 }
3221 case 183:
3222 if (session->endpoint->ignore_183_without_sdp) {
3223 pjsip_rdata_sdp_info *sdp = pjsip_rdata_get_sdp_info(rdata);
3224 if (sdp && sdp->body.ptr) {
3225 ast_trace(-1, "%s: Queueing PROGRESS\n", ast_sip_session_get_name(session));
3226 ast_trace(1, "%s Method: %.*s Status: %d Queueing PROGRESS with SDP\n", ast_sip_session_get_name(session),
3227 (int)rdata->msg_info.cseq->method.name.slen, rdata->msg_info.cseq->method.name.ptr, status.code);
3228 session->early_confirmed = pjsip_100rel_is_reliable(rdata) == PJ_TRUE;
3230 }
3231 } else {
3232 ast_trace(-1, "%s: Queueing PROGRESS\n", ast_sip_session_get_name(session));
3233 ast_trace(1, "%s Method: %.*s Status: %d Queueing PROGRESS without SDP\n", ast_sip_session_get_name(session),
3234 (int)rdata->msg_info.cseq->method.name.slen, rdata->msg_info.cseq->method.name.ptr, status.code);
3236 }
3237 break;
3238 case 200:
3239 ast_trace(-1, "%s: Queueing ANSWER\n", ast_sip_session_get_name(session));
3241 break;
3242 default:
3243 ast_trace(-1, "%s: Not queueing anything\n", ast_sip_session_get_name(session));
3244 break;
3245 }
3246
3248}
@ 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 3163 of file chan_pjsip.c.

3164{
3165 struct pjsip_status_line status = rdata->msg_info.msg->line.status;
3166 struct ast_control_pvt_cause_code *cause_code;
3167 int data_size = sizeof(*cause_code);
3168 SCOPE_ENTER(3, "%s: Status: %d\n", ast_sip_session_get_name(session), status.code);
3169
3170 if (!session->channel) {
3171 SCOPE_EXIT_RTN("%s: No channel\n", ast_sip_session_get_name(session));
3172 }
3173
3174 /* Build and send the tech-specific cause information */
3175 /* size of the string making up the cause code is "SIP " number + " " + reason length */
3176 data_size += 4 + 4 + pj_strlen(&status.reason);
3177 cause_code = ast_alloca(data_size);
3178 memset(cause_code, 0, data_size);
3179
3181
3182 snprintf(cause_code->code, data_size - sizeof(*cause_code) + 1, "SIP %d %.*s", status.code,
3183 (int) pj_strlen(&status.reason), pj_strbuf(&status.reason));
3184
3185 cause_code->ast_cause = ast_sip_hangup_sip2cause(status.code);
3186 ast_queue_control_data(session->channel, AST_CONTROL_PVT_CAUSE_CODE, cause_code, data_size);
3187 ast_channel_hangupcause_hash_set(session->channel, cause_code, data_size);
3188
3190}
#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:1295
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:4340
#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:3531

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 1624 of file chan_pjsip.c.

1625{
1626 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(ast);
1627 struct ast_sip_session_media *media;
1628 int response_code = 0;
1629 int res = 0;
1630 char *device_buf;
1631 size_t device_buf_size;
1632 int i;
1633 const struct ast_stream_topology *topology;
1634 struct ast_frame f = {
1636 .subclass = {
1637 .integer = condition
1638 },
1639 .datalen = datalen,
1640 .data.ptr = (void *)data,
1641 };
1642 char condition_name[256];
1643 unsigned int duration;
1644 char digit;
1645 struct info_dtmf_data *dtmf_data;
1646
1647 SCOPE_ENTER(3, "%s: Indicated %s\n", ast_channel_name(ast),
1648 ast_frame_subclass2str(&f, condition_name, sizeof(condition_name), NULL, 0));
1649
1650 switch (condition) {
1652 if (ast_channel_state(ast) == AST_STATE_RING) {
1653 if (channel->session->endpoint->inband_progress ||
1654 (channel->session->inv_session && channel->session->inv_session->neg &&
1655 pjmedia_sdp_neg_get_state(channel->session->inv_session->neg) == PJMEDIA_SDP_NEG_STATE_DONE)) {
1656 res = -1;
1658 response_code = 180;
1659 } else {
1660 response_code = 183;
1661 }
1662 } else {
1663 response_code = 180;
1664 }
1665 } else {
1666 res = -1;
1667 }
1669 break;
1670 case AST_CONTROL_BUSY:
1671 if (ast_channel_state(ast) != AST_STATE_UP) {
1672 response_code = 486;
1673 } else {
1674 res = -1;
1675 }
1676 break;
1678 if (ast_channel_state(ast) != AST_STATE_UP) {
1679 response_code = 503;
1680 } else {
1681 res = -1;
1682 }
1683 break;
1685 if (ast_channel_state(ast) != AST_STATE_UP) {
1686 response_code = 484;
1687 } else {
1688 res = -1;
1689 }
1690 break;
1692 if (ast_channel_state(ast) != AST_STATE_UP) {
1693 response_code = 100;
1694 } else {
1695 res = -1;
1696 }
1697 break;
1699 if (ast_channel_state(ast) != AST_STATE_UP) {
1700 response_code = 183;
1701 } else {
1702 res = -1;
1703 }
1705 break;
1706 case AST_CONTROL_FLASH:
1707 duration = 300;
1708 digit = '!';
1709 dtmf_data = info_dtmf_data_alloc(channel->session, digit, duration);
1710
1711 if (!dtmf_data) {
1712 res = -1;
1713 break;
1714 }
1715
1716 if (ast_sip_push_task(channel->session->serializer, transmit_info_dtmf, dtmf_data)) {
1717 ast_log(LOG_WARNING, "Error sending FLASH via INFO on channel %s\n", ast_channel_name(ast));
1718 ao2_ref(dtmf_data, -1); /* dtmf_data can't be null here */
1719 res = -1;
1720 }
1721 break;
1723 for (i = 0; i < AST_VECTOR_SIZE(&channel->session->active_media_state->sessions); ++i) {
1724 media = AST_VECTOR_GET(&channel->session->active_media_state->sessions, i);
1725 if (!media || media->type != AST_MEDIA_TYPE_VIDEO) {
1726 continue;
1727 }
1728 if (media->rtp) {
1729 /* FIXME: Only use this for VP8. Additional work would have to be done to
1730 * fully support other video codecs */
1731
1736 /* FIXME Fake RTP write, this will be sent as an RTCP packet. Ideally the
1737 * RTP engine would provide a way to externally write/schedule RTCP
1738 * packets */
1739 struct ast_frame fr;
1741 fr.subclass.integer = AST_CONTROL_VIDUPDATE;
1742 res = ast_rtp_instance_write(media->rtp, &fr);
1743 } else {
1744 ao2_ref(channel->session, +1);
1746 ao2_cleanup(channel->session);
1747 }
1748 }
1749 ast_test_suite_event_notify("AST_CONTROL_VIDUPDATE", "Result: Success");
1750 } else {
1751 ast_test_suite_event_notify("AST_CONTROL_VIDUPDATE", "Result: Failure");
1752 res = -1;
1753 }
1754 }
1755 /* XXX If there were no video streams, then this should set
1756 * res to -1
1757 */
1758 break;
1760 ao2_ref(channel->session, +1);
1762 ao2_cleanup(channel->session);
1763 }
1764 break;
1766 break;
1768 res = -1;
1769 break;
1771 ast_assert(datalen == sizeof(int));
1772 if (*(int *) data) {
1773 /*
1774 * Masquerade is beginning:
1775 * Wait for session serializer to get suspended.
1776 */
1777 ast_channel_unlock(ast);
1779 ast_channel_lock(ast);
1780 } else {
1781 /*
1782 * Masquerade is complete:
1783 * Unsuspend the session serializer.
1784 */
1786 }
1787 break;
1788 case AST_CONTROL_HOLD:
1790 device_buf_size = strlen(ast_channel_name(ast)) + 1;
1791 device_buf = alloca(device_buf_size);
1792 ast_channel_get_device_name(ast, device_buf, device_buf_size);
1794 if (!channel->session->moh_passthrough) {
1795 ast_moh_start(ast, data, NULL);
1796 } else {
1798 ast_log(LOG_WARNING, "Could not queue task to remotely put session '%s' on hold with endpoint '%s'\n",
1800 ao2_ref(channel->session, -1);
1801 }
1802 }
1803 break;
1804 case AST_CONTROL_UNHOLD:
1806 device_buf_size = strlen(ast_channel_name(ast)) + 1;
1807 device_buf = alloca(device_buf_size);
1808 ast_channel_get_device_name(ast, device_buf, device_buf_size);
1810 if (!channel->session->moh_passthrough) {
1811 ast_moh_stop(ast);
1812 } else {
1814 ast_log(LOG_WARNING, "Could not queue task to remotely take session '%s' off hold with endpoint '%s'\n",
1816 ao2_ref(channel->session, -1);
1817 }
1818 }
1819 break;
1821 break;
1823 if (!channel->session->endpoint->media.bundle) {
1824 /* Generate a new SSRC due to media source change and RTP timestamp reset.
1825 Ensures RFC 3550 compliance and avoids SBC interoperability issues (Sonus/Ribbon)*/
1826 for (i = 0; i < AST_VECTOR_SIZE(&channel->session->active_media_state->sessions); ++i) {
1827 media = AST_VECTOR_GET(&channel->session->active_media_state->sessions, i);
1828 if (media && media->rtp) {
1830 }
1831 }
1832 }
1833 break;
1835 if (ast_channel_state(ast) != AST_STATE_UP) {
1836 response_code = 181;
1837 } else {
1838 res = -1;
1839 }
1840 break;
1842 res = 0;
1843
1844 if (channel->session->t38state == T38_PEER_REINVITE) {
1845 const struct ast_control_t38_parameters *parameters = data;
1846
1847 if (parameters->request_response == AST_T38_REQUEST_PARMS) {
1849 }
1850 }
1851
1852 break;
1854 topology = data;
1855 ast_trace(-1, "%s: New topology: %s\n", ast_channel_name(ast),
1856 ast_str_tmp(256, ast_stream_topology_to_str(topology, &STR_TMP)));
1857 res = handle_topology_request_change(channel->session, topology);
1858 break;
1860 break;
1862 break;
1864 break;
1865 case -1:
1866 res = -1;
1867 break;
1868 default:
1869 ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", condition);
1870 res = -1;
1871 break;
1872 }
1873
1874 if (response_code) {
1875 struct indicate_data *ind_data = indicate_data_alloc(channel->session, condition, response_code, data, datalen);
1876
1877 if (!ind_data) {
1878 SCOPE_EXIT_LOG_RTN_VALUE(-1, LOG_ERROR, "%s: Couldn't alloc indicate data\n", ast_channel_name(ast));
1879 }
1880
1881 if (ast_sip_push_task(channel->session->serializer, indicate, ind_data)) {
1882 ast_log(LOG_ERROR, "%s: Cannot send response code %d to endpoint %s. Could not queue task properly\n",
1884 ao2_cleanup(ind_data);
1885 res = -1;
1886 }
1887 }
1888
1889 SCOPE_EXIT_RTN_VALUE(res, "%s\n", ast_channel_name(ast));
1890}
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:10540
@ 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:581
@ 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:7778
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition channel.c:7788
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:596
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::@239 data
unsigned int inband_progress
Definition res_pjsip.h:1106
struct ast_sip_session_media_state::@282 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:620
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition vector.h:691

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 547 of file chan_pjsip.c.

548{
549 struct ast_channel *chan;
550 struct ast_format_cap *caps;
551 RAII_VAR(struct chan_pjsip_pvt *, pvt, NULL, ao2_cleanup);
552 struct ast_sip_channel_pvt *channel;
553 struct ast_variable *var;
554 struct ast_stream_topology *topology;
555 struct ast_channel_initializers initializers = {
557 .tenantid = session->endpoint->tenantid,
558 };
560
562 SCOPE_EXIT_RTN_VALUE(NULL, "Couldn't create pvt\n");
563 }
564
566 S_COR(session->id.number.valid, session->id.number.str, ""),
567 S_COR(session->id.name.valid, session->id.name.str, ""),
568 session->endpoint->accountcode,
569 exten, session->endpoint->context,
570 assignedids, requestor, 0,
571 session->endpoint->persistent, &initializers, "PJSIP/%s-%08x",
573 (unsigned) ast_atomic_fetchadd_int((int *) &chan_idx, +1));
574 if (!chan) {
575 SCOPE_EXIT_RTN_VALUE(NULL, "Couldn't create channel\n");
576 }
577
579
580 if (!(channel = ast_sip_channel_pvt_alloc(pvt, session))) {
581 ast_channel_unlock(chan);
582 ast_hangup(chan);
583 SCOPE_EXIT_RTN_VALUE(NULL, "Couldn't create pvt channel\n");
584 }
585
586 ast_channel_tech_pvt_set(chan, channel);
587
588 if (!ast_stream_topology_get_count(session->pending_media_state->topology) ||
589 !compatible_formats_exist(session->pending_media_state->topology, session->endpoint->media.codecs)) {
591 if (!caps) {
592 ast_channel_unlock(chan);
593 ast_hangup(chan);
594 SCOPE_EXIT_RTN_VALUE(NULL, "Couldn't create caps\n");
595 }
596 ast_format_cap_append_from_cap(caps, session->endpoint->media.codecs, AST_MEDIA_TYPE_UNKNOWN);
597 topology = ast_stream_topology_clone(session->endpoint->media.topology);
598 } else {
599 caps = ast_stream_topology_get_formats(session->pending_media_state->topology);
600 topology = ast_stream_topology_clone(session->pending_media_state->topology);
601 }
602
603 if (!topology || !caps) {
604 ao2_cleanup(caps);
605 ast_stream_topology_free(topology);
606 ast_channel_unlock(chan);
607 ast_hangup(chan);
608 SCOPE_EXIT_RTN_VALUE(NULL, "Couldn't get caps or clone topology\n");
609 }
610
612
614 ast_channel_set_stream_topology(chan, topology);
615
616 if (!ast_format_cap_empty(caps)) {
617 struct ast_format *fmt;
618
620 if (!fmt) {
621 /* Since our capabilities aren't empty, this will succeed */
622 fmt = ast_format_cap_get_format(caps, 0);
623 }
628 ao2_ref(fmt, -1);
629 }
630
631 ao2_ref(caps, -1);
632
633 if (state == AST_STATE_RING) {
634 ast_channel_rings_set(chan, 1);
635 }
636
638
641 ast_channel_caller(chan)->ani2 = session->ani2;
642
643 if (!ast_strlen_zero(exten)) {
644 /* Set provided DNID on the new channel. */
645 ast_channel_dialed(chan)->number.str = ast_strdup(exten);
646 }
647
649
650 ast_channel_callgroup_set(chan, session->endpoint->pickup.callgroup);
651 ast_channel_pickupgroup_set(chan, session->endpoint->pickup.pickupgroup);
652
653 ast_channel_named_callgroups_set(chan, session->endpoint->pickup.named_callgroups);
654 ast_channel_named_pickupgroups_set(chan, session->endpoint->pickup.named_pickupgroups);
655
656 if (!ast_strlen_zero(session->endpoint->language)) {
657 ast_channel_language_set(chan, session->endpoint->language);
658 }
659
660 if (!ast_strlen_zero(session->endpoint->zone)) {
661 struct ast_tone_zone *zone = ast_get_indication_zone(session->endpoint->zone);
662 if (!zone) {
663 ast_log(LOG_ERROR, "Unknown country code '%s' for tonezone. Check indications.conf for available country codes.\n", session->endpoint->zone);
664 }
665 ast_channel_zone_set(chan, zone);
666 }
667
668 for (var = session->endpoint->channel_vars; var; var = var->next) {
669 char buf[512];
671 var->value, buf, sizeof(buf)));
672 }
673
675 ast_channel_unlock(chan);
676
678
680}
#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:82
struct ast_channel_tech chan_pjsip_tech
PBX interface structure for channel registration.
Definition chan_pjsip.c:109
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:526
static unsigned int chan_idx
Definition chan_pjsip.c:80
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:1751
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)
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:744
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:400
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:417
@ 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:3162
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
char * str
Subscriber phone number (Malloced)
Definition channel.h:388
struct ast_party_dialed::@221 number
Dialed/Called number.
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(), 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 82 of file chan_pjsip.c.

83{
84}

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 1241 of file chan_pjsip.c.

1242{
1243 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(ast);
1244 int res = -1;
1246
1247 if (!channel) {
1248 return -1;
1249 }
1250
1251 switch (option) {
1253 if (channel->session->endpoint->media.t38.enabled) {
1254 switch (channel->session->t38state) {
1255 case T38_LOCAL_REINVITE:
1256 case T38_PEER_REINVITE:
1258 break;
1259 case T38_ENABLED:
1261 break;
1262 case T38_REJECTED:
1264 break;
1265 default:
1267 break;
1268 }
1269 }
1270
1271 *((enum ast_t38_state *) data) = state;
1272 res = 0;
1273
1274 break;
1275 default:
1276 break;
1277 }
1278
1279 return res;
1280}
#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:1007

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 843 of file chan_pjsip.c.

844{
845 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(ast);
846 struct ast_sip_session *session = channel->session;
847 struct ast_sip_session_media_read_callback_state *callback_state;
848 struct ast_frame *f;
849 int fdno = ast_channel_fdno(ast) - AST_EXTENDED_FDS;
850 struct ast_frame *cur;
851
852 if (fdno >= AST_VECTOR_SIZE(&session->active_media_state->read_callbacks)) {
853 return &ast_null_frame;
854 }
855
856 callback_state = AST_VECTOR_GET_ADDR(&session->active_media_state->read_callbacks, fdno);
857 f = callback_state->read_callback(session, callback_state->session);
858
859 if (!f) {
860 return f;
861 }
862
863 for (cur = f; cur; cur = AST_LIST_NEXT(cur, frame_list)) {
864 if (cur->frametype == AST_FRAME_VOICE) {
865 break;
866 }
867 }
868
869 if (!cur || callback_state->session != session->active_media_state->default_session[callback_state->session->type]) {
870 return f;
871 }
872
873 session = channel->session;
874
875 /*
876 * Asymmetric RTP only has one native format set at a time.
877 * Therefore we need to update the native format to the current
878 * raw read format BEFORE the native format check
879 */
880 if (!session->endpoint->asymmetric_rtp_codec &&
883 struct ast_format_cap *caps;
884
885 /* For maximum compatibility we ensure that the formats match that of the received media */
886 ast_debug(1, "Oooh, got a frame with format of %s on channel '%s' when we're sending '%s', switching to match\n",
889
891 if (caps) {
896 ao2_ref(caps, -1);
897 }
898
901
902 if (ast_channel_is_bridged(ast)) {
904 }
905 }
906
909 ast_debug(1, "Oooh, got a frame with format of %s on channel '%s' when it has not been negotiated\n",
911 ast_frfree(f);
912 return &ast_null_frame;
913 }
914
915 if (session->dsp) {
916 int dsp_features;
917
918 dsp_features = ast_dsp_get_features(session->dsp);
919 if ((dsp_features & DSP_FEATURE_FAX_DETECT)
920 && session->endpoint->faxdetect_timeout
921 && session->endpoint->faxdetect_timeout <= ast_channel_get_up_time(ast)) {
922 dsp_features &= ~DSP_FEATURE_FAX_DETECT;
923 if (dsp_features) {
924 ast_dsp_set_features(session->dsp, dsp_features);
925 } else {
926 ast_dsp_free(session->dsp);
927 session->dsp = NULL;
928 }
929 ast_debug(3, "Channel driver fax CNG detection timeout on %s\n",
930 ast_channel_name(ast));
931 }
932 }
933 if (session->dsp) {
934 f = ast_dsp_process(ast, session->dsp, f);
935 if (f && (f->frametype == AST_FRAME_DTMF)) {
936 if (f->subclass.integer == 'f') {
937 ast_debug(3, "Channel driver fax CNG detected on %s\n",
938 ast_channel_name(ast));
940 /* When chan_pjsip_cng_tone_detected returns it is possible for the
941 * channel pointed to by ast and by session->channel to differ due to a
942 * masquerade. It's best not to touch things after this.
943 */
944 } else {
945 ast_debug(3, "* Detected inband DTMF '%c' on '%s'\n", f->subclass.integer,
946 ast_channel_name(ast));
947 }
948 }
949 }
950
951 return f;
952}
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:829
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:770
#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:5483
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:10589
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:2843
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:5519
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:1503
#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:523
#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:679

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 1153 of file chan_pjsip.c.

1154{
1156}
@ 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 2764 of file chan_pjsip.c.

2765{
2766 struct ast_stream_topology *topology;
2767 struct ast_channel *chan;
2768
2770 if (!topology) {
2771 return NULL;
2772 }
2773
2774 chan = chan_pjsip_request_with_stream_topology(type, topology, assignedids, requestor, data, cause);
2775
2776 ast_stream_topology_free(topology);
2777
2778 return chan;
2779}
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 2737 of file chan_pjsip.c.

2738{
2739 struct request_data req_data;
2741 SCOPE_ENTER(1, "%s Topology: %s\n", data,
2743
2744 req_data.topology = topology;
2745 req_data.dest = data;
2746 /* Default failure value in case ast_sip_push_task_wait_servant() itself fails. */
2747 req_data.cause = AST_CAUSE_FAILURE;
2748
2749 if (ast_sip_push_task_wait_servant(NULL, request, &req_data)) {
2750 *cause = req_data.cause;
2751 SCOPE_EXIT_RTN_VALUE(NULL, "Couldn't push task\n");
2752 }
2753
2754 session = req_data.session;
2755
2756 if (!(session->channel = chan_pjsip_new(session, AST_STATE_DOWN, NULL, NULL, assignedids, requestor, NULL))) {
2757 /* Session needs to be terminated prematurely */
2758 SCOPE_EXIT_RTN_VALUE(NULL, "Couldn't create channel\n");
2759 }
2760
2761 SCOPE_EXIT_RTN_VALUE(session->channel, "Channel: %s\n", ast_channel_name(session->channel));
2762}
#define AST_CAUSE_FAILURE
Definition causes.h:150
static int request(void *obj)
int ast_sip_push_task_wait_servant(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Push a task to SIP servants and wait for it to complete.
Definition res_pjsip.c: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 2907 of file chan_pjsip.c.

2908{
2909 struct ast_msg_data *msg;
2910 int rc;
2911 struct ast_msg_data_attribute attrs[] =
2912 {
2913 {
2915 .value = (char *)text,
2916 }
2917 };
2918
2920 if (!msg) {
2921 return -1;
2922 }
2923 rc = chan_pjsip_sendtext_data(ast, msg);
2924 ast_free(msg);
2925
2926 return rc;
2927}
#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 2885 of file chan_pjsip.c.

2886{
2887 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(ast);
2888 struct sendtext_data *data = sendtext_data_create(ast, msg);
2889
2890 ast_debug(1, "Sending MESSAGE from '%s' to '%s:%s': %s\n",
2893 ast_channel_name(ast),
2895
2896 if (!data) {
2897 return -1;
2898 }
2899
2900 if (ast_sip_push_task(channel->session->serializer, sendtext, data)) {
2901 ao2_ref(data, -1);
2902 return -1;
2903 }
2904 return 0;
2905}
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 2929 of file chan_pjsip.c.

2930{
2931 RAII_VAR(struct ast_datastore *, datastore, NULL, ao2_cleanup);
2933
2934 if (session->endpoint->media.direct_media.glare_mitigation ==
2936 SCOPE_EXIT_RTN("Direct media no glare mitigation\n");
2937 }
2938
2940 "direct_media_glare_mitigation");
2941
2942 if (!datastore) {
2943 SCOPE_EXIT_RTN("Couldn't create datastore\n");
2944 }
2945
2948}
static struct ast_datastore_info direct_media_mitigation_info
Definition chan_pjsip.c:274
@ AST_SIP_DIRECT_MEDIA_GLARE_MITIGATION_NONE
Definition res_pjsip.h:722

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 2951 of file chan_pjsip.c.

2952{
2954
2955 if (!session->channel) {
2956 SCOPE_EXIT_RTN("%s: No channel\n", ast_sip_session_get_name(session));
2957 }
2958
2959
2960 if (session->active_media_state &&
2961 session->active_media_state->default_session[AST_MEDIA_TYPE_AUDIO]) {
2962 struct ast_sip_session_media *media =
2963 session->active_media_state->default_session[AST_MEDIA_TYPE_AUDIO];
2964 if (media->rtp) {
2966 }
2967 }
2968
2970
2971 ast_set_hangupsource(session->channel, ast_channel_name(session->channel), 0);
2972
2973 ast_trace(-1, "%s: channel cause: %d\n", ast_sip_session_get_name(session),
2975
2976 if (session->inv_session) {
2977 /*
2978 * tech_hangupcause should only be set if off-nominal.
2979 */
2980 if (session->inv_session->cause / 100 > 2) {
2981 ast_trace(-1, "%s: inv_session cause: %d\n", ast_sip_session_get_name(session),
2982 session->inv_session->cause);
2983 ast_channel_tech_hangupcause_set(session->channel, session->inv_session->cause);
2984 } else {
2985 ast_trace(-1, "%s: inv_session cause: %d suppressed\n", ast_sip_session_get_name(session),
2986 session->inv_session->cause);
2987 }
2988 }
2989
2990 if (!ast_channel_hangupcause(session->channel) && session->inv_session) {
2991 int cause = ast_sip_hangup_sip2cause(session->inv_session->cause);
2992
2993 ast_queue_hangup_with_cause(session->channel, cause);
2994 } else {
2995 ast_queue_hangup(session->channel);
2996 }
2997
2999}
int ast_queue_hangup_with_cause(struct ast_channel *chan, int cause)
Queue a hangup frame with hangupcause set.
Definition channel.c:1212
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.

References ast_channel_hangupcause(), ast_channel_name(), ast_channel_tech_hangupcause_set(), ast_channel_uniqueid(), AST_MEDIA_TYPE_AUDIO, ast_queue_hangup(), ast_queue_hangup_with_cause(), ast_rtp_instance_set_stats_vars(), ast_set_hangupsource(), ast_sip_hangup_sip2cause(), ast_sip_session_get_name(), ast_trace, chan_pjsip_remove_hold(), 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 448 of file chan_pjsip.c.

454{
455 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(chan);
456 struct ast_sip_session *session = channel->session;
458 SCOPE_ENTER(1, "%s %s\n", ast_channel_name(chan),
460
461 /* Don't try to do any direct media shenanigans on early bridges */
462 if ((rtp || vrtp || tpeer) && !ast_channel_is_bridged(chan)) {
463 ast_debug(4, "Disregarding setting RTP on %s: channel is not bridged\n", ast_channel_name(chan));
464 SCOPE_EXIT_RTN_VALUE(0, "Channel not bridged\n");
465 }
466
467 if (nat_active && session->endpoint->media.direct_media.disable_on_nat) {
468 ast_debug(4, "Disregarding setting RTP on %s: NAT is active\n", ast_channel_name(chan));
469 SCOPE_EXIT_RTN_VALUE(0, "NAT is active\n");
470 }
471
473 if (!cdata) {
475 }
476
478 ast_log(LOG_ERROR, "Unable to send direct media request for channel %s\n", ast_channel_name(chan));
479 ao2_ref(cdata, -1);
480 }
481
483}
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:377
static int send_direct_media_request(void *data)
Definition chan_pjsip.c:396
static int cdata(void *userdata, int state, const char *cdata, size_t len)
struct ast_rtp_instance * vrtp
Definition chan_pjsip.c:361
struct ast_channel * chan
Definition chan_pjsip.c:359
struct ast_rtp_instance * rtp
Definition chan_pjsip.c:360
struct ast_format_cap * cap
Definition chan_pjsip.c:362

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 2178 of file chan_pjsip.c.

2179{
2180 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(chan);
2181 struct transfer_data *trnf_data = transfer_data_alloc(channel->session, target);
2182
2183 if (!trnf_data) {
2184 return -1;
2185 }
2186
2187 if (ast_sip_push_task(channel->session->serializer, transfer, trnf_data)) {
2188 ast_log(LOG_WARNING, "Error requesting transfer\n");
2189 ao2_cleanup(trnf_data);
2190 return -1;
2191 }
2192
2193 return 0;
2194}
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 1044 of file chan_pjsip.c.

1045{
1046 return chan_pjsip_write_stream(ast, -1, frame);
1047}
static int chan_pjsip_write_stream(struct ast_channel *ast, int stream_num, struct ast_frame *f)
Definition chan_pjsip.c:954

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 954 of file chan_pjsip.c.

955{
956 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(ast);
957 struct ast_sip_session *session = channel->session;
958 struct ast_sip_session_media *media = NULL;
959 int res = 0;
960
961 /* The core provides a guarantee that the stream will exist when we are called if stream_num is provided */
962 if (stream_num >= 0) {
963 /* What is not guaranteed is that a media session will exist */
966 }
967 }
968
969 switch (frame->frametype) {
970 case AST_FRAME_VOICE:
971 if (!media) {
972 return 0;
973 } else if (media->type != AST_MEDIA_TYPE_AUDIO) {
974 ast_debug(3, "Channel %s stream %d is of type '%s', not audio!\n",
976 return 0;
977 } else if (media == channel->session->active_media_state->default_session[AST_MEDIA_TYPE_AUDIO] &&
980 struct ast_str *write_transpath = ast_str_alloca(256);
981 struct ast_str *read_transpath = ast_str_alloca(256);
982
984 "Channel %s asked to send %s frame when native formats are %s (rd:%s->%s;%s wr:%s->%s;%s)\n",
985 ast_channel_name(ast),
986 ast_format_get_name(frame->subclass.format),
993 ast_translate_path_to_str(ast_channel_writetrans(ast), &write_transpath));
994 return 0;
995 } else if (media->write_callback) {
996 res = media->write_callback(session, media, frame);
997
998 }
999 break;
1000 case AST_FRAME_VIDEO:
1001 if (!media) {
1002 return 0;
1003 } else if (media->type != AST_MEDIA_TYPE_VIDEO) {
1004 ast_debug(3, "Channel %s stream %d is of type '%s', not video!\n",
1005 ast_channel_name(ast), stream_num, ast_codec_media_type2str(media->type));
1006 return 0;
1007 } else if (media->write_callback) {
1008 res = media->write_callback(session, media, frame);
1009 }
1010 break;
1011 case AST_FRAME_MODEM:
1012 if (!media) {
1013 return 0;
1014 } else if (media->type != AST_MEDIA_TYPE_IMAGE) {
1015 ast_debug(3, "Channel %s stream %d is of type '%s', not image!\n",
1016 ast_channel_name(ast), stream_num, ast_codec_media_type2str(media->type));
1017 return 0;
1018 } else if (media->write_callback) {
1019 res = media->write_callback(session, media, frame);
1020 }
1021 break;
1022 case AST_FRAME_CNG:
1023 break;
1024 case AST_FRAME_RTCP:
1025 /* We only support writing out feedback */
1026 if (frame->subclass.integer != AST_RTP_RTCP_PSFB || !media) {
1027 return 0;
1028 } else if (media->type != AST_MEDIA_TYPE_VIDEO) {
1029 ast_debug(3, "Channel %s stream %d is of type '%s', not video! Unable to write RTCP feedback.\n",
1030 ast_channel_name(ast), stream_num, ast_codec_media_type2str(media->type));
1031 return 0;
1032 } else if (media->write_callback) {
1033 res = media->write_callback(session, media, frame);
1034 }
1035 break;
1036 default:
1037 ast_log(LOG_WARNING, "Can't send %u type frames with PJSIP\n", frame->frametype);
1038 break;
1039 }
1040
1041 return res;
1042}
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:930

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 327 of file chan_pjsip.c.

329{
330 int changed = 0, position = -1;
331
332 if (media->rtp) {
333 position = rtp_find_rtcp_fd_position(session, media->rtp);
334 }
335
336 if (rtp) {
338 if (media->rtp) {
339 if (position != -1) {
340 ast_channel_set_fd(chan, position + AST_EXTENDED_FDS, -1);
341 }
343 }
344 } else if (!ast_sockaddr_isnull(&media->direct_media_addr)){
346 changed = 1;
347 if (media->rtp) {
349 if (position != -1) {
350 ast_channel_set_fd(chan, position + AST_EXTENDED_FDS, ast_rtp_instance_fd(media->rtp, 1));
351 }
352 }
353 }
354
355 return changed;
356}
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:306
void ast_channel_set_fd(struct ast_channel *chan, int which, int fd)
Definition channel.c:2416
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:733
@ 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 2529 of file chan_pjsip.c.

2530{
2531 session->channel = NULL;
2534}

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

Referenced by chan_pjsip_hangup(), and hangup().

◆ 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 526 of file chan_pjsip.c.

527{
528 struct ast_format_cap *cap_from_top;
529 int res;
530 SCOPE_ENTER(1, "Topology: %s Formats: %s\n",
533
534 cap_from_top = ast_stream_topology_get_formats(top);
535
536 if (!cap_from_top) {
537 SCOPE_EXIT_RTN_VALUE(0, "Topology had no formats\n");
538 }
539
540 res = ast_format_cap_iscompatible(cap_from_top, cap);
541 ao2_ref(cap_from_top, -1);
542
543 SCOPE_EXIT_RTN_VALUE(res, "Compatible? %s\n", res ? "yes" : "no");
544}
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:653

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 276 of file chan_pjsip.c.

277{
278 RAII_VAR(struct ast_datastore *, datastore, NULL, ao2_cleanup);
279
280 if (session->endpoint->media.direct_media.glare_mitigation ==
282 return 0;
283 }
284
285 datastore = ast_sip_session_get_datastore(session, "direct_media_glare_mitigation");
286 if (!datastore) {
287 return 0;
288 }
289
290 /* Removing the datastore ensures we won't try to mitigate glare on subsequent reinvites */
291 ast_sip_session_remove_datastore(session, "direct_media_glare_mitigation");
292
293 if ((session->endpoint->media.direct_media.glare_mitigation ==
295 session->inv_session->role == PJSIP_ROLE_UAC) ||
296 (session->endpoint->media.direct_media.glare_mitigation ==
298 session->inv_session->role == PJSIP_ROLE_UAS)) {
299 return 1;
300 }
301
302 return 0;
303}
@ AST_SIP_DIRECT_MEDIA_GLARE_MITIGATION_INCOMING
Definition res_pjsip.h:730
@ AST_SIP_DIRECT_MEDIA_GLARE_MITIGATION_OUTGOING
Definition res_pjsip.h:726
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 1600 of file chan_pjsip.c.

1602{
1604 int res;
1605 SCOPE_ENTER(1);
1606
1608 if (!refresh_data) {
1609 SCOPE_EXIT_RTN_VALUE(-1, "Couldn't create refresh_data\n");
1610 }
1611
1613 if (res) {
1615 }
1616 SCOPE_EXIT_RTN_VALUE(res, "RC: %d\n", res);
1617}
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 2536 of file chan_pjsip.c.

2537{
2538 struct hangup_data *h_data = data;
2539 struct ast_channel *ast = h_data->chan;
2540 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(ast);
2541 SCOPE_ENTER(1, "%s\n", ast_channel_name(ast));
2542
2543 /*
2544 * Before cleaning we have to ensure that channel or its session is not NULL
2545 * we have seen rare case when taskprocessor calls hangup but channel is NULL
2546 * due to SIP session timeout and answer happening at the same time
2547 */
2548 if (channel) {
2549 struct ast_sip_session *session = channel->session;
2550 if (session) {
2551 int cause = h_data->cause;
2552
2553 if (channel->session->active_media_state &&
2554 channel->session->active_media_state->default_session[AST_MEDIA_TYPE_AUDIO]) {
2555 struct ast_sip_session_media *media =
2557 if (media->rtp) {
2559 }
2560 }
2561
2562 /*
2563 * It's possible that session_terminate might cause the session to be destroyed
2564 * immediately so we need to keep a reference to it so we can NULL session->channel
2565 * afterwards.
2566 */
2570 }
2571 ao2_cleanup(channel);
2572 }
2573 ao2_cleanup(h_data);
2575}
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 2455 of file chan_pjsip.c.

2456{
2457 switch (cause) {
2458 case AST_CAUSE_UNALLOCATED: /* 1 */
2459 case AST_CAUSE_NO_ROUTE_DESTINATION: /* 3 IAX2: Can't find extension in context */
2460 case AST_CAUSE_NO_ROUTE_TRANSIT_NET: /* 2 */
2461 return 404;
2462 case AST_CAUSE_CONGESTION: /* 34 */
2463 case AST_CAUSE_SWITCH_CONGESTION: /* 42 */
2464 return 503;
2465 case AST_CAUSE_NO_USER_RESPONSE: /* 18 */
2466 return 408;
2467 case AST_CAUSE_NO_ANSWER: /* 19 */
2468 case AST_CAUSE_UNREGISTERED: /* 20 */
2469 return 480;
2470 case AST_CAUSE_CALL_REJECTED: /* 21 */
2471 return 403;
2472 case AST_CAUSE_NUMBER_CHANGED: /* 22 */
2473 return 410;
2474 case AST_CAUSE_NORMAL_UNSPECIFIED: /* 31 */
2475 return 480;
2477 return 484;
2479 return 486;
2480 case AST_CAUSE_FAILURE:
2481 return 500;
2482 case AST_CAUSE_FACILITY_REJECTED: /* 29 */
2483 return 501;
2485 return 503;
2487 return 502;
2488 case AST_CAUSE_BEARERCAPABILITY_NOTAVAIL: /* Can't find codec to connect to host */
2489 return 488;
2490 case AST_CAUSE_INTERWORKING: /* Unspecified Interworking issues */
2491 return 500;
2493 default:
2494 ast_debug(1, "AST hangup cause %d (no match found in PJSIP)\n", cause);
2495 return 0;
2496 }
2497
2498 /* Never reached */
2499 return 0;
2500}
#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_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_SWITCH_CONGESTION, AST_CAUSE_UNALLOCATED, AST_CAUSE_UNREGISTERED, AST_CAUSE_USER_BUSY, and ast_debug.

Referenced by chan_pjsip_hangup().

◆ hangup_data_alloc()

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

Definition at line 2514 of file chan_pjsip.c.

2515{
2516 struct hangup_data *h_data = ao2_alloc(sizeof(*h_data), hangup_data_destroy);
2517
2518 if (!h_data) {
2519 return NULL;
2520 }
2521
2522 h_data->cause = cause;
2523 h_data->chan = ast_channel_ref(chan);
2524
2525 return h_data;
2526}
#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 2507 of file chan_pjsip.c.

2508{
2509 struct hangup_data *h_data = obj;
2510
2511 h_data->chan = ast_channel_unref(h_data->chan);
2512}

References ast_channel_unref, and hangup_data::chan.

Referenced by hangup_data_alloc().

◆ indicate()

static int indicate ( void *  data)
static

Definition at line 1337 of file chan_pjsip.c.

1338{
1339 pjsip_tx_data *packet = NULL;
1340 struct indicate_data *ind_data = data;
1341 struct ast_sip_session *session = ind_data->session;
1342 int response_code = ind_data->response_code;
1343
1344 if ((session->inv_session->state != PJSIP_INV_STATE_DISCONNECTED) &&
1345 (pjsip_inv_answer(session->inv_session, response_code, NULL, NULL, &packet) == PJ_SUCCESS)) {
1347 }
1348
1349 ao2_ref(ind_data, -1);
1350
1351 return 0;
1352}
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 1312 of file chan_pjsip.c.

1314{
1315 struct indicate_data *ind_data = ao2_alloc(sizeof(*ind_data), indicate_data_destroy);
1316
1317 if (!ind_data) {
1318 return NULL;
1319 }
1320
1321 ind_data->frame_data = ast_malloc(datalen);
1322 if (!ind_data->frame_data) {
1323 ao2_ref(ind_data, -1);
1324 return NULL;
1325 }
1326
1327 memcpy(ind_data->frame_data, frame_data, datalen);
1328 ind_data->datalen = datalen;
1329 ind_data->condition = condition;
1330 ind_data->response_code = response_code;
1331 ao2_ref(session, +1);
1332 ind_data->session = session;
1333
1334 return ind_data;
1335}
#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 1304 of file chan_pjsip.c.

1305{
1306 struct indicate_data *ind_data = obj;
1307
1308 ast_free(ind_data->frame_data);
1309 ao2_ref(ind_data->session, -1);
1310}

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 2252 of file chan_pjsip.c.

2253{
2254 struct info_dtmf_data *dtmf_data = ao2_alloc(sizeof(*dtmf_data), info_dtmf_data_destroy);
2255 if (!dtmf_data) {
2256 return NULL;
2257 }
2258 ao2_ref(session, +1);
2259 dtmf_data->session = session;
2260 dtmf_data->digit = digit;
2261 dtmf_data->duration = duration;
2262 return dtmf_data;
2263}
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 2246 of file chan_pjsip.c.

2247{
2248 struct info_dtmf_data *dtmf_data = obj;
2249 ao2_ref(dtmf_data->session, -1);
2250}

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 1406 of file chan_pjsip.c.

1407{
1408 struct ast_party_id connected_id;
1409 int update_allowed = 0;
1410
1411 if (!session->endpoint->id.send_connected_line
1412 || (!session->endpoint->id.send_pai && !session->endpoint->id.send_rpid)) {
1413 return 0;
1414 }
1415
1416 /*
1417 * Check if privacy allows the update. Check while the channel
1418 * is locked so we can work with the shallow connected_id copy.
1419 */
1420 ast_channel_lock(session->channel);
1421 connected_id = ast_channel_connected_effective_id(session->channel);
1422 if (connected_id.number.valid
1423 && (session->endpoint->id.trust_outbound
1425 update_allowed = 1;
1426 }
1427 ast_channel_unlock(session->channel);
1428
1429 return update_allowed;
1430}
#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:1807
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 829 of file chan_pjsip.c.

830{
831 struct ast_stream_topology *topology = session->active_media_state->topology;
832 struct ast_stream *stream = ast_stream_topology_get_stream(topology, f->stream_num);
833 const struct ast_format_cap *cap = ast_stream_get_formats(stream);
834
836}
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 3337 of file chan_pjsip.c.

3338{
3339 struct ao2_container *endpoints;
3340
3343 }
3344
3346
3348
3350 ast_log(LOG_ERROR, "Unable to register channel class %s\n", channel_type);
3351 goto end;
3352 }
3353
3355 ast_log(LOG_ERROR, "Unable to register PJSIP_DIAL_CONTACTS dialplan function\n");
3356 goto end;
3357 }
3358
3360 ast_log(LOG_ERROR, "Unable to register PJSIP_PARSE_URI dialplan function\n");
3361 goto end;
3362 }
3363
3365 ast_log(LOG_ERROR, "Unable to register PJSIP_PARSE_URI_FROM dialplan function\n");
3366 goto end;
3367 }
3368
3370 ast_log(LOG_WARNING, "Unable to register PJSIP_MEDIA_OFFER dialplan function\n");
3371 goto end;
3372 }
3373
3375 ast_log(LOG_WARNING, "Unable to register PJSIP_DTMF_MODE dialplan function\n");
3376 goto end;
3377 }
3378
3380 ast_log(LOG_WARNING, "Unable to register PJSIP_MOH_PASSTHROUGH dialplan function\n");
3381 goto end;
3382 }
3383
3385 ast_log(LOG_WARNING, "Unable to register PJSIP_SEND_SESSION_REFRESH dialplan function\n");
3386 goto end;
3387 }
3388
3390 ast_log(LOG_WARNING, "Unable to register PJSIP_TRANSFER_HANDLING dialplan function\n");
3391 goto end;
3392 }
3393
3395 ast_log(LOG_WARNING, "Unable to register PJSIPHangup dialplan application\n");
3396 goto end;
3397 }
3399
3400
3402
3405
3409 ast_log(LOG_ERROR, "Unable to create held channels container\n");
3410 goto end;
3411 }
3412
3417
3419 ast_log(LOG_ERROR, "Unable to register PJSIP Channel CLI\n");
3420 goto end;
3421 }
3422
3423 /* since endpoints are loaded before the channel driver their device
3424 states get set to 'invalid', so they need to be updated */
3425 if ((endpoints = ast_sip_get_endpoints())) {
3427 ao2_ref(endpoints, -1);
3428 }
3429
3430 return 0;
3431
3432end:
3452
3455
3457}
@ 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 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:143
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:172
static struct ast_rtp_glue chan_pjsip_rtp_glue
Local glue for interacting with the RTP engine core.
Definition chan_pjsip.c:486
static pjsip_module refer_callback_module
REFER Callback module, used to attach session data structure to subscription.
static const char channel_type[]
Definition chan_pjsip.c:78
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:164
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:155
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:570
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:539
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:7698
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:192
#define EVENT_FLAG_CALL
Definition manager.h:76
int ast_unregister_application(const char *app)
Unregister an application.
Definition pbx_app.c:392
@ 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:1562
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:133
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:117
#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:414
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_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_uids_onhold, refer_callback_module, 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 1548 of file chan_pjsip.c.

1549{
1550 SCOPE_ENTER(3, "%s: Received response code %d. PT: %s AT: %s\n", ast_sip_session_get_name(session),
1551 rdata->msg_info.msg->line.status.code,
1552 ast_str_tmp(256, ast_stream_topology_to_str(session->pending_media_state->topology, &STR_TMP)),
1553 ast_str_tmp(256, ast_stream_topology_to_str(session->active_media_state->topology, &STR_TMP)));
1554
1555
1556 if (PJSIP_IS_STATUS_IN_CLASS(rdata->msg_info.msg->line.status.code, 200)) {
1557 /* The topology was changed to something new so give notice to what requested
1558 * it so it queries the channel and updates accordingly.
1559 */
1560 if (session->channel) {
1562 SCOPE_EXIT_RTN_VALUE(0, "%s: Queued topology change frame\n", ast_sip_session_get_name(session));
1563 }
1564 SCOPE_EXIT_RTN_VALUE(0, "%s: No channel? Can't queue topology change frame\n", ast_sip_session_get_name(session));
1565 } else if (300 <= rdata->msg_info.msg->line.status.code) {
1566 /* The topology change failed, so drop the current pending media state */
1567 ast_sip_session_media_state_reset(session->pending_media_state);
1568 SCOPE_EXIT_RTN_VALUE(0, "%s: response code > 300. Resetting pending media state\n", ast_sip_session_get_name(session));
1569 }
1570
1571 SCOPE_EXIT_RTN_VALUE(0, "%s: Nothing to do\n", ast_sip_session_get_name(session));
1572}
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 3122 of file chan_pjsip.c.

3123{
3124 int res;
3126
3127 /* Check for a to-tag to determine if this is a reinvite */
3128 if (rdata->msg_info.to->tag.slen) {
3129 /* We don't care about reinvites */
3130 SCOPE_EXIT_RTN_VALUE(0, "Reinvite\n");
3131 }
3132
3133 res = ast_pbx_start(session->channel);
3134
3135 switch (res) {
3136 case AST_PBX_FAILED:
3137 ast_log(LOG_WARNING, "Failed to start PBX ;(\n");
3139 ast_hangup(session->channel);
3140 break;
3141 case AST_PBX_CALL_LIMIT:
3142 ast_log(LOG_WARNING, "Failed to start PBX (call limit reached) \n");
3144 ast_hangup(session->channel);
3145 break;
3146 case AST_PBX_SUCCESS:
3147 default:
3148 break;
3149 }
3150
3151 ast_debug(3, "Started PBX on new PJSIP channel %s\n", ast_channel_name(session->channel));
3152
3153 SCOPE_EXIT_RTN_VALUE((res == AST_PBX_SUCCESS) ? 0 : -1, "RC: %d\n", res);
3154}
@ AST_PBX_FAILED
Definition pbx.h:373
@ AST_PBX_CALL_LIMIT
Definition pbx.h:374
@ AST_PBX_SUCCESS
Definition pbx.h:372
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
Definition pbx.c:4729

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 1499 of file chan_pjsip.c.

1500{
1501 return remote_send_hold_refresh(data, 1);
1502}
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 1486 of file chan_pjsip.c.

1487{
1488 struct ast_sip_session_media *session_media = session->active_media_state->default_session[AST_MEDIA_TYPE_AUDIO];
1489 if (session_media) {
1490 session_media->locally_held = held;
1491 }
1493 ao2_ref(session, -1);
1494
1495 return 0;
1496}
@ AST_SIP_SESSION_REFRESH_METHOD_INVITE
Definition res_pjsip.h:715
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 1505 of file chan_pjsip.c.

1506{
1507 return remote_send_hold_refresh(data, 0);
1508}

References remote_send_hold_refresh().

Referenced by chan_pjsip_indicate().

◆ request()

static int request ( void *  obj)
static

Definition at line 2629 of file chan_pjsip.c.

2630{
2631 struct request_data *req_data = obj;
2632 struct ast_sip_session *session = NULL;
2633 char *tmp = ast_strdupa(req_data->dest), *endpoint_name = NULL, *request_user = NULL;
2634 struct ast_sip_endpoint *endpoint;
2635
2637 AST_APP_ARG(endpoint);
2638 AST_APP_ARG(aor);
2639 );
2640 SCOPE_ENTER(1, "%s\n",tmp);
2641
2642 if (ast_strlen_zero(tmp)) {
2643 ast_log(LOG_ERROR, "Unable to create PJSIP channel with empty destination\n");
2645 SCOPE_EXIT_RTN_VALUE(-1, "Empty destination\n");
2646 }
2647
2648 AST_NONSTANDARD_APP_ARGS(args, tmp, '/');
2649
2651 /* If a request user has been specified extract it from the endpoint name portion */
2652 if ((endpoint_name = strchr(args.endpoint, '@'))) {
2653 request_user = args.endpoint;
2654 *endpoint_name++ = '\0';
2655 } else {
2656 endpoint_name = args.endpoint;
2657 }
2658
2659 if (ast_strlen_zero(endpoint_name)) {
2660 if (request_user) {
2661 ast_log(LOG_ERROR, "Unable to create PJSIP channel with empty endpoint name: %s@<endpoint-name>\n",
2662 request_user);
2663 } else {
2664 ast_log(LOG_ERROR, "Unable to create PJSIP channel with empty endpoint name\n");
2665 }
2667 SCOPE_EXIT_RTN_VALUE(-1, "Empty endpoint name\n");
2668 }
2669 endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint",
2670 endpoint_name);
2671 if (!endpoint) {
2672 ast_log(LOG_ERROR, "Unable to create PJSIP channel - endpoint '%s' was not found\n", endpoint_name);
2674 SCOPE_EXIT_RTN_VALUE(-1, "Endpoint not found\n");
2675 }
2676 } else {
2677 /* First try to find an exact endpoint match, for single (user) or multi-domain (user@domain) */
2678 endpoint_name = args.endpoint;
2679 if (ast_strlen_zero(endpoint_name)) {
2680 ast_log(LOG_ERROR, "Unable to create PJSIP channel with empty endpoint name\n");
2682 SCOPE_EXIT_RTN_VALUE(-1, "Empty endpoint name\n");
2683 }
2684 endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint",
2685 endpoint_name);
2686 if (!endpoint) {
2687 /* It seems it's not a multi-domain endpoint or single endpoint exact match,
2688 * it's possible that it's a SIP trunk with a specified user (user@trunkname),
2689 * so extract the user before @ sign.
2690 */
2691 endpoint_name = strchr(args.endpoint, '@');
2692 if (!endpoint_name) {
2693 /*
2694 * Couldn't find an '@' so it had to be an endpoint
2695 * name that doesn't exist.
2696 */
2697 ast_log(LOG_ERROR, "Unable to create PJSIP channel - endpoint '%s' was not found\n",
2698 args.endpoint);
2700 SCOPE_EXIT_RTN_VALUE(-1, "Endpoint not found\n");
2701 }
2702 request_user = args.endpoint;
2703 *endpoint_name++ = '\0';
2704
2705 if (ast_strlen_zero(endpoint_name)) {
2706 ast_log(LOG_ERROR, "Unable to create PJSIP channel with empty endpoint name: %s@<endpoint-name>\n",
2707 request_user);
2709 SCOPE_EXIT_RTN_VALUE(-1, "Empty endpoint name\n");
2710 }
2711
2712 endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint",
2713 endpoint_name);
2714 if (!endpoint) {
2715 ast_log(LOG_ERROR, "Unable to create PJSIP channel - endpoint '%s' was not found\n", endpoint_name);
2717 SCOPE_EXIT_RTN_VALUE(-1, "Endpoint not found\n");
2718 }
2719 }
2720 }
2721
2722 session = ast_sip_session_create_outgoing(endpoint, NULL, args.aor, request_user,
2723 req_data->topology);
2724 ao2_ref(endpoint, -1);
2725 if (!session) {
2726 ast_log(LOG_ERROR, "Failed to create outgoing session to endpoint '%s'\n", endpoint_name);
2728 SCOPE_EXIT_RTN_VALUE(-1, "Couldn't create session\n");
2729 }
2730
2731 req_data->session = session;
2732
2734}
#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 @519 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 377 of file chan_pjsip.c.

380{
382
383 if (!cdata) {
384 return NULL;
385 }
386
387 cdata->chan = ao2_bump(chan);
388 cdata->rtp = ao2_bump(rtp);
389 cdata->vrtp = ao2_bump(vrtp);
390 cdata->cap = ao2_bump((struct ast_format_cap *)cap);
391 cdata->session = ao2_bump(session);
392
393 return cdata;
394}
static void rtp_direct_media_data_destroy(void *data)
Definition chan_pjsip.c:366

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 366 of file chan_pjsip.c.

367{
368 struct rtp_direct_media_data *cdata = data;
369
370 ao2_cleanup(cdata->session);
371 ao2_cleanup(cdata->cap);
372 ao2_cleanup(cdata->vrtp);
373 ao2_cleanup(cdata->rtp);
374 ao2_cleanup(cdata->chan);
375}

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 306 of file chan_pjsip.c.

307{
308 int index;
309
310 for (index = 0; index < AST_VECTOR_SIZE(&session->active_media_state->read_callbacks); ++index) {
311 struct ast_sip_session_media_read_callback_state *callback_state =
312 AST_VECTOR_GET_ADDR(&session->active_media_state->read_callbacks, index);
313
314 if (callback_state->fd != ast_rtp_instance_fd(rtp, 1)) {
315 continue;
316 }
317
318 return index;
319 }
320
321 return -1;
322}

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 396 of file chan_pjsip.c.

397{
398 struct rtp_direct_media_data *cdata = data;
399 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(cdata->chan);
400 struct ast_sip_session *session;
401 int changed = 0;
402 int res = 0;
403
404 /* XXX In an ideal world each media stream would be direct, but for now preserve behavior
405 * and connect only the default media sessions for audio and video.
406 */
407
408 /* The channel needs to be locked when checking for RTP changes.
409 * Otherwise, we could end up destroying an underlying RTCP structure
410 * at the same time that the channel thread is attempting to read RTCP
411 */
412 ast_channel_lock(cdata->chan);
413 session = channel->session;
414 if (session->active_media_state->default_session[AST_MEDIA_TYPE_AUDIO]) {
415 changed |= check_for_rtp_changes(
416 cdata->chan, cdata->rtp, session->active_media_state->default_session[AST_MEDIA_TYPE_AUDIO], session);
417 }
418 if (session->active_media_state->default_session[AST_MEDIA_TYPE_VIDEO]) {
419 changed |= check_for_rtp_changes(
420 cdata->chan, cdata->vrtp, session->active_media_state->default_session[AST_MEDIA_TYPE_VIDEO], session);
421 }
423
424 if (direct_media_mitigate_glare(cdata->session)) {
425 ast_debug(4, "Disregarding setting RTP on %s: mitigating re-INVITE glare\n", ast_channel_name(cdata->chan));
426 ao2_ref(cdata, -1);
427 return 0;
428 }
429
430 if (cdata->cap && ast_format_cap_count(cdata->cap) &&
431 !ast_format_cap_identical(cdata->session->direct_media_cap, cdata->cap)) {
433 ast_format_cap_append_from_cap(cdata->session->direct_media_cap, cdata->cap, AST_MEDIA_TYPE_UNKNOWN);
434 changed = 1;
435 }
436
437 if (changed) {
438 ast_debug(4, "RTP changed on %s; initiating direct media update\n", ast_channel_name(cdata->chan));
439 res = ast_sip_session_refresh(cdata->session, NULL, NULL, NULL,
440 cdata->session->endpoint->media.direct_media.method, 1, NULL);
441 }
442
443 ao2_ref(cdata, -1);
444 return res;
445}
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:327
static int direct_media_mitigate_glare(struct ast_sip_session *session)
Definition chan_pjsip.c:276
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:687
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:395

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, 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 1574 of file chan_pjsip.c.

1575{
1580 int ret;
1582 ast_str_tmp(256, ast_stream_topology_to_str(refresh_data->media_state->topology, &STR_TMP)));
1583
1584 /* See RFC 6337, especially section 3.2: If the early media SDP was sent reliably, we are allowed
1585 * to send UPDATEs. Only relevant for AST_STATE_RINGING and AST_STATE_RING - if the channel is UP,
1586 * re-INVITES can be sent.
1587 */
1588 if (session->early_confirmed && (state == AST_STATE_RINGING || state == AST_STATE_RING)) {
1590 }
1591
1593 method, 1, refresh_data->media_state);
1594 refresh_data->media_state = NULL;
1596
1598}
static int on_topology_change_response(struct ast_sip_session *session, pjsip_rx_data *rdata)
const char * method
Definition res_pjsip.c:1279
ast_sip_session_refresh_method
Definition res_pjsip.h:713
@ AST_SIP_SESSION_REFRESH_METHOD_UPDATE
Definition res_pjsip.h:717
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 2814 of file chan_pjsip.c.

2815{
2816 struct sendtext_data *data = obj;
2817 pjsip_tx_data *tdata;
2818 const char *body_text = ast_msg_data_get_attribute(data->msg, AST_MSG_DATA_ATTR_BODY);
2819 const char *content_type = ast_msg_data_get_attribute(data->msg, AST_MSG_DATA_ATTR_CONTENT_TYPE);
2820 char *sep;
2821 struct ast_sip_body body = {
2822 .type = "text",
2823 .subtype = "plain",
2824 .body_text = body_text,
2825 };
2826
2827 if (!ast_strlen_zero(content_type)) {
2828 sep = strchr(content_type, '/');
2829 if (sep) {
2830 *sep = '\0';
2831 body.type = content_type;
2832 body.subtype = ++sep;
2833 }
2834 }
2835
2836 if (data->session->inv_session->state == PJSIP_INV_STATE_DISCONNECTED) {
2837 ast_log(LOG_ERROR, "Session already DISCONNECTED [reason=%d (%s)]\n",
2838 data->session->inv_session->cause,
2839 pjsip_get_status_text(data->session->inv_session->cause)->ptr);
2840 } else {
2841 pjsip_from_hdr *hdr;
2842 pjsip_name_addr *name_addr;
2843 const char *from = ast_msg_data_get_attribute(data->msg, AST_MSG_DATA_ATTR_FROM);
2844 const char *to = ast_msg_data_get_attribute(data->msg, AST_MSG_DATA_ATTR_TO);
2845 int invalidate_tdata = 0;
2846
2847 ast_sip_create_request("MESSAGE", data->session->inv_session->dlg, data->session->endpoint, NULL, NULL, &tdata);
2848 ast_sip_add_body(tdata, &body);
2849
2850 /*
2851 * If we have a 'from' in the msg, set the display name in the From
2852 * header to it.
2853 */
2854 if (!ast_strlen_zero(from)) {
2855 hdr = PJSIP_MSG_FROM_HDR(tdata->msg);
2856 name_addr = (pjsip_name_addr *) hdr->uri;
2857 pj_strdup2(tdata->pool, &name_addr->display, from);
2858 invalidate_tdata = 1;
2859 }
2860
2861 /*
2862 * If we have a 'to' in the msg, set the display name in the To
2863 * header to it.
2864 */
2865 if (!ast_strlen_zero(to)) {
2866 hdr = PJSIP_MSG_TO_HDR(tdata->msg);
2867 name_addr = (pjsip_name_addr *) hdr->uri;
2868 pj_strdup2(tdata->pool, &name_addr->display, to);
2869 invalidate_tdata = 1;
2870 }
2871
2872 if (invalidate_tdata) {
2873 pjsip_tx_data_invalidate_msg(tdata);
2874 }
2875
2876 ast_sip_send_request(tdata, data->session->inv_session->dlg, data->session->endpoint, NULL, NULL);
2877 }
2878
2879 ao2_cleanup(data);
2880
2881 return 0;
2882}
@ 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:1979
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:2052
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:1435
SIP body description.
Definition res_pjsip.h:2444
const char * type
Definition res_pjsip.h:2446
const char * body_text
Definition res_pjsip.h:2450
const char * subtype
Definition res_pjsip.h:2448
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_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 2793 of file chan_pjsip.c.

2795{
2796 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(chan);
2797 struct sendtext_data *data = ao2_alloc(sizeof(*data), sendtext_data_destroy);
2798
2799 if (!data) {
2800 return NULL;
2801 }
2802
2803 data->msg = ast_msg_data_dup(msg);
2804 if (!data->msg) {
2805 ao2_cleanup(data);
2806 return NULL;
2807 }
2808 data->session = channel->session;
2809 ao2_ref(data->session, +1);
2810
2811 return data;
2812}
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 2786 of file chan_pjsip.c.

2787{
2788 struct sendtext_data *data = obj;
2789 ao2_cleanup(data->session);
2790 ast_free(data->msg);
2791}

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 494 of file chan_pjsip.c.

496{
497 int i;
498
499 for (i = 0; i < AST_VECTOR_SIZE(&session->active_media_state->sessions); ++i) {
500 struct ast_sip_session_media *session_media;
501
502 session_media = AST_VECTOR_GET(&session->active_media_state->sessions, i);
503 if (!session_media || !session_media->rtp) {
504 continue;
505 }
506
507 ast_rtp_instance_set_channel_id(session_media->rtp, channel_id);
508 }
509}
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:581

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

◆ set_sipdomain_variable()

static void set_sipdomain_variable ( struct ast_sip_session session)
static

Definition at line 3001 of file chan_pjsip.c.

3002{
3003 const pj_str_t *host = ast_sip_pjsip_uri_get_hostname(session->request_uri);
3004 size_t size = pj_strlen(host) + 1;
3005 char *domain = ast_alloca(size);
3006
3007 ast_copy_pj_str(domain, host, size);
3008
3009 pbx_builtin_setvar_helper(session->channel, "SIPDOMAIN", domain);
3010 return;
3011}
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:3496

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

◆ 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 1523 of file chan_pjsip.c.

1525{
1527
1528 refresh_data = ast_calloc(1, sizeof(*refresh_data));
1529 if (!refresh_data) {
1530 return NULL;
1531 }
1532
1535 if (!refresh_data->media_state) {
1537 return NULL;
1538 }
1539 refresh_data->media_state->topology = ast_stream_topology_clone(topology);
1540 if (!refresh_data->media_state->topology) {
1542 return NULL;
1543 }
1544
1545 return refresh_data;
1546}
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 1515 of file chan_pjsip.c.

1516{
1518
1521}
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 2143 of file chan_pjsip.c.

2144{
2145 struct transfer_data *trnf_data = data;
2146 struct ast_sip_endpoint *endpoint = NULL;
2147 struct ast_sip_contact *contact = NULL;
2148 const char *target = trnf_data->target;
2149
2150 if (trnf_data->session->inv_session->state == PJSIP_INV_STATE_DISCONNECTED) {
2151 ast_log(LOG_ERROR, "Session already DISCONNECTED [reason=%d (%s)]\n",
2152 trnf_data->session->inv_session->cause,
2153 pjsip_get_status_text(trnf_data->session->inv_session->cause)->ptr);
2154 } else {
2155 /* See if we have an endpoint; if so, use its contact */
2157 if (endpoint) {
2159 if (contact && !ast_strlen_zero(contact->uri)) {
2160 target = contact->uri;
2161 }
2162 }
2163
2164 if (ast_channel_state(trnf_data->session->channel) == AST_STATE_RING) {
2165 transfer_redirect(trnf_data->session, target);
2166 } else {
2167 transfer_refer(trnf_data->session, target);
2168 }
2169 }
2170
2171 ao2_ref(trnf_data, -1);
2173 ao2_cleanup(contact);
2174 return 0;
2175}
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:390
const ast_string_field uri
Definition res_pjsip.h:412
struct ast_sip_endpoint * endpoint
Definition res_pjsip.h:422
const ast_string_field aors
Definition res_pjsip.h:1080
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 1905 of file chan_pjsip.c.

1906{
1907 struct transfer_data *trnf_data = ao2_alloc(sizeof(*trnf_data), transfer_data_destroy);
1908
1909 if (!trnf_data) {
1910 return NULL;
1911 }
1912
1913 if (!(trnf_data->target = ast_strdup(target))) {
1914 ao2_ref(trnf_data, -1);
1915 return NULL;
1916 }
1917
1918 ao2_ref(session, +1);
1919 trnf_data->session = session;
1920
1921 return trnf_data;
1922}
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 1897 of file chan_pjsip.c.

1898{
1899 struct transfer_data *trnf_data = obj;
1900
1901 ast_free(trnf_data->target);
1902 ao2_cleanup(trnf_data->session);
1903}

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 1924 of file chan_pjsip.c.

1925{
1926 pjsip_tx_data *packet;
1928 pjsip_contact_hdr *contact;
1929 pj_str_t tmp;
1930
1931 if (pjsip_inv_end_session(session->inv_session, 302, NULL, &packet) != PJ_SUCCESS
1932 || !packet) {
1933 ast_log(LOG_WARNING, "Failed to redirect PJSIP session for channel %s\n",
1934 ast_channel_name(session->channel));
1937
1938 return;
1939 }
1940
1941 if (!(contact = pjsip_msg_find_hdr(packet->msg, PJSIP_H_CONTACT, NULL))) {
1942 contact = pjsip_contact_hdr_create(packet->pool);
1943 }
1944
1945 pj_strdup2_with_null(packet->pool, &tmp, target);
1946 if (!(contact->uri = pjsip_parse_uri(packet->pool, tmp.ptr, tmp.slen, PJSIP_PARSE_URI_AS_NAMEADDR))) {
1947 ast_log(LOG_WARNING, "Failed to parse destination URI '%s' for channel %s\n",
1948 target, ast_channel_name(session->channel));
1951 pjsip_tx_data_dec_ref(packet);
1952
1953 return;
1954 }
1955 pjsip_msg_add_hdr(packet->msg, (pjsip_hdr *) contact);
1956
1959}
@ 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 2091 of file chan_pjsip.c.

2092{
2093 pjsip_evsub *sub;
2095 pj_str_t tmp;
2096 pjsip_tx_data *packet;
2097 const char *ref_by_val;
2098 char local_info[pj_strlen(&session->inv_session->dlg->local.info_str) + 1];
2099 struct pjsip_evsub_user xfer_cb;
2100 struct ast_channel *chan = session->channel;
2101
2102 pj_bzero(&xfer_cb, sizeof(xfer_cb));
2103 xfer_cb.on_evsub_state = &xfer_client_on_evsub_state;
2104
2105 if (pjsip_xfer_create_uac(session->inv_session->dlg, &xfer_cb, &sub) != PJ_SUCCESS) {
2108
2109 return;
2110 }
2111
2112 /* refer_callback_module requires a reference to chan
2113 * which will be released in xfer_client_on_evsub_state()
2114 * when the implicit REFER subscription terminates */
2115 pjsip_evsub_set_mod_data(sub, refer_callback_module.id, chan);
2116 ao2_ref(chan, +1);
2117
2118 if (pjsip_xfer_initiate(sub, pj_cstr(&tmp, target), &packet) != PJ_SUCCESS) {
2119 goto failure;
2120 }
2121
2122 ref_by_val = pbx_builtin_getvar_helper(chan, "SIPREFERREDBYHDR");
2123 if (!ast_strlen_zero(ref_by_val)) {
2124 ast_sip_add_header(packet, "Referred-By", ref_by_val);
2125 } else {
2126 ast_copy_pj_str(local_info, &session->inv_session->dlg->local.info_str, sizeof(local_info));
2127 ast_sip_add_header(packet, "Referred-By", local_info);
2128 }
2129
2130 if (pjsip_xfer_send_request(sub, packet) == PJ_SUCCESS) {
2131 return;
2132 }
2133
2134failure:
2137 pjsip_evsub_set_mod_data(sub, refer_callback_module.id, NULL);
2138 pjsip_evsub_terminate(sub, PJ_FALSE);
2139
2140 ao2_ref(chan, -1);
2141}
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:2008

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, NULL, pbx_builtin_getvar_helper(), refer_callback_module, 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 2265 of file chan_pjsip.c.

2266{
2267 RAII_VAR(struct info_dtmf_data *, dtmf_data, data, ao2_cleanup);
2268
2269 struct ast_sip_session *session = dtmf_data->session;
2270 struct pjsip_tx_data *tdata;
2271
2272 RAII_VAR(struct ast_str *, body_text, NULL, ast_free_ptr);
2273
2274 struct ast_sip_body body = {
2275 .type = "application",
2276 .subtype = "dtmf-relay",
2277 };
2278
2279 if (session->inv_session->state == PJSIP_INV_STATE_DISCONNECTED) {
2280 ast_log(LOG_ERROR, "Session already DISCONNECTED [reason=%d (%s)]\n",
2281 session->inv_session->cause,
2282 pjsip_get_status_text(session->inv_session->cause)->ptr);
2283 return -1;
2284 }
2285
2286 if (!(body_text = ast_str_create(32))) {
2287 ast_log(LOG_ERROR, "Could not allocate buffer for INFO DTMF.\n");
2288 return -1;
2289 }
2290 ast_str_set(&body_text, 0, "Signal=%c\r\nDuration=%u\r\n", dtmf_data->digit, dtmf_data->duration);
2291
2293
2294 if (ast_sip_create_request("INFO", session->inv_session->dlg, session->endpoint, NULL, NULL, &tdata)) {
2295 ast_log(LOG_ERROR, "Could not create DTMF INFO request\n");
2296 return -1;
2297 }
2298 if (ast_sip_add_body(tdata, &body)) {
2299 ast_log(LOG_ERROR, "Could not add body to DTMF INFO request\n");
2300 pjsip_tx_data_dec_ref(tdata);
2301 return -1;
2302 }
2304
2305 return 0;
2306}
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 1355 of file chan_pjsip.c.

1356{
1357 const char * xml =
1358 "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\r\n"
1359 " <media_control>\r\n"
1360 " <vc_primitive>\r\n"
1361 " <to_encoder>\r\n"
1362 " <picture_fast_update/>\r\n"
1363 " </to_encoder>\r\n"
1364 " </vc_primitive>\r\n"
1365 " </media_control>\r\n";
1366
1367 const struct ast_sip_body body = {
1368 .type = "application",
1369 .subtype = "media_control+xml",
1370 .body_text = xml
1371 };
1372
1373 RAII_VAR(struct ast_sip_session *, session, data, ao2_cleanup);
1374 struct pjsip_tx_data *tdata;
1375
1376 if (session->inv_session->state == PJSIP_INV_STATE_DISCONNECTED) {
1377 ast_log(LOG_ERROR, "Session already DISCONNECTED [reason=%d (%s)]\n",
1378 session->inv_session->cause,
1379 pjsip_get_status_text(session->inv_session->cause)->ptr);
1380 return -1;
1381 }
1382
1383 if (ast_sip_create_request("INFO", session->inv_session->dlg, session->endpoint, NULL, NULL, &tdata)) {
1384 ast_log(LOG_ERROR, "Could not create text video update INFO request\n");
1385 return -1;
1386 }
1387 if (ast_sip_add_body(tdata, &body)) {
1388 ast_log(LOG_ERROR, "Could not add body to text video update INFO request\n");
1389 return -1;
1390 }
1392
1393 return 0;
1394}

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 261 of file chan_pjsip.c.

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

References ast_free.

◆ 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 1071 of file chan_pjsip.c.

1072{
1073 const char *key = obj;
1074
1075 switch (flags & OBJ_SEARCH_MASK) {
1076 case OBJ_SEARCH_KEY:
1077 break;
1078 case OBJ_SEARCH_OBJECT:
1079 break;
1080 default:
1081 /* Hash can only work on something with a full key. */
1082 ast_assert(0);
1083 return 0;
1084 }
1085 return ast_str_hash(key);
1086}
@ 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 1089 of file chan_pjsip.c.

1090{
1091 const char *left = obj_left;
1092 const char *right = obj_right;
1093 int cmp;
1094
1095 switch (flags & OBJ_SEARCH_MASK) {
1096 case OBJ_SEARCH_OBJECT:
1097 case OBJ_SEARCH_KEY:
1098 cmp = strcmp(left, right);
1099 break;
1101 cmp = strncmp(left, right, strlen(right));
1102 break;
1103 default:
1104 /* Sort can only work on something with a full or partial key. */
1105 ast_assert(0);
1106 cmp = 0;
1107 break;
1108 }
1109 return cmp;
1110}
@ 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 3460 of file chan_pjsip.c.

3461{
3464
3466
3473
3475
3486
3490
3491 return 0;
3492}
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_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_uids_onhold, refer_callback_module, 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 1433 of file chan_pjsip.c.

1434{
1435 struct ast_sip_session *session = data;
1436
1437 if (session->inv_session->state == PJSIP_INV_STATE_DISCONNECTED) {
1438 ast_log(LOG_ERROR, "Session already DISCONNECTED [reason=%d (%s)]\n",
1439 session->inv_session->cause,
1440 pjsip_get_status_text(session->inv_session->cause)->ptr);
1441 ao2_ref(session, -1);
1442 return -1;
1443 }
1444
1445 if (ast_channel_state(session->channel) == AST_STATE_UP
1446 || session->inv_session->role == PJSIP_ROLE_UAC) {
1449 int generate_new_sdp;
1450
1451 method = session->endpoint->id.refresh_method;
1452 if (session->inv_session->options & PJSIP_INV_SUPPORT_UPDATE) {
1454 }
1455
1456 /* Only the INVITE method actually needs SDP, UPDATE can do without */
1457 generate_new_sdp = (method == AST_SIP_SESSION_REFRESH_METHOD_INVITE);
1458
1459 ast_sip_session_refresh(session, NULL, NULL, NULL, method, generate_new_sdp, NULL);
1460 }
1461 } else if (session->endpoint->id.rpid_immediate
1462 && session->inv_session->state != PJSIP_INV_STATE_DISCONNECTED
1464 int response_code = 0;
1465
1466 if (ast_channel_state(session->channel) == AST_STATE_RING) {
1467 response_code = !session->endpoint->inband_progress ? 180 : 183;
1468 } else if (ast_channel_state(session->channel) == AST_STATE_RINGING) {
1469 response_code = 183;
1470 }
1471
1472 if (response_code) {
1473 struct pjsip_tx_data *packet = NULL;
1474
1475 if (pjsip_inv_answer(session->inv_session, response_code, NULL, NULL, &packet) == PJ_SUCCESS) {
1477 }
1478 }
1479 }
1480
1481 ao2_ref(session, -1);
1482 return 0;
1483}
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 2380 of file chan_pjsip.c.

2381{
2383
2384 /*
2385 * Use the channel CALLERID() as the initial connected line data.
2386 * The core or a predial handler may have supplied missing values
2387 * from the session->endpoint->id.self about who we are calling.
2388 */
2389 ast_channel_lock(session->channel);
2391 ast_channel_unlock(session->channel);
2392
2393 /* Supply initial connected line information if available. */
2394 if (!session->id.number.valid && !session->id.name.valid) {
2395 return;
2396 }
2397
2399 connected.id = session->id;
2401
2403}
@ 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:2008
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:9150
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 1974 of file chan_pjsip.c.

1975{
1976 struct ast_channel *chan;
1978 int res = 0;
1979
1980 if (!event) {
1981 return;
1982 }
1983
1984 chan = pjsip_evsub_get_mod_data(sub, refer_callback_module.id);
1985 if (!chan) {
1986 return;
1987 }
1988
1989 if (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_ACCEPTED) {
1990 /* Check if subscription is suppressed and terminate and send completion code, if so. */
1991 pjsip_rx_data *rdata;
1992 pjsip_generic_string_hdr *refer_sub;
1993 const pj_str_t REFER_SUB = { "Refer-Sub", 9 };
1994
1995 ast_debug(3, "Transfer accepted on channel %s\n", ast_channel_name(chan));
1996
1997 /* Check if response message */
1998 if (event->type == PJSIP_EVENT_TSX_STATE && event->body.tsx_state.type == PJSIP_EVENT_RX_MSG) {
1999 rdata = event->body.tsx_state.src.rdata;
2000
2001 /* Find Refer-Sub header */
2002 refer_sub = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &REFER_SUB, NULL);
2003
2004 /* Check if subscription is suppressed. If it is, the far end will not terminate it,
2005 * and the subscription will remain active until it times out. Terminating it here
2006 * eliminates the unnecessary timeout.
2007 */
2008 if (refer_sub && !pj_stricmp2(&refer_sub->hvalue, "false")) {
2009 /* Since no subscription is desired, assume that call has been transferred successfully. */
2010 /* Channel reference will be released at end of function */
2011 /* Terminate subscription. */
2012 pjsip_evsub_set_mod_data(sub, refer_callback_module.id, NULL);
2013 pjsip_evsub_terminate(sub, PJ_TRUE);
2014 res = -1;
2015 }
2016 }
2017 } else if (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_ACTIVE ||
2018 pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_TERMINATED) {
2019 /* Check for NOTIFY complete or error. */
2020 pjsip_msg *msg;
2021 pjsip_msg_body *body;
2022 pjsip_status_line status_line = { .code = 0 };
2023 pj_bool_t is_last;
2024 pj_status_t status;
2025
2026 if (event->type == PJSIP_EVENT_TSX_STATE && event->body.tsx_state.type == PJSIP_EVENT_RX_MSG) {
2027 pjsip_rx_data *rdata;
2028
2029 rdata = event->body.tsx_state.src.rdata;
2030 msg = rdata->msg_info.msg;
2031
2032 if (msg->type == PJSIP_REQUEST_MSG) {
2033 if (!pjsip_method_cmp(&msg->line.req.method, pjsip_get_notify_method())) {
2034 body = msg->body;
2035 if (body && !pj_stricmp2(&body->content_type.type, "message")
2036 && !pj_stricmp2(&body->content_type.subtype, "sipfrag")) {
2037 pjsip_parse_status_line((char *)body->data, body->len, &status_line);
2038 }
2039 }
2040 } else {
2041 status_line.code = msg->line.status.code;
2042 status_line.reason = msg->line.status.reason;
2043 }
2044 } else {
2045 status_line.code = 500;
2046 status_line.reason = *pjsip_get_status_text(500);
2047 }
2048
2049 is_last = (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_TERMINATED);
2050 /* If the status code is >= 200, the subscription is finished. */
2051 if (status_line.code >= 200 || is_last) {
2052 res = -1;
2053
2054 /* If the subscription has terminated, return AST_TRANSFER_SUCCESS for 2XX.
2055 * Return AST_TRANSFER_FAILED for any code < 200.
2056 * Otherwise, return the status code.
2057 * The subscription should not terminate for any code < 200,
2058 * but if it does, that constitutes a failure. */
2059 if (status_line.code < 200) {
2061 } else if (status_line.code >= 300) {
2062 message = status_line.code;
2063 }
2064
2065 /* If subscription not terminated and subscription is finished (status code >= 200)
2066 * terminate it */
2067 if (!is_last) {
2068 pjsip_tx_data *tdata;
2069
2070 status = pjsip_evsub_initiate(sub, pjsip_get_subscribe_method(), 0, &tdata);
2071 if (status == PJ_SUCCESS) {
2072 pjsip_evsub_send_request(sub, tdata);
2073 }
2074 }
2075 /* Finished. Remove session from subscription */
2076 pjsip_evsub_set_mod_data(sub, refer_callback_module.id, NULL);
2077 ast_debug(3, "Transfer channel %s completed: %d %.*s (%s)\n",
2078 ast_channel_name(chan),
2079 status_line.code,
2080 (int)status_line.reason.slen, status_line.reason.ptr,
2081 (message == AST_TRANSFER_SUCCESS) ? "Success" : "Failure");
2082 }
2083 }
2084
2085 if (res) {
2087 ao2_ref(chan, -1);
2088 }
2089}

References ao2_ref, ast_channel_name(), AST_CONTROL_TRANSFER, ast_debug, ast_queue_control_data(), AST_TRANSFER_FAILED, AST_TRANSFER_SUCCESS, NULL, refer_callback_module, 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 3500 of file chan_pjsip.c.

◆ app_pjsip_hangup

char* app_pjsip_hangup = "PJSIPHangup"
static

Definition at line 3325 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 3500 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:3341

Definition at line 3116 of file chan_pjsip.c.

3116 {
3117 .method = "INVITE",
3118 .priority = AST_SIP_SUPPLEMENT_PRIORITY_LAST - 1,
3119 .incoming_request = call_pickup_incoming_request,
3120};

Referenced by load_module(), and unload_module().

◆ chan_idx

unsigned int chan_idx
static

Definition at line 80 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:3339

Definition at line 164 of file chan_pjsip.c.

164 {
165 .method = "ACK",
167 .incoming_request = chan_pjsip_incoming_ack,
168};

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 3282 of file chan_pjsip.c.

3282 {
3283 .name = "PJSIP_DIAL_CONTACTS",
3285};

Referenced by load_module(), and unload_module().

◆ 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 3292 of file chan_pjsip.c.

3292 {
3293 .name = "PJSIP_PARSE_URI_FROM",
3295};

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 3287 of file chan_pjsip.c.

3287 {
3288 .name = "PJSIP_PARSE_URI",
3290};

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 172 of file chan_pjsip.c.

172 {
173 .method = "PRACK",
175 .incoming_request = chan_pjsip_incoming_prack,
176};

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 486 of file chan_pjsip.c.

486 {
487 .type = "PJSIP",
488 .get_rtp_info = chan_pjsip_get_rtp_peer,
489 .get_vrtp_info = chan_pjsip_get_vrtp_peer,
490 .get_codec = chan_pjsip_get_codec,
491 .update_peer = chan_pjsip_set_rtp_peer,
492};
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:252
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:448
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:179
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:223

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 143 of file chan_pjsip.c.

143 {
144 .method = "INVITE",
146 .session_begin = chan_pjsip_session_begin,
147 .session_end = chan_pjsip_session_end,
148 .incoming_request = chan_pjsip_incoming_request,
149 .incoming_response = chan_pjsip_incoming_response,
150 /* It is important that this supplement runs after media has been negotiated */
151 .response_priority = AST_SIP_SESSION_AFTER_MEDIA,
152};
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 155 of file chan_pjsip.c.

155 {
156 .method = "INVITE",
160};
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 109 of file chan_pjsip.c.

109 {
110 .type = channel_type,
111 .description = "PJSIP Channel Driver",
112 .requester = chan_pjsip_request,
113 .requester_with_stream_topology = chan_pjsip_request_with_stream_topology,
114 .send_text = chan_pjsip_sendtext,
115 .send_text_data = chan_pjsip_sendtext_data,
116 .send_digit_begin = chan_pjsip_digit_begin,
117 .send_digit_end = chan_pjsip_digit_end,
118 .call = chan_pjsip_call,
119 .hangup = chan_pjsip_hangup,
120 .answer = chan_pjsip_answer,
121 .read_stream = chan_pjsip_read_stream,
122 .write = chan_pjsip_write,
123 .write_stream = chan_pjsip_write_stream,
124 .exception = chan_pjsip_read_stream,
125 .indicate = chan_pjsip_indicate,
126 .transfer = chan_pjsip_transfer,
127 .fixup = chan_pjsip_fixup,
128 .devicestate = chan_pjsip_devicestate,
129 .queryoption = chan_pjsip_queryoption,
130 .func_channel_read = pjsip_acf_channel_read,
131 .get_pvt_uniqueid = chan_pjsip_get_uniqueid,
133};
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:731
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:843
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 78 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 274 of file chan_pjsip.c.

274{ };

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 3303 of file chan_pjsip.c.

3303 {
3304 .name = "PJSIP_DTMF_MODE",
3307};

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 3297 of file chan_pjsip.c.

3297 {
3298 .name = "PJSIP_MEDIA_OFFER",
3301};

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 3309 of file chan_pjsip.c.

3309 {
3310 .name = "PJSIP_MOH_PASSTHROUGH",
3313};

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 3156 of file chan_pjsip.c.

3156 {
3157 .method = "INVITE",
3159 .incoming_request = pbx_start_incoming_request,
3160};

Referenced by load_module(), and unload_module().

◆ pjsip_uids_onhold

struct ao2_container* pjsip_uids_onhold
static

◆ refer_callback_module

pjsip_module refer_callback_module
static
Initial value:
= {
.name = { "REFER Callback", 14 },
.id = -1,
}

REFER Callback module, used to attach session data structure to subscription.

Definition at line 1962 of file chan_pjsip.c.

1962 {
1963 .name = { "REFER Callback", 14 },
1964 .id = -1,
1965};

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

◆ 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 3315 of file chan_pjsip.c.

3315 {
3316 .name = "PJSIP_SEND_SESSION_REFRESH",
3318};

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 3320 of file chan_pjsip.c.

3320 {
3321 .name = "PJSIP_TRANSFER_HANDLING",
3323};

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:261

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

Definition at line 269 of file chan_pjsip.c.

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

Referenced by chan_pjsip_incoming_request().