Asterisk - The Open Source Telephony Project  GIT-master-a24979a
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...
 
int ast_sip_are_media_types_equal (pjsip_media_type *a, pjsip_media_type *b)
 Compare pjsip media types. 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...
 
int ast_sip_is_media_type_in (pjsip_media_type *a,...)
 Check if a media type is in a list of others. 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)
 
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 = AST_BUILDOPT_SUM, .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 , }
 
pjsip_media_type pjsip_media_type_application_cpim_xpidf_xml
 
pjsip_media_type pjsip_media_type_application_json
 
pjsip_media_type pjsip_media_type_application_media_control_xml
 
pjsip_media_type pjsip_media_type_application_pidf_xml
 
pjsip_media_type pjsip_media_type_application_rlmi_xml
 
pjsip_media_type pjsip_media_type_application_sdp
 
pjsip_media_type pjsip_media_type_application_simple_message_summary
 
pjsip_media_type pjsip_media_type_application_xpidf_xml
 
pjsip_media_type pjsip_media_type_multipart_alternative
 
pjsip_media_type pjsip_media_type_multipart_mixed
 
pjsip_media_type pjsip_media_type_multipart_related
 
pjsip_media_type pjsip_media_type_text_plain
 
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"

Definition at line 59 of file res_pjsip.c.

◆ SERIALIZER_POOL_SIZE

#define SERIALIZER_POOL_SIZE   8

Number of serializers in pool if one not supplied.

Definition at line 62 of file res_pjsip.c.

◆ SIP_SERVANT_ID

#define SIP_SERVANT_ID   0x5E2F1D

Definition at line 2117 of file res_pjsip.c.

◆ TIMEOUT_TIMER2

#define TIMEOUT_TIMER2   5

Definition at line 1363 of file res_pjsip.c.

◆ TIMER_INACTIVE

#define TIMER_INACTIVE   0

Definition at line 1362 of file res_pjsip.c.

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 969 of file res_pjsip.c.

Function Documentation

◆ __init_pj_thread_storage()

static void __init_pj_thread_storage ( void  )
static

Definition at line 2115 of file res_pjsip.c.

2120 {

◆ __init_servant_id_storage()

static void __init_servant_id_storage ( void  )
static

Definition at line 2116 of file res_pjsip.c.

2120 {

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 2814 of file res_pjsip.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 2814 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 1873 of file res_pjsip.c.

1874 {
1875  pj_str_t type;
1876  pj_str_t subtype;
1877  pj_str_t body_text;
1878 
1879  pj_cstr(&type, body->type);
1880  pj_cstr(&subtype, body->subtype);
1881  pj_cstr(&body_text, body->body_text);
1882 
1883  return pjsip_msg_body_create(pool, &type, &subtype, &body_text);
1884 }
static const char type[]
Definition: chan_ooh323.c:109
const char * type
Definition: res_pjsip.h:2110
const char * body_text
Definition: res_pjsip.h:2114
const char * subtype
Definition: res_pjsip.h:2112

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

◆ 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 2035 of file res_pjsip.c.

2036 {
2037  size_t chars_to_copy = MIN(size - 1, pj_strlen(src));
2038  memcpy(dest, pj_strbuf(src), chars_to_copy);
2039  dest[chars_to_copy] = '\0';
2040 }
#define MIN(a, b)
Definition: utils.h:226

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(), dialog_info_generate_body_content(), endpoint_lookup(), extract_contact_addr(), find_aor(), find_aor_name(), find_challenge(), get_auth_header(), get_codecs(), 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(), rfc3326_use_reason_header(), 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_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().

◆ 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
[out]destThe destination buffer
srcThe pj_str_t to copy
Returns
Number of characters copied or negative value on error

Definition at line 2042 of file res_pjsip.c.

2043 {
2044  int res = ast_asprintf(dest, "%.*s", (int)pj_strlen(src), pj_strbuf(src));
2045 
2046  if (res < 0) {
2047  *dest = NULL;
2048  }
2049 
2050  return res;
2051 }
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition: astmm.h:267
#define NULL
Definition: resample.c:96

References ast_asprintf, and NULL.

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 2814 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 1886 of file res_pjsip.c.

1887 {
1888  pjsip_msg_body *pjsip_body = ast_body_to_pjsip_body(tdata->pool, body);
1889  tdata->msg->body = pjsip_body;
1890  return 0;
1891 }
static pjsip_msg_body * ast_body_to_pjsip_body(pj_pool_t *pool, const struct ast_sip_body *body)
Definition: res_pjsip.c:1873

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

◆ 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 message bodies to add
num_bodiesThe parts of the body to add
Return values
0Success
-1Failure

Definition at line 1893 of file res_pjsip.c.

1894 {
1895  int i;
1896  /* NULL for type and subtype automatically creates "multipart/mixed" */
1897  pjsip_msg_body *body = pjsip_multipart_create(tdata->pool, NULL, NULL);
1898 
1899  for (i = 0; i < num_bodies; ++i) {
1900  pjsip_multipart_part *part = pjsip_multipart_create_part(tdata->pool);
1901  part->body = ast_body_to_pjsip_body(tdata->pool, bodies[i]);
1902  pjsip_multipart_add_part(tdata->pool, body, part);
1903  }
1904 
1905  tdata->msg->body = body;
1906  return 0;
1907 }

References ast_body_to_pjsip_body(), and NULL.

◆ 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 83 of file res_pjsip.c.

84 {
85  char date[256];
86  struct tm tm;
87  time_t t = time(NULL);
88 
89  gmtime_r(&t, &tm);
90  strftime(date, sizeof(date), "%a, %d %b %Y %T GMT", &tm);
91 
92  ast_sip_add_header(tdata, "Date", date);
93 }
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:1858

References ast_sip_add_header(), and NULL.

Referenced by add_date_header().

◆ 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 1858 of file res_pjsip.c.

1859 {
1860  pj_str_t hdr_name;
1861  pj_str_t hdr_value;
1862  pjsip_generic_string_hdr *hdr;
1863 
1864  pj_cstr(&hdr_name, name);
1865  pj_cstr(&hdr_value, value);
1866 
1867  hdr = pjsip_generic_string_hdr_create(tdata->pool, &hdr_name, &hdr_value);
1868 
1869  pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *) hdr);
1870  return 0;
1871 }
static const char name[]
Definition: format_mp3.c:68
int value
Definition: syslog.c:37

References name, and value.

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(), rfc3326_add_reason_header(), send_options_response(), sip_publication_respond(), and transfer_refer().

◆ 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 789 of file res_pjsip.c.

790 {
791  pjsip_sip_uri *sip_uri;
792  int i = 0;
793  static const pj_str_t STR_PHONE = { "phone", 5 };
794 
795  if (!endpoint || !endpoint->usereqphone || (!PJSIP_URI_SCHEME_IS_SIP(uri) && !PJSIP_URI_SCHEME_IS_SIPS(uri))) {
796  return;
797  }
798 
799  sip_uri = pjsip_uri_get_uri(uri);
800 
801  if (!pj_strlen(&sip_uri->user)) {
802  return;
803  }
804 
805  if (pj_strbuf(&sip_uri->user)[0] == '+') {
806  i = 1;
807  }
808 
809  /* Test URI user against allowed characters in AST_DIGIT_ANY */
810  for (; i < pj_strlen(&sip_uri->user); i++) {
811  if (!strchr(AST_DIGIT_ANY, pj_strbuf(&sip_uri->user)[i])) {
812  break;
813  }
814  }
815 
816  if (i < pj_strlen(&sip_uri->user)) {
817  return;
818  }
819 
820  sip_uri->user_param = STR_PHONE;
821 }
#define AST_DIGIT_ANY
Definition: file.h:48
unsigned int usereqphone
Definition: res_pjsip.h:923

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

◆ 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
body_textThe string to append to the end of the current body
Return values
0Success
-1Failure

Definition at line 1909 of file res_pjsip.c.

1910 {
1911  size_t combined_size = strlen(body_text) + tdata->msg->body->len;
1912  struct ast_str *body_buffer = ast_str_alloca(combined_size);
1913 
1914  ast_str_set(&body_buffer, 0, "%.*s%s", (int) tdata->msg->body->len, (char *) tdata->msg->body->data, body_text);
1915 
1916  tdata->msg->body->data = pj_pool_alloc(tdata->pool, combined_size);
1917  pj_memcpy(tdata->msg->body->data, ast_str_buffer(body_buffer), combined_size);
1918  tdata->msg->body->len = combined_size;
1919 
1920  return 0;
1921 }
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:739
#define ast_str_alloca(init_len)
Definition: strings.h:826
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:1091
Support for dynamic strings.
Definition: strings.h:604

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

◆ ast_sip_are_media_types_equal()

int ast_sip_are_media_types_equal ( pjsip_media_type *  a,
pjsip_media_type *  b 
)

Compare pjsip media types.

Parameters
pjsip_media_typea
pjsip_media_typeb
Return values
1Media types are equal
0Media types are not equal

Definition at line 2053 of file res_pjsip.c.

2054 {
2055  int rc = 0;
2056  if (a != NULL && b != NULL) {
2057  rc = pjsip_media_type_cmp(a, b, 0) ? 0 : 1;
2058  }
2059  return rc;
2060 }
static struct test_val b
static struct test_val a

References a, b, and NULL.

Referenced by video_info_incoming_request().

◆ 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 2357 of file res_pjsip.c.

2358 {
2359  const char *value;
2360 
2361  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)) {
2362  value = "local";
2363  } 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)) {
2364  value = "local_merge";
2365  } 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)) {
2366  value = "local_first";
2367  } 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)) {
2368  value = "remote";
2369  } 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)) {
2370  value = "remote_merge";
2371  } 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)) {
2372  value = "remote_first";
2373  } else {
2374  value = "unknown";
2375  }
2376 
2377  return value;
2378 }
#define ast_sip_call_codec_pref_test(__param, __codec_pref)
Returns true if the preference is set in the parameter.
Definition: res_pjsip.h:590

References ast_sip_call_codec_pref_test, and value.

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

◆ 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 2380 of file res_pjsip.c.

2381 {
2382  pref->flags = 0;
2383 
2384  if (strcmp(pref_str, "local") == 0) {
2386  } else if (is_outgoing && strcmp(pref_str, "local_merge") == 0) {
2388  } else if (strcmp(pref_str, "local_first") == 0) {
2390  } else if (strcmp(pref_str, "remote") == 0) {
2392  } else if (is_outgoing && strcmp(pref_str, "remote_merge") == 0) {
2394  } else if (strcmp(pref_str, "remote_first") == 0) {
2396  } else {
2397  return -1;
2398  }
2399 
2400  return 0;
2401 }
@ AST_SIP_CALL_CODEC_PREF_ALL
Definition: res_pjsip.h:570
@ AST_SIP_CALL_CODEC_PREF_LOCAL
Definition: res_pjsip.h:576
@ AST_SIP_CALL_CODEC_PREF_REMOTE
Definition: res_pjsip.h:578
@ AST_SIP_CALL_CODEC_PREF_UNION
Definition: res_pjsip.h:566
@ AST_SIP_CALL_CODEC_PREF_FIRST
Definition: res_pjsip.h:572
@ AST_SIP_CALL_CODEC_PREF_INTERSECT
Definition: res_pjsip.h:564
unsigned int flags
Definition: utils.h:200
#define ast_set_flag(p, flag)
Definition: utils.h:70

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

◆ 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 156 of file res_pjsip.c.

174 {
176  ast_log(LOG_WARNING, "No SIP authenticator registered. Assuming authentication is successful\n");
178  }
179  return registered_authenticator->check_authentication(endpoint, rdata, tdata);
180 }
#define ast_log
Definition: astobj2.c:42
#define LOG_WARNING
static struct ast_sip_authenticator * registered_authenticator
Definition: res_pjsip.c:131
@ AST_SIP_AUTHENTICATION_SUCCESS
Definition: res_pjsip.h:1016
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:1045

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

Referenced by authenticate().

◆ 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 823 of file res_pjsip.c.

825 {
826  char enclosed_uri[PJSIP_MAX_URL_SIZE];
827  pj_str_t local_uri = { "sip:temp@temp", 13 }, remote_uri, target_uri;
828  pj_status_t res;
829  pjsip_dialog *dlg = NULL;
830  const char *outbound_proxy = endpoint->outbound_proxy;
831  pjsip_tpselector selector = { .type = PJSIP_TPSELECTOR_NONE, };
832  static const pj_str_t HCONTACT = { "Contact", 7 };
833 
834  snprintf(enclosed_uri, sizeof(enclosed_uri), "<%s>", uri);
835  pj_cstr(&remote_uri, enclosed_uri);
836 
837  pj_cstr(&target_uri, uri);
838 
839  res = pjsip_dlg_create_uac(pjsip_ua_instance(), &local_uri, NULL, &remote_uri, &target_uri, &dlg);
840  if (res == PJ_SUCCESS && !(PJSIP_URI_SCHEME_IS_SIP(dlg->target) || PJSIP_URI_SCHEME_IS_SIPS(dlg->target))) {
841  /* dlg->target is a pjsip_other_uri, but it's assumed to be a
842  * pjsip_sip_uri below. Fail fast. */
843  res = PJSIP_EINVALIDURI;
844  pjsip_dlg_terminate(dlg);
845  }
846  if (res != PJ_SUCCESS) {
847  if (res == PJSIP_EINVALIDURI) {
849  "Endpoint '%s': Could not create dialog to invalid URI '%s'. Is endpoint registered and reachable?\n",
850  ast_sorcery_object_get_id(endpoint), uri);
851  }
852  return NULL;
853  }
854 
855  /* We have to temporarily bump up the sess_count here so the dialog is not prematurely destroyed */
856  dlg->sess_count++;
857 
858  ast_sip_dlg_set_transport(endpoint, dlg, &selector);
859 
860  if (sip_dialog_create_from(dlg->pool, &local_uri, endpoint->fromuser, endpoint->fromdomain, &remote_uri, &selector)) {
861  dlg->sess_count--;
862  pjsip_dlg_terminate(dlg);
863  ast_sip_tpselector_unref(&selector);
864  return NULL;
865  }
866 
867  ast_sip_tpselector_unref(&selector);
868 
869  /* Update the dialog with the new local URI, we do it afterwards so we can use the dialog pool for construction */
870  pj_strdup_with_null(dlg->pool, &dlg->local.info_str, &local_uri);
871  dlg->local.info->uri = pjsip_parse_uri(dlg->pool, dlg->local.info_str.ptr, dlg->local.info_str.slen, 0);
872  if (!dlg->local.info->uri) {
874  "Could not parse URI '%s' for endpoint '%s'\n",
875  dlg->local.info_str.ptr, ast_sorcery_object_get_id(endpoint));
876  dlg->sess_count--;
877  pjsip_dlg_terminate(dlg);
878  return NULL;
879  }
880 
881  dlg->local.contact = pjsip_parse_hdr(dlg->pool, &HCONTACT, local_uri.ptr, local_uri.slen, NULL);
882 
883  if (!ast_strlen_zero(endpoint->contact_user)) {
884  pjsip_sip_uri *sip_uri;
885 
886  sip_uri = pjsip_uri_get_uri(dlg->local.contact->uri);
887  pj_strdup2(dlg->pool, &sip_uri->user, endpoint->contact_user);
888  }
889 
890  /* If a request user has been specified and we are permitted to change it, do so */
891  if (!ast_strlen_zero(request_user)) {
892  pjsip_sip_uri *sip_uri;
893 
894  if (PJSIP_URI_SCHEME_IS_SIP(dlg->target) || PJSIP_URI_SCHEME_IS_SIPS(dlg->target)) {
895  sip_uri = pjsip_uri_get_uri(dlg->target);
896  pj_strdup2(dlg->pool, &sip_uri->user, request_user);
897  }
898  if (PJSIP_URI_SCHEME_IS_SIP(dlg->remote.info->uri) || PJSIP_URI_SCHEME_IS_SIPS(dlg->remote.info->uri)) {
899  sip_uri = pjsip_uri_get_uri(dlg->remote.info->uri);
900  pj_strdup2(dlg->pool, &sip_uri->user, request_user);
901  }
902  }
903 
904  /* Add the user=phone parameter if applicable */
905  ast_sip_add_usereqphone(endpoint, dlg->pool, dlg->target);
906  ast_sip_add_usereqphone(endpoint, dlg->pool, dlg->remote.info->uri);
907 
908  if (!ast_strlen_zero(outbound_proxy)) {
909  pjsip_route_hdr route_set, *route;
910  static const pj_str_t ROUTE_HNAME = { "Route", 5 };
911  pj_str_t tmp;
912 
913  pj_list_init(&route_set);
914 
915  pj_strdup2_with_null(dlg->pool, &tmp, outbound_proxy);
916  if (!(route = pjsip_parse_hdr(dlg->pool, &ROUTE_HNAME, tmp.ptr, tmp.slen, NULL))) {
917  ast_log(LOG_ERROR, "Could not create dialog to endpoint '%s' as outbound proxy URI '%s' is not valid\n",
918  ast_sorcery_object_get_id(endpoint), outbound_proxy);
919  dlg->sess_count--;
920  pjsip_dlg_terminate(dlg);
921  return NULL;
922  }
923  pj_list_insert_nodes_before(&route_set, route);
924 
925  pjsip_dlg_set_route_set(dlg, &route_set);
926  }
927 
928  dlg->sess_count--;
929 
930  return dlg;
931 }
static int tmp()
Definition: bt_open.c:389
#define LOG_ERROR
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.
Definition: res_pjsip.c:789
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:586
void ast_sip_tpselector_unref(pjsip_tpselector *selector)
Unreference a pjsip_tpselector.
Definition: res_pjsip.c:782
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:608
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
char * contact_user
Definition: res_pjsip.h:933
const ast_string_field outbound_proxy
Definition: res_pjsip.h:883
const ast_string_field fromdomain
Definition: res_pjsip.h:883
const ast_string_field fromuser
Definition: res_pjsip.h:883

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

◆ 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 1028 of file res_pjsip.c.

1029 {
1030 #ifdef HAVE_PJSIP_DLG_CREATE_UAS_AND_INC_LOCK
1031  pjsip_dialog *dlg;
1032 
1033  dlg = create_dialog_uas(endpoint, rdata, status, pjsip_dlg_create_uas_and_inc_lock);
1034  if (dlg) {
1035  pjsip_dlg_dec_lock(dlg);
1036  }
1037 
1038  return dlg;
1039 #else
1040  return create_dialog_uas(endpoint, rdata, status, pjsip_dlg_create_uas);
1041 #endif
1042 }
jack_status_t status
Definition: app_jack.c:146
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:972

References create_dialog_uas(), and status.

◆ 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 unknowingly 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 1044 of file res_pjsip.c.

1046 {
1047 #ifdef HAVE_PJSIP_DLG_CREATE_UAS_AND_INC_LOCK
1048  return create_dialog_uas(endpoint, rdata, status, pjsip_dlg_create_uas_and_inc_lock);
1049 #else
1050  /*
1051  * This is put here in order to be compatible with older versions of pjproject.
1052  * Best we can do in this case is immediately lock after getting the dialog.
1053  * However, that does leave a "gap" between creating and locking.
1054  */
1055  pjsip_dialog *dlg;
1056 
1057  dlg = create_dialog_uas(endpoint, rdata, status, pjsip_dlg_create_uas);
1058  if (dlg) {
1059  pjsip_dlg_inc_lock(dlg);
1060  }
1061 
1062  return dlg;
1063 #endif
1064  }

References create_dialog_uas(), and status.

Referenced by create_subscription_tree(), and pre_session_setup().

◆ 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
[out]rdataThe 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 1118 of file res_pjsip.c.

1120 {
1121  return ast_sip_create_rdata_with_contact(rdata, packet, src_name, src_port, transport_type,
1122  local_name, local_port, NULL);
1123 }
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:1066

References ast_sip_create_rdata_with_contact(), and NULL.

◆ 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
[out]rdataThe 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 1066 of file res_pjsip.c.

1068 {
1069  pj_str_t tmp;
1070 
1071  /*
1072  * Initialize the error list in case there is a parse error
1073  * in the given packet.
1074  */
1075  pj_list_init(&rdata->msg_info.parse_err);
1076 
1077  rdata->tp_info.transport = PJ_POOL_ZALLOC_T(rdata->tp_info.pool, pjsip_transport);
1078  if (!rdata->tp_info.transport) {
1079  return -1;
1080  }
1081 
1082  ast_copy_string(rdata->pkt_info.packet, packet, sizeof(rdata->pkt_info.packet));
1083  ast_copy_string(rdata->pkt_info.src_name, src_name, sizeof(rdata->pkt_info.src_name));
1084  rdata->pkt_info.src_port = src_port;
1085  pj_sockaddr_parse(pj_AF_UNSPEC(), 0, pj_cstr(&tmp, src_name), &rdata->pkt_info.src_addr);
1086  pj_sockaddr_set_port(&rdata->pkt_info.src_addr, src_port);
1087 
1088  pjsip_parse_rdata(packet, strlen(packet), rdata);
1089  if (!rdata->msg_info.msg || !pj_list_empty(&rdata->msg_info.parse_err)) {
1090  return -1;
1091  }
1092 
1093  if (!ast_strlen_zero(contact)) {
1094  pjsip_contact_hdr *contact_hdr;
1095 
1096  contact_hdr = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT, NULL);
1097  if (contact_hdr) {
1098  contact_hdr->uri = pjsip_parse_uri(rdata->tp_info.pool, (char *)contact,
1099  strlen(contact), PJSIP_PARSE_URI_AS_NAMEADDR);
1100  if (!contact_hdr->uri) {
1101  ast_log(LOG_WARNING, "Unable to parse contact URI from '%s'.\n", contact);
1102  return -1;
1103  }
1104  }
1105  }
1106 
1107  pj_strdup2(rdata->tp_info.pool, &rdata->msg_info.via->recvd_param, rdata->pkt_info.src_name);
1108  rdata->msg_info.via->rport_param = -1;
1109 
1110  rdata->tp_info.transport->key.type = pjsip_transport_get_type_from_name(pj_cstr(&tmp, transport_type));
1111  rdata->tp_info.transport->type_name = transport_type;
1112  pj_strdup2(rdata->tp_info.pool, &rdata->tp_info.transport->local_name.host, local_name);
1113  rdata->tp_info.transport->local_name.port = local_port;
1114 
1115  return 0;
1116 }
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:406

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

Referenced by ast_sip_create_rdata(), and subscription_persistence_recreate().

◆ 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 1285 of file res_pjsip.c.

1288 {
1289  const pjsip_method *pmethod = get_pjsip_method(method);
1290 
1291  if (!pmethod) {
1292  ast_log(LOG_WARNING, "Unknown method '%s'. Cannot send request\n", method);
1293  return -1;
1294  }
1295 
1296  if (dlg) {
1297  return create_in_dialog_request(pmethod, dlg, tdata);
1298  } else {
1299  ast_assert(endpoint != NULL);
1300  return create_out_of_dialog_request(pmethod, endpoint, uri, contact, tdata);
1301  }
1302 }
static int create_in_dialog_request(const pjsip_method *method, struct pjsip_dialog *dlg, pjsip_tx_data **tdata)
Definition: res_pjsip.c:1157
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:1175
const char * method
Definition: res_pjsip.c:1130
static const pjsip_method * get_pjsip_method(const char *method)
Definition: res_pjsip.c:1146
const pjsip_method * pmethod
Definition: res_pjsip.c:1131
#define ast_assert(a)
Definition: utils.h:734

References ast_assert, ast_log, create_in_dialog_request(), create_out_of_dialog_request(), get_pjsip_method(), LOG_WARNING, method, 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().

◆ 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 207 of file res_pjsip.c.

209 {
211  ast_log(LOG_WARNING, "No SIP outbound authenticator registered. Cannot respond to authentication challenge\n");
212  return -1;
213  }
214  return registered_outbound_authenticator->create_request_with_auth(auths, challenge, old_request, new_request);
215 }
static struct ast_sip_outbound_authenticator * registered_outbound_authenticator
Definition: res_pjsip.c:182
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
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:1066

References ast_log, challenge(), ast_sip_outbound_authenticator::create_request_with_auth, LOG_WARNING, and registered_outbound_authenticator.

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

◆ 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]p_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 2271 of file res_pjsip.c.

2273 {
2274  int res = pjsip_endpt_create_response(ast_sip_get_pjsip_endpoint(), rdata, st_code, NULL, tdata);
2275 
2276  if (!res) {
2277  ast_sip_mod_data_set((*tdata)->pool, (*tdata)->mod_data, supplement_module.id, MOD_DATA_CONTACT, ao2_bump(contact));
2278  }
2279 
2280  return res;
2281 }
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
#define MOD_DATA_CONTACT
Definition: res_pjsip.c:59
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
Definition: res_pjsip.c:513
static pjsip_module supplement_module
Definition: res_pjsip.c:1168
#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:2752

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

Referenced by send_options_response(), and send_response().

◆ 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 2161 of file res_pjsip.c.

2162 {
2163  unsigned int hval = 0;
2164 
2165  if (!ht) {
2166  return NULL;
2167  }
2168 
2169  return pj_hash_get(ht, key, PJ_HASH_KEY_STRING, &hval);
2170 }

References NULL.

◆ 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 2172 of file res_pjsip.c.

2174 {
2175  if (!ht) {
2176  ht = pj_hash_create(pool, 11);
2177  }
2178 
2179  pj_hash_set(pool, ht, key, PJ_HASH_KEY_STRING, 0, val);
2180 
2181  return ht;
2182 }
Definition: ast_expr2.c:325

◆ 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 586 of file res_pjsip.c.

588 {
589  pjsip_sip_uri *uri;
590  pjsip_tpselector sel = { .type = PJSIP_TPSELECTOR_NONE, };
591 
592  uri = pjsip_uri_get_uri(dlg->target);
593  if (!selector) {
594  selector = &sel;
595  }
596 
597  ast_sip_set_tpselector_from_ep_or_uri(endpoint, uri, selector);
598 
599  pjsip_dlg_set_transport(dlg, selector);
600 
601  if (selector == &sel) {
603  }
604 
605  return 0;
606 }
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:770

References ast_sip_set_tpselector_from_ep_or_uri(), and ast_sip_tpselector_unref().

Referenced by ast_sip_create_dialog_uac().

◆ 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 2307 of file res_pjsip.c.

2309 {
2310  switch (dtmf) {
2311  case AST_SIP_DTMF_NONE:
2312  ast_copy_string(buf, "none", buf_len);
2313  break;
2314  case AST_SIP_DTMF_RFC_4733:
2315  ast_copy_string(buf, "rfc4733", buf_len);
2316  break;
2317  case AST_SIP_DTMF_INBAND:
2318  ast_copy_string(buf, "inband", buf_len);
2319  break;
2320  case AST_SIP_DTMF_INFO:
2321  ast_copy_string(buf, "info", buf_len);
2322  break;
2323  case AST_SIP_DTMF_AUTO:
2324  ast_copy_string(buf, "auto", buf_len);
2325  break;
2327  ast_copy_string(buf, "auto_info", buf_len);
2328  break;
2329  default:
2330  buf[0] = '\0';
2331  return -1;
2332  }
2333  return 0;
2334 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
@ AST_SIP_DTMF_NONE
Definition: res_pjsip.h:429
@ AST_SIP_DTMF_AUTO_INFO
Definition: res_pjsip.h:440
@ AST_SIP_DTMF_AUTO
Definition: res_pjsip.h:438
@ AST_SIP_DTMF_INBAND
Definition: res_pjsip.h:434
@ AST_SIP_DTMF_INFO
Definition: res_pjsip.h:436
@ AST_SIP_DTMF_RFC_4733
Definition: res_pjsip.h:432

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, AST_SIP_DTMF_RFC_4733, and buf.

Referenced by dtmf_to_str(), and pjsip_acf_dtmf_mode_read().

◆ 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 1666 of file res_pjsip.c.

1667 {
1668  pjsip_via_hdr *via;
1669 
1670  if (!tdata || !tdata->dest_info.addr.count
1671  || (tdata->dest_info.cur_addr == tdata->dest_info.addr.count - 1)) {
1672  /* No more addresses to try */
1673  return 0;
1674  }
1675 
1676  /* Try next address */
1677  ++tdata->dest_info.cur_addr;
1678 
1679  via = (pjsip_via_hdr*)pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA, NULL);
1680  via->branch_param.slen = 0;
1681 
1682  pjsip_tx_data_invalidate_msg(tdata);
1683 
1684  return 1;
1685 }

References NULL, and send_request_wrapper::tdata.

Referenced by check_request_status(), and handle_registration_response().

◆ 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
amiAMI variable container
countthe number of formatters operated on
Return values
0Success, otherwise non-zero on error

Definition at line 494 of file res_pjsip.c.

496 {
497  int res = 0;
498  struct ast_sip_endpoint_formatter *i;
500  *count = 0;
502  if (i->format_ami && ((res = i->format_ami(endpoint, ami)) < 0)) {
503  return res;
504  }
505 
506  if (!res) {
507  (*count)++;
508  }
509  }
510  return 0;
511 }
ast_mutex_t lock
Definition: app_meetme.c:1093
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:78
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:151
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:494
#define SCOPED_LOCK(varname, lock, lockfunc, unlockfunc)
Scoped Locks.
Definition: lock.h:581
An entity responsible formatting endpoint information.
Definition: res_pjsip.h:2845
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:2849

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

◆ 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 2283 of file res_pjsip.c.

2284 {
2285  if (af == pj_AF_INET() && !ast_strlen_zero(host_ip_ipv4_string)) {
2286  pj_sockaddr_copy_addr(addr, &host_ip_ipv4);
2287  return 0;
2288  } else if (af == pj_AF_INET6() && !ast_strlen_zero(host_ip_ipv6_string)) {
2289  pj_sockaddr_copy_addr(addr, &host_ip_ipv6);
2290  return 0;
2291  }
2292 
2293  return -1;
2294 }
static pj_sockaddr host_ip_ipv4
Definition: res_pjsip.c:72
static char host_ip_ipv6_string[PJ_INET6_ADDRSTRLEN]
Definition: res_pjsip.c:81
static pj_sockaddr host_ip_ipv6
Definition: res_pjsip.c:78
static char host_ip_ipv4_string[PJ_INET6_ADDRSTRLEN]
Definition: res_pjsip.c:75

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

◆ 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 2296 of file res_pjsip.c.

2297 {
2298  if (af == pj_AF_INET()) {
2299  return host_ip_ipv4_string;
2300  } else if (af == pj_AF_INET6()) {
2301  return host_ip_ipv6_string;
2302  }
2303 
2304  return NULL;
2305 }

References host_ip_ipv4_string, host_ip_ipv6_string, and NULL.

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

◆ 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 513 of file res_pjsip.c.

514 {
515  return ast_pjsip_endpoint;
516 }
static pjsip_endpoint * ast_pjsip_endpoint
Definition: res_pjsip.c:67

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(), 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(), handle_new_invite_request(), keepalive_transport_send_keepalive(), load_module(), logging_on_rx_msg(), logging_on_tx_msg(), notify_task(), on_rx_process_uris(), 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(), registrar_on_rx_request(), reschedule_reinvite(), schedule_publish_refresh(), schedule_registration(), send_options_response(), session_reinvite_on_rx_request(), sip_dialog_create_contact(), sip_dialog_create_from(), sip_outbound_publisher_init(), sip_outbound_registration_regc_alloc(), sip_publication_respond(), sip_session_defer_termination_stop_timer(), stir_shaken_inv_end_session(), subscription_persistence_load(), system_create_resolver_and_set_nameservers(), t38_change_state(), transport_apply(), and transport_create().

◆ 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 557 of file res_pjsip.c.

559 {
560  char *host = NULL;
561  static const pj_str_t x_name = { AST_SIP_X_AST_TXP, AST_SIP_X_AST_TXP_LEN };
562  pjsip_param *x_transport;
563 
564  if (!ast_strlen_zero(endpoint->transport)) {
565  ast_copy_string(buf, endpoint->transport, buf_len);
566  return 0;
567  }
568 
569  x_transport = pjsip_param_find(&sip_uri->other_param, &x_name);
570  if (!x_transport) {
571  return -1;
572  }
573 
574  /* Only use x_transport if the uri host is an ip (4 or 6) address */
575  host = ast_alloca(sip_uri->host.slen + 1);
576  ast_copy_pj_str(host, &sip_uri->host, sip_uri->host.slen + 1);
578  return -1;
579  }
580 
581  ast_copy_pj_str(buf, &x_transport->value, buf_len);
582 
583  return 0;
584 }
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:288
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
Parse an IPv4 or IPv6 address string.
Definition: netsock2.c:230
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:2035
#define AST_SIP_X_AST_TXP
Definition: res_pjsip.h:955
#define AST_SIP_X_AST_TXP_LEN
Definition: res_pjsip.h:956
const ast_string_field transport
Definition: res_pjsip.h:883

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(), buf, NULL, PARSE_PORT_FORBID, and ast_sip_endpoint::transport.

Referenced by ast_sip_set_tpselector_from_ep_or_uri().

◆ 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 323 of file res_pjsip.c.

324 {
325  struct endpoint_identifier_list *iter;
326  struct ast_sip_endpoint *endpoint = NULL;
330  endpoint = iter->identifier->identify_endpoint(rdata);
331  if (endpoint) {
332  break;
333  }
334  }
335  return endpoint;
336 }
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:1078
An entity with which Asterisk communicates.
Definition: res_pjsip.h:854
struct ast_sip_endpoint_identifier * identifier
Definition: res_pjsip.c:220

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

◆ 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 2082 of file res_pjsip.c.

2083 {
2084  pjsip_media_type compare;
2085 
2086  if (!content_type) {
2087  return 0;
2088  }
2089 
2090  pjsip_media_type_init2(&compare, type, subtype);
2091 
2092  return pjsip_media_type_cmp(content_type, &compare, 0) ? 0 : -1;
2093 }
static int compare(const char *text, const char *template)

References compare(), and type.

Referenced by asterisk_publication_devicestate_state_change(), asterisk_publication_mwi_state_change(), check_content_type(), and pubsub_on_rx_notify_request().

◆ ast_sip_is_media_type_in()

int ast_sip_is_media_type_in ( pjsip_media_type *  a,
  ... 
)

Check if a media type is in a list of others.

Parameters
apjsip_media_type to search for
...one or more pointers to pjsip_media_types the last of which must be "SENTINEL"
Return values
1Media types are equal
0Media types are not equal

Definition at line 2062 of file res_pjsip.c.

2063 {
2064  int rc = 0;
2065  pjsip_media_type *b = NULL;
2066  va_list ap;
2067 
2068  ast_assert(a != NULL);
2069  va_start(ap, a);
2070 
2071  while ((b = va_arg(ap, pjsip_media_type *)) != (pjsip_media_type *)SENTINEL) {
2072  if (pjsip_media_type_cmp(a, b, 0) == 0) {
2073  rc = 1;
2074  break;
2075  }
2076  }
2077  va_end(ap);
2078 
2079  return rc;
2080 }
#define SENTINEL
Definition: compiler.h:87

References a, ast_assert, b, NULL, and SENTINEL.

Referenced by check_content_disposition().

◆ 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 2410 of file res_pjsip.c.

2411 {
2412  pjsip_name_addr *id_name_addr;
2413  pjsip_sip_uri *id_uri;
2414 
2415  id_name_addr = (pjsip_name_addr *) id_hdr->uri;
2416  id_uri = pjsip_uri_get_uri(id_name_addr->uri);
2417 
2418  if (id->name.valid) {
2419  if (!ast_strlen_zero(id->name.str)) {
2420  int name_buf_len = strlen(id->name.str) * 2 + 1;
2421  char *name_buf = ast_alloca(name_buf_len);
2422 
2423  ast_escape_quoted(id->name.str, name_buf, name_buf_len);
2424  pj_strdup2(pool, &id_name_addr->display, name_buf);
2425  } else {
2426  pj_strdup2(pool, &id_name_addr->display, NULL);
2427  }
2428  }
2429 
2430  if (id->number.valid) {
2431  pj_strdup2(pool, &id_uri->user, id->number.str);
2432  }
2433 }
enum queue_result id
Definition: app_queue.c:1640
char * ast_escape_quoted(const char *string, char *outbuf, int buflen)
Escape characters found in a quoted string.
Definition: main/utils.c:781

References ast_alloca, ast_escape_quoted(), ast_strlen_zero(), id, and NULL.

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

◆ 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 1971 of file res_pjsip.c.

1972 {
1973  /* This method is an onion */
1974  struct sync_task_data std;
1975 
1976  memset(&std, 0, sizeof(std));
1977  ast_mutex_init(&std.lock);
1978  ast_cond_init(&std.cond, NULL);
1979  std.task = sip_task;
1980  std.task_data = task_data;
1981 
1982  if (ast_sip_push_task(serializer, sync_task, &std)) {
1983  ast_mutex_destroy(&std.lock);
1984  ast_cond_destroy(&std.cond);
1985  return -1;
1986  }
1987 
1988  ast_mutex_lock(&std.lock);
1989  while (!std.complete) {
1990  ast_cond_wait(&std.cond, &std.lock);
1991  }
1992  ast_mutex_unlock(&std.lock);
1993 
1994  ast_mutex_destroy(&std.lock);
1995  ast_cond_destroy(&std.cond);
1996  return std.fail;
1997 }
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:1933
#define ast_cond_destroy(cond)
Definition: lock.h:200
#define ast_cond_wait(cond, mutex)
Definition: lock.h:203
#define ast_cond_init(cond, attr)
Definition: lock.h:199
#define ast_mutex_init(pmutex)
Definition: lock.h:184
#define ast_mutex_unlock(a)
Definition: lock.h:188
#define ast_mutex_destroy(a)
Definition: lock.h:186
#define ast_mutex_lock(a)
Definition: lock.h:187
static int sync_task(void *data)
Definition: res_pjsip.c:1951
void * task_data
Definition: stasis.c:1280

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

◆ 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 338 of file res_pjsip.c.

339 {
340  pjsip_generic_string_hdr *hdr;
341  pj_str_t hdr_val;
342 
343  hdr = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &str, NULL);
344  if (!hdr) {
345  return NULL;
346  }
347 
348  pj_strdup_with_null(rdata->tp_info.pool, &hdr_val, &hdr->hvalue);
349 
350  return hdr_val.ptr;
351 }
const char * str
Definition: app_jack.c:147

References NULL, and str.

Referenced by check_date_header(), handle_new_invite_request(), and stir_shaken_incoming_request().

◆ 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 133 of file res_pjsip.c.

134 {
136  ast_log(LOG_WARNING, "Authenticator %p is already registered. Cannot register a new one\n", registered_authenticator);
137  return -1;
138  }
140  ast_debug(1, "Registered SIP authenticator module %p\n", auth);
141 
142  return 0;
143 }
#define ast_debug(level,...)
Log a DEBUG message.

References ast_debug, ast_log, LOG_WARNING, and registered_authenticator.

Referenced by load_module().

◆ 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 474 of file res_pjsip.c.

475 {
478 }
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:52
#define AST_RWLIST_INSERT_TAIL
Definition: linkedlists.h:741

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

◆ 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 303 of file res_pjsip.c.

304 {
306 }
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:226

References ast_sip_register_endpoint_identifier_with_name(), endpoint_identifier_list::identifier, and NULL.

Referenced by load_module().

◆ 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 226 of file res_pjsip.c.

228 {
229  char *prev, *current, *identifier_order;
230  struct endpoint_identifier_list *iter, *id_list_item;
232 
233  id_list_item = ast_calloc(1, sizeof(*id_list_item));
234  if (!id_list_item) {
235  ast_log(LOG_ERROR, "Unable to add endpoint identifier. Out of memory.\n");
236  return -1;
237  }
238  id_list_item->identifier = identifier;
239  id_list_item->name = name;
240 
241  ast_debug(1, "Register endpoint identifier %s(%p)\n", name ?: "", identifier);
242 
243  if (ast_strlen_zero(name)) {
244  /* if an identifier has no name then place in front */
245  AST_RWLIST_INSERT_HEAD(&endpoint_identifiers, id_list_item, list);
246  return 0;
247  }
248 
249  /* see if the name of the identifier is in the global endpoint_identifier_order list */
250  identifier_order = prev = current = ast_sip_get_endpoint_identifier_order();
251 
252  if (ast_strlen_zero(identifier_order)) {
253  id_list_item->priority = UINT_MAX;
254  AST_RWLIST_INSERT_TAIL(&endpoint_identifiers, id_list_item, list);
255  ast_free(identifier_order);
256  return 0;
257  }
258 
259  id_list_item->priority = 0;
260  while ((current = strchr(current, ','))) {
261  ++id_list_item->priority;
262  if (!strncmp(prev, name, current - prev)
263  && strlen(name) == current - prev) {
264  break;
265  }
266  prev = ++current;
267  }
268 
269  if (!current) {
270  /* check to see if it is the only or last item */
271  if (!strcmp(prev, name)) {
272  ++id_list_item->priority;
273  } else {
274  id_list_item->priority = UINT_MAX;
275  }
276  }
277 
278  if (id_list_item->priority == UINT_MAX || AST_RWLIST_EMPTY(&endpoint_identifiers)) {
279  /* if not in the endpoint_identifier_order list then consider it less in
280  priority and add it to the end */
281  AST_RWLIST_INSERT_TAIL(&endpoint_identifiers, id_list_item, list);
282  ast_free(identifier_order);
283  return 0;
284  }
285 
287  if (id_list_item->priority < iter->priority) {
288  AST_RWLIST_INSERT_BEFORE_CURRENT(id_list_item, list);
289  break;
290  }
291 
292  if (!AST_RWLIST_NEXT(iter, list)) {
293  AST_RWLIST_INSERT_AFTER(&endpoint_identifiers, iter, id_list_item, list);
294  break;
295  }
296  }
298 
299  ast_free(identifier_order);
300  return 0;
301 }
#define ast_free(a)
Definition: astmm.h:180
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define AST_RWLIST_EMPTY
Definition: linkedlists.h:452
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
Definition: linkedlists.h:545
#define AST_RWLIST_INSERT_AFTER
Definition: linkedlists.h:702
#define AST_RWLIST_NEXT
Definition: linkedlists.h:441
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:617
#define AST_RWLIST_INSERT_HEAD
Definition: linkedlists.h:718
#define AST_RWLIST_INSERT_BEFORE_CURRENT
Definition: linkedlists.h:610
size_t current
Definition: main/cli.c:113
char * ast_sip_get_endpoint_identifier_order(void)
Retrieve the global endpoint_identifier_order setting.
unsigned int priority
Definition: res_pjsip.c:219

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(), current, endpoint_identifier_list::identifier, lock, LOG_ERROR, name, endpoint_identifier_list::name, endpoint_identifier_list::priority, and SCOPED_LOCK.

Referenced by ast_sip_register_endpoint_identifier(), and load_module().

◆ 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
outbound_authThe authenticator to register
Return values
0Success
-1Failure

Definition at line 184 of file res_pjsip.c.

185 {
187  ast_log(LOG_WARNING, "Outbound authenticator %p is already registered. Cannot register a new one\n", registered_outbound_authenticator);
188  return -1;
189  }
191  ast_debug(1, "Registered SIP outbound authenticator module %p\n", auth);
192 
193  return 0;
194 }

References ast_debug, ast_log, LOG_WARNING, and registered_outbound_authenticator.

Referenced by load_module().

◆ 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 110 of file res_pjsip.c.

111 {
113 }
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:1999
static int register_service(void *data)
Definition: res_pjsip.c:95

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

◆ 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

Definition at line 1306 of file res_pjsip.c.

1307 {
1308  struct ast_sip_supplement *iter;
1309  int inserted = 0;
1311 
1313  if (iter->priority > supplement->priority) {
1315  inserted = 1;
1316  break;
1317  }
1318  }
1320 
1321  if (!inserted) {
1322  AST_RWLIST_INSERT_TAIL(&supplements, supplement, next);
1323  }
1324 }
A supplement to SIP message processing.
Definition: res_pjsip.h:2970
enum ast_sip_supplement_priority priority
Definition: res_pjsip.h:2974
struct ast_sip_supplement * next
Definition: res_pjsip.h:3020

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

◆ 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 156 of file res_pjsip.c.

157 {
158  if (endpoint->allow_unauthenticated_options
159  && !pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_options_method)) {
160  ast_debug(3, "Skipping OPTIONS authentication due to endpoint configuration\n");
161  return 0;
162  }
163 
165  ast_log(LOG_WARNING, "No SIP authenticator registered. Assuming authentication is not required\n");
166  return 0;
167  }
168 
169  return registered_authenticator->requires_authentication(endpoint, rdata);
170 }
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:1035
unsigned int allow_unauthenticated_options
Definition: res_pjsip.h:951

Referenced by authenticate().

◆ 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.
timeoutIf 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 1788 of file res_pjsip.c.

1791 {
1792  struct ast_sip_supplement *supplement;
1793  struct send_request_data *req_data;
1794  struct ast_sip_contact *contact;
1795 
1796  req_data = send_request_data_alloc(endpoint, token, callback);
1797  if (!req_data) {
1798  pjsip_tx_data_dec_ref(tdata);
1799  return -1;
1800  }
1801 
1802  if (endpoint) {
1804  }
1805 
1807 
1809  AST_LIST_TRAVERSE(&supplements, supplement, next) {
1810  if (supplement->outgoing_request
1811  && does_method_match(&tdata->msg->line.req.method.name, supplement->method)) {
1812  supplement->outgoing_request(endpoint, contact, tdata);
1813  }
1814  }
1816 
1817  ast_sip_mod_data_set(tdata->pool, tdata->mod_data, supplement_module.id, MOD_DATA_CONTACT, NULL);
1819 
1820  if (endpt_send_request(endpoint, tdata, timeout, req_data, send_request_cb)
1821  != PJ_SUCCESS) {
1822  ao2_cleanup(req_data);
1823  return -1;
1824  }
1825 
1826  return 0;
1827 }
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
static void send_request_cb(void *token, pjsip_event *e)
Definition: res_pjsip.c:1732
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:1546
static pj_bool_t does_method_match(const pj_str_t *message_method, const char *supplement_method)
Definition: res_pjsip.c:1349
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:1384
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 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:2720
Contact associated with an address of record.
Definition: res_pjsip.h:297
struct ast_sip_endpoint * endpoint
Definition: res_pjsip.h:329
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:3013
const char * method
Definition: res_pjsip.h:2972
Structure to hold information about an outbound request.
Definition: res_pjsip.c:1366

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_contact::endpoint, endpt_send_request(), ast_sip_supplement::method, MOD_DATA_CONTACT, NULL, ast_sip_supplement::outgoing_request, send_request_cb(), send_request_data_alloc(), supplement_module, and ast_sip_endpoint::transport.

Referenced by ast_sip_send_request(), and sip_options_qualify_contact().

◆ 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 1829 of file res_pjsip.c.

1832 {
1833  ast_assert(tdata->msg->type == PJSIP_REQUEST_MSG);
1834 
1835  if (dlg) {
1836  return send_in_dialog_request(tdata, dlg);
1837  } else {
1838  return ast_sip_send_out_of_dialog_request(tdata, endpoint, -1, token, callback);
1839  }
1840 }
static int send_in_dialog_request(pjsip_tx_data *tdata, struct pjsip_dialog *dlg)
Definition: res_pjsip.c:1340
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:1788

References ast_assert, ast_sip_send_out_of_dialog_request(), ast_sip_contact::endpoint, and send_in_dialog_request().

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

◆ 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
sip_endpointThe ast_sip_endpoint associated with this response
Return values
0Success
-1Failure

Definition at line 2230 of file res_pjsip.c.

2231 {
2232  pj_status_t status;
2233 
2234  supplement_outgoing_response(tdata, sip_endpoint);
2235  status = pjsip_endpt_send_response(ast_sip_get_pjsip_endpoint(), res_addr, tdata, NULL, NULL);
2236  if (status != PJ_SUCCESS) {
2237  pjsip_tx_data_dec_ref(tdata);
2238  }
2239 
2240  return status == PJ_SUCCESS ? 0 : -1;
2241 }
static void supplement_outgoing_response(pjsip_tx_data *tdata, struct ast_sip_endpoint *sip_endpoint)
Definition: res_pjsip.c:2208

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

◆ 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
sip_endpointThe ast_sip_endpoint associated with this response
Since
13.4.0
Return values
0Success
-1Failure

Definition at line 2243 of file res_pjsip.c.

2244 {
2245  pjsip_transaction *tsx;
2246 
2247  if (pjsip_tsx_create_uas(NULL, rdata, &tsx) != PJ_SUCCESS) {
2248  struct ast_sip_contact *contact;
2249 
2250  /* ast_sip_create_response bumps the refcount of the contact and adds it to the tdata.
2251  * We'll leak that reference if we don't get rid of it here.
2252  */
2255  ast_sip_mod_data_set(tdata->pool, tdata->mod_data, supplement_module.id, MOD_DATA_CONTACT, NULL);
2256  pjsip_tx_data_dec_ref(tdata);
2257  return -1;
2258  }
2259  pjsip_tsx_recv_msg(tsx, rdata);
2260 
2261  supplement_outgoing_response(tdata, sip_endpoint);
2262 
2263  if (pjsip_tsx_send_msg(tsx, tdata) != PJ_SUCCESS) {
2264  pjsip_tx_data_dec_ref(tdata);
2265  return -1;
2266  }
2267 
2268  return 0;
2269 }

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

◆ 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 1842 of file res_pjsip.c.

1843 {
1844  pjsip_route_hdr *route;
1845  static const pj_str_t ROUTE_HNAME = { "Route", 5 };
1846  pj_str_t tmp;
1847 
1848  pj_strdup2_with_null(tdata->pool, &tmp, proxy);
1849  if (!(route = pjsip_parse_hdr(tdata->pool, &ROUTE_HNAME, tmp.ptr, tmp.slen, NULL))) {
1850  return -1;
1851  }
1852 
1853  pj_list_insert_nodes_before(&tdata->msg->hdr, (pjsip_hdr*)route);
1854 
1855  return 0;
1856 }

References NULL, and tmp().

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

◆ 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 770 of file res_pjsip.c.

772 {
773  char transport_name[128];
774 
775  if (ast_sip_get_transport_name(endpoint, sip_uri, transport_name, sizeof(transport_name))) {
776  return 0;
777  }
778 
779  return ast_sip_set_tpselector_from_transport_name(transport_name, selector);
780 }
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:557
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:752

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

◆ 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 702 of file res_pjsip.c.

703 {
704  int res = 0;
705  struct ast_sip_transport_state *transport_state;
706 
708  if (!transport_state) {
709  ast_log(LOG_ERROR, "Unable to retrieve PJSIP transport state for '%s'\n",
711  return -1;
712  }
713 
714  /* Only flows maintain dynamic state which needs protection */
715  if (transport_state->flow) {
716  ao2_lock(transport_state);
717  }
718 
719  if (transport_state->transport) {
720  selector->type = PJSIP_TPSELECTOR_TRANSPORT;
721  selector->u.transport = transport_state->transport;
722  pjsip_transport_add_ref(selector->u.transport);
723  } else if (transport_state->factory) {
724  selector->type = PJSIP_TPSELECTOR_LISTENER;
725  selector->u.listener = transport_state->factory;
726  } else if (transport->type == AST_TRANSPORT_WS || transport->type == AST_TRANSPORT_WSS) {
727  /* The WebSocket transport has no factory as it can not create outgoing connections, so
728  * even if an endpoint is locked to a WebSocket transport we let the PJSIP logic
729  * find the existing connection if available and use it.
730  */
731  } else if (transport->flow) {
732  /* This is a child of another transport, so we need to establish a new connection */
733 #ifdef HAVE_PJSIP_TRANSPORT_DISABLE_CONNECTION_REUSE
734  selector->disable_connection_reuse = PJ_TRUE;
735 #else
736  ast_log(LOG_WARNING, "Connection reuse could not be disabled on transport '%s' as support is not available\n",
738 #endif
739  } else {
740  res = -1;
741  }
742 
743  if (transport_state->flow) {
744  ao2_unlock(transport_state);
745  }
746 
747  ao2_ref(transport_state, -1);
748 
749  return res;
750 }
#define ao2_unlock(a)
Definition: astobj2.h:729
#define ao2_lock(a)
Definition: astobj2.h:717
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
@ AST_TRANSPORT_WSS
Definition: netsock2.h:64
@ AST_TRANSPORT_WS
Definition: netsock2.h:63
struct ast_sip_transport_state * ast_sip_get_transport_state(const char *transport_id)
Retrieve transport state.
Structure for SIP transport information.
Definition: res_pjsip.h:103
struct pjsip_tpfactory * factory
Transport factory.
Definition: res_pjsip.h:107
struct pjsip_transport * transport
Transport itself.
Definition: res_pjsip.h:105

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, LOG_ERROR, LOG_WARNING, and ast_sip_transport_state::transport.

Referenced by ast_sip_set_tpselector_from_transport_name().

◆ 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 752 of file res_pjsip.c.

753 {
754  RAII_VAR(struct ast_sip_transport *, transport, NULL, ao2_cleanup);
755 
756  if (ast_strlen_zero(transport_name)) {
757  return 0;
758  }
759 
760  transport = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "transport", transport_name);
761  if (!transport) {
762  ast_log(LOG_ERROR, "Unable to retrieve PJSIP transport '%s'\n",
763  transport_name);
764  return -1;
765  }
766 
767  return ast_sip_set_tpselector_from_transport(transport, selector);
768 }
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:702
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
void * ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
Retrieve an object using its unique identifier.
Definition: sorcery.c:1853
Transport to bind to.
Definition: res_pjsip.h:187
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:936

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

◆ 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 2336 of file res_pjsip.c.

2337 {
2338  int result = -1;
2339 
2340  if (!strcasecmp(dtmf_mode, "info")) {
2342  } else if (!strcasecmp(dtmf_mode, "rfc4733")) {
2344  } else if (!strcasecmp(dtmf_mode, "inband")) {
2346  } else if (!strcasecmp(dtmf_mode, "none")) {
2348  } else if (!strcasecmp(dtmf_mode, "auto")) {
2350  } else if (!strcasecmp(dtmf_mode, "auto_info")) {
2352  }
2353 
2354  return result;
2355 }
static PGresult * result
Definition: cel_pgsql.c:84

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

◆ ast_sip_threadpool()

struct ast_threadpool* ast_sip_threadpool ( void  )

Retrieve the SIP threadpool object.

Definition at line 2453 of file res_pjsip.c.

2454 {
2455  return sip_threadpool;
2456 }
static struct ast_threadpool * sip_threadpool
Definition: res_pjsip.c:69

References sip_threadpool.

◆ 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 2448 of file res_pjsip.c.

2449 {
2451 }
long ast_threadpool_queue_size(struct ast_threadpool *pool)
Return the size of the threadpool's task queue.
Definition: threadpool.c:1433

References ast_threadpool_queue_size(), and sip_threadpool.

◆ 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 782 of file res_pjsip.c.

783 {
784  if (selector->type == PJSIP_TPSELECTOR_TRANSPORT && selector->u.transport) {
785  pjsip_transport_dec_ref(selector->u.transport);
786  }
787 }

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

◆ 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 145 of file res_pjsip.c.

146 {
147  if (registered_authenticator != auth) {
148  ast_log(LOG_WARNING, "Trying to unregister authenticator %p but authenticator %p registered\n",
150  return;
151  }
153  ast_debug(1, "Unregistered SIP authenticator %p\n", auth);
154 }

References ast_debug, ast_log, LOG_WARNING, NULL, and registered_authenticator.

◆ 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 480 of file res_pjsip.c.

481 {
482  struct ast_sip_endpoint_formatter *i;
484 
486  if (i == obj) {
488  break;
489  }
490  }
492 }
#define AST_RWLIST_REMOVE_CURRENT
Definition: linkedlists.h:570

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

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

◆ 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 308 of file res_pjsip.c.

309 {
310  struct endpoint_identifier_list *iter;
313  if (iter->identifier == identifier) {
315  ast_free(iter);
316  ast_debug(1, "Unregistered endpoint identifier %p\n", identifier);
317  break;
318  }
319  }
321 }

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

◆ 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 196 of file res_pjsip.c.

197 {
198  if (registered_outbound_authenticator != auth) {
199  ast_log(LOG_WARNING, "Trying to unregister outbound authenticator %p but outbound authenticator %p registered\n",
201  return;
202  }
204  ast_debug(1, "Unregistered SIP outbound authenticator %p\n", auth);
205 }

References ast_debug, ast_log, LOG_WARNING, NULL, and registered_outbound_authenticator.

◆ 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 126 of file res_pjsip.c.

127 {
129 }
static int unregister_service(void *data)
Definition: res_pjsip.c:115

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

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

◆ 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 1326 of file res_pjsip.c.

1327 {
1328  struct ast_sip_supplement *iter;
1330 
1332  if (supplement == iter) {
1334  break;
1335  }
1336  }
1338 }

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

◆ 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 518 of file res_pjsip.c.

520 {
521  pj_str_t host_name;
522  int result = 1;
523 
524  /* Determine if the contact cannot survive a restart/boot. */
525  if (uri->port == rdata->pkt_info.src_port
526  && !pj_strcmp(&uri->host,
527  pj_cstr(&host_name, rdata->pkt_info.src_name))
528  /* We have already checked if the URI scheme is sip: or sips: */
529  && PJSIP_TRANSPORT_IS_RELIABLE(rdata->tp_info.transport)) {
530  pj_str_t type_name;
531 
532  /* Determine the transport parameter value */
533  if (!strcasecmp("WSS", rdata->tp_info.transport->type_name)) {
534  /* WSS is special, as it needs to be ws. */
535  pj_cstr(&type_name, "ws");
536  } else {
537  pj_cstr(&type_name, rdata->tp_info.transport->type_name);
538  }
539 
540  if (!pj_stricmp(&uri->transport_param, &type_name)
541  && (endpoint->nat.rewrite_contact
542  /* Websockets are always rewritten */
543  || !pj_stricmp(&uri->transport_param,
544  pj_cstr(&type_name, "ws")))) {
545  /*
546  * The contact was rewritten to the reliable transport's
547  * source address. Disconnecting the transport for any
548  * reason invalidates the contact.
549  */
550  result = 0;
551  }
552  }
553 
554  return result;
555 }
struct ast_sip_endpoint_nat_configuration nat
Definition: res_pjsip.h:891

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

Referenced by subscription_persistence_update().

◆ check_request_status()

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

Definition at line 1689 of file res_pjsip.c.

1690 {
1691  struct ast_sip_endpoint *endpoint;
1692  pjsip_transaction *tsx;
1693  pjsip_tx_data *tdata;
1694  int res = 0;
1695 
1696  if (!(endpoint = ao2_bump(req_data->endpoint))) {
1697  return 0;
1698  }
1699 
1700  tsx = e->body.tsx_state.tsx;
1701 
1702  switch (tsx->status_code) {
1703  case 401:
1704  case 407:
1705  /* Resend the request with a challenge response if we are challenged. */
1706  res = ++req_data->challenge_count < MAX_RX_CHALLENGES /* Not in a challenge loop */
1708  e->body.tsx_state.src.rdata, tsx->last_tx, &tdata);
1709  break;
1710  case 408:
1711  case 503:
1712  if ((res = ast_sip_failover_request(tsx->last_tx))) {
1713  tdata = tsx->last_tx;
1714  /*
1715  * Bump the ref since it will be on a new transaction and
1716  * we don't want it to go away along with the old transaction.
1717  */
1718  pjsip_tx_data_add_ref(tdata);
1719  }
1720  break;
1721  }
1722 
1723  if (res) {
1724  res = endpt_send_request(endpoint, tdata, -1,
1725  req_data, send_request_cb) == PJ_SUCCESS;
1726  }
1727 
1728  ao2_ref(endpoint, -1);
1729  return res;
1730 }
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:207
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:1666
#define MAX_RX_CHALLENGES
Definition: res_pjsip.h:96
struct ast_sip_auth_vector outbound_auths
Definition: res_pjsip.h:901
struct ast_sip_endpoint * endpoint
Definition: res_pjsip.c:1368
unsigned int challenge_count
Definition: res_pjsip.c:1374

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, ast_sip_endpoint::outbound_auths, and send_request_cb().

Referenced by send_request_cb().

◆ cli_dump_endpt()

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

Definition at line 364 of file res_pjsip.c.

365 {
366  switch (cmd) {
367  case CLI_INIT:
368 #ifdef AST_DEVMODE
369  e->command = "pjsip dump endpt [details]";
370  e->usage =
371  "Usage: pjsip dump endpt [details]\n"
372  " Dump the res_pjsip endpt internals.\n"
373  "\n"
374  "Warning: PJPROJECT documents that the function used by this\n"
375  "CLI command may cause a crash when asking for details because\n"
376  "it tries to access all active memory pools.\n";
377 #else
378  /*
379  * In non-developer mode we will not document or make easily accessible
380  * the details option even though it is still available. The user has
381  * to know it exists to use it. Presumably they would also be aware of
382  * the potential crash warning.
383  */
384  e->command = "pjsip dump endpt";
385  e->usage =
386  "Usage: pjsip dump endpt\n"
387  " Dump the res_pjsip endpt internals.\n";
388 #endif /* AST_DEVMODE */
389  return NULL;
390  case CLI_GENERATE:
391  return NULL;
392  }
393 
394  if (4 < a->argc
395  || (a->argc == 4 && strcasecmp(a->argv[3], "details"))) {
396  return CLI_SHOWUSAGE;
397  }
398 
400 
401  return CLI_SUCCESS;
402 }
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define CLI_SUCCESS
Definition: cli.h:44
@ CLI_INIT
Definition: cli.h:152
@ CLI_GENERATE
Definition: cli.h:153
static int do_cli_dump_endpt(void *v_a)
Definition: res_pjsip.c:353
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177

References a, 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.

◆ 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 404 of file res_pjsip.c.

405 {
406 #define ENDPOINT_IDENTIFIER_FORMAT "%-20.20s\n"
407  struct endpoint_identifier_list *iter;
408 
409  switch (cmd) {
410  case CLI_INIT:
411  e->command = "pjsip show identifiers";
412  e->usage = "Usage: pjsip show identifiers\n"
413  " List all registered endpoint identifiers\n";
414  return NULL;
415  case CLI_GENERATE:
416  return NULL;
417  }
418 
419  if (a->argc != 3) {
420  return CLI_SHOWUSAGE;
421  }
422 
423  ast_cli(a->fd, ENDPOINT_IDENTIFIER_FORMAT, "Identifier Names:");
424  {
428  iter->name ? iter->name : "name not specified");
429  }
430  }
431  return CLI_SUCCESS;
432 #undef ENDPOINT_IDENTIFIER_FORMAT
433 }
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
#define ENDPOINT_IDENTIFIER_FORMAT

References a, 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, lock, endpoint_identifier_list::name, NULL, SCOPED_LOCK, and ast_cli_entry::usage.

◆ cli_show_settings()

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

Definition at line 435 of file res_pjsip.c.

436 {
438 
439  switch (cmd) {
440  case CLI_INIT:
441  e->command = "pjsip show settings";
442  e->usage = "Usage: pjsip show settings\n"
443  " Show global and system configuration options\n";
444  return NULL;
445  case CLI_GENERATE:
446  return NULL;
447  }
448 
449  context.output_buffer = ast_str_create(256);
450  if (!context.output_buffer) {
451  ast_cli(a->fd, "Could not allocate output buffer.\n");
452  return CLI_FAILURE;
453  }
454 
456  ast_free(context.output_buffer);
457  ast_cli(a->fd, "Error retrieving settings.\n");
458  return CLI_FAILURE;
459  }
460 
461  ast_cli(a->fd, "%s", ast_str_buffer(context.output_buffer));
462  ast_free(context.output_buffer);
463  return CLI_SUCCESS;
464 }
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:120
#define CLI_FAILURE
Definition: cli.h:46
int sip_cli_print_global(struct ast_sip_cli_context *context)
int sip_cli_print_system(struct ast_sip_cli_context *context)
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:640
CLI Formatter Context passed to all formatters.
Definition: res_pjsip_cli.h:34

◆ 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 972 of file res_pjsip.c.

974 {
975  pjsip_dialog *dlg;
976  pj_str_t contact;
977  pjsip_transport_type_e type = rdata->tp_info.transport->key.type;
978  pjsip_tpselector selector = { .type = PJSIP_TPSELECTOR_NONE, };
979  pjsip_transport *transport;
980  pjsip_contact_hdr *contact_hdr;
981 
982  ast_assert(status != NULL);
983 
984  contact_hdr = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT, NULL);
985  if (!contact_hdr || ast_sip_set_tpselector_from_ep_or_uri(endpoint, pjsip_uri_get_uri(contact_hdr->uri),
986  &selector)) {
987  return NULL;
988  }
989 
990  transport = rdata->tp_info.transport;
991  if (selector.type == PJSIP_TPSELECTOR_TRANSPORT) {
992  transport = selector.u.transport;
993  }
994  type = transport->key.type;
995 
996  contact.ptr = pj_pool_alloc(rdata->tp_info.pool, PJSIP_MAX_URL_SIZE);
997  contact.slen = pj_ansi_snprintf(contact.ptr, PJSIP_MAX_URL_SIZE,
998  "<%s:%s%.*s%s:%d%s%s>",
999  uas_use_sips_contact(rdata) ? "sips" : "sip",
1000  (type & PJSIP_TRANSPORT_IPV6) ? "[" : "",
1001  (int)transport->local_name.host.slen,
1002  transport->local_name.host.ptr,
1003  (type & PJSIP_TRANSPORT_IPV6) ? "]" : "",
1004  transport->local_name.port,
1005  (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? ";transport=" : "",
1006  (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? pjsip_transport_get_type_name(type) : "");
1007 
1008  *status = create_fun(pjsip_ua_instance(), rdata, &contact, &dlg);
1009  if (*status != PJ_SUCCESS) {
1010  char err[PJ_ERR_MSG_SIZE];
1011 
1012  pj_strerror(*status, err, sizeof(err));
1013  ast_log(LOG_ERROR, "Could not create dialog with endpoint %s. %s\n",
1014  ast_sorcery_object_get_id(endpoint), err);
1015  ast_sip_tpselector_unref(&selector);
1016  return NULL;
1017  }
1018 
1019  dlg->sess_count++;
1020  pjsip_dlg_set_transport(dlg, &selector);
1021  dlg->sess_count--;
1022 
1023  ast_sip_tpselector_unref(&selector);
1024 
1025  return dlg;
1026 }
static int uas_use_sips_contact(pjsip_rx_data *rdata)
Determine if a SIPS Contact header is required.
Definition: res_pjsip.c:943

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

◆ 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 1157 of file res_pjsip.c.

1158 {
1159  if (pjsip_dlg_create_request(dlg, method, -1, tdata) != PJ_SUCCESS) {
1160  ast_log(LOG_WARNING, "Unable to create in-dialog request.\n");
1161  return -1;
1162  }
1163 
1164  return 0;
1165 }

References ast_log, LOG_WARNING, and method.

Referenced by ast_sip_create_request().

◆ 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 1175 of file res_pjsip.c.

1177 {
1178  RAII_VAR(struct ast_sip_contact *, contact, ao2_bump(provided_contact), ao2_cleanup);
1179  pj_str_t remote_uri;
1180  pj_str_t from;
1181  pj_pool_t *pool;
1182  pjsip_tpselector selector = { .type = PJSIP_TPSELECTOR_NONE, };
1183  pjsip_uri *sip_uri;
1184  const char *fromuser;
1185 
1186  if (ast_strlen_zero(uri)) {
1187  if (!endpoint && (!contact || ast_strlen_zero(contact->uri))) {
1188  ast_log(LOG_ERROR, "An endpoint and/or uri must be specified\n");
1189  return -1;
1190  }
1191 
1192  if (!contact) {
1194  }
1195  if (!contact || ast_strlen_zero(contact->uri)) {
1196  ast_log(LOG_WARNING, "Unable to retrieve contact for endpoint %s\n",
1197  ast_sorcery_object_get_id(endpoint));
1198  return -1;
1199  }
1200 
1201  pj_cstr(&remote_uri, contact->uri);
1202  } else {
1203  pj_cstr(&remote_uri, uri);
1204  }
1205 
1206  pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(), "Outbound request", 256, 256);
1207 
1208  if (!pool) {
1209  ast_log(LOG_ERROR, "Unable to create PJLIB memory pool\n");
1210  return -1;
1211  }
1212 
1213  sip_uri = pjsip_parse_uri(pool, remote_uri.ptr, remote_uri.slen, 0);
1214  if (!sip_uri || (!PJSIP_URI_SCHEME_IS_SIP(sip_uri) && !PJSIP_URI_SCHEME_IS_SIPS(sip_uri))) {
1215  ast_log(LOG_ERROR, "Unable to create outbound %.*s request to endpoint %s as URI '%s' is not valid\n",
1216  (int) pj_strlen(&method->name), pj_strbuf(&method->name),
1217  endpoint ? ast_sorcery_object_get_id(endpoint) : "<none>",
1218  pj_strbuf(&remote_uri));
1219  pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
1220  return -1;
1221  }
1222 
1223  ast_sip_set_tpselector_from_ep_or_uri(endpoint, pjsip_uri_get_uri(sip_uri), &selector);
1224 
1225  fromuser = endpoint ? (!ast_strlen_zero(endpoint->fromuser) ? endpoint->fromuser : ast_sorcery_object_get_id(endpoint)) : NULL;
1226  if (sip_dialog_create_from(pool, &from, fromuser,
1227  endpoint ? endpoint->fromdomain : NULL, &remote_uri, &selector)) {
1228  ast_log(LOG_ERROR, "Unable to create From header for %.*s request to endpoint %s\n",
1229  (int) pj_strlen(&method->name), pj_strbuf(&method->name),
1230  endpoint ? ast_sorcery_object_get_id(endpoint) : "<none>");
1231  pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
1232  ast_sip_tpselector_unref(&selector);
1233  return -1;
1234  }
1235 
1236  if (pjsip_endpt_create_request(ast_sip_get_pjsip_endpoint(), method, &remote_uri,
1237  &from, &remote_uri, &from, NULL, -1, NULL, tdata) != PJ_SUCCESS) {
1238  ast_log(LOG_ERROR, "Unable to create outbound %.*s request to endpoint %s\n",
1239  (int) pj_strlen(&method->name), pj_strbuf(&method->name),
1240  endpoint ? ast_sorcery_object_get_id(endpoint) : "<none>");
1241  pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
1242  ast_sip_tpselector_unref(&selector);
1243  return -1;
1244  }
1245 
1246  pjsip_tx_data_set_transport(*tdata, &selector);
1247 
1248  ast_sip_tpselector_unref(&selector);
1249 
1250  if (endpoint && !ast_strlen_zero(endpoint->contact_user)){
1251  pjsip_contact_hdr *contact_hdr;
1252  pjsip_sip_uri *contact_uri;
1253  static const pj_str_t HCONTACT = { "Contact", 7 };
1254  static const pj_str_t HCONTACTSHORT = { "m", 1 };
1255 
1256  contact_hdr = pjsip_msg_find_hdr_by_names((*tdata)->msg, &HCONTACT, &HCONTACTSHORT, NULL);
1257  if (contact_hdr) {
1258  contact_uri = pjsip_uri_get_uri(contact_hdr->uri);
1259  pj_strdup2((*tdata)->pool, &contact_uri->user, endpoint->contact_user);
1260  }
1261  }
1262 
1263  /* Add the user=phone parameter if applicable */
1264  ast_sip_add_usereqphone(endpoint, (*tdata)->pool, (*tdata)->msg->line.req.uri);
1265 
1266  /* If an outbound proxy is specified on the endpoint apply it to this request */
1267  if (endpoint && !ast_strlen_zero(endpoint->outbound_proxy) &&
1268  ast_sip_set_outbound_proxy((*tdata), endpoint->outbound_proxy)) {
1269  ast_log(LOG_ERROR, "Unable to apply outbound proxy on request %.*s to endpoint %s as outbound proxy URI '%s' is not valid\n",
1270  (int) pj_strlen(&method->name), pj_strbuf(&method->name), ast_sorcery_object_get_id(endpoint),
1271  endpoint->outbound_proxy);
1272  pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
1273  return -1;
1274  }
1275 
1276  ast_sip_mod_data_set((*tdata)->pool, (*tdata)->mod_data, supplement_module.id, MOD_DATA_CONTACT, ao2_bump(contact));
1277 
1278  /* We can release this pool since request creation copied all the necessary
1279  * data into the outbound request's pool
1280  */
1281  pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
1282  return 0;
1283 }
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:1842
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 aors
Definition: res_pjsip.h:883

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, method, MOD_DATA_CONTACT, NULL, ast_sip_endpoint::outbound_proxy, RAII_VAR, sip_dialog_create_from(), and supplement_module.

Referenced by ast_sip_create_request().

◆ do_cli_dump_endpt()

static int do_cli_dump_endpt ( void *  v_a)
static

Definition at line 353 of file res_pjsip.c.

354 {
355  struct ast_cli_args *a = v_a;
356 
358  pjsip_endpt_dump(ast_sip_get_pjsip_endpoint(), a->argc == 4 ? PJ_TRUE : PJ_FALSE);
360 
361  return 0;
362 }
void ast_pjproject_log_intercept_begin(int fd)
Begin PJPROJECT log interception for CLI output.
void ast_pjproject_log_intercept_end(void)
End PJPROJECT log interception for CLI output.

References a, ast_pjproject_log_intercept_begin(), ast_pjproject_log_intercept_end(), and ast_sip_get_pjsip_endpoint().

Referenced by cli_dump_endpt().

◆ does_method_match()

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

Definition at line 1349 of file res_pjsip.c.

1350 {
1351  pj_str_t method;
1352 
1353  if (ast_strlen_zero(supplement_method)) {
1354  return PJ_TRUE;
1355  }
1356 
1357  pj_cstr(&method, supplement_method);
1358 
1359  return pj_stristr(&method, message_method) ? PJ_TRUE : PJ_FALSE;
1360 }
static const pjsip_method message_method
Definition: res_pjsip.c:1127

References ast_strlen_zero(), message_method, and method.

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

◆ 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 1546 of file res_pjsip.c.

1548 {
1549  struct send_request_wrapper *req_wrapper;
1550  pj_status_t ret_val;
1551  pjsip_endpoint *endpt = ast_sip_get_pjsip_endpoint();
1552 
1553  if (!cb && token) {
1554  /* Silly. Without a callback we cannot do anything with token. */
1555  pjsip_tx_data_dec_ref(tdata);
1556  return PJ_EINVAL;
1557  }
1558 
1559  /* Create wrapper to detect if the callback was actually called on an error. */
1560  req_wrapper = ao2_alloc(sizeof(*req_wrapper), send_request_wrapper_destructor);
1561  if (!req_wrapper) {
1562  pjsip_tx_data_dec_ref(tdata);
1563  return PJ_ENOMEM;
1564  }
1565 
1566  ast_debug(2, "%p: Wrapper created\n", req_wrapper);
1567 
1568  req_wrapper->token = token;
1569  req_wrapper->callback = cb;
1570  req_wrapper->timeout = timeout;
1571  req_wrapper->timeout_timer = NULL;
1572  req_wrapper->tdata = tdata;
1573  /* Add a reference to tdata. The wrapper destructor cleans it up. */
1574  pjsip_tx_data_add_ref(tdata);
1575 
1576  if (timeout > 0) {
1577  pj_time_val timeout_timer_val = { timeout / 1000, timeout % 1000 };
1578 
1579  req_wrapper->timeout_timer = PJ_POOL_ALLOC_T(tdata->pool, pj_timer_entry);
1580 
1581  ast_debug(2, "%p: Set timer to %d msec\n", req_wrapper, timeout);
1582 
1583  pj_timer_entry_init(req_wrapper->timeout_timer, TIMEOUT_TIMER2,
1584  req_wrapper, send_request_timer_callback);
1585 
1586  /* We need to insure that the wrapper and tdata are available if/when the
1587  * timer callback is executed.
1588  */
1589  ao2_ref(req_wrapper, +1);
1590  ret_val = pj_timer_heap_schedule(pjsip_endpt_get_timer_heap(endpt),
1591  req_wrapper->timeout_timer, &timeout_timer_val);
1592  if (ret_val != PJ_SUCCESS) {
1594  "Failed to set timer. Not sending %.*s request to endpoint %s.\n",
1595  (int) pj_strlen(&tdata->msg->line.req.method.name),
1596  pj_strbuf(&tdata->msg->line.req.method.name),
1597  endpoint ? ast_sorcery_object_get_id(endpoint) : "<unknown>");
1598  ao2_t_ref(req_wrapper, -2, "Drop timer and routine ref");
1599  pjsip_tx_data_dec_ref(tdata);
1600  return ret_val;
1601  }
1602  }
1603 
1604  /* We need to insure that the wrapper and tdata are available when the
1605  * transaction callback is executed.
1606  */
1607  ao2_ref(req_wrapper, +1);
1608  ret_val = pjsip_endpt_send_request(endpt, tdata, -1, req_wrapper, endpt_send_request_cb);
1609  if (ret_val != PJ_SUCCESS) {
1610  char errmsg[PJ_ERR_MSG_SIZE];
1611 
1612  if (!req_wrapper->send_cb_called) {
1613  /* endpt_send_request_cb is not expected to ever be called now. */
1614  ao2_ref(req_wrapper, -1);
1615  }
1616 
1617  /* Complain of failure to send the request. */
1618  pj_strerror(ret_val, errmsg, sizeof(errmsg));
1619  ast_log(LOG_ERROR, "Error %d '%s' sending %.*s request to endpoint %s\n",
1620  (int) ret_val, errmsg, (int) pj_strlen(&tdata->msg->line.req.method.name),
1621  pj_strbuf(&tdata->msg->line.req.method.name),
1622  endpoint ? ast_sorcery_object_get_id(endpoint) : "<unknown>");
1623 
1624  if (timeout > 0) {
1625  int timers_cancelled;
1626 
1627  ao2_lock(req_wrapper);
1628  timers_cancelled = pj_timer_heap_cancel_if_active(
1629  pjsip_endpt_get_timer_heap(endpt),
1630  req_wrapper->timeout_timer, TIMER_INACTIVE);
1631  if (timers_cancelled > 0) {
1632  ao2_ref(req_wrapper, -1);
1633  }
1634 
1635  /* Was the callback called? */
1636  if (req_wrapper->cb_called) {
1637  /*
1638  * Yes so we cannot report any error. The callback
1639  * has already freed any resources associated with
1640  * token.
1641  */
1642  ret_val = PJ_SUCCESS;
1643  } else {
1644  /*
1645  * No so we claim it is called so our caller can free
1646  * any resources associated with token because of
1647  * failure.
1648  */
1649  req_wrapper->cb_called = 1;
1650  }
1651  ao2_unlock(req_wrapper);
1652  } else if (req_wrapper->cb_called) {
1653  /*
1654  * We cannot report any error. The callback has
1655  * already freed any resources associated with
1656  * token.
1657  */
1658  ret_val = PJ_SUCCESS;
1659  }
1660  }
1661 
1662  ao2_ref(req_wrapper, -1);
1663  return ret_val;
1664 }
#define ao2_t_ref(o, delta, tag)
Definition: astobj2.h:460
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:409
static void send_request_timer_callback(pj_timer_heap_t *theap, pj_timer_entry *entry)
Definition: res_pjsip.c:1498
static void send_request_wrapper_destructor(void *obj)
Definition: res_pjsip.c:1538
static void endpt_send_request_cb(void *token, pjsip_event *e)
Definition: res_pjsip.c:1423
#define TIMER_INACTIVE
Definition: res_pjsip.c:1362
#define TIMEOUT_TIMER2
Definition: res_pjsip.c:1363
pj_int32_t timeout
Definition: res_pjsip.c:1414
unsigned int send_cb_called
Definition: res_pjsip.c:1410
pjsip_tx_data * tdata
Definition: res_pjsip.c:1416
unsigned int cb_called
Definition: res_pjsip.c:1408
pj_timer_entry * timeout_timer
Definition: res_pjsip.c:1412
void(* callback)(void *token, pjsip_event *e)
Definition: res_pjsip.c:1406

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

◆ endpt_send_request_cb()

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

Definition at line 1423 of file res_pjsip.c.

1424 {
1425  struct send_request_wrapper *req_wrapper = token;
1426  unsigned int cb_called;
1427 
1428  /*
1429  * Needed because we cannot otherwise tell if this callback was
1430  * called when pjsip_endpt_send_request() returns error.
1431  */
1432  req_wrapper->send_cb_called = 1;
1433 
1434  if (e->body.tsx_state.type == PJSIP_EVENT_TIMER) {
1435  ast_debug(2, "%p: PJSIP tsx timer expired\n", req_wrapper);
1436 
1437  if (req_wrapper->timeout_timer
1438  && req_wrapper->timeout_timer->id != TIMEOUT_TIMER2) {
1439  ast_debug(3, "%p: Timeout already handled\n", req_wrapper);
1440  ao2_ref(req_wrapper, -1);
1441  return;
1442  }
1443  } else {
1444  ast_debug(2, "%p: PJSIP tsx response received\n", req_wrapper);
1445  }
1446 
1447  ao2_lock(req_wrapper);
1448 
1449  /* It's possible that our own timer was already processing while
1450  * we were waiting on the lock so check the timer id. If it's
1451  * still TIMER2 then we still need to process.
1452  */
1453  if (req_wrapper->timeout_timer
1454  && req_wrapper->timeout_timer->id == TIMEOUT_TIMER2) {
1455  int timers_cancelled = 0;
1456 
1457  ast_debug(3, "%p: Cancelling timer\n", req_wrapper);
1458 
1459  timers_cancelled = pj_timer_heap_cancel_if_active(
1460  pjsip_endpt_get_timer_heap(ast_sip_get_pjsip_endpoint()),
1461  req_wrapper->timeout_timer, TIMER_INACTIVE);
1462  if (timers_cancelled > 0) {
1463  /* If the timer was cancelled the callback will never run so
1464  * clean up its reference to the wrapper.
1465  */
1466  ast_debug(3, "%p: Timer cancelled\n", req_wrapper);
1467  ao2_ref(req_wrapper, -1);
1468  } else {
1469  /*
1470  * If it wasn't cancelled, it MAY be in the callback already
1471  * waiting on the lock. When we release the lock, it will
1472  * now know not to proceed.
1473  */
1474  ast_debug(3, "%p: Timer already expired\n", req_wrapper);
1475  }
1476  }
1477 
1478  cb_called = req_wrapper->cb_called;
1479  req_wrapper->cb_called = 1;
1480  ao2_unlock(req_wrapper);
1481 
1482  /* It's possible that our own timer expired and called the callbacks
1483  * so no need to call them again.
1484  */
1485  if (!cb_called && req_wrapper->callback) {
1486  req_wrapper->callback(req_wrapper->token, e);
1487  ast_debug(2, "%p: Callbacks executed\n", req_wrapper);
1488  }
1489 
1490  ao2_ref(req_wrapper, -1);
1491 }

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

◆ get_pjsip_method()

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

Definition at line 1146 of file res_pjsip.c.

1147 {
1148  int i;
1149  for (i = 0; i < ARRAY_LEN(methods); ++i) {
1150  if (!strcmp(method, methods[i].method)) {
1151  return methods[i].pmethod;
1152  }
1153  }
1154  return NULL;
1155 }
static struct @485 methods[]
#define ARRAY_LEN(a)
Definition: utils.h:661

References ARRAY_LEN, method, methods, and NULL.

Referenced by ast_sip_create_request().

◆ load_module()

static int load_module ( void  )
static

Definition at line 2647 of file res_pjsip.c.

2648 {
2650 
2651  /* pjproject and config_system need to be initialized before all else */
2652  if (pj_init() != PJ_SUCCESS) {
2653  return AST_MODULE_LOAD_DECLINE;
2654  }
2655 
2656  if (pjlib_util_init() != PJ_SUCCESS) {
2657  goto error;
2658  }
2659 
2660  /* Register PJMEDIA error codes for SDP parsing errors */
2661  if (pj_register_strerror(PJMEDIA_ERRNO_START, PJ_ERRNO_SPACE_SIZE, pjmedia_strerror)
2662  != PJ_SUCCESS) {
2663  ast_log(LOG_WARNING, "Failed to register pjmedia error codes. Codes will not be decoded.\n");
2664  }
2665 
2666  /* Initialize common media types */
2667  pjsip_media_type_init2(&pjsip_media_type_application_json, "application", "json");
2668  pjsip_media_type_init2(&pjsip_media_type_application_media_control_xml, "application", "media_control+xml");
2669  pjsip_media_type_init2(&pjsip_media_type_application_pidf_xml, "application", "pidf+xml");
2670  pjsip_media_type_init2(&pjsip_media_type_application_xpidf_xml, "application", "xpidf+xml");
2671  pjsip_media_type_init2(&pjsip_media_type_application_cpim_xpidf_xml, "application", "cpim-xpidf+xml");
2672  pjsip_media_type_init2(&pjsip_media_type_application_rlmi_xml, "application", "rlmi+xml");
2673  pjsip_media_type_init2(&pjsip_media_type_application_sdp, "application", "sdp");
2674  pjsip_media_type_init2(&pjsip_media_type_application_simple_message_summary, "application", "simple-message-summary");
2675  pjsip_media_type_init2(&pjsip_media_type_multipart_alternative, "multipart", "alternative");
2676  pjsip_media_type_init2(&pjsip_media_type_multipart_mixed, "multipart", "mixed");
2677  pjsip_media_type_init2(&pjsip_media_type_multipart_related, "multipart", "related");
2678  pjsip_media_type_init2(&pjsip_media_type_text_plain, "text", "plain");
2679 
2680 
2681  if (ast_sip_initialize_system()) {
2682  ast_log(LOG_ERROR, "Failed to initialize SIP 'system' configuration section. Aborting load\n");
2683  goto error;
2684  }
2685 
2686  /* The serializer needs threadpool and threadpool needs pjproject to be initialized so it's next */
2688  options.thread_start = sip_thread_start;
2690  if (!sip_threadpool) {
2691  goto error;
2692  }
2693 
2695  "pjsip/default", SERIALIZER_POOL_SIZE, sip_threadpool, -1);
2696  if (!sip_serializer_pool) {
2697  ast_log(LOG_ERROR, "Failed to create SIP serializer pool. Aborting load\n");
2698  goto error;
2699  }
2700 
2702  ast_log(LOG_ERROR, "Failed to start scheduler. Aborting load\n");
2703  goto error;
2704  }
2705 
2706  /* Now load all the pjproject infrastructure. */
2707  if (load_pjsip()) {
2708  goto error;
2709  }
2710 
2712  ast_log(LOG_ERROR, "Failed to initialize SIP transport monitor. Aborting load\n");
2713  goto error;
2714  }
2715 
2718 
2720  ast_log(LOG_ERROR, "Failed to pre-initialize OPTIONS handling. Aborting load\n");
2721  goto error;
2722  }
2723 
2725  ast_log(LOG_ERROR, "Failed to initialize SIP configuration. Aborting load\n");
2726  goto error;
2727  }
2728 
2731 
2733  ast_log(LOG_ERROR, "Failed to initialize SIP transport management. Aborting load\n");
2734  goto error;
2735  }
2736 
2738  ast_log(LOG_ERROR, "Failed to register distributor module. Aborting load\n");
2739  goto error;
2740  }
2741 
2743  ast_log(LOG_ERROR, "Failed to initialize supplement hooks. Aborting load\n");
2744  goto error;
2745  }
2746 
2748  ast_log(LOG_ERROR, "Failed to initialize OPTIONS handling. Aborting load\n");
2749  goto error;
2750  }
2751 
2753  ast_log(LOG_ERROR, "Failed to initialize message IP updating. Aborting load\n");
2754  goto error;
2755  }
2756 
2758 
2759  AST_TEST_REGISTER(xml_sanitization_end_null);
2760  AST_TEST_REGISTER(xml_sanitization_exceeds_buffer);
2761 
2762  return AST_MODULE_LOAD_SUCCESS;
2763 
2764 error:
2765  unload_pjsip(NULL);
2766 
2767  /* These functions all check for NULLs and are safe to call at any time */
2771 
2772  return AST_MODULE_LOAD_DECLINE;
2773 }
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
int ast_sip_initialize_system(void)
void ast_sip_initialize_dns(void)
void sip_get_threadpool_options(struct ast_threadpool_options *threadpool_options)
Definition: config_system.c:70
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
static int unload_pjsip(void *data)
Definition: res_pjsip.c:2523
pjsip_media_type pjsip_media_type_application_media_control_xml
Definition: res_pjsip.c:2635
static struct ast_cli_entry cli_commands[]
Definition: res_pjsip.c:466
pjsip_media_type pjsip_media_type_application_json
Definition: res_pjsip.c:2634
int ast_sip_register_service(pjsip_module *module)
Register a SIP service in Asterisk.
Definition: res_pjsip.c:110
pjsip_media_type pjsip_media_type_application_sdp
Definition: res_pjsip.c:2641
pjsip_media_type pjsip_media_type_text_plain
Definition: res_pjsip.c:2645
pjsip_media_type pjsip_media_type_application_pidf_xml
Definition: res_pjsip.c:2636
static void sip_thread_start(void)
Definition: res_pjsip.c:2119
#define SERIALIZER_POOL_SIZE
Definition: res_pjsip.c:62
pjsip_media_type pjsip_media_type_application_simple_message_summary
Definition: res_pjsip.c:2640
pjsip_media_type pjsip_media_type_application_rlmi_xml
Definition: res_pjsip.c:2639
pjsip_media_type pjsip_media_type_multipart_mixed
Definition: res_pjsip.c:2643
pjsip_media_type pjsip_media_type_application_xpidf_xml
Definition: res_pjsip.c:2637
pjsip_media_type pjsip_media_type_multipart_alternative
Definition: res_pjsip.c:2642
static int load_pjsip(void)
Definition: res_pjsip.c:2567
pjsip_media_type pjsip_media_type_application_cpim_xpidf_xml
Definition: res_pjsip.c:2638
pjsip_media_type pjsip_media_type_multipart_related
Definition: res_pjsip.c:2644
static struct ast_serializer_pool * sip_serializer_pool
Definition: res_pjsip.c:65
int ast_sip_initialize_scheduler(void)
Initialize scheduler.
int ast_res_pjsip_preinit_options_handling(void)
int ast_sip_initialize_transport_management(void)
void ast_sip_initialize_resolver(void)
int ast_res_pjsip_init_options_handling(int reload)
int ast_sip_initialize_distributor(void)
int ast_sip_destroy_scheduler(void)
void ast_sip_initialize_global_headers(void)
int ast_sip_initialize_transport_events(void)
int ast_res_pjsip_initialize_configuration(void)
int ast_res_pjsip_init_message_filter(void)
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 ast_serializer_pool_destroy(struct ast_serializer_pool *pool)
Destroy the serializer pool.
Definition: serializer.c:39
#define AST_TEST_REGISTER(cb)
Definition: test.h:127
static struct test_options options
void ast_threadpool_shutdown(struct ast_threadpool *pool)
Shut down a threadpool and destroy it.
Definition: threadpool.c:966
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:916
int error(const char *format,...)
Definition: utils/frame.c:999

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(), cli_commands, error(), load_pjsip(), LOG_ERROR, LOG_WARNING, NULL, options, pjsip_media_type_application_cpim_xpidf_xml, pjsip_media_type_application_json, pjsip_media_type_application_media_control_xml, pjsip_media_type_application_pidf_xml, pjsip_media_type_application_rlmi_xml, pjsip_media_type_application_sdp, pjsip_media_type_application_simple_message_summary, pjsip_media_type_application_xpidf_xml, pjsip_media_type_multipart_alternative, pjsip_media_type_multipart_mixed, pjsip_media_type_multipart_related, pjsip_media_type_text_plain, SERIALIZER_POOL_SIZE, sip_get_threadpool_options(), sip_serializer_pool, sip_thread_start(), sip_threadpool, supplement_module, and unload_pjsip().

◆ load_pjsip()

static int load_pjsip ( void  )
static

Definition at line 2567 of file res_pjsip.c.

2568 {
2569  const unsigned int flags = 0; /* no port, no brackets */
2570  pj_status_t status;
2571 
2572  /* The third parameter is just copied from
2573  * example code from PJLIB. This can be adjusted
2574  * if necessary.
2575  */
2577  if (pjsip_endpt_create(&caching_pool.factory, "SIP", &ast_pjsip_endpoint) != PJ_SUCCESS) {
2578  ast_log(LOG_ERROR, "Failed to create PJSIP endpoint structure. Aborting load\n");
2579  goto error;
2580  }
2581 
2582  /* PJSIP will automatically try to add a Max-Forwards header. Since we want to control that,
2583  * we need to stop PJSIP from doing it automatically
2584  */
2586 
2587  memory_pool = pj_pool_create(&caching_pool.factory, "SIP", 1024, 1024, NULL);
2588  if (!memory_pool) {
2589  ast_log(LOG_ERROR, "Failed to create memory pool for SIP. Aborting load\n");
2590  goto error;
2591  }
2592 
2593  if (!pj_gethostip(pj_AF_INET(), &host_ip_ipv4)) {
2594  pj_sockaddr_print(&host_ip_ipv4, host_ip_ipv4_string, sizeof(host_ip_ipv4_string), flags);
2595  ast_verb(3, "Local IPv4 address determined to be: %s\n", host_ip_ipv4_string);
2596  }
2597 
2598  if (!pj_gethostip(pj_AF_INET6(), &host_ip_ipv6)) {
2599  pj_sockaddr_print(&host_ip_ipv6, host_ip_ipv6_string, sizeof(host_ip_ipv6_string), flags);
2600  ast_verb(3, "Local IPv6 address determined to be: %s\n", host_ip_ipv6_string);
2601  }
2602 
2603  pjsip_tsx_layer_init_module(ast_pjsip_endpoint);
2604  pjsip_ua_init_module(ast_pjsip_endpoint, NULL);
2605 
2606  monitor_continue = 1;
2607  status = pj_thread_create(memory_pool, "SIP", (pj_thread_proc *) &monitor_thread_exec,
2608  NULL, PJ_THREAD_DEFAULT_STACK_SIZE * 2, 0, &monitor_thread);
2609  if (status != PJ_SUCCESS) {
2610  ast_log(LOG_ERROR, "Failed to start SIP monitor thread. Aborting load\n");
2611  goto error;
2612  }
2613 
2614  return AST_MODULE_LOAD_SUCCESS;
2615 
2616 error:
2617  return AST_MODULE_LOAD_DECLINE;
2618 }
#define ast_verb(level,...)
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.
static void * monitor_thread_exec(void *endpt)
Definition: res_pjsip.c:2100
pj_pool_t * memory_pool
Definition: res_pjsip.c:2096
pj_thread_t * monitor_thread
Definition: res_pjsip.c:2097
static int monitor_continue
Definition: res_pjsip.c:2098
static void remove_request_headers(pjsip_endpoint *endpt)
Definition: res_pjsip.c:2436
pj_caching_pool caching_pool
Definition: res_pjsip.c:2095

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

Referenced by load_module().

◆ monitor_thread_exec()

static void* monitor_thread_exec ( void *  endpt)
static

Definition at line 2100 of file res_pjsip.c.

2101 {
2102  while (monitor_continue) {
2103  const pj_time_val delay = {0, 10};
2104  pjsip_endpt_handle_events(ast_pjsip_endpoint, &delay);
2105  }
2106  return NULL;
2107 }

References ast_pjsip_endpoint, monitor_continue, and NULL.

Referenced by load_pjsip().

◆ never_called_res_pjsip()

void never_called_res_pjsip ( void  )

Definition at line 2628 of file res_pjsip.c.

2629 {
2630  pjmedia_strerror(0, NULL, 0);
2631 }

References NULL.

◆ register_service()

static int register_service ( void *  data)
static

Definition at line 95 of file res_pjsip.c.

96 {
97  pjsip_module **module = data;
98  if (!ast_pjsip_endpoint) {
99  ast_log(LOG_ERROR, "There is no PJSIP endpoint. Unable to register services\n");
100  return -1;
101  }
102  if (pjsip_endpt_register_module(ast_pjsip_endpoint, *module) != PJ_SUCCESS) {
103  ast_log(LOG_ERROR, "Unable to register module %.*s\n", (int) pj_strlen(&(*module)->name), pj_strbuf(&(*module)->name));
104  return -1;
105  }
106  ast_debug(1, "Registered SIP service %.*s (%p)\n", (int) pj_strlen(&(*module)->name), pj_strbuf(&(*module)->name), *module);
107  return 0;
108 }

References ast_debug, ast_log, ast_pjsip_endpoint, and LOG_ERROR.

Referenced by ast_sip_register_service().

◆ reload_configuration_task()

static int reload_configuration_task ( void *  obj)
static

Definition at line 2515 of file res_pjsip.c.

2516 {
2520  return 0;
2521 }
int ast_res_pjsip_reload_configuration(void)

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

Referenced by reload_module().

◆ reload_module()

static int reload_module ( void  )
static

Definition at line 2775 of file res_pjsip.c.

2776 {
2777  /*
2778  * We must wait for the reload to complete so multiple
2779  * reloads cannot happen at the same time.
2780  */
2782  ast_log(LOG_WARNING, "Failed to reload PJSIP\n");
2783  return -1;
2784  }
2785 
2786  return 0;
2787 }
static int reload_configuration_task(void *obj)
Definition: res_pjsip.c:2515

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

◆ remove_request_headers()

static void remove_request_headers ( pjsip_endpoint *  endpt)
static

Definition at line 2436 of file res_pjsip.c.

2437 {
2438  const pjsip_hdr *request_headers = pjsip_endpt_get_request_headers(endpt);
2439  pjsip_hdr *iter = request_headers->next;
2440 
2441  while (iter != request_headers) {
2442  pjsip_hdr *to_erase = iter;
2443  iter = iter->next;
2444  pj_list_erase(to_erase);
2445  }
2446 }
static struct header_list request_headers

References request_headers.

Referenced by load_pjsip().

◆ send_in_dialog_request()

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

Definition at line 1340 of file res_pjsip.c.

1341 {
1342  if (pjsip_dlg_send_request(dlg, tdata, -1, NULL) != PJ_SUCCESS) {
1343  ast_log(LOG_WARNING, "Unable to send in-dialog request.\n");
1344  return -1;
1345  }
1346  return 0;
1347 }

References ast_log, LOG_WARNING, and NULL.

Referenced by ast_sip_send_request().

◆ send_request_cb()

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

Definition at line 1732 of file res_pjsip.c.

1733 {
1734  struct send_request_data *req_data = token;
1735  pjsip_rx_data *challenge;
1736  struct ast_sip_supplement *supplement;
1737 
1738  if (e->type == PJSIP_EVENT_TSX_STATE) {
1739  switch(e->body.tsx_state.type) {
1740  case PJSIP_EVENT_TRANSPORT_ERROR:
1741  case PJSIP_EVENT_TIMER:
1742  /*
1743  * Check the request status on transport error or timeout. A transport
1744  * error can occur when a TCP socket closes and that can be the result
1745  * of a 503. Also we may need to failover on a timeout (408).
1746  */
1747  if (check_request_status(req_data, e)) {
1748  return;
1749  }
1750  break;
1751  case PJSIP_EVENT_RX_MSG:
1752  challenge = e->body.tsx_state.src.rdata;
1753 
1754  /*
1755  * Call any supplements that want to know about a response
1756  * with any received data.
1757  */
1759  AST_LIST_TRAVERSE(&supplements, supplement, next) {
1760  if (supplement->incoming_response
1761  && does_method_match(&challenge->msg_info.cseq->method.name,
1762  supplement->method)) {
1763  supplement->incoming_response(req_data->endpoint, challenge);
1764  }
1765  }
1767 
1768  if (check_request_status(req_data, e)) {
1769  /*
1770  * Request with challenge response or failover sent.
1771  * Passed our req_data ref to the new request.
1772  */
1773  return;
1774  }
1775  break;
1776  default:
1777  ast_log(LOG_ERROR, "Unexpected PJSIP event %u\n", e->body.tsx_state.type);
1778  break;
1779  }
1780  }
1781 
1782  if (req_data->callback) {
1783  req_data->callback(req_data->token, e);
1784  }
1785  ao2_ref(req_data, -1);
1786 }
static int check_request_status(struct send_request_data *req_data, pjsip_event *e)
Definition: res_pjsip.c:1689
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:3008
void(* callback)(void *token, pjsip_event *e)
Definition: res_pjsip.c:1372

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

◆ 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 1384 of file res_pjsip.c.

1386 {
1387  struct send_request_data *req_data;
1388 
1389  req_data = ao2_alloc_options(sizeof(*req_data), send_request_data_destroy,
1391  if (!req_data) {
1392  return NULL;
1393  }
1394 
1395  req_data->endpoint = ao2_bump(endpoint);
1396  req_data->token = token;
1397  req_data->callback = callback;
1398 
1399  return req_data;
1400 }
@ AO2_ALLOC_OPT_LOCK_NOLOCK
Definition: astobj2.h:367
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:404
static void send_request_data_destroy(void *obj)
Definition: res_pjsip.c:1377

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

◆ send_request_data_destroy()

static void send_request_data_destroy ( void *  obj)
static

Definition at line 1377 of file res_pjsip.c.

1378 {
1379  struct send_request_data *req_data = obj;
1380 
1381  ao2_cleanup(req_data->endpoint);
1382 }

References ao2_cleanup, and send_request_data::endpoint.

Referenced by send_request_data_alloc().

◆ send_request_timer_callback()

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

Definition at line 1498 of file res_pjsip.c.

1499 {
1500  struct send_request_wrapper *req_wrapper = entry->user_data;
1501  unsigned int cb_called;
1502 
1503  ast_debug(2, "%p: Internal tsx timer expired after %d msec\n",
1504  req_wrapper, req_wrapper->timeout);
1505 
1506  ao2_lock(req_wrapper);
1507  /*
1508  * If the id is not TIMEOUT_TIMER2 then the timer was cancelled
1509  * before we got the lock or it was already handled so just clean up.
1510  */
1511  if (entry->id != TIMEOUT_TIMER2) {
1512  ao2_unlock(req_wrapper);
1513  ast_debug(3, "%p: Timeout already handled\n", req_wrapper);
1514  ao2_ref(req_wrapper, -1);
1515  return;
1516  }
1517  entry->id = TIMER_INACTIVE;
1518 
1519  ast_debug(3, "%p: Timer handled here\n", req_wrapper);
1520 
1521  cb_called = req_wrapper->cb_called;
1522  req_wrapper->cb_called = 1;
1523  ao2_unlock(req_wrapper);
1524 
1525  if (!cb_called && req_wrapper->callback) {
1526  pjsip_event event;
1527 
1528  PJSIP_EVENT_INIT_TX_MSG(event, req_wrapper->tdata);
1529  event.body.tsx_state.type = PJSIP_EVENT_TIMER;
1530 
1531  req_wrapper->callback(req_wrapper->token, &event);
1532  ast_debug(2, "%p: Callbacks executed\n", req_wrapper);
1533  }
1534 
1535  ao2_ref(req_wrapper, -1);
1536 }
Definition: search.h:40
Definition: astman.c:222

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

◆ send_request_wrapper_destructor()

static void send_request_wrapper_destructor ( void *  obj)
static

Definition at line 1538 of file res_pjsip.c.

1539 {
1540  struct send_request_wrapper *req_wrapper = obj;
1541 
1542  pjsip_tx_data_dec_ref(req_wrapper->tdata);
1543  ast_debug(2, "%p: wrapper destroyed\n", req_wrapper);
1544 }

References ast_debug, and send_request_wrapper::tdata.

Referenced by endpt_send_request().

◆ 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 608 of file res_pjsip.c.

610 {
611  pj_str_t tmp, local_addr;
612  pjsip_uri *uri;
613  pjsip_sip_uri *sip_uri;
614  pjsip_transport_type_e type;
615  int local_port;
616  char default_user[PJSIP_MAX_URL_SIZE];
617 
618  if (ast_strlen_zero(user)) {
619  ast_sip_get_default_from_user(default_user, sizeof(default_user));
620  user = default_user;
621  }
622 
623  /* Parse the provided target URI so we can determine what transport it will end up using */
624  pj_strdup_with_null(pool, &tmp, target);
625 
626  if (!(uri = pjsip_parse_uri(pool, tmp.ptr, tmp.slen, 0)) ||
627  (!PJSIP_URI_SCHEME_IS_SIP(uri) && !PJSIP_URI_SCHEME_IS_SIPS(uri))) {
628  return -1;
629  }
630 
631  sip_uri = pjsip_uri_get_uri(uri);
632 
633  /* Determine the transport type to use */
634  type = pjsip_transport_get_type_from_name(&sip_uri->transport_param);
635  if (PJSIP_URI_SCHEME_IS_SIPS(sip_uri)) {
636  if (type == PJSIP_TRANSPORT_UNSPECIFIED
637  || !(pjsip_transport_get_flag_from_type(type) & PJSIP_TRANSPORT_SECURE)) {
638  type = PJSIP_TRANSPORT_TLS;
639  }
640  } else if (!sip_uri->transport_param.slen) {
641  type = PJSIP_TRANSPORT_UDP;
642  } else if (type == PJSIP_TRANSPORT_UNSPECIFIED) {
643  return -1;
644  }
645 
646  /* If the host is IPv6 turn the transport into an IPv6 version */
647  if (pj_strchr(&sip_uri->host, ':')) {
648  type |= PJSIP_TRANSPORT_IPV6;
649  }
650 
651  /* In multidomain scenario, username may contain @ with domain info */
652  if (!ast_sip_get_disable_multi_domain() && strchr(user, '@')) {
653  from->ptr = pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE);
654  from->slen = pj_ansi_snprintf(from->ptr, PJSIP_MAX_URL_SIZE,
655  "<sip:%s%s%s>",
656  user,
657  (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? ";transport=" : "",
658  (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? pjsip_transport_get_type_name(type) : "");
659  return 0;
660  }
661 
662  if (!ast_strlen_zero(domain)) {
663  from->ptr = pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE);
664  from->slen = pj_ansi_snprintf(from->ptr, PJSIP_MAX_URL_SIZE,
665  "<sip:%s@%s%s%s>",
666  user,
667  domain,
668  (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? ";transport=" : "",
669  (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? pjsip_transport_get_type_name(type) : "");
670  return 0;
671  }
672 
673  /* Get the local bound address for the transport that will be used when communicating with the provided URI */
674  if (pjsip_tpmgr_find_local_addr(pjsip_endpt_get_tpmgr(ast_sip_get_pjsip_endpoint()), pool, type, selector,
675  &local_addr, &local_port) != PJ_SUCCESS) {
676 
677  /* If no local address can be retrieved using the transport manager use the host one */
678  pj_strdup(pool, &local_addr, pj_gethostname());
679  local_port = pjsip_transport_get_default_port_for_type(PJSIP_TRANSPORT_UDP);
680  }
681 
682  /* If IPv6 was specified in the transport, set the proper type */
683  if (pj_strchr(&local_addr, ':')) {
684  type |= PJSIP_TRANSPORT_IPV6;
685  }
686 
687  from->ptr = pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE);
688  from->slen = pj_ansi_snprintf(from->ptr, PJSIP_MAX_URL_SIZE,
689  "<sip:%s@%s%.*s%s:%d%s%s>",
690  user,
691  (type & PJSIP_TRANSPORT_IPV6) ? "[" : "",
692  (int)local_addr.slen,
693  local_addr.ptr,
694  (type & PJSIP_TRANSPORT_IPV6) ? "]" : "",
695  local_port,
696  (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? ";transport=" : "",
697  (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? pjsip_transport_get_type_name(type) : "");
698 
699  return 0;
700 }
unsigned int ast_sip_get_disable_multi_domain(void)
Retrieve the system setting 'disable multi domain'.
void ast_sip_get_default_from_user(char *from_user, size_t size)
Retrieve the global default from user.
Domain data structure.
Definition: sip.h:887
structure to hold users read from users.conf

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

◆ sip_thread_start()

static void sip_thread_start ( void  )
static

Definition at line 2119 of file res_pjsip.c.

2120 {
2121  pj_thread_desc *desc;
2122  pj_thread_t *thread;
2123  uint32_t *servant_id;
2124 
2125  servant_id = ast_threadstorage_get(&servant_id_storage, sizeof(*servant_id));
2126  if (!servant_id) {
2127  ast_log(LOG_ERROR, "Could not set SIP servant ID in thread-local storage.\n");
2128  return;
2129  }
2130  *servant_id = SIP_SERVANT_ID;
2131 
2132  desc = ast_threadstorage_get(&pj_thread_storage, sizeof(pj_thread_desc));
2133  if (!desc) {
2134  ast_log(LOG_ERROR, "Could not get thread desc from thread-local storage. Expect awful things to occur\n");
2135  return;
2136  }
2137  pj_bzero(*desc, sizeof(*desc));
2138 
2139  if (pj_thread_register("Asterisk Thread", *desc, &thread) != PJ_SUCCESS) {
2140  ast_log(LOG_ERROR, "Couldn't register thread with PJLIB.\n");
2141  }
2142 }
pthread_t thread
Definition: app_meetme.c:1091
static const char desc[]
Definition: cdr_radius.c:84
#define SIP_SERVANT_ID
Definition: res_pjsip.c:2117
static struct ast_threadstorage pj_thread_storage
Definition: res_pjsip.c:2115
static struct ast_threadstorage servant_id_storage
Definition: res_pjsip.c:2116
void * ast_threadstorage_get(struct ast_threadstorage *ts, size_t init_size)
Retrieve thread storage.

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

Referenced by load_module().

◆ stop_monitor_thread()

static void stop_monitor_thread ( void  )
static

Definition at line 2109 of file res_pjsip.c.

2110 {
2111  monitor_continue = 0;
2112  pj_thread_join(monitor_thread);
2113 }

References monitor_continue, and monitor_thread.

Referenced by unload_pjsip().

◆ supplement_on_rx_request()

static pj_bool_t supplement_on_rx_request ( pjsip_rx_data *  rdata)
static

Definition at line 2184 of file res_pjsip.c.

2185 {
2186  struct ast_sip_supplement *supplement;
2187 
2188  if (pjsip_rdata_get_dlg(rdata)) {
2189  return PJ_FALSE;
2190  }
2191 
2193  AST_LIST_TRAVERSE(&supplements, supplement, next) {
2194  if (supplement->incoming_request
2195  && does_method_match(&rdata->msg_info.msg->line.req.method.name, supplement->method)) {
2196  struct ast_sip_endpoint *endpoint;
2197 
2198  endpoint = ast_pjsip_rdata_get_endpoint(rdata);
2199  supplement->incoming_request(endpoint, rdata);
2200  ao2_cleanup(endpoint);
2201  }
2202  }
2204 
2205  return PJ_FALSE;
2206 }
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.
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:2992

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.

◆ supplement_outgoing_response()

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

Definition at line 2208 of file res_pjsip.c.

2209 {
2210  struct ast_sip_supplement *supplement;
2211  pjsip_cseq_hdr *cseq = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CSEQ, NULL);
2213 
2214  if (sip_endpoint) {
2215  ast_sip_message_apply_transport(sip_endpoint->transport, tdata);
2216  }
2217 
2219  AST_LIST_TRAVERSE(&supplements, supplement, next) {
2220  if (supplement->outgoing_response && does_method_match(&cseq->method.name, supplement->method)) {
2221  supplement->outgoing_response(sip_endpoint, contact, tdata);
2222  }
2223  }
2225 
2226  ast_sip_mod_data_set(tdata->pool, tdata->mod_data, supplement_module.id, MOD_DATA_CONTACT, NULL);
2228 }
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:3018

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

◆ sync_task()

static int sync_task ( void *  data)
static

Definition at line 1951 of file res_pjsip.c.

1952 {
1953  struct sync_task_data *std = data;
1954  int ret;
1955 
1956  std->fail = std->task(std->task_data);
1957 
1958  /*
1959  * Once we unlock std->lock after signaling, we cannot access
1960  * std again. The thread waiting within ast_sip_push_task_wait()
1961  * is free to continue and release its local variable (std).
1962  */
1963  ast_mutex_lock(&std->lock);
1964  std->complete = 1;
1965  ast_cond_signal(&std->cond);
1966  ret = std->fail;
1967  ast_mutex_unlock(&std->lock);
1968  return ret;
1969 }
#define ast_cond_signal(cond)
Definition: lock.h:201
ast_cond_t cond
Definition: stasis.c:1278
int(* task)(void *)
Definition: res_pjsip.c:1947
ast_mutex_t lock
Definition: stasis.c:1277

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

◆ 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 943 of file res_pjsip.c.

944 {
945  pjsip_rr_hdr *record_route;
946 
947  if (PJSIP_URI_SCHEME_IS_SIPS(rdata->msg_info.msg->line.req.uri)) {
948  return 1;
949  }
950 
951  record_route = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_RECORD_ROUTE, NULL);
952  if (record_route) {
953  if (PJSIP_URI_SCHEME_IS_SIPS(&record_route->name_addr)) {
954  return 1;
955  }
956  } else {
957  pjsip_contact_hdr *contact;
958 
959  contact = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT, NULL);
960  ast_assert(contact != NULL);
961  if (PJSIP_URI_SCHEME_IS_SIPS(contact->uri)) {
962  return 1;
963  }
964  }
965 
966  return 0;
967 }

References ast_assert, and NULL.

Referenced by create_dialog_uas().

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 2789 of file res_pjsip.c.

2790 {
2791  AST_TEST_UNREGISTER(xml_sanitization_end_null);
2792  AST_TEST_UNREGISTER(xml_sanitization_exceeds_buffer);
2794 
2795  /* The thread this is called from cannot call PJSIP/PJLIB functions,
2796  * so we have to push the work to the threadpool to handle
2797  */
2802 
2803  return 0;
2804 }
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
#define AST_TEST_UNREGISTER(cb)
Definition: test.h:128

◆ unload_pjsip()

static int unload_pjsip ( void *  data)
static

Definition at line 2523 of file res_pjsip.c.

2524 {
2525  /*
2526  * These calls need the pjsip endpoint and serializer to clean up.
2527  * If they're not set, then there's nothing to clean up anyway.
2528  */
2539  }
2540 
2541  if (monitor_thread) {
2543  monitor_thread = NULL;
2544  }
2545 
2546  if (memory_pool) {
2547  /* This mimics the behavior of pj_pool_safe_release
2548  * which was introduced in pjproject 2.6.
2549  */
2550  pj_pool_t *temp_pool = memory_pool;
2551 
2552  memory_pool = NULL;
2553  pj_pool_release(temp_pool);
2554  }
2555 
2557 
2558  if (caching_pool.lock) {
2560  }
2561 
2562  pj_shutdown();
2563 
2564  return 0;
2565 }
void ast_sip_destroy_system(void)
void ast_pjproject_caching_pool_destroy(pj_caching_pool *cp)
Destroy caching pool factory and all cached pools.
void ast_sip_unregister_service(pjsip_module *module)
Definition: res_pjsip.c:126
static void stop_monitor_thread(void)
Definition: res_pjsip.c:2109
void ast_res_pjsip_cleanup_options_handling(void)
void ast_sip_destroy_transport_management(void)
void ast_sip_destroy_distributor(void)
void ast_sip_destroy_global_headers(void)
void ast_res_pjsip_destroy_configuration(void)
void ast_sip_destroy_transport_events(void)
void ast_res_pjsip_cleanup_message_filter(void)

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(), caching_pool, memory_pool, monitor_thread, NULL, sip_serializer_pool, stop_monitor_thread(), and supplement_module.

Referenced by load_module().

◆ unregister_service()

static int unregister_service ( void *  data)
static

Definition at line 115 of file res_pjsip.c.

116 {
117  pjsip_module **module = data;
118  if (!ast_pjsip_endpoint) {
119  return -1;
120  }
121  pjsip_endpt_unregister_module(ast_pjsip_endpoint, *module);
122  ast_debug(1, "Unregistered SIP service %.*s\n", (int) pj_strlen(&(*module)->name), pj_strbuf(&(*module)->name));
123  return 0;
124 }

References ast_debug, and ast_pjsip_endpoint.

Referenced by ast_sip_unregister_service().

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 = AST_BUILDOPT_SUM, .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 2789 of file res_pjsip.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 2814 of file res_pjsip.c.

◆ ast_pjsip_endpoint

pjsip_endpoint* ast_pjsip_endpoint
static

◆ caching_pool

pj_caching_pool caching_pool

Definition at line 2095 of file res_pjsip.c.

Referenced by load_pjsip(), and unload_pjsip().

◆ 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_show_endpoint_identifiers(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: res_pjsip.c:404
static char * cli_dump_endpt(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: res_pjsip.c:364
static char * cli_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: res_pjsip.c:435

Definition at line 435 of file res_pjsip.c.

Referenced by load_module().

◆ 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 72 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 75 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 78 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 81 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 1126 of file res_pjsip.c.

◆ memory_pool

pj_pool_t* memory_pool

Definition at line 2096 of file res_pjsip.c.

Referenced by load_pjsip(), and unload_pjsip().

◆ message_method

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

Definition at line 1127 of file res_pjsip.c.

Referenced by does_method_match().

◆ method

const char* method

◆ 

struct { ... } methods[]

◆ monitor_continue

int monitor_continue
static

Definition at line 2098 of file res_pjsip.c.

Referenced by load_pjsip(), monitor_thread_exec(), and stop_monitor_thread().

◆ monitor_thread

pj_thread_t* monitor_thread

◆ 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 2115 of file res_pjsip.c.

Referenced by sip_thread_start().

◆ pjsip_media_type_application_cpim_xpidf_xml

pjsip_media_type pjsip_media_type_application_cpim_xpidf_xml

Definition at line 2638 of file res_pjsip.c.

Referenced by load_module().

◆ pjsip_media_type_application_json

pjsip_media_type pjsip_media_type_application_json

Common media types used throughout res_pjsip and pjproject

Definition at line 2634 of file res_pjsip.c.

Referenced by load_module().

◆ pjsip_media_type_application_media_control_xml

pjsip_media_type pjsip_media_type_application_media_control_xml

Definition at line 2635 of file res_pjsip.c.

Referenced by load_module(), and video_info_incoming_request().

◆ pjsip_media_type_application_pidf_xml

pjsip_media_type pjsip_media_type_application_pidf_xml

Definition at line 2636 of file res_pjsip.c.

Referenced by load_module().

◆ pjsip_media_type_application_rlmi_xml

pjsip_media_type pjsip_media_type_application_rlmi_xml

Definition at line 2639 of file res_pjsip.c.

Referenced by load_module().

◆ pjsip_media_type_application_sdp

pjsip_media_type pjsip_media_type_application_sdp

Definition at line 2641 of file res_pjsip.c.

Referenced by filter_on_tx_message(), load_module(), and session_outgoing_nat_hook().

◆ pjsip_media_type_application_simple_message_summary

pjsip_media_type pjsip_media_type_application_simple_message_summary

Definition at line 2640 of file res_pjsip.c.

Referenced by load_module().

◆ pjsip_media_type_application_xpidf_xml

pjsip_media_type pjsip_media_type_application_xpidf_xml

Definition at line 2637 of file res_pjsip.c.

Referenced by load_module().

◆ pjsip_media_type_multipart_alternative

pjsip_media_type pjsip_media_type_multipart_alternative

Definition at line 2642 of file res_pjsip.c.

Referenced by check_content_disposition(), and load_module().

◆ pjsip_media_type_multipart_mixed

pjsip_media_type pjsip_media_type_multipart_mixed

Definition at line 2643 of file res_pjsip.c.

Referenced by check_content_disposition(), and load_module().

◆ pjsip_media_type_multipart_related

pjsip_media_type pjsip_media_type_multipart_related

Definition at line 2644 of file res_pjsip.c.

Referenced by load_module().

◆ pjsip_media_type_text_plain

pjsip_media_type pjsip_media_type_text_plain

Definition at line 2645 of file res_pjsip.c.

Referenced by load_module().

◆ pmethod

const pjsip_method* pmethod

Definition at line 1131 of file res_pjsip.c.

Referenced by ast_sip_create_request().

◆ registered_authenticator

struct ast_sip_authenticator* registered_authenticator
static

◆ registered_outbound_authenticator

struct ast_sip_outbound_authenticator* registered_outbound_authenticator
static

◆ 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 2116 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 65 of file res_pjsip.c.

Referenced by ast_sip_push_task(), ast_sip_push_task_wait_serializer(), load_module(), and unload_pjsip().

◆ sip_threadpool

struct ast_threadpool* sip_threadpool
static

◆ supplement_module

pjsip_module supplement_module
static

◆ supplements

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