Asterisk - The Open Source Telephony Project  18.5.0
Data Structures | Macros | Typedefs | Functions | Variables
res_pjsip.c File Reference
#include "asterisk.h"
#include <pjsip.h>
#include <pjsip_simple.h>
#include <pjsip/sip_transaction.h>
#include <pj/timer.h>
#include <pjlib.h>
#include <pjmedia/errno.h>
#include "asterisk/res_pjsip.h"
#include "res_pjsip/include/res_pjsip_private.h"
#include "asterisk/linkedlists.h"
#include "asterisk/logger.h"
#include "asterisk/lock.h"
#include "asterisk/utils.h"
#include "asterisk/astobj2.h"
#include "asterisk/module.h"
#include "asterisk/serializer.h"
#include "asterisk/threadpool.h"
#include "asterisk/taskprocessor.h"
#include "asterisk/uuid.h"
#include "asterisk/sorcery.h"
#include "asterisk/file.h"
#include "asterisk/cli.h"
#include "asterisk/res_pjsip_cli.h"
#include "asterisk/test.h"
#include "asterisk/res_pjsip_presence_xml.h"
#include "asterisk/res_pjproject.h"
Include dependency graph for res_pjsip.c:

Go to the source code of this file.

Data Structures

struct  endpoint_formatters
 
struct  endpoint_identifier_list
 
struct  endpoint_identifiers
 
struct  send_request_data
 Structure to hold information about an outbound request. More...
 
struct  send_request_wrapper
 
struct  supplements
 
struct  sync_task_data
 

Macros

#define ENDPOINT_IDENTIFIER_FORMAT   "%-20.20s\n"
 
#define MOD_DATA_CONTACT   "contact"
 
#define SERIALIZER_POOL_SIZE   8
 
#define SIP_SERVANT_ID   0x5E2F1D
 
#define TIMEOUT_TIMER2   5
 
#define TIMER_INACTIVE   0
 

Typedefs

typedef pj_status_t(* create_dlg_uac) (pjsip_user_agent *ua, pjsip_rx_data *rdata, const pj_str_t *contact, pjsip_dialog **p_dlg)
 

Functions

static void __init_pj_thread_storage (void)
 
static void __init_servant_id_storage (void)
 
static void __reg_module (void)
 
static void __unreg_module (void)
 
static pjsip_msg_body * ast_body_to_pjsip_body (pj_pool_t *pool, const struct ast_sip_body *body)
 
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. More...
 
int ast_copy_pj_str2 (char **dest, const pj_str_t *src)
 Create and copy a pj_str_t into a standard character buffer. More...
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
int ast_sip_add_body (pjsip_tx_data *tdata, const struct ast_sip_body *body)
 Add a body to an outbound SIP message. More...
 
int ast_sip_add_body_multipart (pjsip_tx_data *tdata, const struct ast_sip_body *bodies[], int num_bodies)
 Add a multipart body to an outbound SIP message. More...
 
void ast_sip_add_date_header (pjsip_tx_data *tdata)
 Adds a Date header to the tdata, formatted like: Date: Wed, 01 Jan 2021 14:53:01 GMT. More...
 
int ast_sip_add_header (pjsip_tx_data *tdata, const char *name, const char *value)
 Add a header to an outbound SIP message. More...
 
void ast_sip_add_usereqphone (const struct ast_sip_endpoint *endpoint, pj_pool_t *pool, pjsip_uri *uri)
 Add 'user=phone' parameter to URI if enabled and user is a phone number. More...
 
int ast_sip_append_body (pjsip_tx_data *tdata, const char *body_text)
 Append body data to a SIP message. More...
 
const char * ast_sip_call_codec_pref_to_str (struct ast_flags pref)
 Convert the call codec preference flags to a string. More...
 
int ast_sip_call_codec_str_to_pref (struct ast_flags *pref, const char *pref_str, int is_outgoing)
 Convert a call codec preference string to preference flags. More...
 
enum ast_sip_check_auth_result ast_sip_check_authentication (struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, pjsip_tx_data *tdata)
 Method to determine authentication status of an incoming request. More...
 
pjsip_dialog * ast_sip_create_dialog_uac (const struct ast_sip_endpoint *endpoint, const char *uri, const char *request_user)
 General purpose method for creating a UAC dialog with an endpoint. More...
 
pjsip_dialog * ast_sip_create_dialog_uas (const struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, pj_status_t *status)
 General purpose method for creating a UAS dialog with an endpoint. More...
 
pjsip_dialog * ast_sip_create_dialog_uas_locked (const struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, pj_status_t *status)
 General purpose method for creating a UAS dialog with an endpoint. More...
 
int ast_sip_create_rdata (pjsip_rx_data *rdata, char *packet, const char *src_name, int src_port, char *transport_type, const char *local_name, int local_port)
 General purpose method for creating an rdata structure using specific information. More...
 
int ast_sip_create_rdata_with_contact (pjsip_rx_data *rdata, char *packet, const char *src_name, int src_port, char *transport_type, const char *local_name, int local_port, const char *contact)
 General purpose method for creating an rdata structure using specific information. More...
 
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. More...
 
int ast_sip_create_request_with_auth (const struct ast_sip_auth_vector *auths, pjsip_rx_data *challenge, pjsip_tx_data *old_request, pjsip_tx_data **new_request)
 Create a response to an authentication challenge. More...
 
int ast_sip_create_response (const pjsip_rx_data *rdata, int st_code, struct ast_sip_contact *contact, pjsip_tx_data **tdata)
 General purpose method for creating a SIP response. More...
 
struct ast_taskprocessorast_sip_create_serializer (const char *name)
 Create a new serializer for SIP tasks. More...
 
struct ast_taskprocessorast_sip_create_serializer_group (const char *name, struct ast_serializer_shutdown_group *shutdown_group)
 Create a new serializer for SIP tasks. More...
 
void * ast_sip_dict_get (void *ht, const char *key)
 Retrieves the value associated with the given key. More...
 
void * ast_sip_dict_set (pj_pool_t *pool, void *ht, const char *key, void *val)
 Set the value for the given key. More...
 
int ast_sip_dlg_set_transport (const struct ast_sip_endpoint *endpoint, pjsip_dialog *dlg, pjsip_tpselector *selector)
 Set the transport on a dialog. More...
 
int ast_sip_dtmf_to_str (const enum ast_sip_dtmf_mode dtmf, char *buf, size_t buf_len)
 Convert the DTMF mode enum value into a string. More...
 
int ast_sip_failover_request (pjsip_tx_data *tdata)
 Set a request to use the next value in the list of resolved addresses. More...
 
int ast_sip_format_endpoint_ami (struct ast_sip_endpoint *endpoint, struct ast_sip_ami *ami, int *count)
 Formats the endpoint and sends over AMI. More...
 
int ast_sip_get_host_ip (int af, pj_sockaddr *addr)
 Retrieve the local host address in IP form. More...
 
const char * ast_sip_get_host_ip_string (int af)
 Retrieve the local host address in string form. More...
 
pjsip_endpoint * ast_sip_get_pjsip_endpoint (void)
 Get a pointer to the PJSIP endpoint. More...
 
int ast_sip_get_transport_name (const struct ast_sip_endpoint *endpoint, pjsip_sip_uri *sip_uri, char *buf, size_t buf_len)
 Get the transport name from an endpoint or request uri. More...
 
struct ast_sip_endpointast_sip_identify_endpoint (pjsip_rx_data *rdata)
 Determine the endpoint that has sent a SIP message. More...
 
int ast_sip_is_content_type (pjsip_media_type *content_type, char *type, char *subtype)
 Checks if the given content type matches type/subtype. More...
 
void ast_sip_modify_id_header (pj_pool_t *pool, pjsip_fromto_hdr *id_hdr, const struct ast_party_id *id)
 Set name and number information on an identity header. More...
 
int ast_sip_push_task (struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
 Pushes a task to SIP servants. More...
 
int ast_sip_push_task_synchronous (struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
 Push a task to SIP servants and wait for it to complete. More...
 
static int ast_sip_push_task_wait (struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
 
int ast_sip_push_task_wait_serializer (struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
 Push a task to the serializer and wait for it to complete. More...
 
int ast_sip_push_task_wait_servant (struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
 Push a task to SIP servants and wait for it to complete. More...
 
char * ast_sip_rdata_get_header_value (pjsip_rx_data *rdata, const pj_str_t str)
 Get a specific header value from rdata. More...
 
int ast_sip_register_authenticator (struct ast_sip_authenticator *auth)
 Register a SIP authenticator. More...
 
void ast_sip_register_endpoint_formatter (struct ast_sip_endpoint_formatter *obj)
 Register an endpoint formatter. More...
 
int ast_sip_register_endpoint_identifier (struct ast_sip_endpoint_identifier *identifier)
 Register a SIP endpoint identifier. More...
 
int ast_sip_register_endpoint_identifier_with_name (struct ast_sip_endpoint_identifier *identifier, const char *name)
 Register a SIP endpoint identifier with a name. More...
 
int ast_sip_register_outbound_authenticator (struct ast_sip_outbound_authenticator *auth)
 Register an outbound SIP authenticator. More...
 
int ast_sip_register_service (pjsip_module *module)
 Register a SIP service in Asterisk. More...
 
void ast_sip_register_supplement (struct ast_sip_supplement *supplement)
 Register a supplement to SIP out of dialog processing. More...
 
int ast_sip_requires_authentication (struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata)
 Determine if an incoming request requires authentication. More...
 
int ast_sip_send_out_of_dialog_request (pjsip_tx_data *tdata, struct ast_sip_endpoint *endpoint, int timeout, void *token, void(*callback)(void *token, pjsip_event *e))
 General purpose method for sending an Out-Of-Dialog SIP request. More...
 
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. More...
 
int ast_sip_send_response (pjsip_response_addr *res_addr, pjsip_tx_data *tdata, struct ast_sip_endpoint *sip_endpoint)
 Send a response to an out of dialog request. More...
 
int ast_sip_send_stateful_response (pjsip_rx_data *rdata, pjsip_tx_data *tdata, struct ast_sip_endpoint *sip_endpoint)
 Send a stateful response to an out of dialog request. More...
 
int ast_sip_set_outbound_proxy (pjsip_tx_data *tdata, const char *proxy)
 Set the outbound proxy for an outbound SIP message. More...
 
int ast_sip_set_tpselector_from_ep_or_uri (const struct ast_sip_endpoint *endpoint, pjsip_sip_uri *sip_uri, pjsip_tpselector *selector)
 Sets pjsip_tpselector from an endpoint or uri. More...
 
int ast_sip_set_tpselector_from_transport (const struct ast_sip_transport *transport, pjsip_tpselector *selector)
 Sets pjsip_tpselector from ast_sip_transport. More...
 
int ast_sip_set_tpselector_from_transport_name (const char *transport_name, pjsip_tpselector *selector)
 Sets pjsip_tpselector from ast_sip_transport. More...
 
int ast_sip_str_to_dtmf (const char *dtmf_mode)
 Convert the DTMF mode name into an enum. More...
 
int ast_sip_thread_is_servant (void)
 Determine if the current thread is a SIP servant thread. More...
 
struct ast_threadpoolast_sip_threadpool (void)
 Retrieve the SIP threadpool object. More...
 
long ast_sip_threadpool_queue_size (void)
 Return the size of the SIP threadpool's task queue. More...
 
void ast_sip_tpselector_unref (pjsip_tpselector *selector)
 Unreference a pjsip_tpselector. More...
 
void ast_sip_unregister_authenticator (struct ast_sip_authenticator *auth)
 Unregister a SIP authenticator. More...
 
void ast_sip_unregister_endpoint_formatter (struct ast_sip_endpoint_formatter *obj)
 Unregister an endpoint formatter. More...
 
void ast_sip_unregister_endpoint_identifier (struct ast_sip_endpoint_identifier *identifier)
 Unregister a SIP endpoint identifier. More...
 
void ast_sip_unregister_outbound_authenticator (struct ast_sip_outbound_authenticator *auth)
 Unregister an outbound SIP authenticator. More...
 
void ast_sip_unregister_service (pjsip_module *module)
 
void ast_sip_unregister_supplement (struct ast_sip_supplement *supplement)
 Unregister a an supplement to SIP out of dialog processing. More...
 
int ast_sip_will_uri_survive_restart (pjsip_sip_uri *uri, struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata)
 
 AST_TEST_DEFINE (xml_sanitization_end_null)
 
 AST_TEST_DEFINE (xml_sanitization_exceeds_buffer)
 
static int check_request_status (struct send_request_data *req_data, pjsip_event *e)
 
static char * cli_dump_endpt (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * cli_show_endpoint_identifiers (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * cli_show_settings (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static pjsip_dialog * create_dialog_uas (const struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, pj_status_t *status, create_dlg_uac create_fun)
 
static int create_in_dialog_request (const pjsip_method *method, struct pjsip_dialog *dlg, pjsip_tx_data **tdata)
 
static int create_out_of_dialog_request (const pjsip_method *method, struct ast_sip_endpoint *endpoint, const char *uri, struct ast_sip_contact *provided_contact, pjsip_tx_data **tdata)
 
static int do_cli_dump_endpt (void *v_a)
 
static pj_bool_t does_method_match (const pj_str_t *message_method, const char *supplement_method)
 
static pj_status_t endpt_send_request (struct ast_sip_endpoint *endpoint, pjsip_tx_data *tdata, pj_int32_t timeout, void *token, pjsip_endpt_send_callback cb)
 
static void endpt_send_request_cb (void *token, pjsip_event *e)
 
static const pjsip_method * get_pjsip_method (const char *method)
 
static int load_module (void)
 
static int load_pjsip (void)
 
static void * monitor_thread_exec (void *endpt)
 
void never_called_res_pjsip (void)
 
static int register_service (void *data)
 
static int reload_configuration_task (void *obj)
 
static int reload_module (void)
 
static void remove_request_headers (pjsip_endpoint *endpt)
 
static int send_in_dialog_request (pjsip_tx_data *tdata, struct pjsip_dialog *dlg)
 
static void send_request_cb (void *token, pjsip_event *e)
 
static struct send_request_datasend_request_data_alloc (struct ast_sip_endpoint *endpoint, void *token, void(*callback)(void *token, pjsip_event *e))
 
static void send_request_data_destroy (void *obj)
 
static void send_request_timer_callback (pj_timer_heap_t *theap, pj_timer_entry *entry)
 
static void send_request_wrapper_destructor (void *obj)
 
static int sip_dialog_create_from (pj_pool_t *pool, pj_str_t *from, const char *user, const char *domain, const pj_str_t *target, pjsip_tpselector *selector)
 
static void sip_thread_start (void)
 
static void stop_monitor_thread (void)
 
static pj_bool_t supplement_on_rx_request (pjsip_rx_data *rdata)
 
static void supplement_outgoing_response (pjsip_tx_data *tdata, struct ast_sip_endpoint *sip_endpoint)
 
static int sync_task (void *data)
 
static int uas_use_sips_contact (pjsip_rx_data *rdata)
 Determine if a SIPS Contact header is required. More...
 
static int unload_module (void)
 
static int unload_pjsip (void *data)
 
static int unregister_service (void *data)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "Basic SIP resource" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "30ef0c93b36035ec78c9cfd712d36d9b" , .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload_module, .load_pri = AST_MODPRI_CHANNEL_DEPEND - 5, .requires = "dnsmgr,res_pjproject,res_sorcery_config,res_sorcery_memory,res_sorcery_astdb", .optional_modules = "res_statsd", }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static pjsip_endpoint * ast_pjsip_endpoint
 
pj_caching_pool caching_pool
 
static struct ast_cli_entry cli_commands []
 
struct endpoint_formatters endpoint_formatters = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
 
static struct endpoint_identifiers endpoint_identifiers = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
 
static pj_sockaddr host_ip_ipv4
 
static char host_ip_ipv4_string [PJ_INET6_ADDRSTRLEN]
 
static pj_sockaddr host_ip_ipv6
 
static char host_ip_ipv6_string [PJ_INET6_ADDRSTRLEN]
 
static const pjsip_method info_method = {PJSIP_OTHER_METHOD, {"INFO", 4} }
 
pj_pool_t * memory_pool
 
static const pjsip_method message_method = {PJSIP_OTHER_METHOD, {"MESSAGE", 7} }
 
struct {
   const char *   method
 
   const pjsip_method *   pmethod
 
methods []
 
static int monitor_continue
 
pj_thread_t * monitor_thread
 
static struct ast_threadstorage pj_thread_storage = { .once = PTHREAD_ONCE_INIT , .key_init = __init_pj_thread_storage , .custom_init = NULL , }
 
static struct ast_sip_authenticatorregistered_authenticator
 
static struct ast_sip_outbound_authenticatorregistered_outbound_authenticator
 
static struct ast_threadstorage servant_id_storage = { .once = PTHREAD_ONCE_INIT , .key_init = __init_servant_id_storage , .custom_init = NULL , }
 
static struct ast_serializer_poolsip_serializer_pool
 
static struct ast_threadpoolsip_threadpool
 
static pjsip_module supplement_module
 
struct supplements supplements = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
 

Macro Definition Documentation

◆ ENDPOINT_IDENTIFIER_FORMAT

#define ENDPOINT_IDENTIFIER_FORMAT   "%-20.20s\n"

◆ MOD_DATA_CONTACT

#define MOD_DATA_CONTACT   "contact"

◆ SERIALIZER_POOL_SIZE

#define SERIALIZER_POOL_SIZE   8

Number of serializers in pool if one not supplied.

Definition at line 3267 of file res_pjsip.c.

Referenced by load_module().

◆ SIP_SERVANT_ID

#define SIP_SERVANT_ID   0x5E2F1D

Definition at line 5294 of file res_pjsip.c.

Referenced by ast_sip_thread_is_servant(), and sip_thread_start().

◆ TIMEOUT_TIMER2

#define TIMEOUT_TIMER2   5

◆ TIMER_INACTIVE

#define TIMER_INACTIVE   0

Typedef Documentation

◆ create_dlg_uac

typedef pj_status_t(* create_dlg_uac) (pjsip_user_agent *ua, pjsip_rx_data *rdata, const pj_str_t *contact, pjsip_dialog **p_dlg)

Definition at line 4174 of file res_pjsip.c.

Function Documentation

◆ __init_pj_thread_storage()

static void __init_pj_thread_storage ( void  )
static

Definition at line 5292 of file res_pjsip.c.

5297 {

◆ __init_servant_id_storage()

static void __init_servant_id_storage ( void  )
static

Definition at line 5293 of file res_pjsip.c.

5297 {

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 5962 of file res_pjsip.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 5962 of file res_pjsip.c.

◆ ast_body_to_pjsip_body()

static pjsip_msg_body* ast_body_to_pjsip_body ( pj_pool_t *  pool,
const struct ast_sip_body body 
)
static

Definition at line 5078 of file res_pjsip.c.

References ast_sip_body::body_text, ast_sip_body::subtype, type, and ast_sip_body::type.

Referenced by ast_sip_add_body(), and ast_sip_add_body_multipart().

5079 {
5080  pj_str_t type;
5081  pj_str_t subtype;
5082  pj_str_t body_text;
5083 
5084  pj_cstr(&type, body->type);
5085  pj_cstr(&subtype, body->subtype);
5086  pj_cstr(&body_text, body->body_text);
5087 
5088  return pjsip_msg_body_create(pool, &type, &subtype, &body_text);
5089 }
static const char type[]
Definition: chan_ooh323.c:109
const char * body_text
Definition: res_pjsip.h:2033
static pj_pool_t * pool
Global memory pool for configuration and timers.
const char * type
Definition: res_pjsip.h:2029
const char * subtype
Definition: res_pjsip.h:2031

◆ ast_copy_pj_str()

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.

pj_str_t is not NULL-terminated. Any place that expects a NULL- terminated string needs to have the pj_str_t copied into a separate buffer.

This method copies the pj_str_t contents into the destination buffer and NULL-terminates the buffer.

Parameters
destThe destination buffer
srcThe pj_str_t to copy
sizeThe size of the destination buffer.

Definition at line 5240 of file res_pjsip.c.

References MIN.

Referenced by add_identity_header(), apply_dtls_attrib(), apply_negotiated_sdp_stream(), assign_uuid(), ast_sip_get_transport_name(), ast_sip_report_auth_challenge_sent(), ast_sip_report_auth_failed_challenge_response(), chan_pjsip_get_uniqueid(), change_outgoing_sdp_stream_media_address(), channel_read_pjsip(), cli_complete_subscription_common(), cli_list_subscriptions_detail(), cli_show_subscriptions_detail(), determine_sip_publish_type(), dialog_info_generate_body_content(), endpoint_lookup(), evaluate_like(), extract_contact_addr(), find_aor(), find_aor_name(), find_challenge(), get_auth_header(), get_codecs(), get_destination(), get_endpoint_details(), get_from_header(), get_mid_bundle_group(), get_user_agent(), handle_incoming_sdp(), handle_negotiated_sdp_session_media(), handle_registration_response(), headers_to_vars(), incoming_in_dialog_request(), log_failed_request(), negotiate_incoming_sdp_stream(), options_on_rx_request(), parse_uri_cb(), process_extmap_attributes(), process_ice_attributes(), process_ice_auth_attrb(), process_ssrc_attributes(), publish_request_initial(), pubsub_on_rx_publish_request(), pubsub_on_rx_subscribe_request(), refer_blind_callback(), refer_incoming_blind_request(), refer_incoming_refer_request(), register_aor_core(), rfc3326_use_reason_header(), rx_data_to_ast_msg(), save_response_fields_to_transport(), sdp_requires_deferral(), security_event_populate(), session_inv_on_redirected(), session_outgoing_nat_hook(), set_id_from_hdr(), set_id_from_oli(), set_mid_and_bundle_group(), set_redirecting_value(), set_remote_mslabel_and_stream_group(), set_sipdomain_variable(), sip_resolve(), sip_subscription_to_ami(), sub_persistence_recreate(), subscription_get_generator_from_rdata(), subscription_get_handler_from_rdata(), subscription_persistence_create(), subscription_persistence_update(), and transfer_refer().

5241 {
5242  size_t chars_to_copy = MIN(size - 1, pj_strlen(src));
5243  memcpy(dest, pj_strbuf(src), chars_to_copy);
5244  dest[chars_to_copy] = '\0';
5245 }
#define MIN(a, b)
Definition: utils.h:226

◆ ast_copy_pj_str2()

int ast_copy_pj_str2 ( char **  dest,
const pj_str_t *  src 
)

Create and copy a pj_str_t into a standard character buffer.

pj_str_t is not NULL-terminated. Any place that expects a NULL- terminated string needs to have the pj_str_t copied into a separate buffer.

Copies the pj_str_t contents into a newly allocated buffer pointed to by dest. NULL-terminates the buffer.

Note
Caller is responsible for freeing the allocated memory.
Parameters
dest[out] The destination buffer
srcThe pj_str_t to copy
Return values
Numberof characters copied or negative value on error

Definition at line 5247 of file res_pjsip.c.

References ast_asprintf, and NULL.

5248 {
5249  int res = ast_asprintf(dest, "%.*s", (int)pj_strlen(src), pj_strbuf(src));
5250 
5251  if (res < 0) {
5252  *dest = NULL;
5253  }
5254 
5255  return res;
5256 }
#define NULL
Definition: resample.c:96
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition: astmm.h:269

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 5962 of file res_pjsip.c.

◆ ast_sip_add_body()

int ast_sip_add_body ( pjsip_tx_data *  tdata,
const struct ast_sip_body body 
)

Add a body to an outbound SIP message.

If this is called multiple times, the latest body will replace the current body.

Parameters
tdataThe message to add the body to
bodyThe message body to add
Return values
0Success
-1Failure

Definition at line 5091 of file res_pjsip.c.

References ast_body_to_pjsip_body().

Referenced by build_notify_body(), msg_send(), send_unsolicited_mwi_notify_to_contact(), sendtext(), sip_publisher_service_queue(), transmit_info_dtmf(), and transmit_info_with_vidupdate().

5092 {
5093  pjsip_msg_body *pjsip_body = ast_body_to_pjsip_body(tdata->pool, body);
5094  tdata->msg->body = pjsip_body;
5095  return 0;
5096 }
static pjsip_msg_body * ast_body_to_pjsip_body(pj_pool_t *pool, const struct ast_sip_body *body)
Definition: res_pjsip.c:5078

◆ ast_sip_add_body_multipart()

int ast_sip_add_body_multipart ( pjsip_tx_data *  tdata,
const struct ast_sip_body bodies[],
int  num_bodies 
)

Add a multipart body to an outbound SIP message.

This will treat each part of the input vector as part of a multipart body and add each part to the SIP message.

Parameters
tdataThe message to add the body to
bodiesThe parts of the body to add
Return values
0Success
-1Failure

Definition at line 5098 of file res_pjsip.c.

References ast_body_to_pjsip_body(), and NULL.

5099 {
5100  int i;
5101  /* NULL for type and subtype automatically creates "multipart/mixed" */
5102  pjsip_msg_body *body = pjsip_multipart_create(tdata->pool, NULL, NULL);
5103 
5104  for (i = 0; i < num_bodies; ++i) {
5105  pjsip_multipart_part *part = pjsip_multipart_create_part(tdata->pool);
5106  part->body = ast_body_to_pjsip_body(tdata->pool, bodies[i]);
5107  pjsip_multipart_add_part(tdata->pool, body, part);
5108  }
5109 
5110  tdata->msg->body = body;
5111  return 0;
5112 }
#define NULL
Definition: resample.c:96
static pjsip_msg_body * ast_body_to_pjsip_body(pj_pool_t *pool, const struct ast_sip_body *body)
Definition: res_pjsip.c:5078

◆ ast_sip_add_date_header()

void ast_sip_add_date_header ( pjsip_tx_data *  tdata)

Adds a Date header to the tdata, formatted like: Date: Wed, 01 Jan 2021 14:53:01 GMT.

Since
16.19.0
Note
There is no checking done to see if the header already exists before adding it. It's up to the caller of this function to determine if that needs to be done or not.

Definition at line 3288 of file res_pjsip.c.

References ast_sip_add_header(), and NULL.

Referenced by add_date_header(), and register_aor_core().

3289 {
3290  char date[256];
3291  struct tm tm;
3292  time_t t = time(NULL);
3293 
3294  gmtime_r(&t, &tm);
3295  strftime(date, sizeof(date), "%a, %d %b %Y %T GMT", &tm);
3296 
3297  ast_sip_add_header(tdata, "Date", date);
3298 }
#define NULL
Definition: resample.c:96
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:5063

◆ ast_sip_add_header()

int ast_sip_add_header ( pjsip_tx_data *  tdata,
const char *  name,
const char *  value 
)

Add a header to an outbound SIP message.

Parameters
tdataThe message to add the header to
nameThe header name
valueThe header value
Return values
0Success
-1Failure

Definition at line 5063 of file res_pjsip.c.

Referenced by add_header_from_channel_var(), add_headers_to_message(), ast_sip_add_date_header(), ast_sip_message_apply_transport(), build_notify(), notify_channel(), notify_contact(), notify_uri(), options_incoming_request(), rfc3326_add_reason_header(), send_options_response(), sip_publication_respond(), transfer_refer(), and vars_to_headers().

5064 {
5065  pj_str_t hdr_name;
5066  pj_str_t hdr_value;
5067  pjsip_generic_string_hdr *hdr;
5068 
5069  pj_cstr(&hdr_name, name);
5070  pj_cstr(&hdr_value, value);
5071 
5072  hdr = pjsip_generic_string_hdr_create(tdata->pool, &hdr_name, &hdr_value);
5073 
5074  pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *) hdr);
5075  return 0;
5076 }
int value
Definition: syslog.c:37
static const char name[]
Definition: cdr_mysql.c:74

◆ ast_sip_add_usereqphone()

void ast_sip_add_usereqphone ( const struct ast_sip_endpoint endpoint,
pj_pool_t *  pool,
pjsip_uri *  uri 
)

Add 'user=phone' parameter to URI if enabled and user is a phone number.

Parameters
endpointThe endpoint to use for configuration
poolThe memory pool to allocate the parameter from
uriThe URI to check for user and to add parameter to

Definition at line 3994 of file res_pjsip.c.

References AST_DIGIT_ANY, and ast_sip_endpoint::usereqphone.

Referenced by ast_sip_create_dialog_uac(), create_out_of_dialog_request(), and set_from_header().

3995 {
3996  pjsip_sip_uri *sip_uri;
3997  int i = 0;
3998  static const pj_str_t STR_PHONE = { "phone", 5 };
3999 
4000  if (!endpoint || !endpoint->usereqphone || (!PJSIP_URI_SCHEME_IS_SIP(uri) && !PJSIP_URI_SCHEME_IS_SIPS(uri))) {
4001  return;
4002  }
4003 
4004  sip_uri = pjsip_uri_get_uri(uri);
4005 
4006  if (!pj_strlen(&sip_uri->user)) {
4007  return;
4008  }
4009 
4010  if (pj_strbuf(&sip_uri->user)[0] == '+') {
4011  i = 1;
4012  }
4013 
4014  /* Test URI user against allowed characters in AST_DIGIT_ANY */
4015  for (; i < pj_strlen(&sip_uri->user); i++) {
4016  if (!strchr(AST_DIGIT_ANY, pj_strbuf(&sip_uri->user)[i])) {
4017  break;
4018  }
4019  }
4020 
4021  if (i < pj_strlen(&sip_uri->user)) {
4022  return;
4023  }
4024 
4025  sip_uri->user_param = STR_PHONE;
4026 }
#define AST_DIGIT_ANY
Definition: file.h:48
unsigned int usereqphone
Definition: res_pjsip.h:877

◆ ast_sip_append_body()

int ast_sip_append_body ( pjsip_tx_data *  tdata,
const char *  body_text 
)

Append body data to a SIP message.

This acts mostly the same as ast_sip_add_body, except that rather than replacing a body if it currently exists, it appends data to an existing body.

Parameters
tdataThe message to append the body to
bodyThe string to append to the end of the current body
Return values
0Success
-1Failure

Definition at line 5114 of file res_pjsip.c.

References ast_str_alloca, ast_str_buffer(), and ast_str_set().

5115 {
5116  size_t combined_size = strlen(body_text) + tdata->msg->body->len;
5117  struct ast_str *body_buffer = ast_str_alloca(combined_size);
5118 
5119  ast_str_set(&body_buffer, 0, "%.*s%s", (int) tdata->msg->body->len, (char *) tdata->msg->body->data, body_text);
5120 
5121  tdata->msg->body->data = pj_pool_alloc(tdata->pool, combined_size);
5122  pj_memcpy(tdata->msg->body->data, ast_str_buffer(body_buffer), combined_size);
5123  tdata->msg->body->len = combined_size;
5124 
5125  return 0;
5126 }
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
#define ast_str_alloca(init_len)
Definition: strings.h:800
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:1065
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584

◆ ast_sip_call_codec_pref_to_str()

const char* ast_sip_call_codec_pref_to_str ( struct ast_flags  pref)

Convert the call codec preference flags to a string.

Since
18.0.0
Parameters
prefthe call codec preference setting
Returns
a constant string with either the setting value or 'unknown'
Note
Don't try to free the string!

Definition at line 5534 of file res_pjsip.c.

References value.

Referenced by incoming_call_offer_pref_to_str(), log_caps(), and outgoing_call_offer_pref_to_str().

5535 {
5536  const char *value;
5537 
5538  if (ast_sip_call_codec_pref_test(pref, LOCAL) && ast_sip_call_codec_pref_test(pref, INTERSECT) && ast_sip_call_codec_pref_test(pref, ALL)) {
5539  value = "local";
5540  } else if (ast_sip_call_codec_pref_test(pref, LOCAL) && ast_sip_call_codec_pref_test(pref, UNION) && ast_sip_call_codec_pref_test(pref, ALL)) {
5541  value = "local_merge";
5542  } else if (ast_sip_call_codec_pref_test(pref, LOCAL) && ast_sip_call_codec_pref_test(pref, INTERSECT) && ast_sip_call_codec_pref_test(pref, FIRST)) {
5543  value = "local_first";
5544  } else if (ast_sip_call_codec_pref_test(pref, REMOTE) && ast_sip_call_codec_pref_test(pref, INTERSECT) && ast_sip_call_codec_pref_test(pref, ALL)) {
5545  value = "remote";
5546  } else if (ast_sip_call_codec_pref_test(pref, REMOTE) && ast_sip_call_codec_pref_test(pref, UNION) && ast_sip_call_codec_pref_test(pref, ALL)) {
5547  value = "remote_merge";
5548  } else if (ast_sip_call_codec_pref_test(pref, REMOTE) && ast_sip_call_codec_pref_test(pref, UNION) && ast_sip_call_codec_pref_test(pref, FIRST)) {
5549  value = "remote_first";
5550  } else {
5551  value = "unknown";
5552  }
5553 
5554  return value;
5555 }
int value
Definition: syslog.c:37

◆ ast_sip_call_codec_str_to_pref()

int ast_sip_call_codec_str_to_pref ( struct ast_flags pref,
const char *  pref_str,
int  is_outgoing 
)

Convert a call codec preference string to preference flags.

Since
18.0.0
Parameters
prefA pointer to an ast_flags structure to receive the preference flags
pref_strThe call codec preference setting string
is_outgoingIs for outgoing calls?
Return values
0The string was parsed successfully
-1The string option was invalid

Definition at line 5557 of file res_pjsip.c.

References ast_set_flag, AST_SIP_CALL_CODEC_PREF_ALL, AST_SIP_CALL_CODEC_PREF_FIRST, AST_SIP_CALL_CODEC_PREF_INTERSECT, AST_SIP_CALL_CODEC_PREF_LOCAL, AST_SIP_CALL_CODEC_PREF_REMOTE, AST_SIP_CALL_CODEC_PREF_UNION, and ast_flags::flags.

Referenced by call_offer_pref_handler(), and test_create_joint().

5558 {
5559  pref->flags = 0;
5560 
5561  if (strcmp(pref_str, "local") == 0) {
5563  } else if (is_outgoing && strcmp(pref_str, "local_merge") == 0) {
5565  } else if (strcmp(pref_str, "local_first") == 0) {
5567  } else if (strcmp(pref_str, "remote") == 0) {
5569  } else if (is_outgoing && strcmp(pref_str, "remote_merge") == 0) {
5571  } else if (strcmp(pref_str, "remote_first") == 0) {
5573  } else {
5574  return -1;
5575  }
5576 
5577  return 0;
5578 }
#define ast_set_flag(p, flag)
Definition: utils.h:70
unsigned int flags
Definition: utils.h:200

◆ ast_sip_check_authentication()

enum ast_sip_check_auth_result ast_sip_check_authentication ( struct ast_sip_endpoint endpoint,
pjsip_rx_data *  rdata,
pjsip_tx_data *  tdata 
)

Method to determine authentication status of an incoming request.

This will call into a registered authenticator. The registered authenticator will do what is necessary to determine whether the incoming request passes authentication. A tentative response is passed into this function so that if, say, a digest authentication challenge should be sent in the ensuing response, it can be added to the response.

Parameters
endpointThe endpoint from the request was sent
rdataThe request to potentially authenticate
tdataTentative response to the request
Returns
The result of checking authentication.

Definition at line 3377 of file res_pjsip.c.

References ast_log, AST_SIP_AUTHENTICATION_SUCCESS, ast_sip_authenticator::check_authentication, and LOG_WARNING.

Referenced by authenticate().

3379 {
3380  if (!registered_authenticator) {
3381  ast_log(LOG_WARNING, "No SIP authenticator registered. Assuming authentication is successful\n");
3383  }
3384  return registered_authenticator->check_authentication(endpoint, rdata, tdata);
3385 }
static struct ast_sip_authenticator * registered_authenticator
Definition: res_pjsip.c:3336
#define LOG_WARNING
Definition: logger.h:274
enum ast_sip_check_auth_result(* check_authentication)(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, pjsip_tx_data *tdata)
Check that an incoming request passes authentication.
Definition: res_pjsip.h:965
#define ast_log
Definition: astobj2.c:42

◆ ast_sip_create_dialog_uac()

pjsip_dialog* ast_sip_create_dialog_uac ( const struct ast_sip_endpoint endpoint,
const char *  aor_name,
const char *  request_user 
)

General purpose method for creating a UAC dialog with an endpoint.

Parameters
endpointA pointer to the endpoint
aor_nameOptional name of the AOR to target, may even be an explicit SIP URI
request_userOptional user to place into the target URI
Return values
non-NULLsuccess
NULLfailure

Definition at line 4028 of file res_pjsip.c.

References ast_log, ast_sip_add_usereqphone(), ast_sip_dlg_set_transport(), ast_sip_tpselector_unref(), ast_sorcery_object_get_id(), ast_strlen_zero, ast_sip_endpoint::contact_user, ast_sip_endpoint::fromdomain, ast_sip_endpoint::fromuser, ast_sip_endpoint::info, LOG_ERROR, NULL, ast_sip_endpoint::outbound_proxy, sip_dialog_create_from(), and tmp().

Referenced by ast_sip_create_subscription(), and ast_sip_session_create_outgoing().

4030 {
4031  char enclosed_uri[PJSIP_MAX_URL_SIZE];
4032  pj_str_t local_uri = { "sip:temp@temp", 13 }, remote_uri, target_uri;
4033  pj_status_t res;
4034  pjsip_dialog *dlg = NULL;
4035  const char *outbound_proxy = endpoint->outbound_proxy;
4036  pjsip_tpselector selector = { .type = PJSIP_TPSELECTOR_NONE, };
4037  static const pj_str_t HCONTACT = { "Contact", 7 };
4038 
4039  snprintf(enclosed_uri, sizeof(enclosed_uri), "<%s>", uri);
4040  pj_cstr(&remote_uri, enclosed_uri);
4041 
4042  pj_cstr(&target_uri, uri);
4043 
4044  res = pjsip_dlg_create_uac(pjsip_ua_instance(), &local_uri, NULL, &remote_uri, &target_uri, &dlg);
4045  if (res == PJ_SUCCESS && !(PJSIP_URI_SCHEME_IS_SIP(dlg->target) || PJSIP_URI_SCHEME_IS_SIPS(dlg->target))) {
4046  /* dlg->target is a pjsip_other_uri, but it's assumed to be a
4047  * pjsip_sip_uri below. Fail fast. */
4048  res = PJSIP_EINVALIDURI;
4049  pjsip_dlg_terminate(dlg);
4050  }
4051  if (res != PJ_SUCCESS) {
4052  if (res == PJSIP_EINVALIDURI) {
4054  "Endpoint '%s': Could not create dialog to invalid URI '%s'. Is endpoint registered and reachable?\n",
4055  ast_sorcery_object_get_id(endpoint), uri);
4056  }
4057  return NULL;
4058  }
4059 
4060  /* We have to temporarily bump up the sess_count here so the dialog is not prematurely destroyed */
4061  dlg->sess_count++;
4062 
4063  ast_sip_dlg_set_transport(endpoint, dlg, &selector);
4064 
4065  if (sip_dialog_create_from(dlg->pool, &local_uri, endpoint->fromuser, endpoint->fromdomain, &remote_uri, &selector)) {
4066  dlg->sess_count--;
4067  pjsip_dlg_terminate(dlg);
4068  ast_sip_tpselector_unref(&selector);
4069  return NULL;
4070  }
4071 
4072  ast_sip_tpselector_unref(&selector);
4073 
4074  /* Update the dialog with the new local URI, we do it afterwards so we can use the dialog pool for construction */
4075  pj_strdup_with_null(dlg->pool, &dlg->local.info_str, &local_uri);
4076  dlg->local.info->uri = pjsip_parse_uri(dlg->pool, dlg->local.info_str.ptr, dlg->local.info_str.slen, 0);
4077  if (!dlg->local.info->uri) {
4079  "Could not parse URI '%s' for endpoint '%s'\n",
4080  dlg->local.info_str.ptr, ast_sorcery_object_get_id(endpoint));
4081  dlg->sess_count--;
4082  pjsip_dlg_terminate(dlg);
4083  return NULL;
4084  }
4085 
4086  dlg->local.contact = pjsip_parse_hdr(dlg->pool, &HCONTACT, local_uri.ptr, local_uri.slen, NULL);
4087 
4088  if (!ast_strlen_zero(endpoint->contact_user)) {
4089  pjsip_sip_uri *sip_uri;
4090 
4091  sip_uri = pjsip_uri_get_uri(dlg->local.contact->uri);
4092  pj_strdup2(dlg->pool, &sip_uri->user, endpoint->contact_user);
4093  }
4094 
4095  /* If a request user has been specified and we are permitted to change it, do so */
4096  if (!ast_strlen_zero(request_user)) {
4097  pjsip_sip_uri *sip_uri;
4098 
4099  if (PJSIP_URI_SCHEME_IS_SIP(dlg->target) || PJSIP_URI_SCHEME_IS_SIPS(dlg->target)) {
4100  sip_uri = pjsip_uri_get_uri(dlg->target);
4101  pj_strdup2(dlg->pool, &sip_uri->user, request_user);
4102  }
4103  if (PJSIP_URI_SCHEME_IS_SIP(dlg->remote.info->uri) || PJSIP_URI_SCHEME_IS_SIPS(dlg->remote.info->uri)) {
4104  sip_uri = pjsip_uri_get_uri(dlg->remote.info->uri);
4105  pj_strdup2(dlg->pool, &sip_uri->user, request_user);
4106  }
4107  }
4108 
4109  /* Add the user=phone parameter if applicable */
4110  ast_sip_add_usereqphone(endpoint, dlg->pool, dlg->target);
4111  ast_sip_add_usereqphone(endpoint, dlg->pool, dlg->remote.info->uri);
4112 
4113  if (!ast_strlen_zero(outbound_proxy)) {
4114  pjsip_route_hdr route_set, *route;
4115  static const pj_str_t ROUTE_HNAME = { "Route", 5 };
4116  pj_str_t tmp;
4117 
4118  pj_list_init(&route_set);
4119 
4120  pj_strdup2_with_null(dlg->pool, &tmp, outbound_proxy);
4121  if (!(route = pjsip_parse_hdr(dlg->pool, &ROUTE_HNAME, tmp.ptr, tmp.slen, NULL))) {
4122  ast_log(LOG_ERROR, "Could not create dialog to endpoint '%s' as outbound proxy URI '%s' is not valid\n",
4123  ast_sorcery_object_get_id(endpoint), outbound_proxy);
4124  dlg->sess_count--;
4125  pjsip_dlg_terminate(dlg);
4126  return NULL;
4127  }
4128  pj_list_insert_nodes_before(&route_set, route);
4129 
4130  pjsip_dlg_set_route_set(dlg, &route_set);
4131  }
4132 
4133  dlg->sess_count--;
4134 
4135  return dlg;
4136 }
void ast_sip_add_usereqphone(const struct ast_sip_endpoint *endpoint, pj_pool_t *pool, pjsip_uri *uri)
Add &#39;user=phone&#39; parameter to URI if enabled and user is a phone number.
Definition: res_pjsip.c:3994
const ast_string_field fromuser
Definition: res_pjsip.h:829
char * contact_user
Definition: res_pjsip.h:887
static int tmp()
Definition: bt_open.c:389
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_log
Definition: astobj2.c:42
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
const ast_string_field outbound_proxy
Definition: res_pjsip.h:819
struct ast_sip_endpoint_info_configuration info
Definition: res_pjsip.h:849
#define LOG_ERROR
Definition: logger.h:285
void ast_sip_tpselector_unref(pjsip_tpselector *selector)
Unreference a pjsip_tpselector.
Definition: res_pjsip.c:3987
int ast_sip_dlg_set_transport(const struct ast_sip_endpoint *endpoint, pjsip_dialog *dlg, pjsip_tpselector *selector)
Set the transport on a dialog.
Definition: res_pjsip.c:3791
static int sip_dialog_create_from(pj_pool_t *pool, pj_str_t *from, const char *user, const char *domain, const pj_str_t *target, pjsip_tpselector *selector)
Definition: res_pjsip.c:3813
const ast_string_field fromdomain
Definition: res_pjsip.h:831

◆ ast_sip_create_dialog_uas()

pjsip_dialog* ast_sip_create_dialog_uas ( const struct ast_sip_endpoint endpoint,
pjsip_rx_data *  rdata,
pj_status_t *  status 
)

General purpose method for creating a UAS dialog with an endpoint.

Deprecated:
This function is unsafe (due to the returned object not being locked nor having its reference incremented) and should no longer be used. Instead use ast_sip_create_dialog_uas_locked so a properly locked and referenced object is returned.
Parameters
endpointA pointer to the endpoint
rdataThe request that is starting the dialog
[out]statusOn failure, the reason for failure in creating the dialog

Definition at line 4233 of file res_pjsip.c.

References create_dialog_uas().

4234 {
4235 #ifdef HAVE_PJSIP_DLG_CREATE_UAS_AND_INC_LOCK
4236  pjsip_dialog *dlg;
4237 
4238  dlg = create_dialog_uas(endpoint, rdata, status, pjsip_dlg_create_uas_and_inc_lock);
4239  if (dlg) {
4240  pjsip_dlg_dec_lock(dlg);
4241  }
4242 
4243  return dlg;
4244 #else
4245  return create_dialog_uas(endpoint, rdata, status, pjsip_dlg_create_uas);
4246 #endif
4247 }
static pjsip_dialog * create_dialog_uas(const struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, pj_status_t *status, create_dlg_uac create_fun)
Definition: res_pjsip.c:4177
jack_status_t status
Definition: app_jack.c:146

◆ ast_sip_create_dialog_uas_locked()

pjsip_dialog* ast_sip_create_dialog_uas_locked ( const struct ast_sip_endpoint endpoint,
pjsip_rx_data *  rdata,
pj_status_t *  status 
)

General purpose method for creating a UAS dialog with an endpoint.

This function creates and returns a locked, and referenced counted pjsip dialog object. The caller is thus responsible for freeing the allocated memory, decrementing the reference, and releasing the lock when done with the returned object.

Note
The safest way to unlock the object, and decrement its reference is by calling pjsip_dlg_dec_lock. Alternatively, pjsip_dlg_dec_session can be used to decrement the reference only.

The dialog is returned locked and with a reference in order to ensure that the dialog object, and any of its associated objects (e.g. transaction) are not untimely destroyed. For instance, that could happen when a transport error occurs.

As long as the caller maintains a reference to the dialog there should be no worry that it might unknowningly be destroyed. However, once the caller unlocks the dialog there is a danger that some of the dialog's internal objects could be lost and/or compromised. For example, when the aforementioned transport error occurs the dialog's associated transaction gets destroyed (see pjsip_dlg_on_tsx_state in sip_dialog.c, and mod_inv_on_tsx_state in sip_inv.c).

In this case and before using the dialog again the caller should re-lock the dialog, check to make sure the dialog is still established, and the transaction still exists and has not been destroyed.

Parameters
endpointA pointer to the endpoint
rdataThe request that is starting the dialog
[out]statusOn failure, the reason for failure in creating the dialog
Return values
Alocked, and reference counted pjsip_dialog object.
NULLon failure

Definition at line 4249 of file res_pjsip.c.

References create_dialog_uas().

Referenced by create_subscription_tree(), and pre_session_setup().

4251 {
4252 #ifdef HAVE_PJSIP_DLG_CREATE_UAS_AND_INC_LOCK
4253  return create_dialog_uas(endpoint, rdata, status, pjsip_dlg_create_uas_and_inc_lock);
4254 #else
4255  /*
4256  * This is put here in order to be compatible with older versions of pjproject.
4257  * Best we can do in this case is immediately lock after getting the dialog.
4258  * However, that does leave a "gap" between creating and locking.
4259  */
4260  pjsip_dialog *dlg;
4261 
4262  dlg = create_dialog_uas(endpoint, rdata, status, pjsip_dlg_create_uas);
4263  if (dlg) {
4264  pjsip_dlg_inc_lock(dlg);
4265  }
4266 
4267  return dlg;
4268 #endif
4269  }
static pjsip_dialog * create_dialog_uas(const struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, pj_status_t *status, create_dlg_uac create_fun)
Definition: res_pjsip.c:4177
jack_status_t status
Definition: app_jack.c:146

◆ ast_sip_create_rdata()

int ast_sip_create_rdata ( pjsip_rx_data *  rdata,
char *  packet,
const char *  src_name,
int  src_port,
char *  transport_type,
const char *  local_name,
int  local_port 
)

General purpose method for creating an rdata structure using specific information.

Parameters
rdata[out]The rdata structure that will be populated
packetA SIP message
src_nameThe source IP address of the message
src_portThe source port of the message
transport_typeThe type of transport the message was received on
local_nameThe local IP address the message was received on
local_portThe local port the message was received on
Return values
0success
-1failure

Definition at line 4323 of file res_pjsip.c.

References ast_sip_create_rdata_with_contact(), and NULL.

4325 {
4326  return ast_sip_create_rdata_with_contact(rdata, packet, src_name, src_port, transport_type,
4327  local_name, local_port, NULL);
4328 }
#define NULL
Definition: resample.c:96
int ast_sip_create_rdata_with_contact(pjsip_rx_data *rdata, char *packet, const char *src_name, int src_port, char *transport_type, const char *local_name, int local_port, const char *contact)
General purpose method for creating an rdata structure using specific information.
Definition: res_pjsip.c:4271

◆ ast_sip_create_rdata_with_contact()

int ast_sip_create_rdata_with_contact ( pjsip_rx_data *  rdata,
char *  packet,
const char *  src_name,
int  src_port,
char *  transport_type,
const char *  local_name,
int  local_port,
const char *  contact_uri 
)

General purpose method for creating an rdata structure using specific information.

Since
13.15.0
Parameters
rdata[out]The rdata structure that will be populated
packetA SIP message
src_nameThe source IP address of the message
src_portThe source port of the message
transport_typeThe type of transport the message was received on
local_nameThe local IP address the message was received on
local_portThe local port the message was received on
contact_uriThe contact URI of the message
Return values
0success
-1failure

Definition at line 4271 of file res_pjsip.c.

References ast_copy_string(), ast_log, ast_strlen_zero, LOG_WARNING, NULL, and tmp().

Referenced by ast_sip_create_rdata(), and subscription_persistence_recreate().

4273 {
4274  pj_str_t tmp;
4275 
4276  /*
4277  * Initialize the error list in case there is a parse error
4278  * in the given packet.
4279  */
4280  pj_list_init(&rdata->msg_info.parse_err);
4281 
4282  rdata->tp_info.transport = PJ_POOL_ZALLOC_T(rdata->tp_info.pool, pjsip_transport);
4283  if (!rdata->tp_info.transport) {
4284  return -1;
4285  }
4286 
4287  ast_copy_string(rdata->pkt_info.packet, packet, sizeof(rdata->pkt_info.packet));
4288  ast_copy_string(rdata->pkt_info.src_name, src_name, sizeof(rdata->pkt_info.src_name));
4289  rdata->pkt_info.src_port = src_port;
4290  pj_sockaddr_parse(pj_AF_UNSPEC(), 0, pj_cstr(&tmp, src_name), &rdata->pkt_info.src_addr);
4291  pj_sockaddr_set_port(&rdata->pkt_info.src_addr, src_port);
4292 
4293  pjsip_parse_rdata(packet, strlen(packet), rdata);
4294  if (!rdata->msg_info.msg || !pj_list_empty(&rdata->msg_info.parse_err)) {
4295  return -1;
4296  }
4297 
4298  if (!ast_strlen_zero(contact)) {
4299  pjsip_contact_hdr *contact_hdr;
4300 
4301  contact_hdr = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT, NULL);
4302  if (contact_hdr) {
4303  contact_hdr->uri = pjsip_parse_uri(rdata->tp_info.pool, (char *)contact,
4304  strlen(contact), PJSIP_PARSE_URI_AS_NAMEADDR);
4305  if (!contact_hdr->uri) {
4306  ast_log(LOG_WARNING, "Unable to parse contact URI from '%s'.\n", contact);
4307  return -1;
4308  }
4309  }
4310  }
4311 
4312  pj_strdup2(rdata->tp_info.pool, &rdata->msg_info.via->recvd_param, rdata->pkt_info.src_name);
4313  rdata->msg_info.via->rport_param = -1;
4314 
4315  rdata->tp_info.transport->key.type = pjsip_transport_get_type_from_name(pj_cstr(&tmp, transport_type));
4316  rdata->tp_info.transport->type_name = transport_type;
4317  pj_strdup2(rdata->tp_info.pool, &rdata->tp_info.transport->local_name.host, local_name);
4318  rdata->tp_info.transport->local_name.port = local_port;
4319 
4320  return 0;
4321 }
#define LOG_WARNING
Definition: logger.h:274
static int tmp()
Definition: bt_open.c:389
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_log
Definition: astobj2.c:42
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401

◆ ast_sip_create_request()

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.

Its typical use would be to create one-off requests such as an out of dialog SIP MESSAGE.

The request can either be in- or out-of-dialog. If in-dialog, the dlg parameter MUST be present. If out-of-dialog the endpoint parameter MUST be present. If both are present, then we will assume that the message is to be sent in-dialog.

The uri parameter can be specified if the request should be sent to an explicit URI rather than one configured on the endpoint.

Parameters
methodThe method of the SIP request to send
dlgOptional. If specified, the dialog on which to request the message.
endpointOptional. If specified, the request will be created out-of-dialog to the endpoint.
uriOptional. If specified, the request will be sent to this URI rather than one configured for the endpoint.
contactThe contact with which this request is associated for out-of-dialog requests.
[out]tdataThe newly-created request

The provided contact is attached to tdata with its reference bumped, but will not survive for the entire lifetime of tdata since the contact is cleaned up when all supplements have completed execution.

Return values
0Success
-1Failure

Definition at line 4490 of file res_pjsip.c.

References ast_assert, ast_log, create_in_dialog_request(), create_out_of_dialog_request(), get_pjsip_method(), LOG_WARNING, NULL, and pmethod.

Referenced by msg_send(), notify_channel(), notify_contact(), notify_uri(), send_unsolicited_mwi_notify_to_contact(), sendtext(), sip_options_qualify_contact(), transmit_info_dtmf(), and transmit_info_with_vidupdate().

4493 {
4494  const pjsip_method *pmethod = get_pjsip_method(method);
4495 
4496  if (!pmethod) {
4497  ast_log(LOG_WARNING, "Unknown method '%s'. Cannot send request\n", method);
4498  return -1;
4499  }
4500 
4501  if (dlg) {
4502  return create_in_dialog_request(pmethod, dlg, tdata);
4503  } else {
4504  ast_assert(endpoint != NULL);
4505  return create_out_of_dialog_request(pmethod, endpoint, uri, contact, tdata);
4506  }
4507 }
static const pjsip_method * get_pjsip_method(const char *method)
Definition: res_pjsip.c:4351
static int create_in_dialog_request(const pjsip_method *method, struct pjsip_dialog *dlg, pjsip_tx_data **tdata)
Definition: res_pjsip.c:4362
#define LOG_WARNING
Definition: logger.h:274
const pjsip_method * pmethod
Definition: res_pjsip.c:4336
#define ast_assert(a)
Definition: utils.h:695
#define NULL
Definition: resample.c:96
static int create_out_of_dialog_request(const pjsip_method *method, struct ast_sip_endpoint *endpoint, const char *uri, struct ast_sip_contact *provided_contact, pjsip_tx_data **tdata)
Definition: res_pjsip.c:4380
#define ast_log
Definition: astobj2.c:42
const char * method
Definition: res_pjsip.c:4335

◆ ast_sip_create_request_with_auth()

int ast_sip_create_request_with_auth ( const struct ast_sip_auth_vector auths,
pjsip_rx_data *  challenge,
pjsip_tx_data *  tdata,
pjsip_tx_data **  new_request 
)

Create a response to an authentication challenge.

This will call into an outbound authenticator's create_request_with_auth callback to create a new request with authentication credentials. See the create_request_with_auth callback in the ast_sip_outbound_authenticator structure for details about the parameters and return values.

Definition at line 3412 of file res_pjsip.c.

References ast_log, ast_sip_outbound_authenticator::create_request_with_auth, and LOG_WARNING.

Referenced by check_request_status(), handle_registration_response(), outbound_invite_auth(), session_inv_on_tsx_state_changed(), and sip_outbound_publish_callback().

3414 {
3416  ast_log(LOG_WARNING, "No SIP outbound authenticator registered. Cannot respond to authentication challenge\n");
3417  return -1;
3418  }
3419  return registered_outbound_authenticator->create_request_with_auth(auths, challenge, old_request, new_request);
3420 }
#define LOG_WARNING
Definition: logger.h:274
int(* create_request_with_auth)(const struct ast_sip_auth_vector *auths, struct pjsip_rx_data *challenge, struct pjsip_tx_data *old_request, struct pjsip_tx_data **new_request)
Create a new request with authentication credentials.
Definition: res_pjsip.h:986
static struct ast_sip_outbound_authenticator * registered_outbound_authenticator
Definition: res_pjsip.c:3387
#define ast_log
Definition: astobj2.c:42
static void challenge(const char *realm, pjsip_tx_data *tdata, const pjsip_rx_data *rdata, int is_stale)
astobj2 callback for adding digest challenges to responses

◆ ast_sip_create_response()

int ast_sip_create_response ( const pjsip_rx_data *  rdata,
int  st_code,
struct ast_sip_contact contact,
pjsip_tx_data **  p_tdata 
)

General purpose method for creating a SIP response.

Its typical use would be to create responses for out of dialog requests.

Parameters
rdataThe rdata from the incoming request.
st_codeThe response code to transmit.
contactThe contact with which this request is associated.
[out]tdataThe newly-created response

The provided contact is attached to tdata with its reference bumped, but will not survive for the entire lifetime of tdata since the contact is cleaned up when all supplements have completed execution.

Return values
0Success
-1Failure

Definition at line 5448 of file res_pjsip.c.

References ao2_bump, ast_sip_get_pjsip_endpoint(), ast_sip_mod_data_set, MOD_DATA_CONTACT, NULL, and supplement_module.

Referenced by register_aor_core(), send_options_response(), and send_response().

5450 {
5451  int res = pjsip_endpt_create_response(ast_sip_get_pjsip_endpoint(), rdata, st_code, NULL, tdata);
5452 
5453  if (!res) {
5454  ast_sip_mod_data_set((*tdata)->pool, (*tdata)->mod_data, supplement_module.id, MOD_DATA_CONTACT, ao2_bump(contact));
5455  }
5456 
5457  return res;
5458 }
#define NULL
Definition: resample.c:96
#define ao2_bump(obj)
Definition: astobj2.h:491
static pjsip_module supplement_module
Definition: res_pjsip.c:4373
#define ast_sip_mod_data_set(pool, mod_data, id, key, val)
Utilizing a mod_data array for a given id, set the value associated with the given key...
Definition: res_pjsip.h:2670
#define MOD_DATA_CONTACT
Definition: res_pjsip.c:3264
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
Definition: res_pjsip.c:3718

◆ ast_sip_dict_get()

void* ast_sip_dict_get ( void *  ht,
const char *  key 
)

Retrieves the value associated with the given key.

Parameters
htthe hash table/dictionary to search
keythe key to find
Return values
thevalue associated with the key, NULL otherwise.

Definition at line 5338 of file res_pjsip.c.

References NULL.

5339 {
5340  unsigned int hval = 0;
5341 
5342  if (!ht) {
5343  return NULL;
5344  }
5345 
5346  return pj_hash_get(ht, key, PJ_HASH_KEY_STRING, &hval);
5347 }
#define NULL
Definition: resample.c:96

◆ ast_sip_dict_set()

void* ast_sip_dict_set ( pj_pool_t *  pool,
void *  ht,
const char *  key,
void *  val 
)

Set the value for the given key.

Note - if the hash table does not exist one is created first, the key/value pair is set, and the hash table returned.

Parameters
poolthe pool to allocate memory in
htthe hash table/dictionary in which to store the key/value pair
keythe key to associate a value with
valthe value to associate with a key
Return values
thegiven, or newly created, hash table.

Definition at line 5349 of file res_pjsip.c.

5351 {
5352  if (!ht) {
5353  ht = pj_hash_create(pool, 11);
5354  }
5355 
5356  pj_hash_set(pool, ht, key, PJ_HASH_KEY_STRING, 0, val);
5357 
5358  return ht;
5359 }
Definition: ast_expr2.c:325
static pj_pool_t * pool
Global memory pool for configuration and timers.

◆ ast_sip_dlg_set_transport()

int ast_sip_dlg_set_transport ( const struct ast_sip_endpoint endpoint,
pjsip_dialog *  dlg,
pjsip_tpselector *  selector 
)

Set the transport on a dialog.

Since
13.15.0
Parameters
endpoint
dlg
selector(optional)
Note
This API calls ast_sip_get_transport_name(endpoint, dlg->target) and if the result is non-NULL, calls pjsip_dlg_set_transport. If 'selector' is non-NULL, it is updated with the selector used.
It is the responsibility of the caller to unref the passed in selector if one is provided.

Definition at line 3791 of file res_pjsip.c.

References ast_sip_set_tpselector_from_ep_or_uri(), and ast_sip_tpselector_unref().

Referenced by ast_sip_create_dialog_uac().

3793 {
3794  pjsip_sip_uri *uri;
3795  pjsip_tpselector sel = { .type = PJSIP_TPSELECTOR_NONE, };
3796 
3797  uri = pjsip_uri_get_uri(dlg->target);
3798  if (!selector) {
3799  selector = &sel;
3800  }
3801 
3802  ast_sip_set_tpselector_from_ep_or_uri(endpoint, uri, selector);
3803 
3804  pjsip_dlg_set_transport(dlg, selector);
3805 
3806  if (selector == &sel) {
3808  }
3809 
3810  return 0;
3811 }
int ast_sip_set_tpselector_from_ep_or_uri(const struct ast_sip_endpoint *endpoint, pjsip_sip_uri *sip_uri, pjsip_tpselector *selector)
Sets pjsip_tpselector from an endpoint or uri.
Definition: res_pjsip.c:3975
void ast_sip_tpselector_unref(pjsip_tpselector *selector)
Unreference a pjsip_tpselector.
Definition: res_pjsip.c:3987

◆ ast_sip_dtmf_to_str()

int ast_sip_dtmf_to_str ( const enum ast_sip_dtmf_mode  dtmf,
char *  buf,
size_t  buf_len 
)

Convert the DTMF mode enum value into a string.

Since
13.18.0
Parameters
dtmfthe dtmf mode
bufBuffer to receive dtmf mode string
buf_lenBuffer length
Return values
0Success
-1Failure

Definition at line 5484 of file res_pjsip.c.

References ast_copy_string(), AST_SIP_DTMF_AUTO, AST_SIP_DTMF_AUTO_INFO, AST_SIP_DTMF_INBAND, AST_SIP_DTMF_INFO, AST_SIP_DTMF_NONE, and AST_SIP_DTMF_RFC_4733.

Referenced by dtmf_to_str(), and pjsip_acf_dtmf_mode_read().

5486 {
5487  switch (dtmf) {
5488  case AST_SIP_DTMF_NONE:
5489  ast_copy_string(buf, "none", buf_len);
5490  break;
5491  case AST_SIP_DTMF_RFC_4733:
5492  ast_copy_string(buf, "rfc4733", buf_len);
5493  break;
5494  case AST_SIP_DTMF_INBAND:
5495  ast_copy_string(buf, "inband", buf_len);
5496  break;
5497  case AST_SIP_DTMF_INFO:
5498  ast_copy_string(buf, "info", buf_len);
5499  break;
5500  case AST_SIP_DTMF_AUTO:
5501  ast_copy_string(buf, "auto", buf_len);
5502  break;
5504  ast_copy_string(buf, "auto_info", buf_len);
5505  break;
5506  default:
5507  buf[0] = '\0';
5508  return -1;
5509  }
5510  return 0;
5511 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401

◆ ast_sip_failover_request()

int ast_sip_failover_request ( pjsip_tx_data *  tdata)

Set a request to use the next value in the list of resolved addresses.

Parameters
tdatathe tx data from the original request
Return values
0No more addresses to try
1The request was successfully re-intialized

Definition at line 4871 of file res_pjsip.c.

References NULL, and send_request_cb().

Referenced by check_request_status(), and handle_registration_response().

4872 {
4873  pjsip_via_hdr *via;
4874 
4875  if (!tdata || !tdata->dest_info.addr.count
4876  || (tdata->dest_info.cur_addr == tdata->dest_info.addr.count - 1)) {
4877  /* No more addresses to try */
4878  return 0;
4879  }
4880 
4881  /* Try next address */
4882  ++tdata->dest_info.cur_addr;
4883 
4884  via = (pjsip_via_hdr*)pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA, NULL);
4885  via->branch_param.slen = 0;
4886 
4887  pjsip_tx_data_invalidate_msg(tdata);
4888 
4889  return 1;
4890 }
#define NULL
Definition: resample.c:96

◆ ast_sip_format_endpoint_ami()

int ast_sip_format_endpoint_ami ( struct ast_sip_endpoint endpoint,
struct ast_sip_ami ami,
int *  count 
)

Formats the endpoint and sends over AMI.

Parameters
endpointthe endpoint to format and send
endpointami AMI variable container
countthe number of formatters operated on
Return values
0Success, otherwise non-zero on error

Definition at line 3699 of file res_pjsip.c.

References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_sip_endpoint_formatter::format_ami, lock, and SCOPED_LOCK.

Referenced by ami_show_endpoint().

3701 {
3702  int res = 0;
3703  struct ast_sip_endpoint_formatter *i;
3705  *count = 0;
3707  if (i->format_ami && ((res = i->format_ami(endpoint, ami)) < 0)) {
3708  return res;
3709  }
3710 
3711  if (!res) {
3712  (*count)++;
3713  }
3714  }
3715  return 0;
3716 }
An entity responsible formatting endpoint information.
Definition: res_pjsip.h:2763
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
ast_mutex_t lock
Definition: app_meetme.c:1091
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
#define SCOPED_LOCK(varname, lock, lockfunc, unlockfunc)
Scoped Locks.
Definition: lock.h:581
int(* format_ami)(const struct ast_sip_endpoint *endpoint, struct ast_sip_ami *ami)
Callback used to format endpoint information over AMI.
Definition: res_pjsip.h:2767

◆ ast_sip_get_host_ip()

int ast_sip_get_host_ip ( int  af,
pj_sockaddr *  addr 
)

Retrieve the local host address in IP form.

Parameters
afThe address family to retrieve
addrA place to store the local host address
Return values
0success
-1failure
Since
13.6.0

Definition at line 5460 of file res_pjsip.c.

References ast_strlen_zero, host_ip_ipv4, host_ip_ipv4_string, host_ip_ipv6, and host_ip_ipv6_string.

5461 {
5462  if (af == pj_AF_INET() && !ast_strlen_zero(host_ip_ipv4_string)) {
5463  pj_sockaddr_copy_addr(addr, &host_ip_ipv4);
5464  return 0;
5465  } else if (af == pj_AF_INET6() && !ast_strlen_zero(host_ip_ipv6_string)) {
5466  pj_sockaddr_copy_addr(addr, &host_ip_ipv6);
5467  return 0;
5468  }
5469 
5470  return -1;
5471 }
static pj_sockaddr host_ip_ipv6
Definition: res_pjsip.c:3283
static char host_ip_ipv6_string[PJ_INET6_ADDRSTRLEN]
Definition: res_pjsip.c:3286
#define ast_strlen_zero(foo)
Definition: strings.h:52
static char host_ip_ipv4_string[PJ_INET6_ADDRSTRLEN]
Definition: res_pjsip.c:3280
static pj_sockaddr host_ip_ipv4
Definition: res_pjsip.c:3277

◆ ast_sip_get_host_ip_string()

const char* ast_sip_get_host_ip_string ( int  af)

Retrieve the local host address in string form.

Parameters
afThe address family to retrieve
Return values
non-NULLsuccess
NULLfailure
Since
13.6.0
Note
An empty string may be returned if the address family is valid but no local address exists

Definition at line 5473 of file res_pjsip.c.

References host_ip_ipv4_string, host_ip_ipv6_string, and NULL.

Referenced by create_local_sdp(), create_outgoing_sdp_stream(), and multihomed_rewrite_sdp().

5474 {
5475  if (af == pj_AF_INET()) {
5476  return host_ip_ipv4_string;
5477  } else if (af == pj_AF_INET6()) {
5478  return host_ip_ipv6_string;
5479  }
5480 
5481  return NULL;
5482 }
static char host_ip_ipv6_string[PJ_INET6_ADDRSTRLEN]
Definition: res_pjsip.c:3286
#define NULL
Definition: resample.c:96
static char host_ip_ipv4_string[PJ_INET6_ADDRSTRLEN]
Definition: res_pjsip.c:3280

◆ ast_sip_get_pjsip_endpoint()

pjsip_endpoint* ast_sip_get_pjsip_endpoint ( void  )

Get a pointer to the PJSIP endpoint.

This is useful when modules have specific information they need to register with the PJSIP core.

Return values
NULLendpoint has not been created yet.
non-NULLPJSIP endpoint.

Definition at line 3718 of file res_pjsip.c.

References ast_pjsip_endpoint.

Referenced by acl_on_rx_msg(), ast_res_pjsip_cleanup_options_handling(), ast_res_pjsip_init_options_handling(), ast_sip_create_response(), ast_sip_destroy_transport_events(), ast_sip_initialize_transport_events(), ast_sip_pubsub_register_body_generator(), ast_sip_send_response(), ast_sip_session_defer_termination(), ast_sip_session_resume_reinvite(), authenticate(), cancel_publish_refresh(), cancel_registration(), channel_read_pjsip(), create_out_of_dialog_request(), digest_create_request_with_auth(), distribute(), distributor(), do_cli_dump_endpt(), endpoint_lookup(), endpt_send_request(), endpt_send_request_cb(), exten_state_data_alloc(), exten_state_data_destructor(), exten_state_publisher_cb(), filter_on_tx_message(), find_registrar_aor(), keepalive_transport_send_keepalive(), load_module(), logging_on_rx_msg(), logging_on_tx_msg(), notify_task(), on_rx_process_uris(), options_incoming_request(), parse_uri_cb(), pre_session_setup(), publish_request_initial(), pubsub_on_rx_mwi_notify_request(), pubsub_on_rx_publish_request(), pubsub_on_rx_subscribe_request(), register_aor(), register_aor_core(), registrar_on_rx_request(), reschedule_reinvite(), schedule_publish_refresh(), schedule_registration(), send_options_response(), session_reinvite_on_rx_request(), sip_check_transport(), sip_dialog_create_contact(), sip_dialog_create_from(), sip_outbound_publisher_init(), sip_outbound_registration_regc_alloc(), sip_publication_respond(), sip_replace_resolver(), sip_session_defer_termination_stop_timer(), subscription_persistence_load(), system_create_resolver_and_set_nameservers(), t38_change_state(), transport_apply(), and transport_create().

3719 {
3720  return ast_pjsip_endpoint;
3721 }
static pjsip_endpoint * ast_pjsip_endpoint
Definition: res_pjsip.c:3272

◆ ast_sip_get_transport_name()

int ast_sip_get_transport_name ( const struct ast_sip_endpoint endpoint,
pjsip_sip_uri *  sip_uri,
char *  buf,
size_t  buf_len 
)

Get the transport name from an endpoint or request uri.

Since
13.15.0
Parameters
endpoint
sip_uri
bufBuffer to receive transport name
buf_lenBuffer length
Return values
0Success
-1Failure
Note
If endpoint->transport is not NULL, it is returned in buf. Otherwise if sip_uri has an 'x-ast-txp' parameter AND the sip_uri host is an ip4 or ip6 address, its value is returned,

Definition at line 3762 of file res_pjsip.c.

References ast_alloca, ast_copy_pj_str(), ast_copy_string(), AST_SIP_X_AST_TXP, AST_SIP_X_AST_TXP_LEN, ast_sockaddr_parse(), ast_strlen_zero, host, NULL, PARSE_PORT_FORBID, and ast_sip_endpoint::transport.

Referenced by ast_sip_set_tpselector_from_ep_or_uri().

3764 {
3765  char *host = NULL;
3766  static const pj_str_t x_name = { AST_SIP_X_AST_TXP, AST_SIP_X_AST_TXP_LEN };
3767  pjsip_param *x_transport;
3768 
3769  if (!ast_strlen_zero(endpoint->transport)) {
3770  ast_copy_string(buf, endpoint->transport, buf_len);
3771  return 0;
3772  }
3773 
3774  x_transport = pjsip_param_find(&sip_uri->other_param, &x_name);
3775  if (!x_transport) {
3776  return -1;
3777  }
3778 
3779  /* Only use x_transport if the uri host is an ip (4 or 6) address */
3780  host = ast_alloca(sip_uri->host.slen + 1);
3781  ast_copy_pj_str(host, &sip_uri->host, sip_uri->host.slen + 1);
3782  if (!ast_sockaddr_parse(NULL, host, PARSE_PORT_FORBID)) {
3783  return -1;
3784  }
3785 
3786  ast_copy_pj_str(buf, &x_transport->value, buf_len);
3787 
3788  return 0;
3789 }
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
Parse an IPv4 or IPv6 address string.
Definition: netsock2.c:230
const ast_string_field transport
Definition: res_pjsip.h:817
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define NULL
Definition: resample.c:96
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:5240
#define ast_strlen_zero(foo)
Definition: strings.h:52
static char host[256]
Definition: muted.c:77
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
#define AST_SIP_X_AST_TXP_LEN
Definition: res_pjsip.h:910
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
#define AST_SIP_X_AST_TXP
Definition: res_pjsip.h:909

◆ ast_sip_identify_endpoint()

struct ast_sip_endpoint* ast_sip_identify_endpoint ( pjsip_rx_data *  rdata)

Determine the endpoint that has sent a SIP message.

This will call into each of the registered endpoint identifiers' identify_endpoint() callbacks until one returns a non-NULL endpoint. This will return an ao2 object. Its reference count will need to be decremented when completed using the endpoint.

Parameters
rdataThe inbound SIP message to use when identifying the endpoint.
Return values
NULLNo matching endpoint
non-NULLThe matching endpoint

Definition at line 3528 of file res_pjsip.c.

References ast_assert, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, endpoint_identifier_list::identifier, ast_sip_endpoint_identifier::identify_endpoint, lock, NULL, and SCOPED_LOCK.

Referenced by endpoint_lookup().

3529 {
3530  struct endpoint_identifier_list *iter;
3531  struct ast_sip_endpoint *endpoint = NULL;
3535  endpoint = iter->identifier->identify_endpoint(rdata);
3536  if (endpoint) {
3537  break;
3538  }
3539  }
3540  return endpoint;
3541 }
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
#define ast_assert(a)
Definition: utils.h:695
struct ast_sip_endpoint *(* identify_endpoint)(pjsip_rx_data *rdata)
Callback used to identify the source of a message. See ast_sip_identify_endpoint for more details...
Definition: res_pjsip.h:998
#define NULL
Definition: resample.c:96
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
ast_mutex_t lock
Definition: app_meetme.c:1091
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
#define SCOPED_LOCK(varname, lock, lockfunc, unlockfunc)
Scoped Locks.
Definition: lock.h:581
An entity with which Asterisk communicates.
Definition: res_pjsip.h:812
struct ast_sip_endpoint_identifier * identifier
Definition: res_pjsip.c:3425

◆ ast_sip_is_content_type()

int ast_sip_is_content_type ( pjsip_media_type *  content_type,
char *  type,
char *  subtype 
)

Checks if the given content type matches type/subtype.

Compares the pjsip_media_type with the passed type and subtype and returns the result of that comparison. The media type parameters are ignored.

Parameters
content_typeThe pjsip_media_type structure to compare
typeThe media type to compare
subtypeThe media subtype to compare
Return values
0No match
-1Match

Definition at line 5259 of file res_pjsip.c.

References compare().

Referenced by asterisk_publication_devicestate_state_change(), asterisk_publication_mwi_state_change(), check_content_type(), filter_on_tx_message(), pubsub_on_rx_notify_request(), session_outgoing_nat_hook(), and video_info_incoming_request().

5260 {
5261  pjsip_media_type compare;
5262 
5263  if (!content_type) {
5264  return 0;
5265  }
5266 
5267  pjsip_media_type_init2(&compare, type, subtype);
5268 
5269  return pjsip_media_type_cmp(content_type, &compare, 0) ? 0 : -1;
5270 }
static const char type[]
Definition: chan_ooh323.c:109
static int compare(const char *text, const char *template)

◆ ast_sip_modify_id_header()

void ast_sip_modify_id_header ( pj_pool_t *  pool,
pjsip_fromto_hdr *  id_hdr,
const struct ast_party_id id 
)

Set name and number information on an identity header.

Parameters
poolMemory pool to use for string duplication
id_hdrA From, P-Asserted-Identity, or Remote-Party-ID header to modify
idThe identity information to apply to the header

Definition at line 5587 of file res_pjsip.c.

References ast_alloca, ast_escape_quoted(), ast_strlen_zero, ast_party_id::name, NULL, ast_party_id::number, ast_party_name::str, ast_party_number::str, ast_party_name::valid, and ast_party_number::valid.

Referenced by add_pai_header(), add_rpid_header(), and set_from_header().

5588 {
5589  pjsip_name_addr *id_name_addr;
5590  pjsip_sip_uri *id_uri;
5591 
5592  id_name_addr = (pjsip_name_addr *) id_hdr->uri;
5593  id_uri = pjsip_uri_get_uri(id_name_addr->uri);
5594 
5595  if (id->name.valid) {
5596  if (!ast_strlen_zero(id->name.str)) {
5597  int name_buf_len = strlen(id->name.str) * 2 + 1;
5598  char *name_buf = ast_alloca(name_buf_len);
5599 
5600  ast_escape_quoted(id->name.str, name_buf, name_buf_len);
5601  pj_strdup2(pool, &id_name_addr->display, name_buf);
5602  } else {
5603  pj_strdup2(pool, &id_name_addr->display, NULL);
5604  }
5605  }
5606 
5607  if (id->number.valid) {
5608  pj_strdup2(pool, &id_uri->user, id->number.str);
5609  }
5610 }
char * str
Subscriber phone number (Malloced)
Definition: channel.h:292
struct ast_party_name name
Subscriber name.
Definition: channel.h:341
static pj_pool_t * pool
Global memory pool for configuration and timers.
char * str
Subscriber name (Malloced)
Definition: channel.h:265
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
char * ast_escape_quoted(const char *string, char *outbuf, int buflen)
Escape characters found in a quoted string.
Definition: main/utils.c:635
unsigned char valid
TRUE if the name information is valid/present.
Definition: channel.h:280
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:298
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:343

◆ ast_sip_push_task_wait()

static int ast_sip_push_task_wait ( struct ast_taskprocessor serializer,
int(*)(void *)  sip_task,
void *  task_data 
)
static

Definition at line 5176 of file res_pjsip.c.

References ast_cond_destroy, ast_cond_init, ast_cond_wait, ast_mutex_destroy, ast_mutex_init, ast_mutex_lock, ast_mutex_unlock, ast_sip_push_task(), sync_task_data::complete, sync_task_data::cond, sync_task_data::fail, sync_task_data::lock, NULL, sync_task(), sync_task_data::task, and sync_task_data::task_data.

Referenced by ast_sip_push_task_wait_serializer(), and ast_sip_push_task_wait_servant().

5177 {
5178  /* This method is an onion */
5179  struct sync_task_data std;
5180 
5181  memset(&std, 0, sizeof(std));
5182  ast_mutex_init(&std.lock);
5183  ast_cond_init(&std.cond, NULL);
5184  std.task = sip_task;
5185  std.task_data = task_data;
5186 
5187  if (ast_sip_push_task(serializer, sync_task, &std)) {
5188  ast_mutex_destroy(&std.lock);
5189  ast_cond_destroy(&std.cond);
5190  return -1;
5191  }
5192 
5193  ast_mutex_lock(&std.lock);
5194  while (!std.complete) {
5195  ast_cond_wait(&std.cond, &std.lock);
5196  }
5197  ast_mutex_unlock(&std.lock);
5198 
5199  ast_mutex_destroy(&std.lock);
5200  ast_cond_destroy(&std.cond);
5201  return std.fail;
5202 }
#define ast_cond_wait(cond, mutex)
Definition: lock.h:203
#define ast_cond_init(cond, attr)
Definition: lock.h:199
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
int ast_sip_push_task(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Pushes a task to SIP servants.
Definition: res_pjsip.c:5138
#define ast_cond_destroy(cond)
Definition: lock.h:200
static int sync_task(void *data)
Definition: res_pjsip.c:5156
void * task_data
Definition: stasis.c:1280
#define ast_mutex_init(pmutex)
Definition: lock.h:184
#define ast_mutex_destroy(a)
Definition: lock.h:186
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ ast_sip_rdata_get_header_value()

char* ast_sip_rdata_get_header_value ( pjsip_rx_data *  rdata,
const pj_str_t  str 
)

Get a specific header value from rdata.

Note
The returned value does not need to be freed since it's from the rdata pool
Parameters
rdataThe rdata
strThe header to find
Return values
NULLon failure
Theheader value on success

Definition at line 3543 of file res_pjsip.c.

References NULL.

Referenced by stir_shaken_incoming_request().

3544 {
3545  pjsip_generic_string_hdr *hdr;
3546  pj_str_t hdr_val;
3547 
3548  hdr = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &str, NULL);
3549  if (!hdr) {
3550  return NULL;
3551  }
3552 
3553  pj_strdup_with_null(rdata->tp_info.pool, &hdr_val, &hdr->hvalue);
3554 
3555  return hdr_val.ptr;
3556 }
const char * str
Definition: app_jack.c:147
#define NULL
Definition: resample.c:96

◆ ast_sip_register_authenticator()

int ast_sip_register_authenticator ( struct ast_sip_authenticator auth)

Register a SIP authenticator.

An authenticator has three main purposes: 1) Determining if authentication should be performed on an incoming request 2) Gathering credentials necessary for issuing an authentication challenge 3) Authenticating a request that has credentials

Asterisk provides a default authenticator, but it may be replaced by a custom one if desired.

Parameters
authThe authenticator to register
Return values
0Success
-1Failure

Definition at line 3338 of file res_pjsip.c.

References ast_debug, ast_log, and LOG_WARNING.

Referenced by load_module().

3339 {
3341  ast_log(LOG_WARNING, "Authenticator %p is already registered. Cannot register a new one\n", registered_authenticator);
3342  return -1;
3343  }
3344  registered_authenticator = auth;
3345  ast_debug(1, "Registered SIP authenticator module %p\n", auth);
3346 
3347  return 0;
3348 }
static struct ast_sip_authenticator * registered_authenticator
Definition: res_pjsip.c:3336
#define LOG_WARNING
Definition: logger.h:274
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42

◆ ast_sip_register_endpoint_formatter()

void ast_sip_register_endpoint_formatter ( struct ast_sip_endpoint_formatter obj)

Register an endpoint formatter.

Parameters
objthe formatter to register

Definition at line 3679 of file res_pjsip.c.

References AST_RWLIST_INSERT_TAIL, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, lock, ast_cli_entry::next, and SCOPED_LOCK.

Referenced by ast_res_pjsip_init_options_handling(), ast_sip_initialize_sorcery_auth(), ast_sip_initialize_sorcery_location(), ast_sip_initialize_sorcery_transport(), and load_module().

3680 {
3683 }
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
ast_mutex_t lock
Definition: app_meetme.c:1091
#define SCOPED_LOCK(varname, lock, lockfunc, unlockfunc)
Scoped Locks.
Definition: lock.h:581
#define AST_RWLIST_INSERT_TAIL
Definition: linkedlists.h:740

◆ ast_sip_register_endpoint_identifier()

int ast_sip_register_endpoint_identifier ( struct ast_sip_endpoint_identifier identifier)

Register a SIP endpoint identifier.

An endpoint identifier's purpose is to determine which endpoint a given SIP message has come from.

Multiple endpoint identifiers may be registered so that if an endpoint cannot be identified by one identifier, it may be identified by another.

Asterisk provides two endpoint identifiers. One identifies endpoints based on the user part of the From header URI. The other identifies endpoints based on the source IP address.

If the order in which endpoint identifiers is run is important to you, then be sure to load individual endpoint identifier modules in the order you wish for them to be run in modules.conf

Note
endpoint identifiers registered using this method (no name specified) are placed at the front of the endpoint identifiers list ahead of any named identifiers.
Parameters
identifierThe SIP endpoint identifier to register
Return values
0Success
-1Failure

Definition at line 3508 of file res_pjsip.c.

References ast_sip_register_endpoint_identifier_with_name(), and NULL.

Referenced by load_module().

3509 {
3511 }
#define NULL
Definition: resample.c:96
int ast_sip_register_endpoint_identifier_with_name(struct ast_sip_endpoint_identifier *identifier, const char *name)
Register a SIP endpoint identifier with a name.
Definition: res_pjsip.c:3431

◆ ast_sip_register_endpoint_identifier_with_name()

int ast_sip_register_endpoint_identifier_with_name ( struct ast_sip_endpoint_identifier identifier,
const char *  name 
)

Register a SIP endpoint identifier with a name.

An endpoint identifier's purpose is to determine which endpoint a given SIP message has come from.

Multiple endpoint identifiers may be registered so that if an endpoint cannot be identified by one identifier, it may be identified by another.

Parameters
identifierThe SIP endpoint identifier to register
nameThe name of the endpoint identifier
Return values
0Success
-1Failure

Definition at line 3431 of file res_pjsip.c.

References ast_calloc, ast_debug, ast_free, ast_log, AST_RWLIST_EMPTY, AST_RWLIST_INSERT_AFTER, AST_RWLIST_INSERT_BEFORE_CURRENT, AST_RWLIST_INSERT_HEAD, AST_RWLIST_INSERT_TAIL, AST_RWLIST_NEXT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_sip_get_endpoint_identifier_order(), ast_strlen_zero, endpoint_identifier_list::identifier, lock, LOG_ERROR, endpoint_identifier_list::name, endpoint_identifier_list::priority, and SCOPED_LOCK.

Referenced by ast_sip_register_endpoint_identifier(), and load_module().

3433 {
3434  char *prev, *current, *identifier_order;
3435  struct endpoint_identifier_list *iter, *id_list_item;
3437 
3438  id_list_item = ast_calloc(1, sizeof(*id_list_item));
3439  if (!id_list_item) {
3440  ast_log(LOG_ERROR, "Unable to add endpoint identifier. Out of memory.\n");
3441  return -1;
3442  }
3443  id_list_item->identifier = identifier;
3444  id_list_item->name = name;
3445 
3446  ast_debug(1, "Register endpoint identifier %s(%p)\n", name ?: "", identifier);
3447 
3448  if (ast_strlen_zero(name)) {
3449  /* if an identifier has no name then place in front */
3450  AST_RWLIST_INSERT_HEAD(&endpoint_identifiers, id_list_item, list);
3451  return 0;
3452  }
3453 
3454  /* see if the name of the identifier is in the global endpoint_identifier_order list */
3455  identifier_order = prev = current = ast_sip_get_endpoint_identifier_order();
3456 
3457  if (ast_strlen_zero(identifier_order)) {
3458  id_list_item->priority = UINT_MAX;
3459  AST_RWLIST_INSERT_TAIL(&endpoint_identifiers, id_list_item, list);
3460  ast_free(identifier_order);
3461  return 0;
3462  }
3463 
3464  id_list_item->priority = 0;
3465  while ((current = strchr(current, ','))) {
3466  ++id_list_item->priority;
3467  if (!strncmp(prev, name, current - prev)
3468  && strlen(name) == current - prev) {
3469  break;
3470  }
3471  prev = ++current;
3472  }
3473 
3474  if (!current) {
3475  /* check to see if it is the only or last item */
3476  if (!strcmp(prev, name)) {
3477  ++id_list_item->priority;
3478  } else {
3479  id_list_item->priority = UINT_MAX;
3480  }
3481  }
3482 
3483  if (id_list_item->priority == UINT_MAX || AST_RWLIST_EMPTY(&endpoint_identifiers)) {
3484  /* if not in the endpoint_identifier_order list then consider it less in
3485  priority and add it to the end */
3486  AST_RWLIST_INSERT_TAIL(&endpoint_identifiers, id_list_item, list);
3487  ast_free(identifier_order);
3488  return 0;
3489  }
3490 
3492  if (id_list_item->priority < iter->priority) {
3493  AST_RWLIST_INSERT_BEFORE_CURRENT(id_list_item, list);
3494  break;
3495  }
3496 
3497  if (!AST_RWLIST_NEXT(iter, list)) {
3498  AST_RWLIST_INSERT_AFTER(&endpoint_identifiers, iter, id_list_item, list);
3499  break;
3500  }
3501  }
3503 
3504  ast_free(identifier_order);
3505  return 0;
3506 }
#define AST_RWLIST_NEXT
Definition: linkedlists.h:440
#define AST_RWLIST_INSERT_AFTER
Definition: linkedlists.h:701
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define AST_RWLIST_INSERT_HEAD
Definition: linkedlists.h:717
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
ast_mutex_t lock
Definition: app_meetme.c:1091
#define SCOPED_LOCK(varname, lock, lockfunc, unlockfunc)
Scoped Locks.
Definition: lock.h:581
#define AST_RWLIST_INSERT_BEFORE_CURRENT
Definition: linkedlists.h:609
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
Definition: linkedlists.h:544
#define AST_RWLIST_EMPTY
Definition: linkedlists.h:451
#define LOG_ERROR
Definition: logger.h:285
char * ast_sip_get_endpoint_identifier_order(void)
Retrieve the global endpoint_identifier_order setting.
static const char name[]
Definition: cdr_mysql.c:74
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
struct ast_sip_endpoint_identifier * identifier
Definition: res_pjsip.c:3425
#define AST_RWLIST_INSERT_TAIL
Definition: linkedlists.h:740
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:616

◆ ast_sip_register_outbound_authenticator()

int ast_sip_register_outbound_authenticator ( struct ast_sip_outbound_authenticator outbound_auth)

Register an outbound SIP authenticator.

An outbound authenticator is responsible for creating responses to authentication challenges by remote endpoints.

Parameters
authThe authenticator to register
Return values
0Success
-1Failure

Definition at line 3389 of file res_pjsip.c.

References ast_debug, ast_log, and LOG_WARNING.

Referenced by load_module().

3390 {
3392  ast_log(LOG_WARNING, "Outbound authenticator %p is already registered. Cannot register a new one\n", registered_outbound_authenticator);
3393  return -1;
3394  }
3396  ast_debug(1, "Registered SIP outbound authenticator module %p\n", auth);
3397 
3398  return 0;
3399 }
#define LOG_WARNING
Definition: logger.h:274
static struct ast_sip_outbound_authenticator * registered_outbound_authenticator
Definition: res_pjsip.c:3387
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42

◆ ast_sip_register_service()

int ast_sip_register_service ( pjsip_module *  module)

Register a SIP service in Asterisk.

This is more-or-less a wrapper around pjsip_endpt_register_module(). Registering a service makes it so that PJSIP will call into the service at appropriate times. For more information about PJSIP module callbacks, see the PJSIP documentation. Asterisk modules that call this function will likely do so at module load time.

Parameters
moduleThe module that is to be registered with PJSIP
Return values
0Success
-1Failure

Definition at line 3315 of file res_pjsip.c.

References ast_sip_push_task_wait_servant(), NULL, and register_service().

Referenced by ast_res_pjsip_init_message_filter(), ast_sip_initialize_distributor(), ast_sip_initialize_global_headers(), ast_sip_initialize_transport_management(), and load_module().

3316 {
3318 }
#define NULL
Definition: resample.c:96
static int register_service(void *data)
Definition: res_pjsip.c:3300
int ast_sip_push_task_wait_servant(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Push a task to SIP servants and wait for it to complete.
Definition: res_pjsip.c:5204

◆ ast_sip_register_supplement()

void ast_sip_register_supplement ( struct ast_sip_supplement supplement)

Register a supplement to SIP out of dialog processing.

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

Parameters
supplementThe supplement to register
Return values
0Success
-1Failure

Definition at line 4511 of file res_pjsip.c.

References AST_RWLIST_INSERT_BEFORE_CURRENT, AST_RWLIST_INSERT_TAIL, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, lock, ast_sip_supplement::next, ast_sip_supplement::priority, and SCOPED_LOCK.

Referenced by ast_res_pjsip_init_message_filter(), and load_module().

4512 {
4513  struct ast_sip_supplement *iter;
4514  int inserted = 0;
4516 
4518  if (iter->priority > supplement->priority) {
4520  inserted = 1;
4521  break;
4522  }
4523  }
4525 
4526  if (!inserted) {
4527  AST_RWLIST_INSERT_TAIL(&supplements, supplement, next);
4528  }
4529 }
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
ast_mutex_t lock
Definition: app_meetme.c:1091
struct ast_sip_supplement * next
Definition: res_pjsip.h:2938
#define SCOPED_LOCK(varname, lock, lockfunc, unlockfunc)
Scoped Locks.
Definition: lock.h:581
#define AST_RWLIST_INSERT_BEFORE_CURRENT
Definition: linkedlists.h:609
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
Definition: linkedlists.h:544
#define AST_RWLIST_INSERT_TAIL
Definition: linkedlists.h:740
A supplement to SIP message processing.
Definition: res_pjsip.h:2888
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:616
enum ast_sip_supplement_priority priority
Definition: res_pjsip.h:2892

◆ ast_sip_requires_authentication()

int ast_sip_requires_authentication ( struct ast_sip_endpoint endpoint,
pjsip_rx_data *  rdata 
)

Determine if an incoming request requires authentication.

This calls into the registered authenticator's requires_authentication callback in order to determine if the request requires authentication.

If there is no registered authenticator, then authentication will be assumed not to be required.

Parameters
endpointThe endpoint from which the request originates
rdataThe incoming SIP request
Return values
non-zeroThe request requires authentication
0The request does not require authentication

Definition at line 3361 of file res_pjsip.c.

References ast_sip_endpoint::allow_unauthenticated_options, ast_debug, ast_log, LOG_WARNING, and ast_sip_authenticator::requires_authentication.

Referenced by authenticate().

3362 {
3363  if (endpoint->allow_unauthenticated_options
3364  && !pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_options_method)) {
3365  ast_debug(3, "Skipping OPTIONS authentication due to endpoint configuration\n");
3366  return 0;
3367  }
3368 
3369  if (!registered_authenticator) {
3370  ast_log(LOG_WARNING, "No SIP authenticator registered. Assuming authentication is not required\n");
3371  return 0;
3372  }
3373 
3374  return registered_authenticator->requires_authentication(endpoint, rdata);
3375 }
static struct ast_sip_authenticator * registered_authenticator
Definition: res_pjsip.c:3336
#define LOG_WARNING
Definition: logger.h:274
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
int(* requires_authentication)(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata)
Check if a request requires authentication See ast_sip_requires_authentication for more details...
Definition: res_pjsip.h:955
unsigned int allow_unauthenticated_options
Definition: res_pjsip.h:905

◆ ast_sip_send_out_of_dialog_request()

int ast_sip_send_out_of_dialog_request ( pjsip_tx_data *  tdata,
struct ast_sip_endpoint endpoint,
int  timeout,
void *  token,
void(*)(void *token, pjsip_event *e)  callback 
)

General purpose method for sending an Out-Of-Dialog SIP request.

This is a companion function for ast_sip_create_request. The request created there can be passed to this function, though any request may be passed in.

This will automatically set up handling outbound authentication challenges if they arrive.

Parameters
tdataThe request to send
endpointOptional. If specified, the out-of-dialog request is sent to the endpoint.
timeout.If non-zero, after the timeout the transaction will be terminated and the callback will be called with the PJSIP_EVENT_TIMER type.
tokenData to be passed to the callback upon receipt of out-of-dialog response.
callbackCallback to be called upon receipt of out-of-dialog response.
Return values
0Success
-1Failure (out-of-dialog callback will not be called.)
Note
Timeout processing: There are 2 timers associated with this request, PJSIP timer_b which is set globally in the "system" section of pjsip.conf, and the timeout specified on this call. The timer that expires first (before normal completion) will cause the callback to be run with e->body.tsx_state.type = PJSIP_EVENT_TIMER. The timer that expires second is simply ignored and the callback is not run again.

Definition at line 4993 of file res_pjsip.c.

References ao2_cleanup, AST_LIST_TRAVERSE, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, ast_sip_message_apply_transport(), ast_sip_mod_data_get, ast_sip_mod_data_set, does_method_match(), endpt_send_request(), ast_sip_supplement::method, MOD_DATA_CONTACT, NULL, ast_sip_supplement::outgoing_request, send_request_data_alloc(), supplement_module, and ast_sip_endpoint::transport.

Referenced by ast_sip_send_request(), and sip_options_qualify_contact().

4996 {
4997  struct ast_sip_supplement *supplement;
4998  struct send_request_data *req_data;
4999  struct ast_sip_contact *contact;
5000 
5001  req_data = send_request_data_alloc(endpoint, token, callback);
5002  if (!req_data) {
5003  pjsip_tx_data_dec_ref(tdata);
5004  return -1;
5005  }
5006 
5007  if (endpoint) {
5008  ast_sip_message_apply_transport(endpoint->transport, tdata);
5009  }
5010 
5011  contact = ast_sip_mod_data_get(tdata->mod_data, supplement_module.id, MOD_DATA_CONTACT);
5012 
5014  AST_LIST_TRAVERSE(&supplements, supplement, next) {
5015  if (supplement->outgoing_request
5016  && does_method_match(&tdata->msg->line.req.method.name, supplement->method)) {
5017  supplement->outgoing_request(endpoint, contact, tdata);
5018  }
5019  }
5021 
5022  ast_sip_mod_data_set(tdata->pool, tdata->mod_data, supplement_module.id, MOD_DATA_CONTACT, NULL);
5023  ao2_cleanup(contact);
5024 
5025  if (endpt_send_request(endpoint, tdata, timeout, req_data, send_request_cb)
5026  != PJ_SUCCESS) {
5027  ao2_cleanup(req_data);
5028  return -1;
5029  }
5030 
5031  return 0;
5032 }
const ast_string_field transport
Definition: res_pjsip.h:817
static struct send_request_data * send_request_data_alloc(struct ast_sip_endpoint *endpoint, void *token, void(*callback)(void *token, pjsip_event *e))
Definition: res_pjsip.c:4589
static int timeout
Definition: cdr_mysql.c:86
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
const char * method
Definition: res_pjsip.h:2890
#define NULL
Definition: resample.c:96
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
static pjsip_module supplement_module
Definition: res_pjsip.c:4373
#define ast_sip_mod_data_set(pool, mod_data, id, key, val)
Utilizing a mod_data array for a given id, set the value associated with the given key...
Definition: res_pjsip.h:2670
#define ast_sip_mod_data_get(mod_data, id, key)
Using the dictionary stored in mod_data array at a given id, retrieve the value associated with the g...
Definition: res_pjsip.h:2638
static pj_status_t endpt_send_request(struct ast_sip_endpoint *endpoint, pjsip_tx_data *tdata, pj_int32_t timeout, void *token, pjsip_endpt_send_callback cb)
Definition: res_pjsip.c:4751
static pj_bool_t does_method_match(const pj_str_t *message_method, const char *supplement_method)
Definition: res_pjsip.c:4554
Contact associated with an address of record.
Definition: res_pjsip.h:281
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
void ast_sip_message_apply_transport(const char *transport_name, pjsip_tx_data *tdata)
Apply the configuration for a transport to an outgoing message.
#define MOD_DATA_CONTACT
Definition: res_pjsip.c:3264
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
A supplement to SIP message processing.
Definition: res_pjsip.h:2888
Structure to hold information about an outbound request.
Definition: res_pjsip.c:4571
void(* outgoing_request)(struct ast_sip_endpoint *endpoint, struct ast_sip_contact *contact, struct pjsip_tx_data *tdata)
Called on an outgoing SIP request This method is always called from a SIP servant thread...
Definition: res_pjsip.h:2931
static void send_request_cb(void *token, pjsip_event *e)
Definition: res_pjsip.c:4937

◆ ast_sip_send_request()

int ast_sip_send_request ( pjsip_tx_data *  tdata,
struct pjsip_dialog *  dlg,
struct ast_sip_endpoint endpoint,
void *  token,
void(*)(void *token, pjsip_event *e)  callback 
)

General purpose method for sending a SIP request.

This is a companion function for ast_sip_create_request. The request created there can be passed to this function, though any request may be passed in.

This will automatically set up handling outbound authentication challenges if they arrive.

Parameters
tdataThe request to send
dlgOptional. The dialog in which the request is sent. Otherwise it is out-of-dialog.
endpointOptional. If specified, the out-of-dialog request is sent to the endpoint.
tokenData to be passed to the callback upon receipt of out-of-dialog response.
callbackCallback to be called upon receipt of out-of-dialog response.
Return values
0Success
-1Failure (out-of-dialog callback will not be called.)

Definition at line 5034 of file res_pjsip.c.

References ast_assert, ast_sip_send_out_of_dialog_request(), and send_in_dialog_request().

Referenced by msg_send(), notify_channel(), notify_contact(), notify_uri(), send_unsolicited_mwi_notify_to_contact(), and sendtext().

5037 {
5038  ast_assert(tdata->msg->type == PJSIP_REQUEST_MSG);
5039 
5040  if (dlg) {
5041  return send_in_dialog_request(tdata, dlg);
5042  } else {
5043  return ast_sip_send_out_of_dialog_request(tdata, endpoint, -1, token, callback);
5044  }
5045 }
#define ast_assert(a)
Definition: utils.h:695
int ast_sip_send_out_of_dialog_request(pjsip_tx_data *tdata, struct ast_sip_endpoint *endpoint, int timeout, void *token, void(*callback)(void *token, pjsip_event *e))
General purpose method for sending an Out-Of-Dialog SIP request.
Definition: res_pjsip.c:4993
static int send_in_dialog_request(pjsip_tx_data *tdata, struct pjsip_dialog *dlg)
Definition: res_pjsip.c:4545

◆ ast_sip_send_response()

int ast_sip_send_response ( pjsip_response_addr *  res_addr,
pjsip_tx_data *  tdata,
struct ast_sip_endpoint sip_endpoint 
)

Send a response to an out of dialog request.

Use this function sparingly, since this does not create a transaction within PJSIP. This means that if the request is retransmitted, it is your responsibility to detect this and not process the same request twice, and to send the same response for each retransmission.

Parameters
res_addrThe response address for this response
tdataThe response to send
endpointThe ast_sip_endpoint associated with this response
Return values
0Success
-1Failure

Definition at line 5407 of file res_pjsip.c.

References ast_sip_get_pjsip_endpoint(), NULL, status, and supplement_outgoing_response().

5408 {
5409  pj_status_t status;
5410 
5411  supplement_outgoing_response(tdata, sip_endpoint);
5412  status = pjsip_endpt_send_response(ast_sip_get_pjsip_endpoint(), res_addr, tdata, NULL, NULL);
5413  if (status != PJ_SUCCESS) {
5414  pjsip_tx_data_dec_ref(tdata);
5415  }
5416 
5417  return status == PJ_SUCCESS ? 0 : -1;
5418 }
#define NULL
Definition: resample.c:96
static void supplement_outgoing_response(pjsip_tx_data *tdata, struct ast_sip_endpoint *sip_endpoint)
Definition: res_pjsip.c:5385
jack_status_t status
Definition: app_jack.c:146
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
Definition: res_pjsip.c:3718

◆ ast_sip_send_stateful_response()

int ast_sip_send_stateful_response ( pjsip_rx_data *  rdata,
pjsip_tx_data *  tdata,
struct ast_sip_endpoint sip_endpoint 
)

Send a stateful response to an out of dialog request.

This creates a transaction within PJSIP, meaning that if the request that we are responding to is retransmitted, we will not attempt to re-handle the request.

Parameters
rdataThe request that is being responded to
tdataThe response to send
endpointThe ast_sip_endpoint associated with this response
Since
13.4.0
Return values
0Success
-1Failure

Definition at line 5420 of file res_pjsip.c.

References ao2_cleanup, ast_sip_mod_data_get, ast_sip_mod_data_set, MOD_DATA_CONTACT, NULL, supplement_module, and supplement_outgoing_response().

Referenced by register_aor(), send_options_response(), and send_response().

5421 {
5422  pjsip_transaction *tsx;
5423 
5424  if (pjsip_tsx_create_uas(NULL, rdata, &tsx) != PJ_SUCCESS) {
5425  struct ast_sip_contact *contact;
5426 
5427  /* ast_sip_create_response bumps the refcount of the contact and adds it to the tdata.
5428  * We'll leak that reference if we don't get rid of it here.
5429  */
5430  contact = ast_sip_mod_data_get(tdata->mod_data, supplement_module.id, MOD_DATA_CONTACT);
5431  ao2_cleanup(contact);
5432  ast_sip_mod_data_set(tdata->pool, tdata->mod_data, supplement_module.id, MOD_DATA_CONTACT, NULL);
5433  pjsip_tx_data_dec_ref(tdata);
5434  return -1;
5435  }
5436  pjsip_tsx_recv_msg(tsx, rdata);
5437 
5438  supplement_outgoing_response(tdata, sip_endpoint);
5439 
5440  if (pjsip_tsx_send_msg(tsx, tdata) != PJ_SUCCESS) {
5441  pjsip_tx_data_dec_ref(tdata);
5442  return -1;
5443  }
5444 
5445  return 0;
5446 }
#define NULL
Definition: resample.c:96
static pjsip_module supplement_module
Definition: res_pjsip.c:4373
#define ast_sip_mod_data_set(pool, mod_data, id, key, val)
Utilizing a mod_data array for a given id, set the value associated with the given key...
Definition: res_pjsip.h:2670
#define ast_sip_mod_data_get(mod_data, id, key)
Using the dictionary stored in mod_data array at a given id, retrieve the value associated with the g...
Definition: res_pjsip.h:2638
static void supplement_outgoing_response(pjsip_tx_data *tdata, struct ast_sip_endpoint *sip_endpoint)
Definition: res_pjsip.c:5385
Contact associated with an address of record.
Definition: res_pjsip.h:281
#define MOD_DATA_CONTACT
Definition: res_pjsip.c:3264
#define ao2_cleanup(obj)
Definition: astobj2.h:1958

◆ ast_sip_set_outbound_proxy()

int ast_sip_set_outbound_proxy ( pjsip_tx_data *  tdata,
const char *  proxy 
)

Set the outbound proxy for an outbound SIP message.

Parameters
tdataThe message to set the outbound proxy on
proxySIP uri of the proxy
Return values
0Success
-1Failure

Definition at line 5047 of file res_pjsip.c.

References NULL, and tmp().

Referenced by create_out_of_dialog_request(), path_outgoing_request(), and sip_options_qualify_contact().

5048 {
5049  pjsip_route_hdr *route;
5050  static const pj_str_t ROUTE_HNAME = { "Route", 5 };
5051  pj_str_t tmp;
5052 
5053  pj_strdup2_with_null(tdata->pool, &tmp, proxy);
5054  if (!(route = pjsip_parse_hdr(tdata->pool, &ROUTE_HNAME, tmp.ptr, tmp.slen, NULL))) {
5055  return -1;
5056  }
5057 
5058  pj_list_insert_nodes_before(&tdata->msg->hdr, (pjsip_hdr*)route);
5059 
5060  return 0;
5061 }
static int tmp()
Definition: bt_open.c:389
#define NULL
Definition: resample.c:96

◆ ast_sip_set_tpselector_from_ep_or_uri()

int ast_sip_set_tpselector_from_ep_or_uri ( const struct ast_sip_endpoint endpoint,
pjsip_sip_uri *  sip_uri,
pjsip_tpselector *  selector 
)

Sets pjsip_tpselector from an endpoint or uri.

Since
13.15.0
Parameters
endpointIf endpoint->transport is set, it's used
sip_uriIf sip_uri contains a x-ast-txp parameter, it's used
selectorThe selector to be populated
Return values
0success
-1failure

Definition at line 3975 of file res_pjsip.c.

References ast_sip_get_transport_name(), and ast_sip_set_tpselector_from_transport_name().

Referenced by ast_sip_dlg_set_transport(), create_dialog_uas(), and create_out_of_dialog_request().

3977 {
3978  char transport_name[128];
3979 
3980  if (ast_sip_get_transport_name(endpoint, sip_uri, transport_name, sizeof(transport_name))) {
3981  return 0;
3982  }
3983 
3984  return ast_sip_set_tpselector_from_transport_name(transport_name, selector);
3985 }
int ast_sip_set_tpselector_from_transport_name(const char *transport_name, pjsip_tpselector *selector)
Sets pjsip_tpselector from ast_sip_transport.
Definition: res_pjsip.c:3957
int ast_sip_get_transport_name(const struct ast_sip_endpoint *endpoint, pjsip_sip_uri *sip_uri, char *buf, size_t buf_len)
Get the transport name from an endpoint or request uri.
Definition: res_pjsip.c:3762

◆ ast_sip_set_tpselector_from_transport()

int ast_sip_set_tpselector_from_transport ( const struct ast_sip_transport transport,
pjsip_tpselector *  selector 
)

Sets pjsip_tpselector from ast_sip_transport.

Since
13.8.0
Parameters
transportThe transport to be used
selectorThe selector to be populated
Return values
0success
-1failure
Note
The transport selector must be unreffed using ast_sip_tpselector_unref

Definition at line 3907 of file res_pjsip.c.

References ao2_lock, ao2_ref, ao2_unlock, ast_log, ast_sip_get_transport_state(), ast_sorcery_object_get_id(), AST_TRANSPORT_WS, AST_TRANSPORT_WSS, ast_sip_transport_state::factory, ast_sip_transport_state::flow, ast_sip_transport::flow, LOG_ERROR, LOG_WARNING, ast_sip_transport_state::transport, and ast_sip_transport::type.

Referenced by ast_sip_set_tpselector_from_transport_name().

3908 {
3909  int res = 0;
3910  struct ast_sip_transport_state *transport_state;
3911 
3912  transport_state = ast_sip_get_transport_state(ast_sorcery_object_get_id(transport));
3913  if (!transport_state) {
3914  ast_log(LOG_ERROR, "Unable to retrieve PJSIP transport state for '%s'\n",
3915  ast_sorcery_object_get_id(transport));
3916  return -1;
3917  }
3918 
3919  /* Only flows maintain dynamic state which needs protection */
3920  if (transport_state->flow) {
3921  ao2_lock(transport_state);
3922  }
3923 
3924  if (transport_state->transport) {
3925  selector->type = PJSIP_TPSELECTOR_TRANSPORT;
3926  selector->u.transport = transport_state->transport;
3927  pjsip_transport_add_ref(selector->u.transport);
3928  } else if (transport_state->factory) {
3929  selector->type = PJSIP_TPSELECTOR_LISTENER;
3930  selector->u.listener = transport_state->factory;
3931  } else if (transport->type == AST_TRANSPORT_WS || transport->type == AST_TRANSPORT_WSS) {
3932  /* The WebSocket transport has no factory as it can not create outgoing connections, so
3933  * even if an endpoint is locked to a WebSocket transport we let the PJSIP logic
3934  * find the existing connection if available and use it.
3935  */
3936  } else if (transport->flow) {
3937  /* This is a child of another transport, so we need to establish a new connection */
3938 #ifdef HAVE_PJSIP_TRANSPORT_DISABLE_CONNECTION_REUSE
3939  selector->disable_connection_reuse = PJ_TRUE;
3940 #else
3941  ast_log(LOG_WARNING, "Connection reuse could not be disabled on transport '%s' as support is not available\n",
3942  ast_sorcery_object_get_id(transport));
3943 #endif
3944  } else {
3945  res = -1;
3946  }
3947 
3948  if (transport_state->flow) {
3949  ao2_unlock(transport_state);
3950  }
3951 
3952  ao2_ref(transport_state, -1);
3953 
3954  return res;
3955 }
#define LOG_WARNING
Definition: logger.h:274
#define ao2_unlock(a)
Definition: astobj2.h:730
enum ast_transport type
Definition: res_pjsip.h:193
#define ast_log
Definition: astobj2.c:42
Structure for SIP transport information.
Definition: res_pjsip.h:87
struct pjsip_transport * transport
Transport itself.
Definition: res_pjsip.h:89
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
#define LOG_ERROR
Definition: logger.h:285
struct ast_sip_transport_state * ast_sip_get_transport_state(const char *transport_id)
Retrieve transport state.
struct pjsip_tpfactory * factory
Transport factory.
Definition: res_pjsip.h:91

◆ ast_sip_set_tpselector_from_transport_name()

int ast_sip_set_tpselector_from_transport_name ( const char *  transport_name,
pjsip_tpselector *  selector 
)

Sets pjsip_tpselector from ast_sip_transport.

Since
13.8.0
Parameters
transport_nameThe name of the transport to be used
selectorThe selector to be populated
Return values
0success
-1failure
Note
The transport selector must be unreffed using ast_sip_tpselector_unref

Definition at line 3957 of file res_pjsip.c.

References ao2_cleanup, ast_log, ast_sip_get_sorcery(), ast_sip_set_tpselector_from_transport(), ast_sorcery_retrieve_by_id(), ast_strlen_zero, LOG_ERROR, NULL, RAII_VAR, and ast_sip_transport_state::transport.

Referenced by ast_sip_set_tpselector_from_ep_or_uri(), registration_client_send(), set_transport(), and sip_outbound_registration_regc_alloc().

3958 {
3960 
3961  if (ast_strlen_zero(transport_name)) {
3962  return 0;
3963  }
3964 
3965  transport = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "transport", transport_name);
3966  if (!transport) {
3967  ast_log(LOG_ERROR, "Unable to retrieve PJSIP transport '%s'\n",
3968  transport_name);
3969  return -1;
3970  }
3971 
3973 }
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
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:1853
#define ast_log
Definition: astobj2.c:42
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
struct pjsip_transport * transport
Transport itself.
Definition: res_pjsip.h:89
#define LOG_ERROR
Definition: logger.h:285
Transport to bind to.
Definition: res_pjsip.h:171
int ast_sip_set_tpselector_from_transport(const struct ast_sip_transport *transport, pjsip_tpselector *selector)
Sets pjsip_tpselector from ast_sip_transport.
Definition: res_pjsip.c:3907
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958

◆ ast_sip_str_to_dtmf()

int ast_sip_str_to_dtmf ( const char *  dtmf_mode)

Convert the DTMF mode name into an enum.

Since
13.18.0
Parameters
dtmf_modedtmf mode as a string
Return values
>=0 The enum value
-1Failure

Definition at line 5513 of file res_pjsip.c.

References 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, and result.

Referenced by dtmf_handler(), and pjsip_acf_dtmf_mode_write().

5514 {
5515  int result = -1;
5516 
5517  if (!strcasecmp(dtmf_mode, "info")) {
5518  result = AST_SIP_DTMF_INFO;
5519  } else if (!strcasecmp(dtmf_mode, "rfc4733")) {
5520  result = AST_SIP_DTMF_RFC_4733;
5521  } else if (!strcasecmp(dtmf_mode, "inband")) {
5522  result = AST_SIP_DTMF_INBAND;
5523  } else if (!strcasecmp(dtmf_mode, "none")) {
5524  result = AST_SIP_DTMF_NONE;
5525  } else if (!strcasecmp(dtmf_mode, "auto")) {
5526  result = AST_SIP_DTMF_AUTO;
5527  } else if (!strcasecmp(dtmf_mode, "auto_info")) {
5528  result = AST_SIP_DTMF_AUTO_INFO;
5529  }
5530 
5531  return result;
5532 }
static PGresult * result
Definition: cel_pgsql.c:88

◆ ast_sip_threadpool()

struct ast_threadpool* ast_sip_threadpool ( void  )

Retrieve the SIP threadpool object.

Definition at line 5630 of file res_pjsip.c.

References sip_threadpool.

Referenced by load_module().

5631 {
5632  return sip_threadpool;
5633 }
static struct ast_threadpool * sip_threadpool
Definition: res_pjsip.c:3274

◆ ast_sip_threadpool_queue_size()

long ast_sip_threadpool_queue_size ( void  )

Return the size of the SIP threadpool's task queue.

Since
13.7.0

Definition at line 5625 of file res_pjsip.c.

References ast_threadpool_queue_size().

5626 {
5628 }
static struct ast_threadpool * sip_threadpool
Definition: res_pjsip.c:3274
long ast_threadpool_queue_size(struct ast_threadpool *pool)
Return the size of the threadpool&#39;s task queue.
Definition: threadpool.c:1437

◆ ast_sip_tpselector_unref()

void ast_sip_tpselector_unref ( pjsip_tpselector *  selector)

Unreference a pjsip_tpselector.

Since
17.0.0
Parameters
selectorThe selector to be unreffed

Definition at line 3987 of file res_pjsip.c.

Referenced by ast_sip_create_dialog_uac(), ast_sip_dlg_set_transport(), create_dialog_uas(), create_out_of_dialog_request(), registration_client_send(), set_transport(), and sip_outbound_registration_regc_alloc().

3988 {
3989  if (selector->type == PJSIP_TPSELECTOR_TRANSPORT && selector->u.transport) {
3990  pjsip_transport_dec_ref(selector->u.transport);
3991  }
3992 }

◆ ast_sip_unregister_authenticator()

void ast_sip_unregister_authenticator ( struct ast_sip_authenticator auth)

Unregister a SIP authenticator.

When there is no authenticator registered, requests cannot be challenged or authenticated.

Parameters
authThe authenticator to unregister

Definition at line 3350 of file res_pjsip.c.

References ast_debug, ast_log, LOG_WARNING, and NULL.

Referenced by unload_module().

3351 {
3352  if (registered_authenticator != auth) {
3353  ast_log(LOG_WARNING, "Trying to unregister authenticator %p but authenticator %p registered\n",
3354  auth, registered_authenticator);
3355  return;
3356  }
3358  ast_debug(1, "Unregistered SIP authenticator %p\n", auth);
3359 }
static struct ast_sip_authenticator * registered_authenticator
Definition: res_pjsip.c:3336
#define LOG_WARNING
Definition: logger.h:274
#define NULL
Definition: resample.c:96
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42

◆ ast_sip_unregister_endpoint_formatter()

void ast_sip_unregister_endpoint_formatter ( struct ast_sip_endpoint_formatter obj)

Unregister an endpoint formatter.

Parameters
objthe formatter to unregister

Definition at line 3685 of file res_pjsip.c.

References AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, lock, and SCOPED_LOCK.

Referenced by ast_res_pjsip_cleanup_options_handling(), ast_sip_destroy_sorcery_auth(), ast_sip_destroy_sorcery_location(), ast_sip_destroy_sorcery_transport(), and unload_module().

3686 {
3687  struct ast_sip_endpoint_formatter *i;
3689 
3691  if (i == obj) {
3693  break;
3694  }
3695  }
3697 }
An entity responsible formatting endpoint information.
Definition: res_pjsip.h:2763
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
ast_mutex_t lock
Definition: app_meetme.c:1091
#define AST_RWLIST_REMOVE_CURRENT
Definition: linkedlists.h:569
#define SCOPED_LOCK(varname, lock, lockfunc, unlockfunc)
Scoped Locks.
Definition: lock.h:581
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
Definition: linkedlists.h:544
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:616

◆ ast_sip_unregister_endpoint_identifier()

void ast_sip_unregister_endpoint_identifier ( struct ast_sip_endpoint_identifier identifier)

Unregister a SIP endpoint identifier.

This stops an endpoint identifier from being used.

Parameters
identifierThe SIP endoint identifier to unregister

Definition at line 3513 of file res_pjsip.c.

References ast_debug, ast_free, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, endpoint_identifier_list::identifier, lock, and SCOPED_LOCK.

Referenced by unload_module().

3514 {
3515  struct endpoint_identifier_list *iter;
3518  if (iter->identifier == identifier) {
3520  ast_free(iter);
3521  ast_debug(1, "Unregistered endpoint identifier %p\n", identifier);
3522  break;
3523  }
3524  }
3526 }
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
ast_mutex_t lock
Definition: app_meetme.c:1091
#define AST_RWLIST_REMOVE_CURRENT
Definition: linkedlists.h:569
#define SCOPED_LOCK(varname, lock, lockfunc, unlockfunc)
Scoped Locks.
Definition: lock.h:581
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
Definition: linkedlists.h:544
#define ast_free(a)
Definition: astmm.h:182
struct ast_sip_endpoint_identifier * identifier
Definition: res_pjsip.c:3425
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:616

◆ ast_sip_unregister_outbound_authenticator()

void ast_sip_unregister_outbound_authenticator ( struct ast_sip_outbound_authenticator auth)

Unregister an outbound SIP authenticator.

When there is no outbound authenticator registered, authentication challenges will be handled as any other final response would be.

Parameters
authThe authenticator to unregister

Definition at line 3401 of file res_pjsip.c.

References ast_debug, ast_log, LOG_WARNING, and NULL.

Referenced by unload_module().

3402 {
3403  if (registered_outbound_authenticator != auth) {
3404  ast_log(LOG_WARNING, "Trying to unregister outbound authenticator %p but outbound authenticator %p registered\n",
3406  return;
3407  }
3409  ast_debug(1, "Unregistered SIP outbound authenticator %p\n", auth);
3410 }
#define LOG_WARNING
Definition: logger.h:274
static struct ast_sip_outbound_authenticator * registered_outbound_authenticator
Definition: res_pjsip.c:3387
#define NULL
Definition: resample.c:96
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42

◆ ast_sip_unregister_service()

void ast_sip_unregister_service ( pjsip_module *  module)

This is the opposite of ast_sip_register_service(). Unregistering a service means that PJSIP will no longer call into the module any more. This will likely occur when an Asterisk module is unloaded.

Parameters
moduleThe PJSIP module to unregister

Definition at line 3331 of file res_pjsip.c.

References ast_sip_push_task_wait_servant(), NULL, and unregister_service().

Referenced by ast_res_pjsip_cleanup_message_filter(), ast_sip_destroy_distributor(), ast_sip_destroy_global_headers(), ast_sip_destroy_transport_management(), load_module(), unload_module(), and unload_pjsip().

3332 {
3334 }
#define NULL
Definition: resample.c:96
int ast_sip_push_task_wait_servant(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Push a task to SIP servants and wait for it to complete.
Definition: res_pjsip.c:5204
static int unregister_service(void *data)
Definition: res_pjsip.c:3320

◆ ast_sip_unregister_supplement()

void ast_sip_unregister_supplement ( struct ast_sip_supplement supplement)

Unregister a an supplement to SIP out of dialog processing.

Parameters
supplementThe supplement to unregister

Definition at line 4531 of file res_pjsip.c.

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

Referenced by ast_res_pjsip_cleanup_message_filter(), and unload_module().

4532 {
4533  struct ast_sip_supplement *iter;
4535 
4537  if (supplement == iter) {
4539  break;
4540  }
4541  }
4543 }
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
ast_mutex_t lock
Definition: app_meetme.c:1091
#define AST_RWLIST_REMOVE_CURRENT
Definition: linkedlists.h:569
struct ast_sip_supplement * next
Definition: res_pjsip.h:2938
#define SCOPED_LOCK(varname, lock, lockfunc, unlockfunc)
Scoped Locks.
Definition: lock.h:581
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
Definition: linkedlists.h:544
A supplement to SIP message processing.
Definition: res_pjsip.h:2888
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:616

◆ ast_sip_will_uri_survive_restart()

int ast_sip_will_uri_survive_restart ( pjsip_sip_uri *  uri,
struct ast_sip_endpoint endpoint,
pjsip_rx_data *  rdata 
)

Definition at line 3723 of file res_pjsip.c.

References ast_sip_endpoint::nat, result, and ast_sip_endpoint_nat_configuration::rewrite_contact.

Referenced by register_aor_core(), and subscription_persistence_update().

3725 {
3726  pj_str_t host_name;
3727  int result = 1;
3728 
3729  /* Determine if the contact cannot survive a restart/boot. */
3730  if (uri->port == rdata->pkt_info.src_port
3731  && !pj_strcmp(&uri->host,
3732  pj_cstr(&host_name, rdata->pkt_info.src_name))
3733  /* We have already checked if the URI scheme is sip: or sips: */
3734  && PJSIP_TRANSPORT_IS_RELIABLE(rdata->tp_info.transport)) {
3735  pj_str_t type_name;
3736 
3737  /* Determine the transport parameter value */
3738  if (!strcasecmp("WSS", rdata->tp_info.transport->type_name)) {
3739  /* WSS is special, as it needs to be ws. */
3740  pj_cstr(&type_name, "ws");
3741  } else {
3742  pj_cstr(&type_name, rdata->tp_info.transport->type_name);
3743  }
3744 
3745  if (!pj_stricmp(&uri->transport_param, &type_name)
3746  && (endpoint->nat.rewrite_contact
3747  /* Websockets are always rewritten */
3748  || !pj_stricmp(&uri->transport_param,
3749  pj_cstr(&type_name, "ws")))) {
3750  /*
3751  * The contact was rewritten to the reliable transport's
3752  * source address. Disconnecting the transport for any
3753  * reason invalidates the contact.
3754  */
3755  result = 0;
3756  }
3757  }
3758 
3759  return result;
3760 }
struct ast_sip_endpoint_nat_configuration nat
Definition: res_pjsip.h:845
static PGresult * result
Definition: cel_pgsql.c:88

◆ AST_TEST_DEFINE() [1/2]

AST_TEST_DEFINE ( xml_sanitization_end_null  )

Definition at line 5636 of file res_pjsip.c.

References ast_sip_sanitize_xml(), AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, sip_to_pjsip::info(), TEST_EXECUTE, and TEST_INIT.

5637 {
5638  char sanitized[8];
5639 
5640  switch (cmd) {
5641  case TEST_INIT:
5642  info->name = "xml_sanitization_end_null";
5643  info->category = "/res/res_pjsip/";
5644  info->summary = "Ensure XML sanitization works as expected with a long string";
5645  info->description = "This test sanitizes a string which exceeds the output\n"
5646  "buffer size. Once done the string is confirmed to be NULL terminated.";
5647  return AST_TEST_NOT_RUN;
5648  case TEST_EXECUTE:
5649  break;
5650  }
5651 
5652  ast_sip_sanitize_xml("aaaaaaaaaaaa", sanitized, sizeof(sanitized));
5653  if (sanitized[7] != '\0') {
5654  ast_test_status_update(test, "Sanitized XML string is not null-terminated when it should be\n");
5655  return AST_TEST_FAIL;
5656  }
5657 
5658  return AST_TEST_PASS;
5659 }
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
def info(msg)
void ast_sip_sanitize_xml(const char *input, char *output, size_t len)
Replace offensive XML characters with XML entities.
Definition: presence_xml.c:29

◆ AST_TEST_DEFINE() [2/2]

AST_TEST_DEFINE ( xml_sanitization_exceeds_buffer  )

Definition at line 5661 of file res_pjsip.c.

References ast_sip_sanitize_xml(), AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, sip_to_pjsip::info(), TEST_EXECUTE, and TEST_INIT.

5662 {
5663  char sanitized[8];
5664 
5665  switch (cmd) {
5666  case TEST_INIT:
5667  info->name = "xml_sanitization_exceeds_buffer";
5668  info->category = "/res/res_pjsip/";
5669  info->summary = "Ensure XML sanitization does not exceed buffer when output won't fit";
5670  info->description = "This test sanitizes a string which before sanitization would\n"
5671  "fit within the output buffer. After sanitization, however, the string would\n"
5672  "exceed the buffer. Once done the string is confirmed to be NULL terminated.";
5673  return AST_TEST_NOT_RUN;
5674  case TEST_EXECUTE:
5675  break;
5676  }
5677 
5678  ast_sip_sanitize_xml("<><><>&", sanitized, sizeof(sanitized));
5679  if (sanitized[7] != '\0') {
5680  ast_test_status_update(test, "Sanitized XML string is not null-terminated when it should be\n");
5681  return AST_TEST_FAIL;
5682  }
5683 
5684  return AST_TEST_PASS;
5685 }
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
def info(msg)
void ast_sip_sanitize_xml(const char *input, char *output, size_t len)
Replace offensive XML characters with XML entities.
Definition: presence_xml.c:29

◆ check_request_status()

static int check_request_status ( struct send_request_data req_data,
pjsip_event *  e 
)
static

Definition at line 4894 of file res_pjsip.c.

References ao2_bump, ao2_ref, ast_sip_create_request_with_auth(), ast_sip_failover_request(), send_request_data::challenge_count, send_request_data::endpoint, endpt_send_request(), MAX_RX_CHALLENGES, and ast_sip_endpoint::outbound_auths.

Referenced by send_request_cb().

4895 {
4896  struct ast_sip_endpoint *endpoint;
4897  pjsip_transaction *tsx;
4898  pjsip_tx_data *tdata;
4899  int res = 0;
4900 
4901  if (!(endpoint = ao2_bump(req_data->endpoint))) {
4902  return 0;
4903  }
4904 
4905  tsx = e->body.tsx_state.tsx;
4906 
4907  switch (tsx->status_code) {
4908  case 401:
4909  case 407:
4910  /* Resend the request with a challenge response if we are challenged. */
4911  res = ++req_data->challenge_count < MAX_RX_CHALLENGES /* Not in a challenge loop */
4913  e->body.tsx_state.src.rdata, tsx->last_tx, &tdata);
4914  break;
4915  case 408:
4916  case 503:
4917  if ((res = ast_sip_failover_request(tsx->last_tx))) {
4918  tdata = tsx->last_tx;
4919  /*
4920  * Bump the ref since it will be on a new transaction and
4921  * we don't want it to go away along with the old transaction.
4922  */
4923  pjsip_tx_data_add_ref(tdata);
4924  }
4925  break;
4926  }
4927 
4928  if (res) {
4929  res = endpt_send_request(endpoint, tdata, -1,
4930  req_data, send_request_cb) == PJ_SUCCESS;
4931  }
4932 
4933  ao2_ref(endpoint, -1);
4934  return res;
4935 }
struct ast_sip_auth_vector outbound_auths
Definition: res_pjsip.h:855
#define ao2_bump(obj)
Definition: astobj2.h:491
#define ao2_ref(o, delta)
Definition: astobj2.h:464
An entity with which Asterisk communicates.
Definition: res_pjsip.h:812
static pj_status_t endpt_send_request(struct ast_sip_endpoint *endpoint, pjsip_tx_data *tdata, pj_int32_t timeout, void *token, pjsip_endpt_send_callback cb)
Definition: res_pjsip.c:4751
#define MAX_RX_CHALLENGES
Definition: res_pjsip.h:80
int ast_sip_failover_request(pjsip_tx_data *tdata)
Set a request to use the next value in the list of resolved addresses.
Definition: res_pjsip.c:4871
unsigned int challenge_count
Definition: res_pjsip.c:4579
static void send_request_cb(void *token, pjsip_event *e)
Definition: res_pjsip.c:4937
int ast_sip_create_request_with_auth(const struct ast_sip_auth_vector *auths, pjsip_rx_data *challenge, pjsip_tx_data *old_request, pjsip_tx_data **new_request)
Create a response to an authentication challenge.
Definition: res_pjsip.c:3412
struct ast_sip_endpoint * endpoint
Definition: res_pjsip.c:4573

◆ cli_dump_endpt()

static char* cli_dump_endpt ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 3569 of file res_pjsip.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_sip_push_task_wait_servant(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, do_cli_dump_endpt(), NULL, and ast_cli_entry::usage.

3570 {
3571  switch (cmd) {
3572  case CLI_INIT:
3573 #ifdef AST_DEVMODE
3574  e->command = "pjsip dump endpt [details]";
3575  e->usage =
3576  "Usage: pjsip dump endpt [details]\n"
3577  " Dump the res_pjsip endpt internals.\n"
3578  "\n"
3579  "Warning: PJPROJECT documents that the function used by this\n"
3580  "CLI command may cause a crash when asking for details because\n"
3581  "it tries to access all active memory pools.\n";
3582 #else
3583  /*
3584  * In non-developer mode we will not document or make easily accessible
3585  * the details option even though it is still available. The user has
3586  * to know it exists to use it. Presumably they would also be aware of
3587  * the potential crash warning.
3588  */
3589  e->command = "pjsip dump endpt";
3590  e->usage =
3591  "Usage: pjsip dump endpt\n"
3592  " Dump the res_pjsip endpt internals.\n";
3593 #endif /* AST_DEVMODE */
3594  return NULL;
3595  case CLI_GENERATE:
3596  return NULL;
3597  }
3598 
3599  if (4 < a->argc
3600  || (a->argc == 4 && strcasecmp(a->argv[3], "details"))) {
3601  return CLI_SHOWUSAGE;
3602  }
3603 
3605 
3606  return CLI_SUCCESS;
3607 }
const int argc
Definition: cli.h:160
Definition: cli.h:152
#define NULL
Definition: resample.c:96
int ast_sip_push_task_wait_servant(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Push a task to SIP servants and wait for it to complete.
Definition: res_pjsip.c:5204
const char *const * argv
Definition: cli.h:161
#define CLI_SHOWUSAGE
Definition: cli.h:45
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
static int do_cli_dump_endpt(void *v_a)
Definition: res_pjsip.c:3558

◆ cli_show_endpoint_identifiers()

static char* cli_show_endpoint_identifiers ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 3609 of file res_pjsip.c.

References ast_cli_args::argc, ast_cli(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ENDPOINT_IDENTIFIER_FORMAT, ast_cli_args::fd, lock, endpoint_identifier_list::name, NULL, SCOPED_LOCK, and ast_cli_entry::usage.

3610 {
3611 #define ENDPOINT_IDENTIFIER_FORMAT "%-20.20s\n"
3612  struct endpoint_identifier_list *iter;
3613 
3614  switch (cmd) {
3615  case CLI_INIT:
3616  e->command = "pjsip show identifiers";
3617  e->usage = "Usage: pjsip show identifiers\n"
3618  " List all registered endpoint identifiers\n";
3619  return NULL;
3620  case CLI_GENERATE:
3621  return NULL;
3622  }
3623 
3624  if (a->argc != 3) {
3625  return CLI_SHOWUSAGE;
3626  }
3627 
3628  ast_cli(a->fd, ENDPOINT_IDENTIFIER_FORMAT, "Identifier Names:");
3629  {
3633  iter->name ? iter->name : "name not specified");
3634  }
3635  }
3636  return CLI_SUCCESS;
3637 #undef ENDPOINT_IDENTIFIER_FORMAT
3638 }
const int argc
Definition: cli.h:160
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
Definition: cli.h:152
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
#define ENDPOINT_IDENTIFIER_FORMAT
const int fd
Definition: cli.h:159
ast_mutex_t lock
Definition: app_meetme.c:1091
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
#define SCOPED_LOCK(varname, lock, lockfunc, unlockfunc)
Scoped Locks.
Definition: lock.h:581
#define CLI_SHOWUSAGE
Definition: cli.h:45
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44

◆ cli_show_settings()

static char* cli_show_settings ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 3640 of file res_pjsip.c.

References ast_cli(), ast_free, ast_str_buffer(), ast_str_create, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, NULL, ast_sip_cli_context::output_buffer, sip_cli_print_global(), sip_cli_print_system(), and ast_cli_entry::usage.

3641 {
3643 
3644  switch (cmd) {
3645  case CLI_INIT:
3646  e->command = "pjsip show settings";
3647  e->usage = "Usage: pjsip show settings\n"
3648  " Show global and system configuration options\n";
3649  return NULL;
3650  case CLI_GENERATE:
3651  return NULL;
3652  }
3653 
3654  context.output_buffer = ast_str_create(256);
3655  if (!context.output_buffer) {
3656  ast_cli(a->fd, "Could not allocate output buffer.\n");
3657  return CLI_FAILURE;
3658  }
3659 
3661  ast_free(context.output_buffer);
3662  ast_cli(a->fd, "Error retrieving settings.\n");
3663  return CLI_FAILURE;
3664  }
3665 
3666  ast_cli(a->fd, "%s", ast_str_buffer(context.output_buffer));
3667  ast_free(context.output_buffer);
3668  return CLI_SUCCESS;
3669 }
int sip_cli_print_global(struct ast_sip_cli_context *context)
int sip_cli_print_system(struct ast_sip_cli_context *context)
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
Definition: cli.h:152
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
const int fd
Definition: cli.h:159
#define CLI_FAILURE
Definition: cli.h:46
#define ast_free(a)
Definition: astmm.h:182
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620

◆ create_dialog_uas()

static pjsip_dialog* create_dialog_uas ( const struct ast_sip_endpoint endpoint,
pjsip_rx_data *  rdata,
pj_status_t *  status,
create_dlg_uac  create_fun 
)
static

Definition at line 4177 of file res_pjsip.c.

References ast_assert, ast_log, ast_sip_set_tpselector_from_ep_or_uri(), ast_sip_tpselector_unref(), ast_sorcery_object_get_id(), LOG_ERROR, NULL, ast_sip_transport_state::transport, type, and uas_use_sips_contact().

Referenced by ast_sip_create_dialog_uas(), and ast_sip_create_dialog_uas_locked().

4179 {
4180  pjsip_dialog *dlg;
4181  pj_str_t contact;
4182  pjsip_transport_type_e type = rdata->tp_info.transport->key.type;
4183  pjsip_tpselector selector = { .type = PJSIP_TPSELECTOR_NONE, };
4184  pjsip_transport *transport;
4185  pjsip_contact_hdr *contact_hdr;
4186 
4187  ast_assert(status != NULL);
4188 
4189  contact_hdr = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT, NULL);
4190  if (!contact_hdr || ast_sip_set_tpselector_from_ep_or_uri(endpoint, pjsip_uri_get_uri(contact_hdr->uri),
4191  &selector)) {
4192  return NULL;
4193  }
4194 
4195  transport = rdata->tp_info.transport;
4196  if (selector.type == PJSIP_TPSELECTOR_TRANSPORT) {
4197  transport = selector.u.transport;
4198  }
4199  type = transport->key.type;
4200 
4201  contact.ptr = pj_pool_alloc(rdata->tp_info.pool, PJSIP_MAX_URL_SIZE);
4202  contact.slen = pj_ansi_snprintf(contact.ptr, PJSIP_MAX_URL_SIZE,
4203  "<%s:%s%.*s%s:%d%s%s>",
4204  uas_use_sips_contact(rdata) ? "sips" : "sip",
4205  (type & PJSIP_TRANSPORT_IPV6) ? "[" : "",
4206  (int)transport->local_name.host.slen,
4207  transport->local_name.host.ptr,
4208  (type & PJSIP_TRANSPORT_IPV6) ? "]" : "",
4209  transport->local_name.port,
4210  (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? ";transport=" : "",
4211  (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? pjsip_transport_get_type_name(type) : "");
4212 
4213  *status = create_fun(pjsip_ua_instance(), rdata, &contact, &dlg);
4214  if (*status != PJ_SUCCESS) {
4215  char err[PJ_ERR_MSG_SIZE];
4216 
4217  pj_strerror(*status, err, sizeof(err));
4218  ast_log(LOG_ERROR, "Could not create dialog with endpoint %s. %s\n",
4219  ast_sorcery_object_get_id(endpoint), err);
4220  ast_sip_tpselector_unref(&selector);
4221  return NULL;
4222  }
4223 
4224  dlg->sess_count++;
4225  pjsip_dlg_set_transport(dlg, &selector);
4226  dlg->sess_count--;
4227 
4228  ast_sip_tpselector_unref(&selector);
4229 
4230  return dlg;
4231 }
static const char type[]
Definition: chan_ooh323.c:109
#define ast_assert(a)
Definition: utils.h:695
#define NULL
Definition: resample.c:96
#define ast_log
Definition: astobj2.c:42
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
#define LOG_ERROR
Definition: logger.h:285
int ast_sip_set_tpselector_from_ep_or_uri(const struct ast_sip_endpoint *endpoint, pjsip_sip_uri *sip_uri, pjsip_tpselector *selector)
Sets pjsip_tpselector from an endpoint or uri.
Definition: res_pjsip.c:3975
void ast_sip_tpselector_unref(pjsip_tpselector *selector)
Unreference a pjsip_tpselector.
Definition: res_pjsip.c:3987
static int uas_use_sips_contact(pjsip_rx_data *rdata)
Determine if a SIPS Contact header is required.
Definition: res_pjsip.c:4148
jack_status_t status
Definition: app_jack.c:146

◆ create_in_dialog_request()

static int create_in_dialog_request ( const pjsip_method *  method,
struct pjsip_dialog *  dlg,
pjsip_tx_data **  tdata 
)
static

Definition at line 4362 of file res_pjsip.c.

References ast_log, LOG_WARNING, and supplement_on_rx_request().

Referenced by ast_sip_create_request().

4363 {
4364  if (pjsip_dlg_create_request(dlg, method, -1, tdata) != PJ_SUCCESS) {
4365  ast_log(LOG_WARNING, "Unable to create in-dialog request.\n");
4366  return -1;
4367  }
4368 
4369  return 0;
4370 }
#define LOG_WARNING
Definition: logger.h:274
#define ast_log
Definition: astobj2.c:42
const char * method
Definition: res_pjsip.c:4335

◆ create_out_of_dialog_request()

static int create_out_of_dialog_request ( const pjsip_method *  method,
struct ast_sip_endpoint endpoint,
const char *  uri,
struct ast_sip_contact provided_contact,
pjsip_tx_data **  tdata 
)
static

Definition at line 4380 of file res_pjsip.c.

References ao2_bump, ao2_cleanup, ast_sip_endpoint::aors, ast_log, ast_sip_add_usereqphone(), ast_sip_get_pjsip_endpoint(), ast_sip_location_retrieve_contact_from_aor_list(), ast_sip_mod_data_set, ast_sip_set_outbound_proxy(), ast_sip_set_tpselector_from_ep_or_uri(), ast_sip_tpselector_unref(), ast_sorcery_object_get_id(), ast_strlen_zero, ast_sip_endpoint::contact_user, ast_sip_endpoint::fromdomain, ast_sip_endpoint::fromuser, LOG_ERROR, LOG_WARNING, MOD_DATA_CONTACT, NULL, ast_sip_endpoint::outbound_proxy, pool, RAII_VAR, sip_dialog_create_from(), and supplement_module.

Referenced by ast_sip_create_request().

4382 {
4383  RAII_VAR(struct ast_sip_contact *, contact, ao2_bump(provided_contact), ao2_cleanup);
4384  pj_str_t remote_uri;
4385  pj_str_t from;
4386  pj_pool_t *pool;
4387  pjsip_tpselector selector = { .type = PJSIP_TPSELECTOR_NONE, };
4388  pjsip_uri *sip_uri;
4389  const char *fromuser;
4390 
4391  if (ast_strlen_zero(uri)) {
4392  if (!endpoint && (!contact || ast_strlen_zero(contact->uri))) {
4393  ast_log(LOG_ERROR, "An endpoint and/or uri must be specified\n");
4394  return -1;
4395  }
4396 
4397  if (!contact) {
4399  }
4400  if (!contact || ast_strlen_zero(contact->uri)) {
4401  ast_log(LOG_WARNING, "Unable to retrieve contact for endpoint %s\n",
4402  ast_sorcery_object_get_id(endpoint));
4403  return -1;
4404  }
4405 
4406  pj_cstr(&remote_uri, contact->uri);
4407  } else {
4408  pj_cstr(&remote_uri, uri);
4409  }
4410 
4411  pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(), "Outbound request", 256, 256);
4412 
4413  if (!pool) {
4414  ast_log(LOG_ERROR, "Unable to create PJLIB memory pool\n");
4415  return -1;
4416  }
4417 
4418  sip_uri = pjsip_parse_uri(pool, remote_uri.ptr, remote_uri.slen, 0);
4419  if (!sip_uri || (!PJSIP_URI_SCHEME_IS_SIP(sip_uri) && !PJSIP_URI_SCHEME_IS_SIPS(sip_uri))) {
4420  ast_log(LOG_ERROR, "Unable to create outbound %.*s request to endpoint %s as URI '%s' is not valid\n",
4421  (int) pj_strlen(&method->name), pj_strbuf(&method->name),
4422  endpoint ? ast_sorcery_object_get_id(endpoint) : "<none>",
4423  pj_strbuf(&remote_uri));
4424  pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
4425  return -1;
4426  }
4427 
4428  ast_sip_set_tpselector_from_ep_or_uri(endpoint, pjsip_uri_get_uri(sip_uri), &selector);
4429 
4430  fromuser = endpoint ? (!ast_strlen_zero(endpoint->fromuser) ? endpoint->fromuser : ast_sorcery_object_get_id(endpoint)) : NULL;
4431  if (sip_dialog_create_from(pool, &from, fromuser,
4432  endpoint ? endpoint->fromdomain : NULL, &remote_uri, &selector)) {
4433  ast_log(LOG_ERROR, "Unable to create From header for %.*s request to endpoint %s\n",
4434  (int) pj_strlen(&method->name), pj_strbuf(&method->name),
4435  endpoint ? ast_sorcery_object_get_id(endpoint) : "<none>");
4436  pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
4437  ast_sip_tpselector_unref(&selector);
4438  return -1;
4439  }
4440 
4441  if (pjsip_endpt_create_request(ast_sip_get_pjsip_endpoint(), method, &remote_uri,
4442  &from, &remote_uri, &from, NULL, -1, NULL, tdata) != PJ_SUCCESS) {
4443  ast_log(LOG_ERROR, "Unable to create outbound %.*s request to endpoint %s\n",
4444  (int) pj_strlen(&method->name), pj_strbuf(&method->name),
4445  endpoint ? ast_sorcery_object_get_id(endpoint) : "<none>");
4446  pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
4447  ast_sip_tpselector_unref(&selector);
4448  return -1;
4449  }
4450 
4451  pjsip_tx_data_set_transport(*tdata, &selector);
4452 
4453  ast_sip_tpselector_unref(&selector);
4454 
4455  if (endpoint && !ast_strlen_zero(endpoint->contact_user)){
4456  pjsip_contact_hdr *contact_hdr;
4457  pjsip_sip_uri *contact_uri;
4458  static const pj_str_t HCONTACT = { "Contact", 7 };
4459  static const pj_str_t HCONTACTSHORT = { "m", 1 };
4460 
4461  contact_hdr = pjsip_msg_find_hdr_by_names((*tdata)->msg, &HCONTACT, &HCONTACTSHORT, NULL);
4462  if (contact_hdr) {
4463  contact_uri = pjsip_uri_get_uri(contact_hdr->uri);
4464  pj_strdup2((*tdata)->pool, &contact_uri->user, endpoint->contact_user);
4465  }
4466  }
4467 
4468  /* Add the user=phone parameter if applicable */
4469  ast_sip_add_usereqphone(endpoint, (*tdata)->pool, (*tdata)->msg->line.req.uri);
4470 
4471  /* If an outbound proxy is specified on the endpoint apply it to this request */
4472  if (endpoint && !ast_strlen_zero(endpoint->outbound_proxy) &&
4473  ast_sip_set_outbound_proxy((*tdata), endpoint->outbound_proxy)) {
4474  ast_log(LOG_ERROR, "Unable to apply outbound proxy on request %.*s to endpoint %s as outbound proxy URI '%s' is not valid\n",
4475  (int) pj_strlen(&method->name), pj_strbuf(&method->name), ast_sorcery_object_get_id(endpoint),
4476  endpoint->outbound_proxy);
4477  pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
4478  return -1;
4479  }
4480 
4481  ast_sip_mod_data_set((*tdata)->pool, (*tdata)->mod_data, supplement_module.id, MOD_DATA_CONTACT, ao2_bump(contact));
4482 
4483  /* We can release this pool since request creation copied all the necessary
4484  * data into the outbound request's pool
4485  */
4486  pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
4487  return 0;
4488 }
void ast_sip_add_usereqphone(const struct ast_sip_endpoint *endpoint, pj_pool_t *pool, pjsip_uri *uri)
Add &#39;user=phone&#39; parameter to URI if enabled and user is a phone number.
Definition: res_pjsip.c:3994
int ast_sip_set_outbound_proxy(pjsip_tx_data *tdata, const char *proxy)
Set the outbound proxy for an outbound SIP message.
Definition: res_pjsip.c:5047
const ast_string_field fromuser
Definition: res_pjsip.h:829
#define LOG_WARNING
Definition: logger.h:274
char * contact_user
Definition: res_pjsip.h:887
static pj_pool_t * pool
Global memory pool for configuration and timers.
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ao2_bump(obj)
Definition: astobj2.h:491
#define ast_log
Definition: astobj2.c:42
static pjsip_module supplement_module
Definition: res_pjsip.c:4373
#define ast_sip_mod_data_set(pool, mod_data, id, key, val)
Utilizing a mod_data array for a given id, set the value associated with the given key...
Definition: res_pjsip.h:2670
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
const char * method
Definition: res_pjsip.c:4335
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
const ast_string_field outbound_proxy
Definition: res_pjsip.h:819
#define LOG_ERROR
Definition: logger.h:285
int ast_sip_set_tpselector_from_ep_or_uri(const struct ast_sip_endpoint *endpoint, pjsip_sip_uri *sip_uri, pjsip_tpselector *selector)
Sets pjsip_tpselector from an endpoint or uri.
Definition: res_pjsip.c:3975
Contact associated with an address of record.
Definition: res_pjsip.h:281
void ast_sip_tpselector_unref(pjsip_tpselector *selector)
Unreference a pjsip_tpselector.
Definition: res_pjsip.c:3987
#define MOD_DATA_CONTACT
Definition: res_pjsip.c:3264
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
const ast_string_field aors
Definition: res_pjsip.h:821
static int sip_dialog_create_from(pj_pool_t *pool, pj_str_t *from, const char *user, const char *domain, const pj_str_t *target, pjsip_tpselector *selector)
Definition: res_pjsip.c:3813
const ast_string_field fromdomain
Definition: res_pjsip.h:831
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
Definition: res_pjsip.c:3718

◆ do_cli_dump_endpt()

static int do_cli_dump_endpt ( void *  v_a)
static

Definition at line 3558 of file res_pjsip.c.

References a, ast_cli_args::argc, ast_pjproject_log_intercept_begin(), ast_pjproject_log_intercept_end(), ast_sip_get_pjsip_endpoint(), and ast_cli_args::fd.

Referenced by cli_dump_endpt().

3559 {
3560  struct ast_cli_args *a = v_a;
3561 
3563  pjsip_endpt_dump(ast_sip_get_pjsip_endpoint(), a->argc == 4 ? PJ_TRUE : PJ_FALSE);
3565 
3566  return 0;
3567 }
const int argc
Definition: cli.h:160
const int fd
Definition: cli.h:159
void ast_pjproject_log_intercept_end(void)
End PJPROJECT log interception for CLI output.
void ast_pjproject_log_intercept_begin(int fd)
Begin PJPROJECT log interception for CLI output.
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
Definition: res_pjsip.c:3718
static struct test_val a

◆ does_method_match()

static pj_bool_t does_method_match ( const pj_str_t *  message_method,
const char *  supplement_method 
)
static

Definition at line 4554 of file res_pjsip.c.

References ast_strlen_zero, and method.

Referenced by ast_sip_send_out_of_dialog_request(), send_request_cb(), supplement_on_rx_request(), and supplement_outgoing_response().

4555 {
4556  pj_str_t method;
4557 
4558  if (ast_strlen_zero(supplement_method)) {
4559  return PJ_TRUE;
4560  }
4561 
4562  pj_cstr(&method, supplement_method);
4563 
4564  return pj_stristr(&method, message_method) ? PJ_TRUE : PJ_FALSE;
4565 }
static const pjsip_method message_method
Definition: res_pjsip.c:4332
#define ast_strlen_zero(foo)
Definition: strings.h:52
const char * method
Definition: res_pjsip.c:4335

◆ endpt_send_request()

static pj_status_t endpt_send_request ( struct ast_sip_endpoint endpoint,
pjsip_tx_data *  tdata,
pj_int32_t  timeout,
void *  token,
pjsip_endpt_send_callback  cb 
)
static

Definition at line 4751 of file res_pjsip.c.

References ao2_alloc, ao2_lock, ao2_ref, ao2_t_ref, ao2_unlock, ast_debug, ast_log, ast_sip_get_pjsip_endpoint(), ast_sorcery_object_get_id(), send_request_wrapper::callback, send_request_wrapper::cb_called, endpt_send_request_cb(), LOG_ERROR, NULL, send_request_wrapper::send_cb_called, send_request_timer_callback(), send_request_wrapper_destructor(), send_request_wrapper::tdata, timeout, send_request_wrapper::timeout, send_request_wrapper::timeout_timer, TIMEOUT_TIMER2, TIMER_INACTIVE, and send_request_wrapper::token.

Referenced by ast_sip_send_out_of_dialog_request(), and check_request_status().

4753 {
4754  struct send_request_wrapper *req_wrapper;
4755  pj_status_t ret_val;
4756  pjsip_endpoint *endpt = ast_sip_get_pjsip_endpoint();
4757 
4758  if (!cb && token) {
4759  /* Silly. Without a callback we cannot do anything with token. */
4760  pjsip_tx_data_dec_ref(tdata);
4761  return PJ_EINVAL;
4762  }
4763 
4764  /* Create wrapper to detect if the callback was actually called on an error. */
4765  req_wrapper = ao2_alloc(sizeof(*req_wrapper), send_request_wrapper_destructor);
4766  if (!req_wrapper) {
4767  pjsip_tx_data_dec_ref(tdata);
4768  return PJ_ENOMEM;
4769  }
4770 
4771  ast_debug(2, "%p: Wrapper created\n", req_wrapper);
4772 
4773  req_wrapper->token = token;
4774  req_wrapper->callback = cb;
4775  req_wrapper->timeout = timeout;
4776  req_wrapper->timeout_timer = NULL;
4777  req_wrapper->tdata = tdata;
4778  /* Add a reference to tdata. The wrapper destructor cleans it up. */
4779  pjsip_tx_data_add_ref(tdata);
4780 
4781  if (timeout > 0) {
4782  pj_time_val timeout_timer_val = { timeout / 1000, timeout % 1000 };
4783 
4784  req_wrapper->timeout_timer = PJ_POOL_ALLOC_T(tdata->pool, pj_timer_entry);
4785 
4786  ast_debug(2, "%p: Set timer to %d msec\n", req_wrapper, timeout);
4787 
4788  pj_timer_entry_init(req_wrapper->timeout_timer, TIMEOUT_TIMER2,
4789  req_wrapper, send_request_timer_callback);
4790 
4791  /* We need to insure that the wrapper and tdata are available if/when the
4792  * timer callback is executed.
4793  */
4794  ao2_ref(req_wrapper, +1);
4795  ret_val = pj_timer_heap_schedule(pjsip_endpt_get_timer_heap(endpt),
4796  req_wrapper->timeout_timer, &timeout_timer_val);
4797  if (ret_val != PJ_SUCCESS) {
4799  "Failed to set timer. Not sending %.*s request to endpoint %s.\n",
4800  (int) pj_strlen(&tdata->msg->line.req.method.name),
4801  pj_strbuf(&tdata->msg->line.req.method.name),
4802  endpoint ? ast_sorcery_object_get_id(endpoint) : "<unknown>");
4803  ao2_t_ref(req_wrapper, -2, "Drop timer and routine ref");
4804  pjsip_tx_data_dec_ref(tdata);
4805  return ret_val;
4806  }
4807  }
4808 
4809  /* We need to insure that the wrapper and tdata are available when the
4810  * transaction callback is executed.
4811  */
4812  ao2_ref(req_wrapper, +1);
4813  ret_val = pjsip_endpt_send_request(endpt, tdata, -1, req_wrapper, endpt_send_request_cb);
4814  if (ret_val != PJ_SUCCESS) {
4815  char errmsg[PJ_ERR_MSG_SIZE];
4816 
4817  if (!req_wrapper->send_cb_called) {
4818  /* endpt_send_request_cb is not expected to ever be called now. */
4819  ao2_ref(req_wrapper, -1);
4820  }
4821 
4822  /* Complain of failure to send the request. */
4823  pj_strerror(ret_val, errmsg, sizeof(errmsg));
4824  ast_log(LOG_ERROR, "Error %d '%s' sending %.*s request to endpoint %s\n",
4825  (int) ret_val, errmsg, (int) pj_strlen(&tdata->msg->line.req.method.name),
4826  pj_strbuf(&tdata->msg->line.req.method.name),
4827  endpoint ? ast_sorcery_object_get_id(endpoint) : "<unknown>");
4828 
4829  if (timeout > 0) {
4830  int timers_cancelled;
4831 
4832  ao2_lock(req_wrapper);
4833  timers_cancelled = pj_timer_heap_cancel_if_active(
4834  pjsip_endpt_get_timer_heap(endpt),
4835  req_wrapper->timeout_timer, TIMER_INACTIVE);
4836  if (timers_cancelled > 0) {
4837  ao2_ref(req_wrapper, -1);
4838  }
4839 
4840  /* Was the callback called? */
4841  if (req_wrapper->cb_called) {
4842  /*
4843  * Yes so we cannot report any error. The callback
4844  * has already freed any resources associated with
4845  * token.
4846  */
4847  ret_val = PJ_SUCCESS;
4848  } else {
4849  /*
4850  * No so we claim it is called so our caller can free
4851  * any resources associated with token because of
4852  * failure.
4853  */
4854  req_wrapper->cb_called = 1;
4855  }
4856  ao2_unlock(req_wrapper);
4857  } else if (req_wrapper->cb_called) {
4858  /*
4859  * We cannot report any error. The callback has
4860  * already freed any resources associated with
4861  * token.
4862  */
4863  ret_val = PJ_SUCCESS;
4864  }
4865  }
4866 
4867  ao2_ref(req_wrapper, -1);
4868  return ret_val;
4869 }
#define ao2_t_ref(o, delta, tag)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:463
void(* callback)(void *token, pjsip_event *e)
Definition: res_pjsip.c:4611
pj_int32_t timeout
Definition: res_pjsip.c:4619
pj_timer_entry * timeout_timer
Definition: res_pjsip.c:4617
static int timeout
Definition: cdr_mysql.c:86
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
#define TIMEOUT_TIMER2
Definition: res_pjsip.c:4568
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
unsigned int cb_called
Definition: res_pjsip.c:4613
#define LOG_ERROR
Definition: logger.h:285
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
static void endpt_send_request_cb(void *token, pjsip_event *e)
Definition: res_pjsip.c:4628
#define TIMER_INACTIVE
Definition: res_pjsip.c:4567
static void send_request_timer_callback(pj_timer_heap_t *theap, pj_timer_entry *entry)
Definition: res_pjsip.c:4703
pjsip_tx_data * tdata
Definition: res_pjsip.c:4621
unsigned int send_cb_called
Definition: res_pjsip.c:4615
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
Definition: res_pjsip.c:3718
static void send_request_wrapper_destructor(void *obj)
Definition: res_pjsip.c:4743

◆ endpt_send_request_cb()

static void endpt_send_request_cb ( void *  token,
pjsip_event *  e 
)
static

Definition at line 4628 of file res_pjsip.c.

References ao2_lock, ao2_ref, ao2_unlock, ast_debug, ast_sip_get_pjsip_endpoint(), send_request_wrapper::callback, send_request_wrapper::cb_called, send_request_wrapper::send_cb_called, send_request_wrapper::timeout_timer, TIMEOUT_TIMER2, TIMER_INACTIVE, and send_request_wrapper::token.

Referenced by endpt_send_request().

4629 {
4630  struct send_request_wrapper *req_wrapper = token;
4631  unsigned int cb_called;
4632 
4633  /*
4634  * Needed because we cannot otherwise tell if this callback was
4635  * called when pjsip_endpt_send_request() returns error.
4636  */
4637  req_wrapper->send_cb_called = 1;
4638 
4639  if (e->body.tsx_state.type == PJSIP_EVENT_TIMER) {
4640  ast_debug(2, "%p: PJSIP tsx timer expired\n", req_wrapper);
4641 
4642  if (req_wrapper->timeout_timer
4643  && req_wrapper->timeout_timer->id != TIMEOUT_TIMER2) {
4644  ast_debug(3, "%p: Timeout already handled\n", req_wrapper);
4645  ao2_ref(req_wrapper, -1);
4646  return;
4647  }
4648  } else {
4649  ast_debug(2, "%p: PJSIP tsx response received\n", req_wrapper);
4650  }
4651 
4652  ao2_lock(req_wrapper);
4653 
4654  /* It's possible that our own timer was already processing while
4655  * we were waiting on the lock so check the timer id. If it's
4656  * still TIMER2 then we still need to process.
4657  */
4658  if (req_wrapper->timeout_timer
4659  && req_wrapper->timeout_timer->id == TIMEOUT_TIMER2) {
4660  int timers_cancelled = 0;
4661 
4662  ast_debug(3, "%p: Cancelling timer\n", req_wrapper);
4663 
4664  timers_cancelled = pj_timer_heap_cancel_if_active(
4665  pjsip_endpt_get_timer_heap(ast_sip_get_pjsip_endpoint()),
4666  req_wrapper->timeout_timer, TIMER_INACTIVE);
4667  if (timers_cancelled > 0) {
4668  /* If the timer was cancelled the callback will never run so
4669  * clean up its reference to the wrapper.
4670  */
4671  ast_debug(3, "%p: Timer cancelled\n", req_wrapper);
4672  ao2_ref(req_wrapper, -1);
4673  } else {
4674  /*
4675  * If it wasn't cancelled, it MAY be in the callback already
4676  * waiting on the lock. When we release the lock, it will
4677  * now know not to proceed.
4678  */
4679  ast_debug(3, "%p: Timer already expired\n", req_wrapper);
4680  }
4681  }
4682 
4683  cb_called = req_wrapper->cb_called;
4684  req_wrapper->cb_called = 1;
4685  ao2_unlock(req_wrapper);
4686 
4687  /* It's possible that our own timer expired and called the callbacks
4688  * so no need to call them again.
4689  */
4690  if (!cb_called && req_wrapper->callback) {
4691  req_wrapper->callback(req_wrapper->token, e);
4692  ast_debug(2, "%p: Callbacks executed\n", req_wrapper);
4693  }
4694 
4695  ao2_ref(req_wrapper, -1);
4696 }
void(* callback)(void *token, pjsip_event *e)
Definition: res_pjsip.c:4611
pj_timer_entry * timeout_timer
Definition: res_pjsip.c:4617
#define ao2_unlock(a)
Definition: astobj2.h:730
#define TIMEOUT_TIMER2
Definition: res_pjsip.c:4568
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
unsigned int cb_called
Definition: res_pjsip.c:4613
#define TIMER_INACTIVE
Definition: res_pjsip.c:4567
unsigned int send_cb_called
Definition: res_pjsip.c:4615
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
Definition: res_pjsip.c:3718

◆ get_pjsip_method()

static const pjsip_method* get_pjsip_method ( const char *  method)
static

Definition at line 4351 of file res_pjsip.c.

References ARRAY_LEN, methods, and NULL.

Referenced by ast_sip_create_request().

4352 {
4353  int i;
4354  for (i = 0; i < ARRAY_LEN(methods); ++i) {
4355  if (!strcmp(method, methods[i].method)) {
4356  return methods[i].pmethod;
4357  }
4358  }
4359  return NULL;
4360 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static struct @481 methods[]
#define NULL
Definition: resample.c:96
const char * method
Definition: res_pjsip.c:4335

◆ load_module()

static int load_module ( void  )
static

Definition at line 5810 of file res_pjsip.c.

References ARRAY_LEN, ast_cli_register_multiple, ast_log, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_res_pjsip_init_message_filter(), ast_res_pjsip_init_options_handling(), ast_res_pjsip_initialize_configuration(), ast_res_pjsip_preinit_options_handling(), ast_serializer_pool_create(), ast_serializer_pool_destroy(), ast_sip_destroy_scheduler(), ast_sip_initialize_distributor(), ast_sip_initialize_dns(), ast_sip_initialize_global_headers(), ast_sip_initialize_resolver(), ast_sip_initialize_scheduler(), ast_sip_initialize_system(), ast_sip_initialize_transport_events(), ast_sip_initialize_transport_management(), ast_sip_register_service(), AST_TEST_REGISTER, ast_threadpool_create(), ast_threadpool_shutdown(), error(), load_pjsip(), LOG_ERROR, LOG_WARNING, NULL, SERIALIZER_POOL_SIZE, sip_get_threadpool_options(), sip_thread_start(), supplement_module, ast_threadpool_options::thread_start, and unload_pjsip().

Referenced by unload_module().

5811 {
5813 
5814  /* pjproject and config_system need to be initialized before all else */
5815  if (pj_init() != PJ_SUCCESS) {
5816  return AST_MODULE_LOAD_DECLINE;
5817  }
5818 
5819  if (pjlib_util_init() != PJ_SUCCESS) {
5820  goto error;
5821  }
5822 
5823  /* Register PJMEDIA error codes for SDP parsing errors */
5824  if (pj_register_strerror(PJMEDIA_ERRNO_START, PJ_ERRNO_SPACE_SIZE, pjmedia_strerror)
5825  != PJ_SUCCESS) {
5826  ast_log(LOG_WARNING, "Failed to register pjmedia error codes. Codes will not be decoded.\n");
5827  }
5828 
5829  if (ast_sip_initialize_system()) {
5830  ast_log(LOG_ERROR, "Failed to initialize SIP 'system' configuration section. Aborting load\n");
5831  goto error;
5832  }
5833 
5834  /* The serializer needs threadpool and threadpool needs pjproject to be initialized so it's next */
5836  options.thread_start = sip_thread_start;
5838  if (!sip_threadpool) {
5839  goto error;
5840  }
5841 
5843  "pjsip/default", SERIALIZER_POOL_SIZE, sip_threadpool, -1);
5844  if (!sip_serializer_pool) {
5845  ast_log(LOG_ERROR, "Failed to create SIP serializer pool. Aborting load\n");
5846  goto error;
5847  }
5848 
5850  ast_log(LOG_ERROR, "Failed to start scheduler. Aborting load\n");
5851  goto error;
5852  }
5853 
5854  /* Now load all the pjproject infrastructure. */
5855  if (load_pjsip()) {
5856  goto error;
5857  }
5858 
5860  ast_log(LOG_ERROR, "Failed to initialize SIP transport monitor. Aborting load\n");
5861  goto error;
5862  }
5863 
5866 
5868  ast_log(LOG_ERROR, "Failed to pre-initialize OPTIONS handling. Aborting load\n");
5869  goto error;
5870  }
5871 
5873  ast_log(LOG_ERROR, "Failed to initialize SIP configuration. Aborting load\n");
5874  goto error;
5875  }
5876 
5879 
5881  ast_log(LOG_ERROR, "Failed to initialize SIP transport management. Aborting load\n");
5882  goto error;
5883  }
5884 
5886  ast_log(LOG_ERROR, "Failed to register distributor module. Aborting load\n");
5887  goto error;
5888  }
5889 
5891  ast_log(LOG_ERROR, "Failed to initialize supplement hooks. Aborting load\n");
5892  goto error;
5893  }
5894 
5896  ast_log(LOG_ERROR, "Failed to initialize OPTIONS handling. Aborting load\n");
5897  goto error;
5898  }
5899 
5901  ast_log(LOG_ERROR, "Failed to initialize message IP updating. Aborting load\n");
5902  goto error;
5903  }
5904 
5906 
5907  AST_TEST_REGISTER(xml_sanitization_end_null);
5908  AST_TEST_REGISTER(xml_sanitization_exceeds_buffer);
5909 
5910  return AST_MODULE_LOAD_SUCCESS;
5911 
5912 error:
5913  unload_pjsip(NULL);
5914 
5915  /* These functions all check for NULLs and are safe to call at any time */
5919 
5920  return AST_MODULE_LOAD_DECLINE;
5921 }
int ast_res_pjsip_preinit_options_handling(void)
static struct ast_cli_entry cli_commands[]
Definition: res_pjsip.c:3671
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
void ast_sip_initialize_global_headers(void)
int ast_sip_initialize_scheduler(void)
Initialize scheduler.
int ast_sip_initialize_distributor(void)
int ast_serializer_pool_destroy(struct ast_serializer_pool *pool)
Destroy the serializer pool.
Definition: serializer.c:39
#define LOG_WARNING
Definition: logger.h:274
static struct ast_threadpool * sip_threadpool
Definition: res_pjsip.c:3274
int ast_sip_destroy_scheduler(void)
static void sip_thread_start(void)
Definition: res_pjsip.c:5296
#define AST_TEST_REGISTER(cb)
Definition: test.h:127
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
int ast_sip_initialize_transport_management(void)
#define NULL
Definition: resample.c:96
void ast_sip_initialize_dns(void)
void ast_sip_initialize_resolver(void)
int ast_sip_register_service(pjsip_module *module)
Register a SIP service in Asterisk.
Definition: res_pjsip.c:3315
#define ast_log
Definition: astobj2.c:42
static pjsip_module supplement_module
Definition: res_pjsip.c:4373
static int load_pjsip(void)
Definition: res_pjsip.c:5744
int ast_sip_initialize_system(void)
#define LOG_ERROR
Definition: logger.h:285
void sip_get_threadpool_options(struct ast_threadpool_options *threadpool_options)
Definition: config_system.c:70
int ast_res_pjsip_init_options_handling(int reload)
int ast_sip_initialize_transport_events(void)
static struct ast_serializer_pool * sip_serializer_pool
Definition: res_pjsip.c:3270
struct ast_threadpool * ast_threadpool_create(const char *name, struct ast_threadpool_listener *listener, const struct ast_threadpool_options *options)
Create a new threadpool.
Definition: threadpool.c:915
#define SERIALIZER_POOL_SIZE
Definition: res_pjsip.c:3267
int ast_res_pjsip_initialize_configuration(void)
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
void ast_threadpool_shutdown(struct ast_threadpool *pool)
Shut down a threadpool and destroy it.
Definition: threadpool.c:965
static int unload_pjsip(void *data)
Definition: res_pjsip.c:5700
struct ast_serializer_pool * ast_serializer_pool_create(const char *name, unsigned int size, struct ast_threadpool *threadpool, int timeout)
Create a serializer pool.
Definition: serializer.c:76
int error(const char *format,...)
Definition: utils/frame.c:999
int ast_res_pjsip_init_message_filter(void)
static struct test_options options

◆ load_pjsip()

static int load_pjsip ( void  )
static

Definition at line 5744 of file res_pjsip.c.

References ast_log, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_pjproject_caching_pool_init(), ast_pjsip_endpoint, ast_verb, error(), host_ip_ipv4, host_ip_ipv4_string, host_ip_ipv6, host_ip_ipv6_string, LOG_ERROR, monitor_thread_exec(), never_called_res_pjsip(), NULL, remove_request_headers(), and status.

Referenced by load_module().

5745 {
5746  const unsigned int flags = 0; /* no port, no brackets */
5747  pj_status_t status;
5748 
5749  /* The third parameter is just copied from
5750  * example code from PJLIB. This can be adjusted
5751  * if necessary.
5752  */
5754  if (pjsip_endpt_create(&caching_pool.factory, "SIP", &ast_pjsip_endpoint) != PJ_SUCCESS) {
5755  ast_log(LOG_ERROR, "Failed to create PJSIP endpoint structure. Aborting load\n");
5756  goto error;
5757  }
5758 
5759  /* PJSIP will automatically try to add a Max-Forwards header. Since we want to control that,
5760  * we need to stop PJSIP from doing it automatically
5761  */
5763 
5764  memory_pool = pj_pool_create(&caching_pool.factory, "SIP", 1024, 1024, NULL);
5765  if (!memory_pool) {
5766  ast_log(LOG_ERROR, "Failed to create memory pool for SIP. Aborting load\n");
5767  goto error;
5768  }
5769 
5770  if (!pj_gethostip(pj_AF_INET(), &host_ip_ipv4)) {
5771  pj_sockaddr_print(&host_ip_ipv4, host_ip_ipv4_string, sizeof(host_ip_ipv4_string), flags);
5772  ast_verb(3, "Local IPv4 address determined to be: %s\n", host_ip_ipv4_string);
5773  }
5774 
5775  if (!pj_gethostip(pj_AF_INET6(), &host_ip_ipv6)) {
5776  pj_sockaddr_print(&host_ip_ipv6, host_ip_ipv6_string, sizeof(host_ip_ipv6_string), flags);
5777  ast_verb(3, "Local IPv6 address determined to be: %s\n", host_ip_ipv6_string);
5778  }
5779 
5780  pjsip_tsx_layer_init_module(ast_pjsip_endpoint);
5781  pjsip_ua_init_module(ast_pjsip_endpoint, NULL);
5782 
5783  monitor_continue = 1;
5784  status = pj_thread_create(memory_pool, "SIP", (pj_thread_proc *) &monitor_thread_exec,
5785  NULL, PJ_THREAD_DEFAULT_STACK_SIZE * 2, 0, &monitor_thread);
5786  if (status != PJ_SUCCESS) {
5787  ast_log(LOG_ERROR, "Failed to start SIP monitor thread. Aborting load\n");
5788  goto error;
5789  }
5790 
5791  return AST_MODULE_LOAD_SUCCESS;
5792 
5793 error:
5794  return AST_MODULE_LOAD_DECLINE;
5795 }
static pj_sockaddr host_ip_ipv6
Definition: res_pjsip.c:3283
pj_thread_t * monitor_thread
Definition: res_pjsip.c:5274
pj_caching_pool caching_pool
Definition: res_pjsip.c:5272
static char host_ip_ipv6_string[PJ_INET6_ADDRSTRLEN]
Definition: res_pjsip.c:3286
#define NULL
Definition: resample.c:96
#define ast_verb(level,...)
Definition: logger.h:463
static void * monitor_thread_exec(void *endpt)
Definition: res_pjsip.c:5277
#define ast_log
Definition: astobj2.c:42
void ast_pjproject_caching_pool_init(pj_caching_pool *cp, const pj_pool_factory_policy *policy, pj_size_t max_capacity)
Initialize the caching pool factory.
#define LOG_ERROR
Definition: logger.h:285
static pjsip_endpoint * ast_pjsip_endpoint
Definition: res_pjsip.c:3272
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
static char host_ip_ipv4_string[PJ_INET6_ADDRSTRLEN]
Definition: res_pjsip.c:3280
static int monitor_continue
Definition: res_pjsip.c:5275
pj_pool_t * memory_pool
Definition: res_pjsip.c:5273
static pj_sockaddr host_ip_ipv4
Definition: res_pjsip.c:3277
static void remove_request_headers(pjsip_endpoint *endpt)
Definition: res_pjsip.c:5613
int error(const char *format,...)
Definition: utils/frame.c:999
jack_status_t status
Definition: app_jack.c:146

◆ monitor_thread_exec()

static void* monitor_thread_exec ( void *  endpt)
static

Definition at line 5277 of file res_pjsip.c.

References ast_pjsip_endpoint, and NULL.

Referenced by load_pjsip().

5278 {
5279  while (monitor_continue) {
5280  const pj_time_val delay = {0, 10};
5281  pjsip_endpt_handle_events(ast_pjsip_endpoint, &delay);
5282  }
5283  return NULL;
5284 }
#define NULL
Definition: resample.c:96
static pjsip_endpoint * ast_pjsip_endpoint
Definition: res_pjsip.c:3272
static int monitor_continue
Definition: res_pjsip.c:5275

◆ never_called_res_pjsip()

void never_called_res_pjsip ( void  )

Definition at line 5805 of file res_pjsip.c.

References NULL.

Referenced by load_pjsip().

5806 {
5807  pjmedia_strerror(0, NULL, 0);
5808 }
#define NULL
Definition: resample.c:96

◆ register_service()

static int register_service ( void *  data)
static

Definition at line 3300 of file res_pjsip.c.

References ast_debug, ast_log, ast_pjsip_endpoint, and LOG_ERROR.

Referenced by ast_sip_register_service().

3301 {
3302  pjsip_module **module = data;
3303  if (!ast_pjsip_endpoint) {
3304  ast_log(LOG_ERROR, "There is no PJSIP endpoint. Unable to register services\n");
3305  return -1;
3306  }
3307  if (pjsip_endpt_register_module(ast_pjsip_endpoint, *module) != PJ_SUCCESS) {
3308  ast_log(LOG_ERROR, "Unable to register module %.*s\n", (int) pj_strlen(&(*module)->name), pj_strbuf(&(*module)->name));
3309  return -1;
3310  }
3311  ast_debug(1, "Registered SIP service %.*s (%p)\n", (int) pj_strlen(&(*module)->name), pj_strbuf(&(*module)->name), *module);
3312  return 0;
3313 }
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285
static pjsip_endpoint * ast_pjsip_endpoint
Definition: res_pjsip.c:3272

◆ reload_configuration_task()

static int reload_configuration_task ( void *  obj)
static

Definition at line 5692 of file res_pjsip.c.

References ast_res_pjsip_init_options_handling(), ast_res_pjsip_reload_configuration(), and ast_sip_initialize_dns().

Referenced by reload_module().

5693 {
5697  return 0;
5698 }
void ast_sip_initialize_dns(void)
int ast_res_pjsip_init_options_handling(int reload)
int ast_res_pjsip_reload_configuration(void)

◆ reload_module()

static int reload_module ( void  )
static

Definition at line 5923 of file res_pjsip.c.

References ast_log, ast_sip_push_task_wait_servant(), LOG_WARNING, NULL, and reload_configuration_task().

Referenced by unload_module().

5924 {
5925  /*
5926  * We must wait for the reload to complete so multiple
5927  * reloads cannot happen at the same time.
5928  */
5930  ast_log(LOG_WARNING, "Failed to reload PJSIP\n");
5931  return -1;
5932  }
5933 
5934  return 0;
5935 }
#define LOG_WARNING
Definition: logger.h:274
#define NULL
Definition: resample.c:96
int ast_sip_push_task_wait_servant(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Push a task to SIP servants and wait for it to complete.
Definition: res_pjsip.c:5204
#define ast_log
Definition: astobj2.c:42
static int reload_configuration_task(void *obj)
Definition: res_pjsip.c:5692

◆ remove_request_headers()

static void remove_request_headers ( pjsip_endpoint *  endpt)
static

Definition at line 5613 of file res_pjsip.c.

References request_headers.

Referenced by load_pjsip().

5614 {
5615  const pjsip_hdr *request_headers = pjsip_endpt_get_request_headers(endpt);
5616  pjsip_hdr *iter = request_headers->next;
5617 
5618  while (iter != request_headers) {
5619  pjsip_hdr *to_erase = iter;
5620  iter = iter->next;
5621  pj_list_erase(to_erase);
5622  }
5623 }
static struct header_list request_headers

◆ send_in_dialog_request()

static int send_in_dialog_request ( pjsip_tx_data *  tdata,
struct pjsip_dialog *  dlg 
)
static

Definition at line 4545 of file res_pjsip.c.

References ast_log, LOG_WARNING, and NULL.

Referenced by ast_sip_send_request().

4546 {
4547  if (pjsip_dlg_send_request(dlg, tdata, -1, NULL) != PJ_SUCCESS) {
4548  ast_log(LOG_WARNING, "Unable to send in-dialog request.\n");
4549  return -1;
4550  }
4551  return 0;
4552 }
#define LOG_WARNING
Definition: logger.h:274
#define NULL
Definition: resample.c:96
#define ast_log
Definition: astobj2.c:42

◆ send_request_cb()

static void send_request_cb ( void *  token,
pjsip_event *  e 
)
static

Definition at line 4937 of file res_pjsip.c.

References ao2_ref, AST_LIST_TRAVERSE, ast_log, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, send_request_data::callback, challenge(), check_request_status(), does_method_match(), send_request_data::endpoint, ast_sip_supplement::incoming_response, LOG_ERROR, ast_sip_supplement::method, ast_sip_supplement::next, and send_request_data::token.

Referenced by ast_sip_failover_request().

4938 {
4939  struct send_request_data *req_data = token;
4940  pjsip_rx_data *challenge;
4941  struct ast_sip_supplement *supplement;
4942 
4943  if (e->type == PJSIP_EVENT_TSX_STATE) {
4944  switch(e->body.tsx_state.type) {
4945  case PJSIP_EVENT_TRANSPORT_ERROR:
4946  case PJSIP_EVENT_TIMER:
4947  /*
4948  * Check the request status on transport error or timeout. A transport
4949  * error can occur when a TCP socket closes and that can be the result
4950  * of a 503. Also we may need to failover on a timeout (408).
4951  */
4952  if (check_request_status(req_data, e)) {
4953  return;
4954  }
4955  break;
4956  case PJSIP_EVENT_RX_MSG:
4957  challenge = e->body.tsx_state.src.rdata;
4958 
4959  /*
4960  * Call any supplements that want to know about a response
4961  * with any received data.
4962  */
4964  AST_LIST_TRAVERSE(&supplements, supplement, next) {
4965  if (supplement->incoming_response
4966  && does_method_match(&challenge->msg_info.cseq->method.name,
4967  supplement->method)) {
4968  supplement->incoming_response(req_data->endpoint, challenge);
4969  }
4970  }
4972 
4973  if (check_request_status(req_data, e)) {
4974  /*
4975  * Request with challenge response or failover sent.
4976  * Passed our req_data ref to the new request.
4977  */
4978  return;
4979  }
4980  break;
4981  default:
4982  ast_log(LOG_ERROR, "Unexpected PJSIP event %u\n", e->body.tsx_state.type);
4983  break;
4984  }
4985  }
4986 
4987  if (req_data->callback) {
4988  req_data->callback(req_data->token, e);
4989  }
4990  ao2_ref(req_data, -1);
4991 }
static int check_request_status(struct send_request_data *req_data, pjsip_event *e)
Definition: res_pjsip.c:4894
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
const char * method
Definition: res_pjsip.h:2890
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
#define ast_log
Definition: astobj2.c:42
void(* incoming_response)(struct ast_sip_endpoint *endpoint, struct pjsip_rx_data *rdata)
Called on an incoming SIP response This method is always called from a SIP servant thread...
Definition: res_pjsip.h:2926
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct ast_sip_supplement * next
Definition: res_pjsip.h:2938
static void challenge(const char *realm, pjsip_tx_data *tdata, const pjsip_rx_data *rdata, int is_stale)
astobj2 callback for adding digest challenges to responses
#define LOG_ERROR
Definition: logger.h:285
static pj_bool_t does_method_match(const pj_str_t *message_method, const char *supplement_method)
Definition: res_pjsip.c:4554
void(* callback)(void *token, pjsip_event *e)
Definition: res_pjsip.c:4577
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
A supplement to SIP message processing.
Definition: res_pjsip.h:2888
Structure to hold information about an outbound request.
Definition: res_pjsip.c:4571
struct ast_sip_endpoint * endpoint
Definition: res_pjsip.c:4573

◆ send_request_data_alloc()

static struct send_request_data* send_request_data_alloc ( struct ast_sip_endpoint endpoint,
void *  token,
void(*)(void *token, pjsip_event *e)  callback 
)
static

Definition at line 4589 of file res_pjsip.c.

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_alloc_options, ao2_bump, send_request_data::callback, send_request_data::endpoint, NULL, send_request_data_destroy(), and send_request_data::token.

Referenced by ast_sip_send_out_of_dialog_request().

4591 {
4592  struct send_request_data *req_data;
4593 
4594  req_data = ao2_alloc_options(sizeof(*req_data), send_request_data_destroy,
4596  if (!req_data) {
4597  return NULL;
4598  }
4599 
4600  req_data->endpoint = ao2_bump(endpoint);
4601  req_data->token = token;
4602  req_data->callback = callback;
4603 
4604  return req_data;
4605 }
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:406
#define NULL
Definition: resample.c:96
#define ao2_bump(obj)
Definition: astobj2.h:491
static void send_request_data_destroy(void *obj)
Definition: res_pjsip.c:4582
void(* callback)(void *token, pjsip_event *e)
Definition: res_pjsip.c:4577
Structure to hold information about an outbound request.
Definition: res_pjsip.c:4571
struct ast_sip_endpoint * endpoint
Definition: res_pjsip.c:4573

◆ send_request_data_destroy()

static void send_request_data_destroy ( void *  obj)
static

Definition at line 4582 of file res_pjsip.c.

References ao2_cleanup, and send_request_data::endpoint.

Referenced by send_request_data_alloc().

4583 {
4584  struct send_request_data *req_data = obj;
4585 
4586  ao2_cleanup(req_data->endpoint);
4587 }
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
Structure to hold information about an outbound request.
Definition: res_pjsip.c:4571
struct ast_sip_endpoint * endpoint
Definition: res_pjsip.c:4573

◆ send_request_timer_callback()

static void send_request_timer_callback ( pj_timer_heap_t *  theap,
pj_timer_entry *  entry 
)
static

Definition at line 4703 of file res_pjsip.c.

References ao2_lock, ao2_ref, ao2_unlock, ast_debug, send_request_wrapper::callback, send_request_wrapper::cb_called, send_request_wrapper::tdata, send_request_wrapper::timeout, TIMEOUT_TIMER2, TIMER_INACTIVE, and send_request_wrapper::token.

Referenced by endpt_send_request().

4704 {
4705  struct send_request_wrapper *req_wrapper = entry->user_data;
4706  unsigned int cb_called;
4707 
4708  ast_debug(2, "%p: Internal tsx timer expired after %d msec\n",
4709  req_wrapper, req_wrapper->timeout);
4710 
4711  ao2_lock(req_wrapper);
4712  /*
4713  * If the id is not TIMEOUT_TIMER2 then the timer was cancelled
4714  * before we got the lock or it was already handled so just clean up.
4715  */
4716  if (entry->id != TIMEOUT_TIMER2) {
4717  ao2_unlock(req_wrapper);
4718  ast_debug(3, "%p: Timeout already handled\n", req_wrapper);
4719  ao2_ref(req_wrapper, -1);
4720  return;
4721  }
4722  entry->id = TIMER_INACTIVE;
4723 
4724  ast_debug(3, "%p: Timer handled here\n", req_wrapper);
4725 
4726  cb_called = req_wrapper->cb_called;
4727  req_wrapper->cb_called = 1;
4728  ao2_unlock(req_wrapper);
4729 
4730  if (!cb_called && req_wrapper->callback) {
4731  pjsip_event event;
4732 
4733  PJSIP_EVENT_INIT_TX_MSG(event, req_wrapper->tdata);
4734  event.body.tsx_state.type = PJSIP_EVENT_TIMER;
4735 
4736  req_wrapper->callback(req_wrapper->token, &event);
4737  ast_debug(2, "%p: Callbacks executed\n", req_wrapper);
4738  }
4739 
4740  ao2_ref(req_wrapper, -1);
4741 }
void(* callback)(void *token, pjsip_event *e)
Definition: res_pjsip.c:4611
pj_int32_t timeout
Definition: res_pjsip.c:4619
Definition: astman.c:222
#define ao2_unlock(a)
Definition: astobj2.h:730
#define TIMEOUT_TIMER2
Definition: res_pjsip.c:4568
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
unsigned int cb_called
Definition: res_pjsip.c:4613
#define TIMER_INACTIVE
Definition: res_pjsip.c:4567
pjsip_tx_data * tdata
Definition: res_pjsip.c:4621
Definition: search.h:40

◆ send_request_wrapper_destructor()

static void send_request_wrapper_destructor ( void *  obj)
static

Definition at line 4743 of file res_pjsip.c.

References ast_debug, and send_request_wrapper::tdata.

Referenced by endpt_send_request().

4744 {
4745  struct send_request_wrapper *req_wrapper = obj;
4746 
4747  pjsip_tx_data_dec_ref(req_wrapper->tdata);
4748  ast_debug(2, "%p: wrapper destroyed\n", req_wrapper);
4749 }
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
pjsip_tx_data * tdata
Definition: res_pjsip.c:4621

◆ sip_dialog_create_from()

static int sip_dialog_create_from ( pj_pool_t *  pool,
pj_str_t *  from,
const char *  user,
const char *  domain,
const pj_str_t *  target,
pjsip_tpselector *  selector 
)
static

Definition at line 3813 of file res_pjsip.c.

References ast_sip_get_default_from_user(), ast_sip_get_disable_multi_domain(), ast_sip_get_pjsip_endpoint(), ast_strlen_zero, tmp(), and type.

Referenced by ast_sip_create_dialog_uac(), and create_out_of_dialog_request().

3815 {
3816  pj_str_t tmp, local_addr;
3817  pjsip_uri *uri;
3818  pjsip_sip_uri *sip_uri;
3819  pjsip_transport_type_e type;
3820  int local_port;
3821  char default_user[PJSIP_MAX_URL_SIZE];
3822 
3823  if (ast_strlen_zero(user)) {
3824  ast_sip_get_default_from_user(default_user, sizeof(default_user));
3825  user = default_user;
3826  }
3827 
3828  /* Parse the provided target URI so we can determine what transport it will end up using */
3829  pj_strdup_with_null(pool, &tmp, target);
3830 
3831  if (!(uri = pjsip_parse_uri(pool, tmp.ptr, tmp.slen, 0)) ||
3832  (!PJSIP_URI_SCHEME_IS_SIP(uri) && !PJSIP_URI_SCHEME_IS_SIPS(uri))) {
3833  return -1;
3834  }
3835 
3836  sip_uri = pjsip_uri_get_uri(uri);
3837 
3838  /* Determine the transport type to use */
3839  type = pjsip_transport_get_type_from_name(&sip_uri->transport_param);
3840  if (PJSIP_URI_SCHEME_IS_SIPS(sip_uri)) {
3841  if (type == PJSIP_TRANSPORT_UNSPECIFIED
3842  || !(pjsip_transport_get_flag_from_type(type) & PJSIP_TRANSPORT_SECURE)) {
3843  type = PJSIP_TRANSPORT_TLS;
3844  }
3845  } else if (!sip_uri->transport_param.slen) {
3846  type = PJSIP_TRANSPORT_UDP;
3847  } else if (type == PJSIP_TRANSPORT_UNSPECIFIED) {
3848  return -1;
3849  }
3850 
3851  /* If the host is IPv6 turn the transport into an IPv6 version */
3852  if (pj_strchr(&sip_uri->host, ':')) {
3853  type |= PJSIP_TRANSPORT_IPV6;
3854  }
3855 
3856  /* In multidomain scenario, username may contain @ with domain info */
3857  if (!ast_sip_get_disable_multi_domain() && strchr(user, '@')) {
3858  from->ptr = pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE);
3859  from->slen = pj_ansi_snprintf(from->ptr, PJSIP_MAX_URL_SIZE,
3860  "<sip:%s%s%s>",
3861  user,
3862  (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? ";transport=" : "",
3863  (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? pjsip_transport_get_type_name(type) : "");
3864  return 0;
3865  }
3866 
3867  if (!ast_strlen_zero(domain)) {
3868  from->ptr = pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE);
3869  from->slen = pj_ansi_snprintf(from->ptr, PJSIP_MAX_URL_SIZE,
3870  "<sip:%s@%s%s%s>",
3871  user,
3872  domain,
3873  (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? ";transport=" : "",
3874  (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? pjsip_transport_get_type_name(type) : "");
3875  return 0;
3876  }
3877 
3878  /* Get the local bound address for the transport that will be used when communicating with the provided URI */
3879  if (pjsip_tpmgr_find_local_addr(pjsip_endpt_get_tpmgr(ast_sip_get_pjsip_endpoint()), pool, type, selector,
3880  &local_addr, &local_port) != PJ_SUCCESS) {
3881 
3882  /* If no local address can be retrieved using the transport manager use the host one */
3883  pj_strdup(pool, &local_addr, pj_gethostname());
3884  local_port = pjsip_transport_get_default_port_for_type(PJSIP_TRANSPORT_UDP);
3885  }
3886 
3887  /* If IPv6 was specified in the transport, set the proper type */
3888  if (pj_strchr(&local_addr, ':')) {
3889  type |= PJSIP_TRANSPORT_IPV6;
3890  }
3891 
3892  from->ptr = pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE);
3893  from->slen = pj_ansi_snprintf(from->ptr, PJSIP_MAX_URL_SIZE,
3894  "<sip:%s@%s%.*s%s:%d%s%s>",
3895  user,
3896  (type & PJSIP_TRANSPORT_IPV6) ? "[" : "",
3897  (int)local_addr.slen,
3898  local_addr.ptr,
3899  (type & PJSIP_TRANSPORT_IPV6) ? "]" : "",
3900  local_port,
3901  (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? ";transport=" : "",
3902  (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? pjsip_transport_get_type_name(type) : "");
3903 
3904  return 0;
3905 }
static const char type[]
Definition: chan_ooh323.c:109
static int tmp()
Definition: bt_open.c:389
static pj_pool_t * pool
Global memory pool for configuration and timers.
Domain data structure.
Definition: sip.h:888
#define ast_strlen_zero(foo)
Definition: strings.h:52
unsigned int ast_sip_get_disable_multi_domain(void)
Retrieve the system setting &#39;disable multi domain&#39;.
void ast_sip_get_default_from_user(char *from_user, size_t size)
Retrieve the global default from user.
structure to hold users read from users.conf
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
Definition: res_pjsip.c:3718

◆ sip_thread_start()

static void sip_thread_start ( void  )
static

Definition at line 5296 of file res_pjsip.c.

References ast_log, ast_threadstorage_get(), desc, LOG_ERROR, pj_thread_storage, servant_id_storage, SIP_SERVANT_ID, and thread.

Referenced by load_module().

5297 {
5298  pj_thread_desc *desc;
5299  pj_thread_t *thread;
5300  uint32_t *servant_id;
5301 
5302  servant_id = ast_threadstorage_get(&servant_id_storage, sizeof(*servant_id));
5303  if (!servant_id) {
5304  ast_log(LOG_ERROR, "Could not set SIP servant ID in thread-local storage.\n");
5305  return;
5306  }
5307  *servant_id = SIP_SERVANT_ID;
5308 
5309  desc = ast_threadstorage_get(&pj_thread_storage, sizeof(pj_thread_desc));
5310  if (!desc) {
5311  ast_log(LOG_ERROR, "Could not get thread desc from thread-local storage. Expect awful things to occur\n");
5312  return;
5313  }
5314  pj_bzero(*desc, sizeof(*desc));
5315 
5316  if (pj_thread_register("Asterisk Thread", *desc, &thread) != PJ_SUCCESS) {
5317  ast_log(LOG_ERROR, "Couldn't register thread with PJLIB.\n");
5318  }
5319 }
pthread_t thread
Definition: app_meetme.c:1089
void * ast_threadstorage_get(struct ast_threadstorage *ts, size_t init_size)
Retrieve thread storage.
static struct ast_threadstorage pj_thread_storage
Definition: res_pjsip.c:5292
static const char desc[]
Definition: cdr_mysql.c:73
#define ast_log
Definition: astobj2.c:42
#define SIP_SERVANT_ID
Definition: res_pjsip.c:5294
#define LOG_ERROR
Definition: logger.h:285
static struct ast_threadstorage servant_id_storage
Definition: res_pjsip.c:5293

◆ stop_monitor_thread()

static void stop_monitor_thread ( void  )
static

Definition at line 5286 of file res_pjsip.c.

Referenced by unload_pjsip().

5287 {
5288  monitor_continue = 0;
5289  pj_thread_join(monitor_thread);
5290 }
pj_thread_t * monitor_thread
Definition: res_pjsip.c:5274
static int monitor_continue
Definition: res_pjsip.c:5275

◆ supplement_on_rx_request()

static pj_bool_t supplement_on_rx_request ( pjsip_rx_data *  rdata)
static

Definition at line 5361 of file res_pjsip.c.

References ao2_cleanup, AST_LIST_TRAVERSE, ast_pjsip_rdata_get_endpoint(), AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, does_method_match(), ast_sip_supplement::incoming_request, ast_sip_supplement::method, and ast_sip_supplement::next.

Referenced by create_in_dialog_request().

5362 {
5363  struct ast_sip_supplement *supplement;
5364 
5365  if (pjsip_rdata_get_dlg(rdata)) {
5366  return PJ_FALSE;
5367  }
5368 
5370  AST_LIST_TRAVERSE(&supplements, supplement, next) {
5371  if (supplement->incoming_request
5372  && does_method_match(&rdata->msg_info.msg->line.req.method.name, supplement->method)) {
5373  struct ast_sip_endpoint *endpoint;
5374 
5375  endpoint = ast_pjsip_rdata_get_endpoint(rdata);
5376  supplement->incoming_request(endpoint, rdata);
5377  ao2_cleanup(endpoint);
5378  }
5379  }
5381 
5382  return PJ_FALSE;
5383 }
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
const char * method
Definition: res_pjsip.h:2890
struct ast_sip_endpoint * ast_pjsip_rdata_get_endpoint(pjsip_rx_data *rdata)
Get the looked-up endpoint on an out-of dialog request or response.
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
struct ast_sip_supplement * next
Definition: res_pjsip.h:2938
An entity with which Asterisk communicates.
Definition: res_pjsip.h:812
static pj_bool_t does_method_match(const pj_str_t *message_method, const char *supplement_method)
Definition: res_pjsip.c:4554
int(* incoming_request)(struct ast_sip_endpoint *endpoint, struct pjsip_rx_data *rdata)
Called on incoming SIP request This method can indicate a failure in processing in its return...
Definition: res_pjsip.h:2910
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
A supplement to SIP message processing.
Definition: res_pjsip.h:2888

◆ supplement_outgoing_response()

static void supplement_outgoing_response ( pjsip_tx_data *  tdata,
struct ast_sip_endpoint sip_endpoint 
)
static

Definition at line 5385 of file res_pjsip.c.

References ao2_cleanup, AST_LIST_TRAVERSE, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, ast_sip_message_apply_transport(), ast_sip_mod_data_get, ast_sip_mod_data_set, does_method_match(), ast_sip_supplement::method, MOD_DATA_CONTACT, NULL, ast_sip_supplement::outgoing_response, supplement_module, and ast_sip_endpoint::transport.

Referenced by ast_sip_send_response(), and ast_sip_send_stateful_response().

5386 {
5387  struct ast_sip_supplement *supplement;
5388  pjsip_cseq_hdr *cseq = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CSEQ, NULL);
5390 
5391  if (sip_endpoint) {
5392  ast_sip_message_apply_transport(sip_endpoint->transport, tdata);
5393  }
5394 
5396  AST_LIST_TRAVERSE(&supplements, supplement, next) {
5397  if (supplement->outgoing_response && does_method_match(&cseq->method.name, supplement->method)) {
5398  supplement->outgoing_response(sip_endpoint, contact, tdata);
5399  }
5400  }
5402 
5403  ast_sip_mod_data_set(tdata->pool, tdata->mod_data, supplement_module.id, MOD_DATA_CONTACT, NULL);
5404  ao2_cleanup(contact);
5405 }
void(* outgoing_response)(struct ast_sip_endpoint *endpoint, struct ast_sip_contact *contact, struct pjsip_tx_data *tdata)
Called on an outgoing SIP response This method is always called from a SIP servant thread...
Definition: res_pjsip.h:2936
const ast_string_field transport
Definition: res_pjsip.h:817
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
const char * method
Definition: res_pjsip.h:2890
#define NULL
Definition: resample.c:96
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
static pjsip_module supplement_module
Definition: res_pjsip.c:4373
#define ast_sip_mod_data_set(pool, mod_data, id, key, val)
Utilizing a mod_data array for a given id, set the value associated with the given key...
Definition: res_pjsip.h:2670
#define ast_sip_mod_data_get(mod_data, id, key)
Using the dictionary stored in mod_data array at a given id, retrieve the value associated with the g...
Definition: res_pjsip.h:2638
static pj_bool_t does_method_match(const pj_str_t *message_method, const char *supplement_method)
Definition: res_pjsip.c:4554
Contact associated with an address of record.
Definition: res_pjsip.h:281
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
void ast_sip_message_apply_transport(const char *transport_name, pjsip_tx_data *tdata)
Apply the configuration for a transport to an outgoing message.
#define MOD_DATA_CONTACT
Definition: res_pjsip.c:3264
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
A supplement to SIP message processing.
Definition: res_pjsip.h:2888

◆ sync_task()

static int sync_task ( void *  data)
static

Definition at line 5156 of file res_pjsip.c.

References ast_cond_signal, ast_mutex_lock, ast_mutex_unlock, sync_task_data::complete, sync_task_data::cond, sync_task_data::fail, sync_task_data::lock, sync_task_data::task, and sync_task_data::task_data.

Referenced by ast_sip_push_task_wait().

5157 {
5158  struct sync_task_data *std = data;
5159  int ret;
5160 
5161  std->fail = std->task(std->task_data);
5162 
5163  /*
5164  * Once we unlock std->lock after signaling, we cannot access
5165  * std again. The thread waiting within ast_sip_push_task_wait()
5166  * is free to continue and release its local variable (std).
5167  */
5168  ast_mutex_lock(&std->lock);
5169  std->complete = 1;
5170  ast_cond_signal(&std->cond);
5171  ret = std->fail;
5172  ast_mutex_unlock(&std->lock);
5173  return ret;
5174 }
#define ast_mutex_lock(a)
Definition: lock.h:187
#define ast_cond_signal(cond)
Definition: lock.h:201
ast_cond_t cond
Definition: stasis.c:1278
ast_mutex_t lock
Definition: stasis.c:1277
int(* task)(void *)
Definition: res_pjsip.c:5152
void * task_data
Definition: stasis.c:1280
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ uas_use_sips_contact()

static int uas_use_sips_contact ( pjsip_rx_data *  rdata)
static

Determine if a SIPS Contact header is required.

This uses the guideline provided in RFC 3261 Section 12.1.1 to determine if the Contact header must be a sips: URI.

Parameters
rdataThe incoming dialog-starting request
Return values
0SIPS not required
1SIPS required

Definition at line 4148 of file res_pjsip.c.

References ast_assert, and NULL.

Referenced by create_dialog_uas().

4149 {
4150  pjsip_rr_hdr *record_route;
4151 
4152  if (PJSIP_URI_SCHEME_IS_SIPS(rdata->msg_info.msg->line.req.uri)) {
4153  return 1;
4154  }
4155 
4156  record_route = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_RECORD_ROUTE, NULL);
4157  if (record_route) {
4158  if (PJSIP_URI_SCHEME_IS_SIPS(&record_route->name_addr)) {
4159  return 1;
4160  }
4161  } else {
4162  pjsip_contact_hdr *contact;
4163 
4164  contact = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT, NULL);
4165  ast_assert(contact != NULL);
4166  if (PJSIP_URI_SCHEME_IS_SIPS(contact->uri)) {
4167  return 1;
4168  }
4169  }
4170 
4171  return 0;
4172 }
#define ast_assert(a)
Definition: utils.h:695
#define NULL
Definition: resample.c:96

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 5937 of file res_pjsip.c.

References ARRAY_LEN, ast_cli_unregister_multiple(), AST_MODFLAG_GLOBAL_SYMBOLS, AST_MODFLAG_LOAD_ORDER, AST_MODPRI_CHANNEL_DEPEND, AST_MODULE_INFO(), AST_MODULE_SUPPORT_CORE, ast_serializer_pool_destroy(), ast_sip_destroy_scheduler(), ast_sip_push_task_wait_servant(), AST_TEST_UNREGISTER, ast_threadpool_shutdown(), ASTERISK_GPL_KEY, load_module(), NULL, reload(), reload_module(), and unload_pjsip().

5938 {
5939  AST_TEST_UNREGISTER(xml_sanitization_end_null);
5940  AST_TEST_UNREGISTER(xml_sanitization_exceeds_buffer);
5942 
5943  /* The thread this is called from cannot call PJSIP/PJLIB functions,
5944  * so we have to push the work to the threadpool to handle
5945  */
5950 
5951  return 0;
5952 }
static struct ast_cli_entry cli_commands[]
Definition: res_pjsip.c:3671
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
int ast_serializer_pool_destroy(struct ast_serializer_pool *pool)
Destroy the serializer pool.
Definition: serializer.c:39
static struct ast_threadpool * sip_threadpool
Definition: res_pjsip.c:3274
int ast_sip_destroy_scheduler(void)
#define NULL
Definition: resample.c:96
int ast_sip_push_task_wait_servant(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Push a task to SIP servants and wait for it to complete.
Definition: res_pjsip.c:5204
#define AST_TEST_UNREGISTER(cb)
Definition: test.h:128
static struct ast_serializer_pool * sip_serializer_pool
Definition: res_pjsip.c:3270
void ast_threadpool_shutdown(struct ast_threadpool *pool)
Shut down a threadpool and destroy it.
Definition: threadpool.c:965
static int unload_pjsip(void *data)
Definition: res_pjsip.c:5700

◆ unload_pjsip()

static int unload_pjsip ( void *  data)
static

Definition at line 5700 of file res_pjsip.c.

References ast_pjproject_caching_pool_destroy(), ast_pjsip_endpoint, ast_res_pjsip_cleanup_message_filter(), ast_res_pjsip_cleanup_options_handling(), ast_res_pjsip_destroy_configuration(), ast_sip_destroy_distributor(), ast_sip_destroy_global_headers(), ast_sip_destroy_system(), ast_sip_destroy_transport_events(), ast_sip_destroy_transport_management(), ast_sip_unregister_service(), memory_pool, NULL, stop_monitor_thread(), and supplement_module.

Referenced by load_module(), and unload_module().

5701 {
5702  /*
5703  * These calls need the pjsip endpoint and serializer to clean up.
5704  * If they're not set, then there's nothing to clean up anyway.
5705  */
5716  }
5717 
5718  if (monitor_thread) {
5720  monitor_thread = NULL;
5721  }
5722 
5723  if (memory_pool) {
5724  /* This mimics the behavior of pj_pool_safe_release
5725  * which was introduced in pjproject 2.6.
5726  */
5727  pj_pool_t *temp_pool = memory_pool;
5728 
5729  memory_pool = NULL;
5730  pj_pool_release(temp_pool);
5731  }
5732 
5734 
5735  if (caching_pool.lock) {
5737  }
5738 
5739  pj_shutdown();
5740 
5741  return 0;
5742 }
void ast_pjproject_caching_pool_destroy(pj_caching_pool *cp)
Destroy caching pool factory and all cached pools.
void ast_sip_destroy_global_headers(void)
pj_thread_t * monitor_thread
Definition: res_pjsip.c:5274
pj_caching_pool caching_pool
Definition: res_pjsip.c:5272
#define NULL
Definition: resample.c:96
void ast_res_pjsip_cleanup_options_handling(void)
void ast_sip_destroy_transport_events(void)
void ast_sip_unregister_service(pjsip_module *module)
Definition: res_pjsip.c:3331
void ast_sip_destroy_transport_management(void)
static pjsip_module supplement_module
Definition: res_pjsip.c:4373
static pjsip_endpoint * ast_pjsip_endpoint
Definition: res_pjsip.c:3272
static struct ast_serializer_pool * sip_serializer_pool
Definition: res_pjsip.c:3270
pj_pool_t * memory_pool
Definition: res_pjsip.c:5273
void ast_res_pjsip_destroy_configuration(void)
void ast_res_pjsip_cleanup_message_filter(void)
void ast_sip_destroy_system(void)
static void stop_monitor_thread(void)
Definition: res_pjsip.c:5286
void ast_sip_destroy_distributor(void)

◆ unregister_service()

static int unregister_service ( void *  data)
static

Definition at line 3320 of file res_pjsip.c.

References ast_debug, and ast_pjsip_endpoint.

Referenced by ast_sip_unregister_service().

3321 {
3322  pjsip_module **module = data;
3323  if (!ast_pjsip_endpoint) {
3324  return -1;
3325  }
3326  pjsip_endpt_unregister_module(ast_pjsip_endpoint, *module);
3327  ast_debug(1, "Unregistered SIP service %.*s\n", (int) pj_strlen(&(*module)->name), pj_strbuf(&(*module)->name));
3328  return 0;
3329 }
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
static pjsip_endpoint * ast_pjsip_endpoint
Definition: res_pjsip.c:3272

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "Basic SIP resource" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "30ef0c93b36035ec78c9cfd712d36d9b" , .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload_module, .load_pri = AST_MODPRI_CHANNEL_DEPEND - 5, .requires = "dnsmgr,res_pjproject,res_sorcery_config,res_sorcery_memory,res_sorcery_astdb", .optional_modules = "res_statsd", }
static

Definition at line 5962 of file res_pjsip.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 5962 of file res_pjsip.c.

◆ ast_pjsip_endpoint

pjsip_endpoint* ast_pjsip_endpoint
static

◆ caching_pool

pj_caching_pool caching_pool

Definition at line 5272 of file res_pjsip.c.

◆ cli_commands

struct ast_cli_entry cli_commands[]
static
Initial value:
= {
{ .handler = cli_dump_endpt , .summary = "Dump the res_pjsip endpt internals" ,},
{ .handler = cli_show_settings , .summary = "Show global and system configuration options" ,},
{ .handler = cli_show_endpoint_identifiers , .summary = "List registered endpoint identifiers" ,}
}
static char * cli_dump_endpt(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: res_pjsip.c:3569
static char * cli_show_endpoint_identifiers(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: res_pjsip.c:3609
static char * cli_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: res_pjsip.c:3640

Definition at line 3671 of file res_pjsip.c.

◆ endpoint_formatters

struct endpoint_formatters endpoint_formatters = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }

◆ endpoint_identifiers

struct endpoint_identifiers endpoint_identifiers = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
static

◆ host_ip_ipv4

pj_sockaddr host_ip_ipv4
static

Local host address for IPv4

Definition at line 3277 of file res_pjsip.c.

Referenced by ast_sip_get_host_ip(), and load_pjsip().

◆ host_ip_ipv4_string

char host_ip_ipv4_string[PJ_INET6_ADDRSTRLEN]
static

Local host address for IPv4 (string form)

Definition at line 3280 of file res_pjsip.c.

Referenced by ast_sip_get_host_ip(), ast_sip_get_host_ip_string(), and load_pjsip().

◆ host_ip_ipv6

pj_sockaddr host_ip_ipv6
static

Local host address for IPv6

Definition at line 3283 of file res_pjsip.c.

Referenced by ast_sip_get_host_ip(), and load_pjsip().

◆ host_ip_ipv6_string

char host_ip_ipv6_string[PJ_INET6_ADDRSTRLEN]
static

Local host address for IPv6 (string form)

Definition at line 3286 of file res_pjsip.c.

Referenced by ast_sip_get_host_ip(), ast_sip_get_host_ip_string(), and load_pjsip().

◆ info_method

const pjsip_method info_method = {PJSIP_OTHER_METHOD, {"INFO", 4} }
static

Definition at line 4331 of file res_pjsip.c.

◆ memory_pool

pj_pool_t* memory_pool

Definition at line 5273 of file res_pjsip.c.

Referenced by unload_pjsip().

◆ message_method

const pjsip_method message_method = {PJSIP_OTHER_METHOD, {"MESSAGE", 7} }
static

Definition at line 4332 of file res_pjsip.c.

◆ method

const char* method

◆ methods

struct { ... } methods[]

◆ monitor_continue

int monitor_continue
static

Definition at line 5275 of file res_pjsip.c.

◆ monitor_thread

pj_thread_t* monitor_thread

Definition at line 5274 of file res_pjsip.c.

◆ pj_thread_storage

struct ast_threadstorage pj_thread_storage = { .once = PTHREAD_ONCE_INIT , .key_init = __init_pj_thread_storage , .custom_init = NULL , }
static

Definition at line 5292 of file res_pjsip.c.

Referenced by sip_thread_start().

◆ pmethod

const pjsip_method* pmethod

Definition at line 4336 of file res_pjsip.c.

Referenced by ast_sip_create_request().

◆ registered_authenticator

struct ast_sip_authenticator* registered_authenticator
static

Definition at line 3336 of file res_pjsip.c.

◆ registered_outbound_authenticator

struct ast_sip_outbound_authenticator* registered_outbound_authenticator
static

Definition at line 3387 of file res_pjsip.c.

◆ servant_id_storage

struct ast_threadstorage servant_id_storage = { .once = PTHREAD_ONCE_INIT , .key_init = __init_servant_id_storage , .custom_init = NULL , }
static

Definition at line 5293 of file res_pjsip.c.

Referenced by ast_sip_thread_is_servant(), and sip_thread_start().

◆ sip_serializer_pool

struct ast_serializer_pool* sip_serializer_pool
static

Pool of serializers to use if not supplied.

Definition at line 3270 of file res_pjsip.c.

◆ sip_threadpool

struct ast_threadpool* sip_threadpool
static

Definition at line 3274 of file res_pjsip.c.

Referenced by ast_sip_threadpool().

◆ supplement_module

pjsip_module supplement_module
static

◆ supplements

struct supplements supplements = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }