Asterisk - The Open Source Telephony Project GIT-master-70eff7f
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 int set_transport_info_local_addr (struct pjsip_tx_data *tdata, pj_sockaddr *local_addr)
 Determine the local signaling address used for an outgoing request.
 
static struct topology_change_refresh_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 pj_status_t transport_info_on_tx_request (pjsip_tx_data *tdata)
 Store transport information for outgoing PJSIP session requests.
 
static int uid_hold_hash_fn (const void *obj, const int flags)
 
static int uid_hold_sort_fn (const void *obj_left, const void *obj_right, const int flags)
 
static int unload_module (void)
 Unload the PJSIP channel from Asterisk.
 
static int update_connected_line_information (void *data)
 Update connected line information.
 
static int update_devstate (void *obj, void *arg, int flags)
 
static void update_initial_connected_line (struct ast_sip_session *session)
 
static void xfer_client_on_evsub_state (pjsip_evsub *sub, pjsip_event *event)
 Callback function to report status of implicit REFER-NOTIFY subscription.
 

Variables

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

Detailed Description

PSJIP SIP Channel Driver.

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

Definition in file chan_pjsip.c.

Macro Definition Documentation

◆ UNIQUEID_BUFSIZE

#define UNIQUEID_BUFSIZE   256

Definition at line 76 of file chan_pjsip.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 3692 of file chan_pjsip.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 3692 of file chan_pjsip.c.

◆ answer()

static int answer ( void *  data)
static

Definition at line 783 of file chan_pjsip.c.

784{
785 struct answer_data *ans_data = data;
786 pj_status_t status = PJ_SUCCESS;
787 pjsip_tx_data *packet = NULL;
788 struct ast_sip_session *session = ans_data->session;
790
791 if (session->inv_session->state == PJSIP_INV_STATE_DISCONNECTED) {
792 ast_log(LOG_ERROR, "Session already DISCONNECTED [reason=%d (%s)]\n",
793 session->inv_session->cause,
794 pjsip_get_status_text(session->inv_session->cause)->ptr);
795 SCOPE_EXIT_RTN_VALUE(0, "Disconnected\n");
796 }
797
798 pjsip_dlg_inc_lock(session->inv_session->dlg);
799 if (session->inv_session->invite_tsx) {
800 status = pjsip_inv_answer(session->inv_session, 200, NULL, NULL, &packet);
801 } else {
802 ast_log(LOG_ERROR,"Cannot answer '%s' because there is no associated SIP transaction\n",
803 ast_channel_name(session->channel));
804 }
805 pjsip_dlg_dec_lock(session->inv_session->dlg);
806
807 if (status == PJ_SUCCESS && packet) {
809 }
810
811 if (status != PJ_SUCCESS) {
812 char err[PJ_ERR_MSG_SIZE];
813
814 pj_strerror(status, err, sizeof(err));
815 ast_log(LOG_WARNING,"Cannot answer '%s': %s\n",
816 ast_channel_name(session->channel), err);
817 /*
818 * Return this value so we can distinguish between this
819 * failure and the taskpool synchronous push failing.
820 */
821 SCOPE_EXIT_RTN_VALUE(-2, "pjproject failure\n");
822 }
824}
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:779
unsigned long indent
Definition chan_pjsip.c:780
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 3692 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 2500 of file chan_pjsip.c.

2501{
2502 struct ast_sip_session *session = data;
2503 pjsip_tx_data *tdata;
2504 int res = 0;
2505 SCOPE_ENTER(1, "%s Topology: %s\n",
2507 ast_str_tmp(256, ast_stream_topology_to_str(session->pending_media_state->topology, &STR_TMP))
2508 );
2509
2510
2512
2513 if (res) {
2514 ast_set_hangupsource(session->channel, ast_channel_name(session->channel), 0);
2515 ast_queue_hangup(session->channel);
2516 } else {
2520 }
2521 SCOPE_EXIT_RTN_VALUE(res, "RC: %d\n", res);
2522}
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:590
int ast_queue_hangup(struct ast_channel *chan)
Queue a hangup frame.
Definition channel.c:1182
const char * ast_channel_uniqueid(const struct ast_channel *chan)
void ast_set_hangupsource(struct ast_channel *chan, const char *source, int force)
Set the source of the hangup in this channel and it's bridge.
Definition channel.c:2498
#define SCOPE_ENTER(level,...)
void ast_sip_session_send_request(struct ast_sip_session *session, pjsip_tx_data *tdata)
Send a SIP request.
int ast_sip_session_create_invite(struct ast_sip_session *session, pjsip_tx_data **tdata)
Creates an INVITE request.
const char * ast_stream_topology_to_str(const struct ast_stream_topology *topology, struct ast_str **buf)
Get a string representing the topology for debugging/display purposes.
Definition stream.c:939
#define ast_str_tmp(init_len, __expr)
Provides a temporary ast_str and returns a copy of its buffer.
Definition strings.h:1189

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

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

◆ call_pickup_incoming_request()

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

Definition at line 3256 of file chan_pjsip.c.

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

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

◆ chan_pjsip_add_hold()

static int chan_pjsip_add_hold ( const char *  chan_uid)
static

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

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

Definition at line 1218 of file chan_pjsip.c.

1219{
1220 RAII_VAR(char *, hold_uid, NULL, ao2_cleanup);
1221
1222 hold_uid = ao2_find(pjsip_uids_onhold, chan_uid, OBJ_SEARCH_KEY);
1223 if (hold_uid) {
1224 /* Device is already on hold. Nothing to do. */
1225 return 0;
1226 }
1227
1228 /* Device wasn't in hold list already. Create a new one. */
1229 hold_uid = ao2_alloc_options(strlen(chan_uid) + 1, NULL,
1231 if (!hold_uid) {
1232 return -1;
1233 }
1234
1235 ast_copy_string(hold_uid, chan_uid, strlen(chan_uid) + 1);
1236
1237 if (ao2_link(pjsip_uids_onhold, hold_uid) == 0) {
1238 return -1;
1239 }
1240
1241 return 0;
1242}
#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 827 of file chan_pjsip.c.

828{
829 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(ast);
830 struct ast_sip_session *session;
831 struct answer_data ans_data = { 0, };
832 int res;
833 SCOPE_ENTER(1, "%s\n", ast_channel_name(ast));
834
835 if (ast_channel_state(ast) == AST_STATE_UP) {
836 SCOPE_EXIT_RTN_VALUE(0, "Already up\n");
837 return 0;
838 }
839
841 session = ao2_bump(channel->session);
842
843 /* the answer task needs to be pushed synchronously otherwise a race condition
844 can occur between this thread and bridging (specifically when native bridging
845 attempts to do direct media) */
847 ans_data.session = session;
848 ans_data.indent = ast_trace_get_indent();
849 res = ast_sip_push_task_wait_serializer(session->serializer, answer, &ans_data);
850 if (res) {
851 if (res == -1) {
852 ast_log(LOG_ERROR,"Cannot answer '%s': Unable to push answer task to the taskpool.\n",
853 ast_channel_name(session->channel));
854 }
855 ao2_ref(session, -1);
856 ast_channel_lock(ast);
857 SCOPE_EXIT_RTN_VALUE(-1, "Couldn't push task\n");
858 }
859 ao2_ref(session, -1);
860 ast_channel_lock(ast);
861
863}
#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:783
void * ast_channel_tech_pvt(const struct ast_channel *chan)
#define ast_channel_lock(chan)
Definition channel.h:2983
#define ast_channel_unlock(chan)
Definition channel.h:2984
ast_channel_state
ast_channel states
@ AST_STATE_UP
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
Definition channel.c:7422
#define ast_trace_get_indent()
#define ast_sip_push_task_wait_serializer(serializer, sip_task, task_data)
Definition res_pjsip.h:2221
A structure which contains a channel implementation and session.
struct ast_sip_session * session
Pointer to session.

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

◆ chan_pjsip_call()

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

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

Definition at line 2525 of file chan_pjsip.c.

2526{
2527 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(ast);
2528 struct ast_sip_session *session = ao2_bump(channel->session);
2529
2530 SCOPE_ENTER(1, "%s Topology: %s\n", ast_sip_session_get_name(session),
2531 ast_str_tmp(256, ast_stream_topology_to_str(session->pending_media_state->topology, &STR_TMP)));
2532
2533 ast_channel_unlock(ast);
2534
2535 /* The creation of the INVITE needs to be pushed synchronously to prevent a race condition
2536 with bridging on attended transfers that can result in a loss of set Caller ID. */
2538 ast_log(LOG_WARNING, "Error attempting to place outbound call to '%s'\n", dest);
2539 ao2_ref(session, -1);
2540 ast_channel_lock(ast);
2541 SCOPE_EXIT_RTN_VALUE(-1, "Couldn't push task\n");
2542 }
2543
2544 ao2_ref(session, -1);
2545 ast_channel_lock(ast);
2546 SCOPE_EXIT_RTN_VALUE(0, "'call' task pushed\n");
2547}
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 866 of file chan_pjsip.c.

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

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

Referenced by chan_pjsip_read_stream().

◆ chan_pjsip_devicestate()

static int chan_pjsip_devicestate ( const char *  data)
static

Function called to get the device state of an endpoint.

Definition at line 1275 of file chan_pjsip.c.

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

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

◆ chan_pjsip_digit_begin()

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

Function called by core to start a DTMF digit.

Definition at line 2292 of file chan_pjsip.c.

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

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

◆ chan_pjsip_digit_end()

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

Function called by core to stop a DTMF digit.

Definition at line 2404 of file chan_pjsip.c.

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

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

◆ chan_pjsip_fixup()

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

Function called by core to change the underlying owner channel.

Definition at line 1146 of file chan_pjsip.c.

1147{
1148 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(newchan);
1149
1150 if (channel->session->channel != oldchan) {
1151 return -1;
1152 }
1153
1154 /*
1155 * The masquerade has suspended the channel's session
1156 * serializer so we can safely change it outside of
1157 * the serializer thread.
1158 */
1159 channel->session->channel = newchan;
1160
1162
1163 return 0;
1164}

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:742
#define SCOPE_EXIT_RTN(...)

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

◆ chan_pjsip_get_hold()

static int chan_pjsip_get_hold ( const char *  chan_uid)
static

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

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

Definition at line 1262 of file chan_pjsip.c.

1263{
1264 RAII_VAR(char *, hold_uid, NULL, ao2_cleanup);
1265
1266 hold_uid = ao2_find(pjsip_uids_onhold, chan_uid, OBJ_SEARCH_KEY);
1267 if (!hold_uid) {
1268 return 0;
1269 }
1270
1271 return 1;
1272}

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:739
struct ast_datastore * ast_sip_session_get_datastore(struct ast_sip_session *session, const char *name)
Retrieve a session datastore.
@ AST_RTP_GLUE_RESULT_LOCAL
Definition rtp_engine.h:167
@ AST_RTP_GLUE_RESULT_REMOTE
Definition rtp_engine.h:165
@ AST_RTP_GLUE_RESULT_FORBID
Definition rtp_engine.h:163
Structure for a data store object.
Definition datastore.h:64
struct ast_sip_media_rtp_configuration rtp
Definition res_pjsip.h:1019
struct ast_sip_direct_media_configuration direct_media
Definition res_pjsip.h:1021
struct ast_sip_endpoint_media_configuration media
Definition res_pjsip.h:1100
enum ast_sip_session_media_encryption encryption
Definition res_pjsip.h:958
struct ast_sip_endpoint * endpoint
#define ast_assert(a)
Definition utils.h:779

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

◆ chan_pjsip_get_uniqueid()

static const char * chan_pjsip_get_uniqueid ( struct ast_channel ast)
static

Definition at line 1376 of file chan_pjsip.c.

1377{
1378 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(ast);
1379 char *uniqueid = ast_threadstorage_get(&uniqueid_threadbuf, UNIQUEID_BUFSIZE);
1380
1381 if (!channel || !uniqueid) {
1382 return "";
1383 }
1384
1385 ast_copy_pj_str(uniqueid, &channel->session->inv_session->dlg->call_id->id, UNIQUEID_BUFSIZE);
1386
1387 return uniqueid;
1388}
#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:2176
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 2675 of file chan_pjsip.c.

2676{
2677 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(ast);
2678 int cause;
2679 int tech_cause;
2680 int original_tech_cause;
2681 struct hangup_data *h_data;
2682 SCOPE_ENTER(1, "%s\n", ast_channel_name(ast));
2683
2684 if (!channel || !channel->session) {
2685 SCOPE_EXIT_RTN_VALUE(-1, "%s: No channel or session\n", ast_channel_name(ast));
2686 }
2687
2689 tech_cause = hangup_cause2sip(cause);
2690 original_tech_cause = ast_channel_tech_hangupcause(channel->session->channel);
2691 if (!original_tech_cause) {
2692 ast_channel_tech_hangupcause_set(channel->session->channel, tech_cause);
2693 }
2694
2695 h_data = hangup_data_alloc(tech_cause, ast);
2696 if (!h_data) {
2697 goto failure;
2698 }
2699
2700 if (ast_sip_push_task(channel->session->serializer, hangup, h_data)) {
2701 ast_log(LOG_WARNING, "Unable to push hangup task to the taskpool. Expect bad things\n");
2702 goto failure;
2703 }
2704
2705 SCOPE_EXIT_RTN_VALUE(0, "%s: Cause: %d Tech Cause: %d\n", ast_channel_name(ast),
2706 cause, tech_cause);
2707
2708failure:
2709 /* Go ahead and do our cleanup of the session and channel even if we're not going
2710 * to be able to send our SIP request/response
2711 */
2712 clear_session_and_channel(channel->session, ast);
2713 ao2_cleanup(channel);
2714 ao2_cleanup(h_data);
2715
2716 SCOPE_EXIT_RTN_VALUE(-1, "%s: Cause: %d\n", ast_channel_name(ast), cause);
2717}
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 3442 of file chan_pjsip.c.

3443{
3445
3446 if (rdata->msg_info.msg->line.req.method.id == PJSIP_ACK_METHOD) {
3447 if (session->endpoint->media.direct_media.enabled && session->channel) {
3448 ast_trace(-1, "%s: Queueing SRCCHANGE\n", ast_sip_session_get_name(session));
3450 }
3451 }
3453}
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame without payload.
Definition channel.c:1289
#define ast_trace(level,...)
@ AST_CONTROL_SRCCHANGE

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

◆ chan_pjsip_incoming_prack()

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

Definition at line 3455 of file chan_pjsip.c.

3456{
3458
3459 if (pj_strcmp2(&rdata->msg_info.msg->line.req.method.name, "PRACK") == 0 &&
3460 pjmedia_sdp_neg_get_state(session->inv_session->neg) == PJMEDIA_SDP_NEG_STATE_DONE) {
3461
3462 session->early_confirmed = 1;
3463 }
3465}

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

3199{
3200 RAII_VAR(struct ast_datastore *, datastore, NULL, ao2_cleanup);
3201 struct transport_info_data *transport_data;
3202 pjsip_tx_data *packet = NULL;
3204
3205 if (session->channel) {
3206 SCOPE_EXIT_RTN_VALUE(0, "%s: No channel\n", ast_sip_session_get_name(session));
3207 }
3208
3209 /* Check for a to-tag to determine if this is a reinvite */
3210 if (rdata->msg_info.to->tag.slen) {
3211 /* Weird case. We've received a reinvite but we don't have a channel. The most
3212 * typical case for this happening is that a blind transfer fails, and so the
3213 * transferer attempts to reinvite himself back into the call. We already got
3214 * rid of that channel, and the other side of the call is unrecoverable.
3215 *
3216 * We treat this as a failure, so our best bet is to just hang this call
3217 * up and not create a new channel. Clearing defer_terminate here ensures that
3218 * calling ast_sip_session_terminate() can result in a BYE being sent ASAP.
3219 */
3220 session->defer_terminate = 0;
3222 SCOPE_EXIT_RTN_VALUE(-1, "%s: We have a To tag but no channel. Terminating session\n", ast_sip_session_get_name(session));
3223 }
3224
3225 datastore = ast_sip_session_alloc_datastore(&transport_info, "transport_info");
3226 if (!datastore) {
3227 SCOPE_EXIT_LOG_RTN_VALUE(-1, LOG_ERROR, "%s: Couldn't alloc transport_info datastore\n", ast_sip_session_get_name(session));
3228 }
3229
3230 transport_data = ast_calloc(1, sizeof(*transport_data));
3231 if (!transport_data) {
3232 SCOPE_EXIT_LOG_RTN_VALUE(-1, LOG_ERROR, "%s: Couldn't alloc transport_info\n", ast_sip_session_get_name(session));
3233 }
3234 pj_sockaddr_cp(&transport_data->local_addr, &rdata->tp_info.transport->local_addr);
3235 pj_sockaddr_cp(&transport_data->remote_addr, &rdata->pkt_info.src_addr);
3236 datastore->data = transport_data;
3238
3239 if (!(session->channel = chan_pjsip_new(session, AST_STATE_RING, session->exten, NULL, NULL, NULL, NULL))) {
3240 if (pjsip_inv_end_session(session->inv_session, 503, NULL, &packet) == PJ_SUCCESS
3241 && packet) {
3243 }
3244
3245 SCOPE_EXIT_LOG_RTN_VALUE(-1, LOG_ERROR, "%s: Failed to allocate new PJSIP channel on incoming SIP INVITE\n",
3247 }
3248
3250
3251 /* channel gets created on incoming request, but we wait to call start
3252 so other supplements have a chance to run */
3254}
#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:643
@ 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 3385 of file chan_pjsip.c.

3386{
3387 struct pjsip_status_line status = rdata->msg_info.msg->line.status;
3388 SCOPE_ENTER(3, "%s: Status: %d\n", ast_sip_session_get_name(session), status.code);
3389
3390 if (!session->channel) {
3391 SCOPE_EXIT_RTN("%s: No channel\n", ast_sip_session_get_name(session));
3392 }
3393
3394 switch (status.code) {
3395 case 180: {
3396 pjsip_rdata_sdp_info *sdp = pjsip_rdata_get_sdp_info(rdata);
3397 if (sdp && sdp->body.ptr) {
3398 ast_trace(-1, "%s: Queueing PROGRESS\n", ast_sip_session_get_name(session));
3399 session->early_confirmed = pjsip_100rel_is_reliable(rdata) == PJ_TRUE;
3401 } else {
3402 ast_trace(-1, "%s: Queueing RINGING\n", ast_sip_session_get_name(session));
3404 }
3405
3406 ast_channel_lock(session->channel);
3407 if (ast_channel_state(session->channel) != AST_STATE_UP) {
3409 }
3410 ast_channel_unlock(session->channel);
3411 break;
3412 }
3413 case 183:
3414 if (session->endpoint->ignore_183_without_sdp) {
3415 pjsip_rdata_sdp_info *sdp = pjsip_rdata_get_sdp_info(rdata);
3416 if (sdp && sdp->body.ptr) {
3417 ast_trace(-1, "%s: Queueing PROGRESS\n", ast_sip_session_get_name(session));
3418 ast_trace(1, "%s Method: %.*s Status: %d Queueing PROGRESS with SDP\n", ast_sip_session_get_name(session),
3419 (int)rdata->msg_info.cseq->method.name.slen, rdata->msg_info.cseq->method.name.ptr, status.code);
3420 session->early_confirmed = pjsip_100rel_is_reliable(rdata) == PJ_TRUE;
3422 }
3423 } else {
3424 ast_trace(-1, "%s: Queueing PROGRESS\n", ast_sip_session_get_name(session));
3425 ast_trace(1, "%s Method: %.*s Status: %d Queueing PROGRESS without SDP\n", ast_sip_session_get_name(session),
3426 (int)rdata->msg_info.cseq->method.name.slen, rdata->msg_info.cseq->method.name.ptr, status.code);
3428 }
3429 break;
3430 case 200:
3431 ast_trace(-1, "%s: Queueing ANSWER\n", ast_sip_session_get_name(session));
3433 break;
3434 default:
3435 ast_trace(-1, "%s: Not queueing anything\n", ast_sip_session_get_name(session));
3436 break;
3437 }
3438
3440}
@ 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 3347 of file chan_pjsip.c.

3348{
3349 struct pjsip_status_line status = rdata->msg_info.msg->line.status;
3350 struct ast_control_pvt_cause_code *cause_code;
3351 int data_size = sizeof(*cause_code);
3352 SCOPE_ENTER(3, "%s: Status: %d\n", ast_sip_session_get_name(session), status.code);
3353
3354 if (!session->channel) {
3355 SCOPE_EXIT_RTN("%s: No channel\n", ast_sip_session_get_name(session));
3356 }
3357
3358 /* Build and send the tech-specific cause information */
3359 /* size of the string making up the cause code is "SIP " number + " " + reason length */
3360 data_size += 4 + 4 + pj_strlen(&status.reason);
3361 cause_code = ast_alloca(data_size);
3362 memset(cause_code, 0, data_size);
3363
3365
3366 /*
3367 * The cause code string is built in the format "SIP <status code> <reason phrase>".
3368 * Unfortunately, the ast_control_pvt_cause_code structure doesn't have a separate
3369 * field for the numeric code and adding it would break ABI so we'll have to parse
3370 * this string in chan_pjsip_session_end() later. If the string needs to be
3371 * changed, make sure the parsing in chan_pjsip_session_end() is adjusted as well.
3372 */
3373 snprintf(cause_code->code, data_size - sizeof(*cause_code) + 1, "SIP %d %.*s", status.code,
3374 (int) pj_strlen(&status.reason), pj_strbuf(&status.reason));
3375
3376 cause_code->ast_cause = ast_sip_hangup_sip2cause(status.code);
3377 ast_queue_control_data(session->channel, AST_CONTROL_PVT_CAUSE_CODE, cause_code, data_size);
3378 ast_channel_hangupcause_hash_set(session->channel, cause_code, data_size);
3379
3380 SCOPE_EXIT_RTN("%s: ast_cause: %d tech_cause: %s\n", ast_sip_session_get_name(session),
3381 cause_code->ast_cause, cause_code->code);
3382}
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition astmm.h:288
int ast_queue_control_data(struct ast_channel *chan, enum ast_control_frame_type control, const void *data, size_t datalen)
Queue a control frame with payload.
Definition channel.c:1296
void ast_channel_hangupcause_hash_set(struct ast_channel *chan, const struct ast_control_pvt_cause_code *cause_code, int datalen)
Sets the HANGUPCAUSE hash and optionally the SIP_CAUSE hash on the given channel.
Definition channel.c:4368
#define AST_CHANNEL_NAME
Definition channel.h:173
@ AST_CONTROL_PVT_CAUSE_CODE
const int ast_sip_hangup_sip2cause(int cause)
Convert SIP hangup causes to Asterisk hangup causes.
Definition res_pjsip.c:3525

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

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

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

◆ chan_pjsip_new()

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

Function called to create a new PJSIP Asterisk channel.

Definition at line 643 of file chan_pjsip.c.

644{
645 struct ast_channel *chan;
646 struct ast_format_cap *caps;
647 RAII_VAR(struct chan_pjsip_pvt *, pvt, NULL, ao2_cleanup);
648 struct ast_sip_channel_pvt *channel;
649 struct ast_variable *var;
650 struct ast_stream_topology *topology;
651 struct ast_channel_initializers initializers = {
653 .tenantid = session->endpoint->tenantid,
654 };
656
658 SCOPE_EXIT_RTN_VALUE(NULL, "Couldn't create pvt\n");
659 }
660
662 S_COR(session->id.number.valid, session->id.number.str, ""),
663 S_COR(session->id.name.valid, session->id.name.str, ""),
664 session->endpoint->accountcode,
665 exten, session->endpoint->context,
666 assignedids, requestor, 0,
667 session->endpoint->persistent, &initializers, "PJSIP/%s-%08x",
669 (unsigned) ast_atomic_fetchadd_int((int *) &chan_idx, +1));
670 if (!chan) {
671 SCOPE_EXIT_RTN_VALUE(NULL, "Couldn't create channel\n");
672 }
673
675
676 if (!(channel = ast_sip_channel_pvt_alloc(pvt, session))) {
677 ast_channel_unlock(chan);
678 ast_hangup(chan);
679 SCOPE_EXIT_RTN_VALUE(NULL, "Couldn't create pvt channel\n");
680 }
681
682 ast_channel_tech_pvt_set(chan, channel);
683
684 if (!ast_stream_topology_get_count(session->pending_media_state->topology) ||
685 !compatible_formats_exist(session->pending_media_state->topology, session->endpoint->media.codecs)) {
687 if (!caps) {
688 ast_channel_unlock(chan);
689 ast_hangup(chan);
690 SCOPE_EXIT_RTN_VALUE(NULL, "Couldn't create caps\n");
691 }
692 ast_format_cap_append_from_cap(caps, session->endpoint->media.codecs, AST_MEDIA_TYPE_UNKNOWN);
693 topology = ast_stream_topology_clone(session->endpoint->media.topology);
694 } else {
695 caps = ast_stream_topology_get_formats(session->pending_media_state->topology);
696 topology = ast_stream_topology_clone(session->pending_media_state->topology);
697 }
698
699 if (!topology || !caps) {
700 ao2_cleanup(caps);
701 ast_stream_topology_free(topology);
702 ast_channel_unlock(chan);
703 ast_hangup(chan);
704 SCOPE_EXIT_RTN_VALUE(NULL, "Couldn't get caps or clone topology\n");
705 }
706
708
710 ast_channel_set_stream_topology(chan, topology);
711
712 if (!ast_format_cap_empty(caps)) {
713 struct ast_format *fmt;
714
716 if (!fmt) {
717 /* Since our capabilities aren't empty, this will succeed */
718 fmt = ast_format_cap_get_format(caps, 0);
719 }
724 ao2_ref(fmt, -1);
725 }
726
727 ao2_ref(caps, -1);
728
729 if (state == AST_STATE_RING) {
730 ast_channel_rings_set(chan, 1);
731 }
732
734
737 ast_channel_caller(chan)->ani2 = session->ani2;
738
739 if (!ast_strlen_zero(exten)) {
740 /* Set provided DNID on the new channel. */
741 ast_channel_dialed(chan)->number.str = ast_strdup(exten);
742 }
743
745
746 ast_channel_callgroup_set(chan, session->endpoint->pickup.callgroup);
747 ast_channel_pickupgroup_set(chan, session->endpoint->pickup.pickupgroup);
748
749 ast_channel_named_callgroups_set(chan, session->endpoint->pickup.named_callgroups);
750 ast_channel_named_pickupgroups_set(chan, session->endpoint->pickup.named_pickupgroups);
751
752 if (!ast_strlen_zero(session->endpoint->language)) {
753 ast_channel_language_set(chan, session->endpoint->language);
754 }
755
756 if (!ast_strlen_zero(session->endpoint->zone)) {
757 struct ast_tone_zone *zone = ast_get_indication_zone(session->endpoint->zone);
758 if (!zone) {
759 ast_log(LOG_ERROR, "Unknown country code '%s' for tonezone. Check indications.conf for available country codes.\n", session->endpoint->zone);
760 }
761 ast_channel_zone_set(chan, zone);
762 }
763
765 ast_channel_unlock(chan);
766
767 for (var = session->endpoint->channel_vars; var; var = var->next) {
768 char buf[512];
770 var->value, buf, sizeof(buf)));
771 }
772
774
776}
#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:622
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:1752
void ast_channel_zone_set(struct ast_channel *chan, struct ast_tone_zone *value)
void ast_channel_priority_set(struct ast_channel *chan, int value)
void ast_channel_pickupgroup_set(struct ast_channel *chan, ast_group_t value)
void ast_channel_adsicpe_set(struct ast_channel *chan, enum ast_channel_adsicpe value)
void ast_channel_tech_set(struct ast_channel *chan, const struct ast_channel_tech *value)
void ast_channel_set_writeformat(struct ast_channel *chan, struct ast_format *format)
char buf[BUFSIZE]
Definition eagi_proxy.c:66
int ast_format_cap_empty(const struct ast_format_cap *cap)
Determine if a format cap has no formats in it.
Definition format_cap.c:752
struct ast_format * ast_format_cap_get_format(const struct ast_format_cap *cap, int position)
Get the format at a specific index.
Definition format_cap.c:408
struct ast_format * ast_format_cap_get_best_by_type(const struct ast_format_cap *cap, enum ast_media_type type)
Get the most preferred format for a particular media type.
Definition format_cap.c:425
@ AST_FORMAT_CAP_FLAG_DEFAULT
Definition format_cap.h:38
#define ast_format_cap_alloc(flags)
Allocate a new ast_format_cap structure.
Definition format_cap.h:49
void ast_channel_stage_snapshot_done(struct ast_channel *chan)
Clear flag to indicate channel snapshot is being staged, and publish snapshot.
void ast_channel_stage_snapshot(struct ast_channel *chan)
Set flag to indicate channel snapshot is being staged.
char * ast_get_encoded_str(const char *stream, char *result, size_t result_len)
Decode a stream of encoded control or extended ASCII characters.
Definition main/app.c:3163
struct ast_tone_zone * ast_get_indication_zone(const char *country)
locate ast_tone_zone
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition lock.h:764
struct ast_sip_channel_pvt * ast_sip_channel_pvt_alloc(void *pvt, struct ast_sip_session *session)
Allocate a new SIP channel pvt structure.
int ast_stream_topology_get_count(const struct ast_stream_topology *topology)
Get the number of streams in a topology.
Definition stream.c:768
void ast_stream_topology_free(struct ast_stream_topology *topology)
Unreference and destroy a stream topology.
Definition stream.c:746
struct ast_format_cap * ast_stream_topology_get_formats(struct ast_stream_topology *topology)
Create a format capabilities structure representing the topology.
Definition stream.c:933
struct ast_stream_topology * ast_stream_topology_clone(const struct ast_stream_topology *topology)
Create a deep clone of an existing stream topology.
Definition stream.c:670
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition strings.h:65
Helper struct for initializing additional channel information on channel creation.
Definition channel.h:615
uint32_t version
struct ABI version
Definition channel.h:625
Format capabilities structure, holds formats + preference order + etc.
Definition format_cap.c:54
Definition of a media format.
Definition format.c:43
int ani2
Automatic Number Identification 2 (Info Digits)
Definition channel.h:435
struct ast_party_dialed::@218 number
Dialed/Called number.
char * str
Subscriber phone number (Malloced)
Definition channel.h:388
A set of tones for a given locale.
Definition indications.h:74
Structure for variables, used for configurations and for channel variables.
The PJSIP channel driver pvt, stored in the ast_sip_channel_pvt data structure.
Definition chan_pjsip.h:42

References ast_party_caller::ani2, AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_alloc_options, ao2_cleanup, ao2_ref, AST_ADSI_UNAVAILABLE, ast_atomic_fetchadd_int(), ast_channel_adsicpe_set(), ast_channel_alloc_with_initializers, ast_channel_caller(), ast_channel_callgroup_set(), ast_channel_dialed(), AST_CHANNEL_INITIALIZERS_VERSION, ast_channel_named_callgroups_set(), ast_channel_named_pickupgroups_set(), ast_channel_nativeformats_set(), ast_channel_pickupgroup_set(), ast_channel_priority_set(), ast_channel_rings_set(), ast_channel_set_rawreadformat(), ast_channel_set_rawwriteformat(), ast_channel_set_readformat(), ast_channel_set_stream_topology(), ast_channel_set_writeformat(), ast_channel_stage_snapshot(), ast_channel_stage_snapshot_done(), ast_channel_tech_pvt_set(), ast_channel_tech_set(), ast_channel_uniqueid(), ast_channel_unlock, ast_channel_zone_set(), ast_format_cap_alloc, ast_format_cap_append_from_cap(), ast_format_cap_empty(), AST_FORMAT_CAP_FLAG_DEFAULT, ast_format_cap_get_best_by_type(), ast_format_cap_get_format(), ast_get_encoded_str(), ast_get_indication_zone(), ast_hangup(), ast_log, AST_MEDIA_TYPE_AUDIO, AST_MEDIA_TYPE_UNKNOWN, ast_party_id_copy(), ast_sip_channel_pvt_alloc(), ast_sip_session_get_name(), ast_sorcery_object_get_id(), AST_STATE_RING, ast_strdup, ast_stream_topology_clone(), ast_stream_topology_free(), ast_stream_topology_get_count(), ast_stream_topology_get_formats(), ast_strlen_zero(), buf, chan_idx, chan_pjsip_pvt_dtor(), chan_pjsip_tech, compatible_formats_exist(), LOG_ERROR, NULL, ast_party_dialed::number, pbx_builtin_setvar_helper(), 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 1335 of file chan_pjsip.c.

1336{
1337 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(ast);
1338 int res = -1;
1340
1341 if (!channel) {
1342 return -1;
1343 }
1344
1345 switch (option) {
1347 if (channel->session->endpoint->media.t38.enabled) {
1348 switch (channel->session->t38state) {
1349 case T38_LOCAL_REINVITE:
1350 case T38_PEER_REINVITE:
1352 break;
1353 case T38_ENABLED:
1355 break;
1356 case T38_REJECTED:
1358 break;
1359 default:
1361 break;
1362 }
1363 }
1364
1365 *((enum ast_t38_state *) data) = state;
1366 res = 0;
1367
1368 break;
1369 default:
1370 break;
1371 }
1372
1373 return res;
1374}
#define T38_ENABLED
ast_t38_state
Possible T38 states on channels.
Definition channel.h:898
@ T38_STATE_UNAVAILABLE
Definition channel.h:899
@ T38_STATE_UNKNOWN
Definition channel.h:900
@ T38_STATE_REJECTED
Definition channel.h:902
@ T38_STATE_NEGOTIATED
Definition channel.h:903
@ T38_STATE_NEGOTIATING
Definition channel.h:901
#define AST_OPTION_T38_STATE
@ T38_LOCAL_REINVITE
@ T38_REJECTED
struct ast_sip_t38_configuration t38
Definition res_pjsip.h:1023

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

◆ chan_pjsip_read_stream()

static struct ast_frame * chan_pjsip_read_stream ( struct ast_channel ast)
static

Function called by core to read any waiting frames.

Note
The channel is already locked.

Definition at line 939 of file chan_pjsip.c.

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

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

◆ chan_pjsip_remove_hold()

static void chan_pjsip_remove_hold ( const char *  chan_uid)
static

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

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

Definition at line 1249 of file chan_pjsip.c.

1250{
1252}
@ 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 2861 of file chan_pjsip.c.

2862{
2863 struct ast_stream_topology *topology;
2864 struct ast_channel *chan;
2865
2867 if (!topology) {
2868 return NULL;
2869 }
2870
2871 chan = chan_pjsip_request_with_stream_topology(type, topology, assignedids, requestor, data, cause);
2872
2873 ast_stream_topology_free(topology);
2874
2875 return chan;
2876}
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 2834 of file chan_pjsip.c.

2835{
2836 struct request_data req_data;
2838 SCOPE_ENTER(1, "%s Topology: %s\n", data,
2840
2841 req_data.topology = topology;
2842 req_data.dest = data;
2843 /* Default failure value in case ast_sip_push_task_wait_servant() itself fails. */
2844 req_data.cause = AST_CAUSE_FAILURE;
2845
2846 if (ast_sip_push_task_wait_servant(NULL, request, &req_data)) {
2847 *cause = req_data.cause;
2848 SCOPE_EXIT_RTN_VALUE(NULL, "Couldn't push task\n");
2849 }
2850
2851 session = req_data.session;
2852
2853 if (!(session->channel = chan_pjsip_new(session, AST_STATE_DOWN, NULL, NULL, assignedids, requestor, NULL))) {
2854 /* Session needs to be terminated prematurely */
2855 SCOPE_EXIT_RTN_VALUE(NULL, "Couldn't create channel\n");
2856 }
2857
2858 SCOPE_EXIT_RTN_VALUE(session->channel, "Channel: %s\n", ast_channel_name(session->channel));
2859}
#define AST_CAUSE_FAILURE
Definition causes.h:150
static int request(void *obj)
#define ast_sip_push_task_wait_servant(serializer, sip_task, task_data)
Definition res_pjsip.h:2165
struct ast_stream_topology * topology

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

Referenced by chan_pjsip_request().

◆ chan_pjsip_sendtext()

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

Definition at line 3005 of file chan_pjsip.c.

3006{
3007 struct ast_msg_data *msg;
3008 int rc;
3009 struct ast_msg_data_attribute attrs[] =
3010 {
3011 {
3013 .value = (char *)text,
3014 }
3015 };
3016
3018 if (!msg) {
3019 return -1;
3020 }
3021 rc = chan_pjsip_sendtext_data(ast, msg);
3022 ast_free(msg);
3023
3024 return rc;
3025}
#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 2983 of file chan_pjsip.c.

2984{
2985 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(ast);
2986 struct sendtext_data *data = sendtext_data_create(ast, msg);
2987
2988 ast_debug(1, "Sending MESSAGE from '%s' to '%s:%s': %s\n",
2991 ast_channel_name(ast),
2993
2994 if (!data) {
2995 return -1;
2996 }
2997
2998 if (ast_sip_push_task(channel->session->serializer, sendtext, data)) {
2999 ao2_ref(data, -1);
3000 return -1;
3001 }
3002 return 0;
3003}
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 3027 of file chan_pjsip.c.

3028{
3029 RAII_VAR(struct ast_datastore *, datastore, NULL, ao2_cleanup);
3031
3032 if (session->endpoint->media.direct_media.glare_mitigation ==
3034 SCOPE_EXIT_RTN("Direct media no glare mitigation\n");
3035 }
3036
3038 "direct_media_glare_mitigation");
3039
3040 if (!datastore) {
3041 SCOPE_EXIT_RTN("Couldn't create datastore\n");
3042 }
3043
3046}
static struct ast_datastore_info direct_media_mitigation_info
Definition chan_pjsip.c:370
@ AST_SIP_DIRECT_MEDIA_GLARE_MITIGATION_NONE
Definition res_pjsip.h:724

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

◆ chan_pjsip_session_end()

static void chan_pjsip_session_end ( struct ast_sip_session session)
static

Function called when the session ends.

Definition at line 3049 of file chan_pjsip.c.

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

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

◆ chan_pjsip_set_rtp_peer()

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

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

Definition at line 544 of file chan_pjsip.c.

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

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

2274{
2275 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(chan);
2276 struct transfer_data *trnf_data = transfer_data_alloc(channel->session, target);
2277
2278 if (!trnf_data) {
2279 return -1;
2280 }
2281
2282 if (ast_sip_push_task(channel->session->serializer, transfer, trnf_data)) {
2283 ast_log(LOG_WARNING, "Error requesting transfer\n");
2284 ao2_cleanup(trnf_data);
2285 return -1;
2286 }
2287
2288 return 0;
2289}
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 1140 of file chan_pjsip.c.

1141{
1142 return chan_pjsip_write_stream(ast, -1, frame);
1143}
static int chan_pjsip_write_stream(struct ast_channel *ast, int stream_num, struct ast_frame *f)

References chan_pjsip_write_stream().

◆ chan_pjsip_write_stream()

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

Definition at line 1050 of file chan_pjsip.c.

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

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

Referenced by chan_pjsip_write().

◆ check_for_rtp_changes()

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

Definition at line 423 of file chan_pjsip.c.

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

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

Referenced by send_direct_media_request().

◆ clear_session_and_channel()

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

Clear a channel from a session along with its PVT.

Definition at line 2626 of file chan_pjsip.c.

2627{
2628 session->channel = NULL;
2631}

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

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

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

Referenced by chan_pjsip_new().

◆ direct_media_mitigate_glare()

static int direct_media_mitigate_glare ( struct ast_sip_session session)
static

Definition at line 372 of file chan_pjsip.c.

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

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

Referenced by send_direct_media_request().

◆ handle_topology_request_change()

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

Definition at line 1694 of file chan_pjsip.c.

1696{
1698 int res;
1699 SCOPE_ENTER(1);
1700
1702 if (!refresh_data) {
1703 SCOPE_EXIT_RTN_VALUE(-1, "Couldn't create refresh_data\n");
1704 }
1705
1707 if (res) {
1709 }
1710 SCOPE_EXIT_RTN_VALUE(res, "RC: %d\n", res);
1711}
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 2633 of file chan_pjsip.c.

2634{
2635 struct hangup_data *h_data = data;
2636 struct ast_channel *ast = h_data->chan;
2637 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(ast);
2638 SCOPE_ENTER(1, "%s\n", ast_channel_name(ast));
2639
2640 /*
2641 * Before cleaning we have to ensure that channel or its session is not NULL
2642 * we have seen rare case when taskprocessor calls hangup but channel is NULL
2643 * due to SIP session timeout and answer happening at the same time
2644 */
2645 if (channel) {
2646 struct ast_sip_session *session = channel->session;
2647 if (session) {
2648 int cause = h_data->cause;
2649
2650 if (channel->session->active_media_state &&
2651 channel->session->active_media_state->default_session[AST_MEDIA_TYPE_AUDIO]) {
2652 struct ast_sip_session_media *media =
2654 if (media->rtp) {
2656 }
2657 }
2658
2659 /*
2660 * It's possible that session_terminate might cause the session to be destroyed
2661 * immediately so we need to keep a reference to it so we can NULL session->channel
2662 * afterwards.
2663 */
2667 }
2668 ao2_cleanup(channel);
2669 }
2670 ao2_cleanup(h_data);
2672}
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 2550 of file chan_pjsip.c.

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

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

Referenced by chan_pjsip_hangup(), and chan_pjsip_session_end().

◆ hangup_data_alloc()

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

Definition at line 2611 of file chan_pjsip.c.

2612{
2613 struct hangup_data *h_data = ao2_alloc(sizeof(*h_data), hangup_data_destroy);
2614
2615 if (!h_data) {
2616 return NULL;
2617 }
2618
2619 h_data->cause = cause;
2620 h_data->chan = ast_channel_ref(chan);
2621
2622 return h_data;
2623}
#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 2604 of file chan_pjsip.c.

2605{
2606 struct hangup_data *h_data = obj;
2607
2608 h_data->chan = ast_channel_unref(h_data->chan);
2609}

References ast_channel_unref, and hangup_data::chan.

Referenced by hangup_data_alloc().

◆ indicate()

static int indicate ( void *  data)
static

Definition at line 1431 of file chan_pjsip.c.

1432{
1433 pjsip_tx_data *packet = NULL;
1434 struct indicate_data *ind_data = data;
1435 struct ast_sip_session *session = ind_data->session;
1436 int response_code = ind_data->response_code;
1437
1438 if ((session->inv_session->state != PJSIP_INV_STATE_DISCONNECTED) &&
1439 (pjsip_inv_answer(session->inv_session, response_code, NULL, NULL, &packet) == PJ_SUCCESS)) {
1441 }
1442
1443 ao2_ref(ind_data, -1);
1444
1445 return 0;
1446}
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 1406 of file chan_pjsip.c.

1408{
1409 struct indicate_data *ind_data = ao2_alloc(sizeof(*ind_data), indicate_data_destroy);
1410
1411 if (!ind_data) {
1412 return NULL;
1413 }
1414
1415 ind_data->frame_data = ast_malloc(datalen);
1416 if (!ind_data->frame_data) {
1417 ao2_ref(ind_data, -1);
1418 return NULL;
1419 }
1420
1421 memcpy(ind_data->frame_data, frame_data, datalen);
1422 ind_data->datalen = datalen;
1423 ind_data->condition = condition;
1424 ind_data->response_code = response_code;
1425 ao2_ref(session, +1);
1426 ind_data->session = session;
1427
1428 return ind_data;
1429}
#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 1398 of file chan_pjsip.c.

1399{
1400 struct indicate_data *ind_data = obj;
1401
1402 ast_free(ind_data->frame_data);
1403 ao2_ref(ind_data->session, -1);
1404}

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

2348{
2349 struct info_dtmf_data *dtmf_data = ao2_alloc(sizeof(*dtmf_data), info_dtmf_data_destroy);
2350 if (!dtmf_data) {
2351 return NULL;
2352 }
2353 ao2_ref(session, +1);
2354 dtmf_data->session = session;
2355 dtmf_data->digit = digit;
2356 dtmf_data->duration = duration;
2357 return dtmf_data;
2358}
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 2341 of file chan_pjsip.c.

2342{
2343 struct info_dtmf_data *dtmf_data = obj;
2344 ao2_ref(dtmf_data->session, -1);
2345}

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

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

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

Referenced by update_connected_line_information().

◆ is_compatible_format()

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

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

Definition at line 925 of file chan_pjsip.c.

926{
927 struct ast_stream_topology *topology = session->active_media_state->topology;
928 struct ast_stream *stream = ast_stream_topology_get_stream(topology, f->stream_num);
929 const struct ast_format_cap *cap = ast_stream_get_formats(stream);
930
932}
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 3529 of file chan_pjsip.c.

3530{
3531 struct ao2_container *endpoints;
3532
3535 }
3536
3538
3540
3542 ast_log(LOG_ERROR, "Unable to register channel class %s\n", channel_type);
3543 goto end;
3544 }
3545
3547 ast_log(LOG_ERROR, "Unable to register PJSIP_DIAL_CONTACTS dialplan function\n");
3548 goto end;
3549 }
3550
3552 ast_log(LOG_ERROR, "Unable to register PJSIP_PARSE_URI dialplan function\n");
3553 goto end;
3554 }
3555
3557 ast_log(LOG_ERROR, "Unable to register PJSIP_PARSE_URI_FROM dialplan function\n");
3558 goto end;
3559 }
3560
3562 ast_log(LOG_WARNING, "Unable to register PJSIP_MEDIA_OFFER dialplan function\n");
3563 goto end;
3564 }
3565
3567 ast_log(LOG_WARNING, "Unable to register PJSIP_DTMF_MODE dialplan function\n");
3568 goto end;
3569 }
3570
3572 ast_log(LOG_WARNING, "Unable to register PJSIP_MOH_PASSTHROUGH dialplan function\n");
3573 goto end;
3574 }
3575
3577 ast_log(LOG_WARNING, "Unable to register PJSIP_SEND_SESSION_REFRESH dialplan function\n");
3578 goto end;
3579 }
3580
3582 ast_log(LOG_WARNING, "Unable to register PJSIP_TRANSFER_HANDLING dialplan function\n");
3583 goto end;
3584 }
3585
3587 ast_log(LOG_WARNING, "Unable to register PJSIPHangup dialplan application\n");
3588 goto end;
3589 }
3591
3592
3594
3597
3601 ast_log(LOG_ERROR, "Unable to create held channels container\n");
3602 goto end;
3603 }
3604
3609
3611 ast_log(LOG_ERROR, "Unable to register PJSIP Channel CLI\n");
3612 goto end;
3613 }
3614
3615 /* since endpoints are loaded before the channel driver their device
3616 states get set to 'invalid', so they need to be updated */
3617 if ((endpoints = ast_sip_get_endpoints())) {
3619 ao2_ref(endpoints, -1);
3620 }
3621
3622 return 0;
3623
3624end:
3644
3647
3649}
@ AO2_ALLOC_OPT_LOCK_RWLOCK
Definition astobj2.h:365
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container,...
Definition astobj2.h:1693
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Allocate and initialize a hash container with the desired number of buckets.
Definition astobj2.h:1303
@ AO2_CONTAINER_ALLOC_OPT_DUPS_REJECT
Reject objects with duplicate keys in container.
Definition astobj2.h:1188
static int uid_hold_sort_fn(const void *obj_left, const void *obj_right, const int flags)
static pjsip_module chan_pjsip_module
General PJSIP module for chan_pjsip, currently used for REFER subscription data and outgoing request ...
static char * app_pjsip_hangup
static int update_devstate(void *obj, void *arg, int flags)
static struct ast_sip_session_supplement chan_pjsip_supplement
SIP session supplement structure.
Definition chan_pjsip.c: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:582
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:571
int ast_channel_register(const struct ast_channel_tech *tech)
Register a channel technology (a new channel driver) Called by a channel module to register the kind ...
Definition channel.c:540
int pjsip_channel_cli_register(void)
Registers the channel cli commands.
int pjsip_app_hangup(struct ast_channel *chan, const char *data)
PJSIPHangup Dialplan App.
int pjsip_action_hangup(struct mansession *s, const struct message *m)
PJSIPHangup Manager Action.
char * end
Definition eagi_proxy.c:73
int ast_format_cap_append_by_type(struct ast_format_cap *cap, enum ast_media_type type)
Add all codecs Asterisk knows about for a specific type to the capabilities structure.
Definition format_cap.c:216
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition manager.c:7782
static struct ao2_container * endpoints
#define EVENT_FLAG_SYSTEM
Definition manager.h:75
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition manager.h:193
#define EVENT_FLAG_CALL
Definition manager.h:76
int ast_unregister_application(const char *app)
Unregister an application.
Definition pbx_app.c:404
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition module.h:78
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition module.h:640
#define ast_custom_function_register(acf)
Register a custom function.
Definition pbx.h:1563
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
void ast_sip_unregister_service(pjsip_module *module)
Definition res_pjsip.c:127
struct ao2_container * ast_sip_get_endpoints(void)
Retrieve any endpoints available to sorcery.
int ast_sip_register_service(pjsip_module *module)
Register a SIP service in Asterisk.
Definition res_pjsip.c:111
#define ast_sip_session_register_supplement(supplement)
void ast_sip_session_unregister_supplement(struct ast_sip_session_supplement *supplement)
Unregister a an supplement to SIP session processing.
#define ast_rtp_glue_register(glue)
Definition rtp_engine.h:905
int ast_rtp_glue_unregister(struct ast_rtp_glue *glue)
Unregister RTP glue.
Definition rtp_engine.c:418
Generic container type.
struct ast_format_cap * capabilities
Definition channel.h:652

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

◆ on_topology_change_response()

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

Definition at line 1642 of file chan_pjsip.c.

1643{
1644 SCOPE_ENTER(3, "%s: Received response code %d. PT: %s AT: %s\n", ast_sip_session_get_name(session),
1645 rdata->msg_info.msg->line.status.code,
1646 ast_str_tmp(256, ast_stream_topology_to_str(session->pending_media_state->topology, &STR_TMP)),
1647 ast_str_tmp(256, ast_stream_topology_to_str(session->active_media_state->topology, &STR_TMP)));
1648
1649
1650 if (PJSIP_IS_STATUS_IN_CLASS(rdata->msg_info.msg->line.status.code, 200)) {
1651 /* The topology was changed to something new so give notice to what requested
1652 * it so it queries the channel and updates accordingly.
1653 */
1654 if (session->channel) {
1656 SCOPE_EXIT_RTN_VALUE(0, "%s: Queued topology change frame\n", ast_sip_session_get_name(session));
1657 }
1658 SCOPE_EXIT_RTN_VALUE(0, "%s: No channel? Can't queue topology change frame\n", ast_sip_session_get_name(session));
1659 } else if (300 <= rdata->msg_info.msg->line.status.code) {
1660 /* The topology change failed, so drop the current pending media state */
1661 ast_sip_session_media_state_reset(session->pending_media_state);
1662 SCOPE_EXIT_RTN_VALUE(0, "%s: response code > 300. Resetting pending media state\n", ast_sip_session_get_name(session));
1663 }
1664
1665 SCOPE_EXIT_RTN_VALUE(0, "%s: Nothing to do\n", ast_sip_session_get_name(session));
1666}
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 3306 of file chan_pjsip.c.

3307{
3308 int res;
3310
3311 /* Check for a to-tag to determine if this is a reinvite */
3312 if (rdata->msg_info.to->tag.slen) {
3313 /* We don't care about reinvites */
3314 SCOPE_EXIT_RTN_VALUE(0, "Reinvite\n");
3315 }
3316
3317 res = ast_pbx_start(session->channel);
3318
3319 switch (res) {
3320 case AST_PBX_FAILED:
3321 ast_log(LOG_WARNING, "Failed to start PBX ;(\n");
3323 ast_hangup(session->channel);
3324 break;
3325 case AST_PBX_CALL_LIMIT:
3326 ast_log(LOG_WARNING, "Failed to start PBX (call limit reached) \n");
3328 ast_hangup(session->channel);
3329 break;
3330 case AST_PBX_SUCCESS:
3331 default:
3332 break;
3333 }
3334
3335 ast_debug(3, "Started PBX on new PJSIP channel %s\n", ast_channel_name(session->channel));
3336
3337 SCOPE_EXIT_RTN_VALUE((res == AST_PBX_SUCCESS) ? 0 : -1, "RC: %d\n", res);
3338}
@ AST_PBX_FAILED
Definition pbx.h:374
@ AST_PBX_CALL_LIMIT
Definition pbx.h:375
@ AST_PBX_SUCCESS
Definition pbx.h:373
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
Definition pbx.c:3268

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

◆ remote_send_hold()

static int remote_send_hold ( void *  data)
static

Update local hold state to be held.

Definition at line 1593 of file chan_pjsip.c.

1594{
1595 return remote_send_hold_refresh(data, 1);
1596}
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 1580 of file chan_pjsip.c.

1581{
1582 struct ast_sip_session_media *session_media = session->active_media_state->default_session[AST_MEDIA_TYPE_AUDIO];
1583 if (session_media) {
1584 session_media->locally_held = held;
1585 }
1587 ao2_ref(session, -1);
1588
1589 return 0;
1590}
@ AST_SIP_SESSION_REFRESH_METHOD_INVITE
Definition res_pjsip.h:717
int ast_sip_session_refresh(struct ast_sip_session *session, ast_sip_session_request_creation_cb on_request_creation, ast_sip_session_sdp_creation_cb on_sdp_creation, ast_sip_session_response_cb on_response, enum ast_sip_session_refresh_method method, int generate_new_sdp, struct ast_sip_session_media_state *media_state)
Send a reinvite or UPDATE on a session.
unsigned int locally_held
Stream is on hold by local side.

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

Referenced by remote_send_hold(), and remote_send_unhold().

◆ remote_send_unhold()

static int remote_send_unhold ( void *  data)
static

Update local hold state to be unheld.

Definition at line 1599 of file chan_pjsip.c.

1600{
1601 return remote_send_hold_refresh(data, 0);
1602}

References remote_send_hold_refresh().

Referenced by chan_pjsip_indicate().

◆ request()

static int request ( void *  obj)
static

Definition at line 2726 of file chan_pjsip.c.

2727{
2728 struct request_data *req_data = obj;
2729 struct ast_sip_session *session = NULL;
2730 char *tmp = ast_strdupa(req_data->dest), *endpoint_name = NULL, *request_user = NULL;
2731 struct ast_sip_endpoint *endpoint;
2732
2734 AST_APP_ARG(endpoint);
2735 AST_APP_ARG(aor);
2736 );
2737 SCOPE_ENTER(1, "%s\n",tmp);
2738
2739 if (ast_strlen_zero(tmp)) {
2740 ast_log(LOG_ERROR, "Unable to create PJSIP channel with empty destination\n");
2742 SCOPE_EXIT_RTN_VALUE(-1, "Empty destination\n");
2743 }
2744
2745 AST_NONSTANDARD_APP_ARGS(args, tmp, '/');
2746
2748 /* If a request user has been specified extract it from the endpoint name portion */
2749 if ((endpoint_name = strchr(args.endpoint, '@'))) {
2750 request_user = args.endpoint;
2751 *endpoint_name++ = '\0';
2752 } else {
2753 endpoint_name = args.endpoint;
2754 }
2755
2756 if (ast_strlen_zero(endpoint_name)) {
2757 if (request_user) {
2758 ast_log(LOG_ERROR, "Unable to create PJSIP channel with empty endpoint name: %s@<endpoint-name>\n",
2759 request_user);
2760 } else {
2761 ast_log(LOG_ERROR, "Unable to create PJSIP channel with empty endpoint name\n");
2762 }
2764 SCOPE_EXIT_RTN_VALUE(-1, "Empty endpoint name\n");
2765 }
2766 endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint",
2767 endpoint_name);
2768 if (!endpoint) {
2769 ast_log(LOG_ERROR, "Unable to create PJSIP channel - endpoint '%s' was not found\n", endpoint_name);
2771 SCOPE_EXIT_RTN_VALUE(-1, "Endpoint not found\n");
2772 }
2773 } else {
2774 /* First try to find an exact endpoint match, for single (user) or multi-domain (user@domain) */
2775 endpoint_name = args.endpoint;
2776 if (ast_strlen_zero(endpoint_name)) {
2777 ast_log(LOG_ERROR, "Unable to create PJSIP channel with empty endpoint name\n");
2779 SCOPE_EXIT_RTN_VALUE(-1, "Empty endpoint name\n");
2780 }
2781 endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint",
2782 endpoint_name);
2783 if (!endpoint) {
2784 /* It seems it's not a multi-domain endpoint or single endpoint exact match,
2785 * it's possible that it's a SIP trunk with a specified user (user@trunkname),
2786 * so extract the user before @ sign.
2787 */
2788 endpoint_name = strchr(args.endpoint, '@');
2789 if (!endpoint_name) {
2790 /*
2791 * Couldn't find an '@' so it had to be an endpoint
2792 * name that doesn't exist.
2793 */
2794 ast_log(LOG_ERROR, "Unable to create PJSIP channel - endpoint '%s' was not found\n",
2795 args.endpoint);
2797 SCOPE_EXIT_RTN_VALUE(-1, "Endpoint not found\n");
2798 }
2799 request_user = args.endpoint;
2800 *endpoint_name++ = '\0';
2801
2802 if (ast_strlen_zero(endpoint_name)) {
2803 ast_log(LOG_ERROR, "Unable to create PJSIP channel with empty endpoint name: %s@<endpoint-name>\n",
2804 request_user);
2806 SCOPE_EXIT_RTN_VALUE(-1, "Empty endpoint name\n");
2807 }
2808
2809 endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint",
2810 endpoint_name);
2811 if (!endpoint) {
2812 ast_log(LOG_ERROR, "Unable to create PJSIP channel - endpoint '%s' was not found\n", endpoint_name);
2814 SCOPE_EXIT_RTN_VALUE(-1, "Endpoint not found\n");
2815 }
2816 }
2817 }
2818
2819 session = ast_sip_session_create_outgoing(endpoint, NULL, args.aor, request_user,
2820 req_data->topology);
2821 ao2_ref(endpoint, -1);
2822 if (!session) {
2823 ast_log(LOG_ERROR, "Failed to create outgoing session to endpoint '%s'\n", endpoint_name);
2825 SCOPE_EXIT_RTN_VALUE(-1, "Couldn't create session\n");
2826 }
2827
2828 req_data->session = session;
2829
2831}
#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 @522 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 473 of file chan_pjsip.c.

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

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

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

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

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

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

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

References ao2_ref, ast_channel_lock, ast_channel_name(), ast_channel_tech_pvt(), ast_channel_unlock, ast_debug, ast_format_cap_append_from_cap(), ast_format_cap_count(), ast_format_cap_identical(), ast_format_cap_remove_by_type(), AST_MEDIA_TYPE_AUDIO, AST_MEDIA_TYPE_UNKNOWN, AST_MEDIA_TYPE_VIDEO, ast_sip_session_refresh(), cdata(), ast_sip_session::channel, check_for_rtp_changes(), direct_media_mitigate_glare(), NULL, 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 1668 of file chan_pjsip.c.

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

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

Referenced by handle_topology_request_change().

◆ sendtext()

static int sendtext ( void *  obj)
static

Definition at line 2911 of file chan_pjsip.c.

2912{
2913 struct sendtext_data *data = obj;
2914 pjsip_tx_data *tdata;
2915 const char *body_text = ast_msg_data_get_attribute(data->msg, AST_MSG_DATA_ATTR_BODY);
2916 const char *content_type = ast_msg_data_get_attribute(data->msg, AST_MSG_DATA_ATTR_CONTENT_TYPE);
2917 char *sep;
2918 struct ast_sip_body body = {
2919 .type = "text",
2920 .subtype = "plain",
2921 .body_text = body_text,
2922 };
2923
2924 if (!ast_strlen_zero(content_type)) {
2925 char *content_type_copy = ast_strdupa(content_type);
2926 sep = strchr(content_type_copy, '/');
2927 if (sep) {
2928 *sep = '\0';
2929 body.type = content_type_copy;
2930 body.subtype = ++sep;
2931 }
2932 }
2933
2934 if (data->session->inv_session->state == PJSIP_INV_STATE_DISCONNECTED) {
2935 ast_log(LOG_ERROR, "Session already DISCONNECTED [reason=%d (%s)]\n",
2936 data->session->inv_session->cause,
2937 pjsip_get_status_text(data->session->inv_session->cause)->ptr);
2938 } else {
2939 pjsip_from_hdr *hdr;
2940 pjsip_name_addr *name_addr;
2941 const char *from = ast_msg_data_get_attribute(data->msg, AST_MSG_DATA_ATTR_FROM);
2942 const char *to = ast_msg_data_get_attribute(data->msg, AST_MSG_DATA_ATTR_TO);
2943 int invalidate_tdata = 0;
2944
2945 ast_sip_create_request("MESSAGE", data->session->inv_session->dlg, data->session->endpoint, NULL, NULL, &tdata);
2946 ast_sip_add_body(tdata, &body);
2947
2948 /*
2949 * If we have a 'from' in the msg, set the display name in the From
2950 * header to it.
2951 */
2952 if (!ast_strlen_zero(from)) {
2953 hdr = PJSIP_MSG_FROM_HDR(tdata->msg);
2954 name_addr = (pjsip_name_addr *) hdr->uri;
2955 pj_strdup2(tdata->pool, &name_addr->display, from);
2956 invalidate_tdata = 1;
2957 }
2958
2959 /*
2960 * If we have a 'to' in the msg, set the display name in the To
2961 * header to it.
2962 */
2963 if (!ast_strlen_zero(to)) {
2964 hdr = PJSIP_MSG_TO_HDR(tdata->msg);
2965 name_addr = (pjsip_name_addr *) hdr->uri;
2966 pj_strdup2(tdata->pool, &name_addr->display, to);
2967 invalidate_tdata = 1;
2968 }
2969
2970 if (invalidate_tdata) {
2971 pjsip_tx_data_invalidate_msg(tdata);
2972 }
2973
2974 ast_sip_send_request(tdata, data->session->inv_session->dlg, data->session->endpoint, NULL, NULL);
2975 }
2976
2977 ao2_cleanup(data);
2978
2979 return 0;
2980}
@ 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:1977
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:2050
int ast_sip_create_request(const char *method, struct pjsip_dialog *dlg, struct ast_sip_endpoint *endpoint, const char *uri, struct ast_sip_contact *contact, pjsip_tx_data **tdata)
General purpose method for creating a SIP request.
Definition res_pjsip.c:1433
SIP body description.
Definition res_pjsip.h:2501
const char * type
Definition res_pjsip.h:2503
const char * body_text
Definition res_pjsip.h:2507
const char * subtype
Definition res_pjsip.h:2505
struct ast_sip_session * session

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

Referenced by chan_pjsip_sendtext_data().

◆ sendtext_data_create()

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

Definition at line 2890 of file chan_pjsip.c.

2892{
2893 struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(chan);
2894 struct sendtext_data *data = ao2_alloc(sizeof(*data), sendtext_data_destroy);
2895
2896 if (!data) {
2897 return NULL;
2898 }
2899
2900 data->msg = ast_msg_data_dup(msg);
2901 if (!data->msg) {
2902 ao2_cleanup(data);
2903 return NULL;
2904 }
2905 data->session = channel->session;
2906 ao2_ref(data->session, +1);
2907
2908 return data;
2909}
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 2883 of file chan_pjsip.c.

2884{
2885 struct sendtext_data *data = obj;
2886 ao2_cleanup(data->session);
2887 ast_free(data->msg);
2888}

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

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

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

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

◆ set_sipdomain_variable()

static void set_sipdomain_variable ( struct ast_sip_session session)
static

Definition at line 3185 of file chan_pjsip.c.

3186{
3187 const pj_str_t *host = ast_sip_pjsip_uri_get_hostname(session->request_uri);
3188 size_t size = pj_strlen(host) + 1;
3189 char *domain = ast_alloca(size);
3190
3191 ast_copy_pj_str(domain, host, size);
3192
3193 pbx_builtin_setvar_helper(session->channel, "SIPDOMAIN", domain);
3194 return;
3195}
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:3471

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

Referenced by chan_pjsip_incoming_request().

◆ set_transport_info_local_addr()

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

Determine the local signaling address used for an outgoing request.

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

Definition at line 283 of file chan_pjsip.c.

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

References ast_sip_get_pjsip_endpoint().

Referenced by transport_info_on_tx_request().

◆ topology_change_refresh_data_alloc()

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

Definition at line 1617 of file chan_pjsip.c.

1619{
1621
1622 refresh_data = ast_calloc(1, sizeof(*refresh_data));
1623 if (!refresh_data) {
1624 return NULL;
1625 }
1626
1629 if (!refresh_data->media_state) {
1631 return NULL;
1632 }
1633 refresh_data->media_state->topology = ast_stream_topology_clone(topology);
1634 if (!refresh_data->media_state->topology) {
1636 return NULL;
1637 }
1638
1639 return refresh_data;
1640}
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 1609 of file chan_pjsip.c.

1610{
1612
1615}
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 2238 of file chan_pjsip.c.

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

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

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

◆ transfer_data_alloc()

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

Definition at line 1999 of file chan_pjsip.c.

2000{
2001 struct transfer_data *trnf_data = ao2_alloc(sizeof(*trnf_data), transfer_data_destroy);
2002
2003 if (!trnf_data) {
2004 return NULL;
2005 }
2006
2007 if (!(trnf_data->target = ast_strdup(target))) {
2008 ao2_ref(trnf_data, -1);
2009 return NULL;
2010 }
2011
2012 ao2_ref(session, +1);
2013 trnf_data->session = session;
2014
2015 return trnf_data;
2016}
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 1991 of file chan_pjsip.c.

1992{
1993 struct transfer_data *trnf_data = obj;
1994
1995 ast_free(trnf_data->target);
1996 ao2_cleanup(trnf_data->session);
1997}

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

2019{
2020 pjsip_tx_data *packet;
2022 pjsip_contact_hdr *contact;
2023 pj_str_t tmp;
2024
2025 if (pjsip_inv_end_session(session->inv_session, 302, NULL, &packet) != PJ_SUCCESS
2026 || !packet) {
2027 ast_log(LOG_WARNING, "Failed to redirect PJSIP session for channel %s\n",
2028 ast_channel_name(session->channel));
2031
2032 return;
2033 }
2034
2035 if (!(contact = pjsip_msg_find_hdr(packet->msg, PJSIP_H_CONTACT, NULL))) {
2036 contact = pjsip_contact_hdr_create(packet->pool);
2037 }
2038
2039 pj_strdup2_with_null(packet->pool, &tmp, target);
2040 if (!(contact->uri = pjsip_parse_uri(packet->pool, tmp.ptr, tmp.slen, PJSIP_PARSE_URI_AS_NAMEADDR))) {
2041 ast_log(LOG_WARNING, "Failed to parse destination URI '%s' for channel %s\n",
2042 target, ast_channel_name(session->channel));
2045 pjsip_tx_data_dec_ref(packet);
2046
2047 return;
2048 }
2049 pjsip_msg_add_hdr(packet->msg, (pjsip_hdr *) contact);
2050
2053}
@ 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 2186 of file chan_pjsip.c.

2187{
2188 pjsip_evsub *sub;
2190 pj_str_t tmp;
2191 pjsip_tx_data *packet;
2192 const char *ref_by_val;
2193 char local_info[pj_strlen(&session->inv_session->dlg->local.info_str) + 1];
2194 struct pjsip_evsub_user xfer_cb;
2195 struct ast_channel *chan = session->channel;
2196
2197 pj_bzero(&xfer_cb, sizeof(xfer_cb));
2198 xfer_cb.on_evsub_state = &xfer_client_on_evsub_state;
2199
2200 if (pjsip_xfer_create_uac(session->inv_session->dlg, &xfer_cb, &sub) != PJ_SUCCESS) {
2203
2204 return;
2205 }
2206
2207 /* chan_pjsip_module requires a reference to chan
2208 * which will be released in xfer_client_on_evsub_state()
2209 * when the implicit REFER subscription terminates */
2210 pjsip_evsub_set_mod_data(sub, chan_pjsip_module.id, chan);
2211 ao2_ref(chan, +1);
2212
2213 if (pjsip_xfer_initiate(sub, pj_cstr(&tmp, target), &packet) != PJ_SUCCESS) {
2214 goto failure;
2215 }
2216
2217 ref_by_val = pbx_builtin_getvar_helper(chan, "SIPREFERREDBYHDR");
2218 if (!ast_strlen_zero(ref_by_val)) {
2219 ast_sip_add_header(packet, "Referred-By", ref_by_val);
2220 } else {
2221 ast_copy_pj_str(local_info, &session->inv_session->dlg->local.info_str, sizeof(local_info));
2222 ast_sip_add_header(packet, "Referred-By", local_info);
2223 }
2224
2225 if (pjsip_xfer_send_request(sub, packet) == PJ_SUCCESS) {
2226 return;
2227 }
2228
2229failure:
2232 pjsip_evsub_set_mod_data(sub, chan_pjsip_module.id, NULL);
2233 pjsip_evsub_terminate(sub, PJ_FALSE);
2234
2235 ao2_ref(chan, -1);
2236}
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:2006

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

Referenced by transfer().

◆ transmit_info_dtmf()

static int transmit_info_dtmf ( void *  data)
static

Definition at line 2360 of file chan_pjsip.c.

2361{
2362 RAII_VAR(struct info_dtmf_data *, dtmf_data, data, ao2_cleanup);
2363
2364 struct ast_sip_session *session = dtmf_data->session;
2365 struct pjsip_tx_data *tdata;
2366
2367 RAII_VAR(struct ast_str *, body_text, NULL, ast_free_ptr);
2368
2369 struct ast_sip_body body = {
2370 .type = "application",
2371 .subtype = "dtmf-relay",
2372 };
2373
2374 if (session->inv_session->state == PJSIP_INV_STATE_DISCONNECTED) {
2375 ast_log(LOG_ERROR, "Session already DISCONNECTED [reason=%d (%s)]\n",
2376 session->inv_session->cause,
2377 pjsip_get_status_text(session->inv_session->cause)->ptr);
2378 return -1;
2379 }
2380
2381 if (!(body_text = ast_str_create(32))) {
2382 ast_log(LOG_ERROR, "Could not allocate buffer for INFO DTMF.\n");
2383 return -1;
2384 }
2385 ast_str_set(&body_text, 0, "Signal=%c\r\nDuration=%u\r\n", dtmf_data->digit, dtmf_data->duration);
2386
2388
2389 if (ast_sip_create_request("INFO", session->inv_session->dlg, session->endpoint, NULL, NULL, &tdata)) {
2390 ast_log(LOG_ERROR, "Could not create DTMF INFO request\n");
2391 return -1;
2392 }
2393 if (ast_sip_add_body(tdata, &body)) {
2394 ast_log(LOG_ERROR, "Could not add body to DTMF INFO request\n");
2395 pjsip_tx_data_dec_ref(tdata);
2396 return -1;
2397 }
2399
2400 return 0;
2401}
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 1449 of file chan_pjsip.c.

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

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.

◆ transport_info_on_tx_request()

static pj_status_t transport_info_on_tx_request ( pjsip_tx_data *  tdata)
static

Store transport information for outgoing PJSIP session requests.

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

Definition at line 319 of file chan_pjsip.c.

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

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

◆ uid_hold_hash_fn()

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

AO2 hash function for on hold UIDs

Definition at line 1167 of file chan_pjsip.c.

1168{
1169 const char *key = obj;
1170
1171 switch (flags & OBJ_SEARCH_MASK) {
1172 case OBJ_SEARCH_KEY:
1173 break;
1174 case OBJ_SEARCH_OBJECT:
1175 break;
1176 default:
1177 /* Hash can only work on something with a full key. */
1178 ast_assert(0);
1179 return 0;
1180 }
1181 return ast_str_hash(key);
1182}
@ 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 1185 of file chan_pjsip.c.

1186{
1187 const char *left = obj_left;
1188 const char *right = obj_right;
1189 int cmp;
1190
1191 switch (flags & OBJ_SEARCH_MASK) {
1192 case OBJ_SEARCH_OBJECT:
1193 case OBJ_SEARCH_KEY:
1194 cmp = strcmp(left, right);
1195 break;
1197 cmp = strncmp(left, right, strlen(right));
1198 break;
1199 default:
1200 /* Sort can only work on something with a full or partial key. */
1201 ast_assert(0);
1202 cmp = 0;
1203 break;
1204 }
1205 return cmp;
1206}
@ 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 3652 of file chan_pjsip.c.

3653{
3656
3658
3665
3667
3678
3682
3683 return 0;
3684}
void pjsip_channel_cli_unregister(void)
Unregisters the channel cli commands.

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

◆ update_connected_line_information()

static int update_connected_line_information ( void *  data)
static

Update connected line information.

Definition at line 1527 of file chan_pjsip.c.

1528{
1529 struct ast_sip_session *session = data;
1530
1531 if (session->inv_session->state == PJSIP_INV_STATE_DISCONNECTED) {
1532 ast_log(LOG_ERROR, "Session already DISCONNECTED [reason=%d (%s)]\n",
1533 session->inv_session->cause,
1534 pjsip_get_status_text(session->inv_session->cause)->ptr);
1535 ao2_ref(session, -1);
1536 return -1;
1537 }
1538
1539 if (ast_channel_state(session->channel) == AST_STATE_UP
1540 || session->inv_session->role == PJSIP_ROLE_UAC) {
1543 int generate_new_sdp;
1544
1545 method = session->endpoint->id.refresh_method;
1546 if (session->inv_session->options & PJSIP_INV_SUPPORT_UPDATE) {
1548 }
1549
1550 /* Only the INVITE method actually needs SDP, UPDATE can do without */
1551 generate_new_sdp = (method == AST_SIP_SESSION_REFRESH_METHOD_INVITE);
1552
1553 ast_sip_session_refresh(session, NULL, NULL, NULL, method, generate_new_sdp, NULL);
1554 }
1555 } else if (session->endpoint->id.rpid_immediate
1556 && session->inv_session->state != PJSIP_INV_STATE_DISCONNECTED
1558 int response_code = 0;
1559
1560 if (ast_channel_state(session->channel) == AST_STATE_RING) {
1561 response_code = !session->endpoint->inband_progress ? 180 : 183;
1562 } else if (ast_channel_state(session->channel) == AST_STATE_RINGING) {
1563 response_code = 183;
1564 }
1565
1566 if (response_code) {
1567 struct pjsip_tx_data *packet = NULL;
1568
1569 if (pjsip_inv_answer(session->inv_session, response_code, NULL, NULL, &packet) == PJ_SUCCESS) {
1571 }
1572 }
1573 }
1574
1575 ao2_ref(session, -1);
1576 return 0;
1577}
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 2475 of file chan_pjsip.c.

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

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

Referenced by call().

◆ xfer_client_on_evsub_state()

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

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

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

Definition at line 2069 of file chan_pjsip.c.

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

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

Referenced by transfer_refer().

Variable Documentation

◆ __mod_info

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

Definition at line 3692 of file chan_pjsip.c.

◆ app_pjsip_hangup

char* app_pjsip_hangup = "PJSIPHangup"
static

Definition at line 3517 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 3692 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:3398

Definition at line 3300 of file chan_pjsip.c.

3300 {
3301 .method = "INVITE",
3302 .priority = AST_SIP_SUPPLEMENT_PRIORITY_LAST - 1,
3303 .incoming_request = call_pickup_incoming_request,
3304};

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

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

3474 {
3475 .name = "PJSIP_DIAL_CONTACTS",
3477};

Referenced by load_module(), and unload_module().

◆ chan_pjsip_module

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

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

Definition at line 2056 of file chan_pjsip.c.

2056 {
2057 .name = { "chan_pjsip", 10 },
2058 .id = -1,
2059 .on_tx_request = transport_info_on_tx_request,
2060};

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

◆ chan_pjsip_parse_uri_from_function

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

Definition at line 3484 of file chan_pjsip.c.

3484 {
3485 .name = "PJSIP_PARSE_URI_FROM",
3487};

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

3479 {
3480 .name = "PJSIP_PARSE_URI",
3482};

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

582 {
583 .type = "PJSIP",
584 .get_rtp_info = chan_pjsip_get_rtp_peer,
585 .get_vrtp_info = chan_pjsip_get_vrtp_peer,
586 .get_codec = chan_pjsip_get_codec,
587 .update_peer = chan_pjsip_set_rtp_peer,
588};
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:544
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:827
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:939
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 370 of file chan_pjsip.c.

370{ };

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

3495 {
3496 .name = "PJSIP_DTMF_MODE",
3499};

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

3489 {
3490 .name = "PJSIP_MEDIA_OFFER",
3493};

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

3501 {
3502 .name = "PJSIP_MOH_PASSTHROUGH",
3505};

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

3340 {
3341 .method = "INVITE",
3343 .incoming_request = pbx_start_incoming_request,
3344};

Referenced by load_module(), and unload_module().

◆ pjsip_uids_onhold

struct ao2_container* pjsip_uids_onhold
static

◆ session_refresh_function

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

Definition at line 3507 of file chan_pjsip.c.

3507 {
3508 .name = "PJSIP_SEND_SESSION_REFRESH",
3510};

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

3512 {
3513 .name = "PJSIP_TRANSFER_HANDLING",
3515};

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