Asterisk - The Open Source Telephony Project GIT-master-3dae2cf
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 "asterisk/strings.h"
#include "pjsip/sip_parser.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/causes.h"
#include "asterisk/cli.h"
#include "asterisk/callerid.h"
#include "asterisk/res_pjsip_cli.h"
#include "asterisk/test.h"
#include "asterisk/res_pjsip_presence_xml.h"
#include "asterisk/res_pjproject.h"
#include "asterisk/utf8.h"
#include "asterisk/acl.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  response_code_map
 
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 DEBUG_BUF_SIZE   256
 
#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...
 
pjsip_generic_string_hdr * ast_sip_add_header2 (pjsip_tx_data *tdata, const char *name, const char *value)
 Add a header to an outbound SIP message, returning a pointer to the header. 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...
 
struct ast_sip_transport_stateast_sip_find_transport_state_in_use (struct ast_sip_request_transport_details *details)
 Returns the transport state currently in use based on request transport details. 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...
 
pjsip_sip_uri * ast_sip_get_contact_sip_uri (pjsip_tx_data *tdata)
 Return the SIP URI of the Contact header. More...
 
struct ast_sip_endpointast_sip_get_endpoint (const char *to, int get_default_outbound, char **uri)
 Retrieves an endpoint and URI from the "to" string. 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...
 
const int ast_sip_hangup_sip2cause (int cause)
 Convert SIP hangup causes to Asterisk hangup causes. 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_allowed_uri (pjsip_uri *uri)
 Check whether a pjsip_uri is allowed or not. 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...
 
int ast_sip_is_uri_sip_sips (pjsip_uri *uri)
 Check whether a pjsip_uri is SIP/SIPS or not. 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...
 
const pj_str_t * ast_sip_pjsip_uri_get_hostname (pjsip_uri *uri)
 Get the host portion of the pjsip_uri. More...
 
struct pjsip_param * ast_sip_pjsip_uri_get_other_param (pjsip_uri *uri, const pj_str_t *param_str)
 Find an 'other' SIP/SIPS URI parameter by name. More...
 
const pj_str_t * ast_sip_pjsip_uri_get_username (pjsip_uri *uri)
 Get the user portion of the pjsip_uri. 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_rewrite_uri_to_local (pjsip_sip_uri *uri, pjsip_tx_data *tdata)
 Replace domain and port of SIP URI to point to (external) signaling address of this Asterisk instance. 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_id_connected_line (struct pjsip_rx_data *rdata, struct ast_party_id *id)
 Set the ID for a connected line update. More...
 
int ast_sip_set_id_from_invite (struct pjsip_rx_data *rdata, struct ast_party_id *id, struct ast_party_id *default_id, int trust_inbound)
 Set the ID from an INVITE. 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_request_transport_details (struct ast_sip_request_transport_details *details, pjsip_tx_data *tdata, int use_ipv6)
 Sets request transport details based on tdata. 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_str2rc (const char *name)
 Convert name to SIP response code. 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_update_from (pjsip_tx_data *tdata, char *from)
 Overwrite fields in the outbound 'From' header. More...
 
int ast_sip_update_to_uri (pjsip_tx_data *tdata, const char *to)
 Replace the To URI in the tdata with the supplied one. 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 void clean_contact_from_tdata (pjsip_tx_data *tdata)
 
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 int find_transport_state_in_use (void *obj, void *arg, int flags)
 Callback function for finding the transport the request is going out on. More...
 
static pjsip_fromto_hdr * get_id_header (pjsip_rx_data *rdata, const pj_str_t *header_name)
 
static const pjsip_method * get_pjsip_method (const char *method)
 
static struct ast_sip_endpointhandle_atsign (const char *to, char *destination, char **uri, char *slash, char *atsign, char *scheme, int get_default_outbound)
 
static struct ast_sip_endpointhandle_single_token (const char *to, char *destination, int get_default_outbound, char **uri)
 
static struct ast_sip_endpointhandle_slash (const char *to, char *destination, char **uri, char *slash, char *atsign, char *scheme)
 
static int insert_user_in_contact_uri (const char *to, const char *endpoint_name, const char *aors, const char *user, char **uri)
 Find a contact and insert a "user@" into its URI. More...
 
static int load_module (void)
 
static int load_pjsip (void)
 
static void * monitor_thread_exec (void *endpt)
 
void never_called_res_pjsip (void)
 
static void pool_destroy_callback (void *arg)
 
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 set_id_from_from (struct pjsip_rx_data *rdata, struct ast_party_id *id)
 
static void set_id_from_hdr (pjsip_fromto_hdr *hdr, struct ast_party_id *id)
 
static int set_id_from_pai (pjsip_rx_data *rdata, struct ast_party_id *id)
 
static int set_id_from_rpid (pjsip_rx_data *rdata, struct ast_party_id *id)
 
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_geolocation,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 const struct response_code_map rc_map []
 
static const pjsip_method refer_method = {PJSIP_OTHER_METHOD, {"REFER", 5} }
 
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

◆ DEBUG_BUF_SIZE

#define DEBUG_BUF_SIZE   256

◆ ENDPOINT_IDENTIFIER_FORMAT

#define ENDPOINT_IDENTIFIER_FORMAT   "%-20.20s\n"

◆ MOD_DATA_CONTACT

#define MOD_DATA_CONTACT   "contact"

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

◆ SIP_SERVANT_ID

#define SIP_SERVANT_ID   0x5E2F1D

Definition at line 2283 of file res_pjsip.c.

◆ TIMEOUT_TIMER2

#define TIMEOUT_TIMER2   5

Definition at line 1513 of file res_pjsip.c.

◆ TIMER_INACTIVE

#define TIMER_INACTIVE   0

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

Function Documentation

◆ __init_pj_thread_storage()

static void __init_pj_thread_storage ( void  )
static

Definition at line 2281 of file res_pjsip.c.

2286{

◆ __init_servant_id_storage()

static void __init_servant_id_storage ( void  )
static

Definition at line 2282 of file res_pjsip.c.

2286{

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 4097 of file res_pjsip.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

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

2040{
2041 pj_str_t type;
2042 pj_str_t subtype;
2043 pj_str_t body_text;
2044
2045 pj_cstr(&type, body->type);
2046 pj_cstr(&subtype, body->subtype);
2047 pj_cstr(&body_text, body->body_text);
2048
2049 return pjsip_msg_body_create(pool, &type, &subtype, &body_text);
2050}
static const char type[]
Definition: chan_ooh323.c:109
const char * type
Definition: res_pjsip.h:2326
const char * body_text
Definition: res_pjsip.h:2330
const char * subtype
Definition: res_pjsip.h:2328

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

2202{
2203 size_t chars_to_copy = MIN(size - 1, pj_strlen(src));
2204 memcpy(dest, pj_strbuf(src), chars_to_copy);
2205 dest[chars_to_copy] = '\0';
2206}
#define MIN(a, b)
Definition: utils.h:231

References MIN.

Referenced by apply_dtls_attrib(), apply_negotiated_sdp_stream(), assign_uuid(), ast_sip_get_transport_name(), ast_sip_header_to_security_mechanism(), ast_sip_report_auth_challenge_sent(), ast_sip_report_auth_failed_challenge_response(), chan_pjsip_get_uniqueid(), change_outgoing_sdp_stream_media_address(), channel_read_pjsip(), cli_complete_subscription_common(), cli_list_subscriptions_detail(), cli_show_subscriptions_detail(), determine_sip_publish_type(), dialog_info_generate_body_content(), endpoint_lookup(), evaluate_like(), extract_contact_addr(), find_aor2(), find_aor_name(), find_challenge(), get_auth_header(), get_codecs(), get_dest_tn(), get_destination(), get_endpoint_details(), get_from_header(), get_mid_bundle_group(), get_user_agent(), handle_incoming_request(), 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(), rfc3329_incoming_response(), rx_data_to_ast_msg(), save_response_fields_to_transport(), sdp_requires_deferral(), security_event_populate(), session_inv_on_redirected(), session_outgoing_nat_hook(), set_id_from_hdr(), set_id_from_oli(), set_mid_and_bundle_group(), set_redirecting_value(), set_remote_mslabel_and_stream_group(), set_sipdomain_variable(), sip_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 2208 of file res_pjsip.c.

2209{
2210 int res = ast_asprintf(dest, "%.*s", (int)pj_strlen(src), pj_strbuf(src));
2211
2212 if (res < 0) {
2213 *dest = NULL;
2214 }
2215
2216 return res;
2217}
#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 4097 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 2052 of file res_pjsip.c.

2053{
2054 pjsip_msg_body *pjsip_body = ast_body_to_pjsip_body(tdata->pool, body);
2055 tdata->msg->body = pjsip_body;
2056 return 0;
2057}
static pjsip_msg_body * ast_body_to_pjsip_body(pj_pool_t *pool, const struct ast_sip_body *body)
Definition: res_pjsip.c:2039

References ast_body_to_pjsip_body().

Referenced by aoc_bye_outgoing_request(), aoc_bye_outgoing_response(), aoc_send_as_xml(), 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 2059 of file res_pjsip.c.

2060{
2061 int i;
2062 /* NULL for type and subtype automatically creates "multipart/mixed" */
2063 pjsip_msg_body *body = pjsip_multipart_create(tdata->pool, NULL, NULL);
2064
2065 for (i = 0; i < num_bodies; ++i) {
2066 pjsip_multipart_part *part = pjsip_multipart_create_part(tdata->pool);
2067 part->body = ast_body_to_pjsip_body(tdata->pool, bodies[i]);
2068 pjsip_multipart_add_part(tdata->pool, body, part);
2069 }
2070
2071 tdata->msg->body = body;
2072 return 0;
2073}

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

91{
92 char date[256];
93 struct tm tm;
94 time_t t = time(NULL);
95
96 gmtime_r(&t, &tm);
97 strftime(date, sizeof(date), "%a, %d %b %Y %T GMT", &tm);
98
99 ast_sip_add_header(tdata, "Date", date);
100}
int ast_sip_add_header(pjsip_tx_data *tdata, const char *name, const char *value)
Add a header to an outbound SIP message.
Definition: res_pjsip.c:2008

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

2009{
2010 pj_str_t hdr_name;
2011 pj_str_t hdr_value;
2012 pjsip_generic_string_hdr *hdr;
2013
2014 pj_cstr(&hdr_name, name);
2015 pj_cstr(&hdr_value, value);
2016
2017 hdr = pjsip_generic_string_hdr_create(tdata->pool, &hdr_name, &hdr_value);
2018
2019 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *) hdr);
2020 return 0;
2021}
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_add_security_headers(), ast_sip_message_apply_transport(), build_notify(), handle_outgoing_request(), notify_channel(), notify_contact(), notify_uri(), options_incoming_request(), rfc3326_add_reason_header(), send_options_response(), sip_publication_respond(), transfer_refer(), and vars_to_headers().

◆ ast_sip_add_header2()

pjsip_generic_string_hdr * ast_sip_add_header2 ( pjsip_tx_data *  tdata,
const char *  name,
const char *  value 
)

Add a header to an outbound SIP message, returning a pointer to the header.

Parameters
tdataThe message to add the header to
nameThe header name
valueThe header value
Returns
The pjsip_generic_string_hdr * added.

Definition at line 2023 of file res_pjsip.c.

2025{
2026 pj_str_t hdr_name;
2027 pj_str_t hdr_value;
2028 pjsip_generic_string_hdr *hdr;
2029
2030 pj_cstr(&hdr_name, name);
2031 pj_cstr(&hdr_value, value);
2032
2033 hdr = pjsip_generic_string_hdr_create(tdata->pool, &hdr_name, &hdr_value);
2034
2035 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *) hdr);
2036 return hdr;
2037}

References name, and value.

Referenced by handle_outgoing_request().

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

931{
932 pjsip_sip_uri *sip_uri;
933 int i = 0;
934 static const pj_str_t STR_PHONE = { "phone", 5 };
935
936 if (!endpoint || !endpoint->usereqphone || (!PJSIP_URI_SCHEME_IS_SIP(uri) && !PJSIP_URI_SCHEME_IS_SIPS(uri))) {
937 return;
938 }
939
940 sip_uri = pjsip_uri_get_uri(uri);
941
942 if (!pj_strlen(&sip_uri->user)) {
943 return;
944 }
945
946 if (pj_strbuf(&sip_uri->user)[0] == '+') {
947 i = 1;
948 }
949
950 /* Test URI user against allowed characters in AST_DIGIT_ANY */
951 for (; i < pj_strlen(&sip_uri->user); i++) {
952 if (!strchr(AST_DIGIT_ANY, pj_strbuf(&sip_uri->user)[i])) {
953 break;
954 }
955 }
956
957 if (i < pj_strlen(&sip_uri->user)) {
958 return;
959 }
960
961 sip_uri->user_param = STR_PHONE;
962}
#define AST_DIGIT_ANY
Definition: file.h:48
unsigned int usereqphone
Definition: res_pjsip.h:1027

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

2076{
2077 size_t combined_size = strlen(body_text) + tdata->msg->body->len;
2078 struct ast_str *body_buffer = ast_str_alloca(combined_size);
2079
2080 ast_str_set(&body_buffer, 0, "%.*s%s", (int) tdata->msg->body->len, (char *) tdata->msg->body->data, body_text);
2081
2082 tdata->msg->body->data = pj_pool_alloc(tdata->pool, combined_size);
2083 pj_memcpy(tdata->msg->body->data, ast_str_buffer(body_buffer), combined_size);
2084 tdata->msg->body->len = combined_size;
2085
2086 return 0;
2087}
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
#define ast_str_alloca(init_len)
Definition: strings.h:848
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1113
Support for dynamic strings.
Definition: strings.h:623

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
athe first media type
bthe second media type
Return values
1Media types are equal
0Media types are not equal

Definition at line 2219 of file res_pjsip.c.

2220{
2221 int rc = 0;
2222 if (a != NULL && b != NULL) {
2223 rc = pjsip_media_type_cmp(a, b, 0) ? 0 : 1;
2224 }
2225 return rc;
2226}
static struct test_val b
static struct test_val a

References a, b, and NULL.

Referenced by find_pidf(), and 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 2554 of file res_pjsip.c.

2555{
2556 const char *value;
2557
2558 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)) {
2559 value = "local";
2560 } 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)) {
2561 value = "local_merge";
2562 } 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)) {
2563 value = "local_first";
2564 } 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)) {
2565 value = "remote";
2566 } 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)) {
2567 value = "remote_merge";
2568 } 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)) {
2569 value = "remote_first";
2570 } else {
2571 value = "unknown";
2572 }
2573
2574 return value;
2575}
#define ast_sip_call_codec_pref_test(__param, __codec_pref)
Returns true if the preference is set in the parameter.
Definition: res_pjsip.h:694

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

2578{
2579 pref->flags = 0;
2580
2581 if (strcmp(pref_str, "local") == 0) {
2583 } else if (is_outgoing && strcmp(pref_str, "local_merge") == 0) {
2585 } else if (strcmp(pref_str, "local_first") == 0) {
2587 } else if (strcmp(pref_str, "remote") == 0) {
2589 } else if (is_outgoing && strcmp(pref_str, "remote_merge") == 0) {
2591 } else if (strcmp(pref_str, "remote_first") == 0) {
2593 } else {
2594 return -1;
2595 }
2596
2597 return 0;
2598}
@ AST_SIP_CALL_CODEC_PREF_ALL
Definition: res_pjsip.h:674
@ AST_SIP_CALL_CODEC_PREF_LOCAL
Definition: res_pjsip.h:680
@ AST_SIP_CALL_CODEC_PREF_REMOTE
Definition: res_pjsip.h:682
@ AST_SIP_CALL_CODEC_PREF_UNION
Definition: res_pjsip.h:670
@ AST_SIP_CALL_CODEC_PREF_FIRST
Definition: res_pjsip.h:676
@ AST_SIP_CALL_CODEC_PREF_INTERSECT
Definition: res_pjsip.h:668
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 179 of file res_pjsip.c.

181{
183 ast_log(LOG_WARNING, "No SIP authenticator registered. Assuming authentication is successful\n");
185 }
186 return registered_authenticator->check_authentication(endpoint, rdata, tdata);
187}
#define ast_log
Definition: astobj2.c:42
#define LOG_WARNING
static struct ast_sip_authenticator * registered_authenticator
Definition: res_pjsip.c:138
@ AST_SIP_AUTHENTICATION_SUCCESS
Definition: res_pjsip.h:1232
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:1261

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

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

966{
967 char enclosed_uri[PJSIP_MAX_URL_SIZE];
968 pj_str_t local_uri = { "sip:temp@temp", 13 }, remote_uri, target_uri;
969 pj_status_t res;
970 pjsip_dialog *dlg = NULL;
971 const char *outbound_proxy = endpoint->outbound_proxy;
972 pjsip_tpselector selector = { .type = PJSIP_TPSELECTOR_NONE, };
973 static const pj_str_t HCONTACT = { "Contact", 7 };
974
975 if (!ast_begins_with(uri, "<")) {
976 snprintf(enclosed_uri, sizeof(enclosed_uri), "<%s>", uri);
977 } else {
978 snprintf(enclosed_uri, sizeof(enclosed_uri), "%s", uri);
979 }
980 pj_cstr(&remote_uri, enclosed_uri);
981
982 pj_cstr(&target_uri, uri);
983
984 res = pjsip_dlg_create_uac(pjsip_ua_instance(), &local_uri, NULL, &remote_uri, &target_uri, &dlg);
985 if (res == PJ_SUCCESS && !(PJSIP_URI_SCHEME_IS_SIP(dlg->target) || PJSIP_URI_SCHEME_IS_SIPS(dlg->target))) {
986 /* dlg->target is a pjsip_other_uri, but it's assumed to be a
987 * pjsip_sip_uri below. Fail fast. */
988 res = PJSIP_EINVALIDURI;
989 pjsip_dlg_terminate(dlg);
990 }
991 if (res != PJ_SUCCESS) {
992 if (res == PJSIP_EINVALIDURI) {
994 "Endpoint '%s': Could not create dialog to invalid URI '%s'. Is endpoint registered and reachable?\n",
995 ast_sorcery_object_get_id(endpoint), uri);
996 }
997 return NULL;
998 }
999
1000 /* We have to temporarily bump up the sess_count here so the dialog is not prematurely destroyed */
1001 dlg->sess_count++;
1002
1003 ast_sip_dlg_set_transport(endpoint, dlg, &selector);
1004
1005 if (sip_dialog_create_from(dlg->pool, &local_uri, endpoint->fromuser, endpoint->fromdomain, &remote_uri, &selector)) {
1006 dlg->sess_count--;
1007 pjsip_dlg_terminate(dlg);
1008 ast_sip_tpselector_unref(&selector);
1009 return NULL;
1010 }
1011
1012 ast_sip_tpselector_unref(&selector);
1013
1014 /* Update the dialog with the new local URI, we do it afterwards so we can use the dialog pool for construction */
1015 pj_strdup_with_null(dlg->pool, &dlg->local.info_str, &local_uri);
1016 dlg->local.info->uri = pjsip_parse_uri(dlg->pool, dlg->local.info_str.ptr, dlg->local.info_str.slen, 0);
1017 if (!dlg->local.info->uri) {
1019 "Could not parse URI '%s' for endpoint '%s'\n",
1020 dlg->local.info_str.ptr, ast_sorcery_object_get_id(endpoint));
1021 dlg->sess_count--;
1022 pjsip_dlg_terminate(dlg);
1023 return NULL;
1024 }
1025
1026 dlg->local.contact = pjsip_parse_hdr(dlg->pool, &HCONTACT, local_uri.ptr, local_uri.slen, NULL);
1027
1028 if (!ast_strlen_zero(endpoint->contact_user)) {
1029 pjsip_sip_uri *sip_uri;
1030
1031 sip_uri = pjsip_uri_get_uri(dlg->local.contact->uri);
1032 pj_strdup2(dlg->pool, &sip_uri->user, endpoint->contact_user);
1033 }
1034
1035 /* If a request user has been specified and we are permitted to change it, do so */
1036 if (!ast_strlen_zero(request_user)) {
1037 pjsip_sip_uri *sip_uri;
1038
1039 if (PJSIP_URI_SCHEME_IS_SIP(dlg->target) || PJSIP_URI_SCHEME_IS_SIPS(dlg->target)) {
1040 sip_uri = pjsip_uri_get_uri(dlg->target);
1041 pj_strdup2(dlg->pool, &sip_uri->user, request_user);
1042 }
1043 if (PJSIP_URI_SCHEME_IS_SIP(dlg->remote.info->uri) || PJSIP_URI_SCHEME_IS_SIPS(dlg->remote.info->uri)) {
1044 sip_uri = pjsip_uri_get_uri(dlg->remote.info->uri);
1045 pj_strdup2(dlg->pool, &sip_uri->user, request_user);
1046 }
1047 }
1048
1049 /* Add the user=phone parameter if applicable */
1050 ast_sip_add_usereqphone(endpoint, dlg->pool, dlg->target);
1051 ast_sip_add_usereqphone(endpoint, dlg->pool, dlg->remote.info->uri);
1052 ast_sip_add_usereqphone(endpoint, dlg->pool, dlg->local.info->uri);
1053
1054 if (!ast_strlen_zero(outbound_proxy)) {
1055 pjsip_route_hdr route_set, *route;
1056 static const pj_str_t ROUTE_HNAME = { "Route", 5 };
1057 pj_str_t tmp;
1058
1059 pj_list_init(&route_set);
1060
1061 pj_strdup2_with_null(dlg->pool, &tmp, outbound_proxy);
1062 if (!(route = pjsip_parse_hdr(dlg->pool, &ROUTE_HNAME, tmp.ptr, tmp.slen, NULL))) {
1063 ast_log(LOG_ERROR, "Could not create dialog to endpoint '%s' as outbound proxy URI '%s' is not valid\n",
1064 ast_sorcery_object_get_id(endpoint), outbound_proxy);
1065 dlg->sess_count--;
1066 pjsip_dlg_terminate(dlg);
1067 return NULL;
1068 }
1069 pj_list_insert_nodes_before(&route_set, route);
1070
1071 pjsip_dlg_set_route_set(dlg, &route_set);
1072 }
1073
1074 dlg->sess_count--;
1075
1076 return dlg;
1077}
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:930
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:727
void ast_sip_tpselector_unref(pjsip_tpselector *selector)
Unreference a pjsip_tpselector.
Definition: res_pjsip.c:923
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:749
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2317
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
static int force_inline attribute_pure ast_begins_with(const char *str, const char *prefix)
Checks whether a string begins with another.
Definition: strings.h:97
char * contact_user
Definition: res_pjsip.h:1037
const ast_string_field outbound_proxy
Definition: res_pjsip.h:987
const ast_string_field fromdomain
Definition: res_pjsip.h:987
const ast_string_field fromuser
Definition: res_pjsip.h:987

References ast_begins_with(), 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(), ast_sip_session_create_outgoing(), and refer_send().

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

1177{
1178#ifdef HAVE_PJSIP_DLG_CREATE_UAS_AND_INC_LOCK
1179 pjsip_dialog *dlg;
1180
1181 dlg = create_dialog_uas(endpoint, rdata, status, pjsip_dlg_create_uas_and_inc_lock);
1182 if (dlg) {
1183 pjsip_dlg_dec_lock(dlg);
1184 }
1185
1186 return dlg;
1187#else
1188 return create_dialog_uas(endpoint, rdata, status, pjsip_dlg_create_uas);
1189#endif
1190}
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:1118

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

1194{
1195#ifdef HAVE_PJSIP_DLG_CREATE_UAS_AND_INC_LOCK
1196 return create_dialog_uas(endpoint, rdata, status, pjsip_dlg_create_uas_and_inc_lock);
1197#else
1198 /*
1199 * This is put here in order to be compatible with older versions of pjproject.
1200 * Best we can do in this case is immediately lock after getting the dialog.
1201 * However, that does leave a "gap" between creating and locking.
1202 */
1203 pjsip_dialog *dlg;
1204
1205 dlg = create_dialog_uas(endpoint, rdata, status, pjsip_dlg_create_uas);
1206 if (dlg) {
1207 pjsip_dlg_inc_lock(dlg);
1208 }
1209
1210 return dlg;
1211#endif
1212 }

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

1268{
1269 return ast_sip_create_rdata_with_contact(rdata, packet, src_name, src_port, transport_type,
1270 local_name, local_port, NULL);
1271}
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:1214

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

1216{
1217 pj_str_t tmp;
1218
1219 /*
1220 * Initialize the error list in case there is a parse error
1221 * in the given packet.
1222 */
1223 pj_list_init(&rdata->msg_info.parse_err);
1224
1225 rdata->tp_info.transport = PJ_POOL_ZALLOC_T(rdata->tp_info.pool, pjsip_transport);
1226 if (!rdata->tp_info.transport) {
1227 return -1;
1228 }
1229
1230 ast_copy_string(rdata->pkt_info.packet, packet, sizeof(rdata->pkt_info.packet));
1231 ast_copy_string(rdata->pkt_info.src_name, src_name, sizeof(rdata->pkt_info.src_name));
1232 rdata->pkt_info.src_port = src_port;
1233 pj_sockaddr_parse(pj_AF_UNSPEC(), 0, pj_cstr(&tmp, src_name), &rdata->pkt_info.src_addr);
1234 pj_sockaddr_set_port(&rdata->pkt_info.src_addr, src_port);
1235
1236 pjsip_parse_rdata(packet, strlen(packet), rdata);
1237 if (!rdata->msg_info.msg || !pj_list_empty(&rdata->msg_info.parse_err)) {
1238 return -1;
1239 }
1240
1241 if (!ast_strlen_zero(contact)) {
1242 pjsip_contact_hdr *contact_hdr;
1243
1244 contact_hdr = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT, NULL);
1245 if (contact_hdr) {
1246 contact_hdr->uri = pjsip_parse_uri(rdata->tp_info.pool, (char *)contact,
1247 strlen(contact), PJSIP_PARSE_URI_AS_NAMEADDR);
1248 if (!contact_hdr->uri) {
1249 ast_log(LOG_WARNING, "Unable to parse contact URI from '%s'.\n", contact);
1250 return -1;
1251 }
1252 }
1253 }
1254
1255 pj_strdup2(rdata->tp_info.pool, &rdata->msg_info.via->recvd_param, rdata->pkt_info.src_name);
1256 rdata->msg_info.via->rport_param = -1;
1257
1258 rdata->tp_info.transport->key.type = pjsip_transport_get_type_from_name(pj_cstr(&tmp, transport_type));
1259 rdata->tp_info.transport->type_name = transport_type;
1260 pj_strdup2(rdata->tp_info.pool, &rdata->tp_info.transport->local_name.host, local_name);
1261 rdata->tp_info.transport->local_name.port = local_port;
1262
1263 return 0;
1264}
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425

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

1438{
1439 const pjsip_method *pmethod = get_pjsip_method(method);
1440
1441 if (!pmethod) {
1442 ast_log(LOG_WARNING, "Unknown method '%s'. Cannot send request\n", method);
1443 return -1;
1444 }
1445
1446 if (dlg) {
1447 return create_in_dialog_request(pmethod, dlg, tdata);
1448 } else {
1449 ast_assert(endpoint != NULL);
1450 return create_out_of_dialog_request(pmethod, endpoint, uri, contact, tdata);
1451 }
1452}
static int create_in_dialog_request(const pjsip_method *method, struct pjsip_dialog *dlg, pjsip_tx_data **tdata)
Definition: res_pjsip.c:1307
static const pjsip_method * get_pjsip_method(const char *method)
Definition: res_pjsip.c:1296
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:1325
const char * method
Definition: res_pjsip.c:1279
const pjsip_method * pmethod
Definition: res_pjsip.c:1280
#define ast_assert(a)
Definition: utils.h:739

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 aoc_send_as_xml(), 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 214 of file res_pjsip.c.

216{
218 ast_log(LOG_WARNING, "No SIP outbound authenticator registered. Cannot respond to authentication challenge\n");
219 return -1;
220 }
221 return registered_outbound_authenticator->create_request_with_auth(auths, challenge, old_request, new_request);
222}
static struct ast_sip_outbound_authenticator * registered_outbound_authenticator
Definition: res_pjsip.c:189
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:1282

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(), refer_client_on_evsub_state(), 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 2468 of file res_pjsip.c.

2470{
2471 int res = pjsip_endpt_create_response(ast_sip_get_pjsip_endpoint(), rdata, st_code, NULL, tdata);
2472
2473 if (!res) {
2474 ast_sip_mod_data_set((*tdata)->pool, (*tdata)->mod_data, supplement_module.id, MOD_DATA_CONTACT, ao2_bump(contact));
2475 }
2476
2477 return res;
2478}
#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:66
pjsip_endpoint * ast_sip_get_pjsip_endpoint(void)
Get a pointer to the PJSIP endpoint.
Definition: res_pjsip.c:520
static pjsip_module supplement_module
Definition: res_pjsip.c:1318
#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:2979

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

2328{
2329 unsigned int hval = 0;
2330
2331 if (!ht) {
2332 return NULL;
2333 }
2334
2335 return pj_hash_get(ht, key, PJ_HASH_KEY_STRING, &hval);
2336}

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

2340{
2341 if (!ht) {
2342 ht = pj_hash_create(pool, 11);
2343 }
2344
2345 pj_hash_set(pool, ht, key, PJ_HASH_KEY_STRING, 0, val);
2346
2347 return ht;
2348}
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 727 of file res_pjsip.c.

729{
730 pjsip_sip_uri *uri;
731 pjsip_tpselector sel = { .type = PJSIP_TPSELECTOR_NONE, };
732
733 uri = pjsip_uri_get_uri(dlg->target);
734 if (!selector) {
735 selector = &sel;
736 }
737
738 ast_sip_set_tpselector_from_ep_or_uri(endpoint, uri, selector);
739
740 pjsip_dlg_set_transport(dlg, selector);
741
742 if (selector == &sel) {
744 }
745
746 return 0;
747}
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:911

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

2506{
2507 switch (dtmf) {
2508 case AST_SIP_DTMF_NONE:
2509 ast_copy_string(buf, "none", buf_len);
2510 break;
2512 ast_copy_string(buf, "rfc4733", buf_len);
2513 break;
2515 ast_copy_string(buf, "inband", buf_len);
2516 break;
2517 case AST_SIP_DTMF_INFO:
2518 ast_copy_string(buf, "info", buf_len);
2519 break;
2520 case AST_SIP_DTMF_AUTO:
2521 ast_copy_string(buf, "auto", buf_len);
2522 break;
2524 ast_copy_string(buf, "auto_info", buf_len);
2525 break;
2526 default:
2527 buf[0] = '\0';
2528 return -1;
2529 }
2530 return 0;
2531}
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
@ AST_SIP_DTMF_NONE
Definition: res_pjsip.h:542
@ AST_SIP_DTMF_AUTO_INFO
Definition: res_pjsip.h:553
@ AST_SIP_DTMF_AUTO
Definition: res_pjsip.h:551
@ AST_SIP_DTMF_INBAND
Definition: res_pjsip.h:547
@ AST_SIP_DTMF_INFO
Definition: res_pjsip.h:549
@ AST_SIP_DTMF_RFC_4733
Definition: res_pjsip.h:545

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

1817{
1818 pjsip_via_hdr *via;
1819
1820 if (!tdata || !tdata->dest_info.addr.count
1821 || (tdata->dest_info.cur_addr == tdata->dest_info.addr.count - 1)) {
1822 /* No more addresses to try */
1823 return 0;
1824 }
1825
1826 /* Try next address */
1827 ++tdata->dest_info.cur_addr;
1828
1829 via = (pjsip_via_hdr*)pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA, NULL);
1830 via->branch_param.slen = 0;
1831
1832 pjsip_tx_data_invalidate_msg(tdata);
1833
1834 return 1;
1835}

References NULL, and send_request_wrapper::tdata.

Referenced by check_request_status(), and handle_registration_response().

◆ ast_sip_find_transport_state_in_use()

struct ast_sip_transport_state * ast_sip_find_transport_state_in_use ( struct ast_sip_request_transport_details details)

Returns the transport state currently in use based on request transport details.

Parameters
details
Return values
transport_state
Note
ao2_cleanup(...) or ao2_ref(..., -1) must be called on the returned object

Definition at line 595 of file res_pjsip.c.

595 {
597
599 return NULL;
600 }
601
603}
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container,...
Definition: astobj2.h:1693
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
static struct ao2_container * transport_states
static int find_transport_state_in_use(void *obj, void *arg, int flags)
Callback function for finding the transport the request is going out on.
Definition: res_pjsip.c:576
struct ao2_container * ast_sip_get_transport_states(void)
Retrieves all transport states.
Generic container type.
#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:941

References ao2_callback, ao2_cleanup, ast_sip_get_transport_states(), find_transport_state_in_use(), NULL, RAII_VAR, and transport_states.

Referenced by ast_sip_rewrite_uri_to_local(), and process_nat().

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

503{
504 int res = 0;
507 *count = 0;
509 if (i->format_ami && ((res = i->format_ami(endpoint, ami)) < 0)) {
510 return res;
511 }
512
513 if (!res) {
514 (*count)++;
515 }
516 }
517 return 0;
518}
ast_mutex_t lock
Definition: app_sla.c:331
#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:583
An entity responsible formatting endpoint information.
Definition: res_pjsip.h:3072
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:3076

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

pjsip_sip_uri * ast_sip_get_contact_sip_uri ( pjsip_tx_data *  tdata)

Return the SIP URI of the Contact header.

Parameters
tdata
Return values
Pointerto SIP URI of Contact
NULLif Contact header not found or not a SIP(S) URI
Note
Do not free the returned object.

Definition at line 564 of file res_pjsip.c.

565{
566 pjsip_contact_hdr *contact = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CONTACT, NULL);
567
568 if (!contact || (!PJSIP_URI_SCHEME_IS_SIP(contact->uri) && !PJSIP_URI_SCHEME_IS_SIPS(contact->uri))) {
569 return NULL;
570 }
571
572 return pjsip_uri_get_uri(contact->uri);
573}

References NULL.

Referenced by ast_sip_rewrite_uri_to_local(), ast_sip_set_request_transport_details(), and process_nat().

◆ ast_sip_get_endpoint()

struct ast_sip_endpoint * ast_sip_get_endpoint ( const char *  to,
int  get_default_outbound,
char **  uri 
)

Retrieves an endpoint and URI from the "to" string.

This URI is used as the Request URI.

Expects the given 'to' to be in one of the following formats: Why we allow so many is a mystery.

Basic:

 endpoint        : We'll get URI from the default aor/contact
 endpoint/aor    : We'll get the URI from the specific aor/contact
 endpoint@domain : We toss the domain part and just use the endpoint

These all use the endpoint and specified URI:

     endpoint/<sip[s]:host>
     endpoint/<sip[s]:user@host>
     endpoint/"Bob" <sip[s]:host>
     endpoint/"Bob" <sip[s]:user@host>
     endpoint/sip[s]:host
     endpoint/sip[s]:user@host
     endpoint/host
     endpoint/user@host

These all use the default endpoint and specified URI:

     <sip[s]:host>
     <sip[s]:user@host>
     "Bob" <sip[s]:host>
     "Bob" <sip[s]:user@host>
     sip[s]:host
     sip[s]:user@host

These use the default endpoint and specified host:

     host
     user@host

This form is similar to a dialstring:

     PJSIP/user@endpoint

In this case, the user will be added to the endpoint contact's URI. If the contact URI already has a user, it will be replaced.

The ones that have the sip[s] scheme are the easiest to parse. The rest all have some issue.

 endpoint vs host              : We have to test for endpoint first
 endpoint/aor vs endpoint/host : We have to test for aor first
                                 What if there's an aor with the same
                                 name as the host?
 endpoint@domain vs user@host  : We have to test for endpoint first.
                                 What if there's an endpoint with the
                                 same name as the user?
Parameters
to'To' field with possible endpoint
get_default_outboundIf nonzero, try to retrieve the default outbound endpoint if no endpoint was found. Otherwise, return NULL if no endpoint was found.
uriPointer to a char* which will be set to the URI. Always must be ast_free'd by the caller - even if the return value is NULL!
Note
The logic below could probably be condensed but then it wouldn't be as clear.

Definition at line 3249 of file res_pjsip.c.

3250{
3251 char *destination;
3252 char *slash = NULL;
3253 char *atsign = NULL;
3254 char *scheme = NULL;
3255 struct ast_sip_endpoint *endpoint = NULL;
3256
3257 destination = ast_strdupa(to);
3258
3259 slash = strchr(destination, '/');
3260 atsign = strchr(destination, '@');
3261 scheme = S_OR(strstr(destination, "sip:"), strstr(destination, "sips:"));
3262
3263 if (!slash && !atsign && !scheme) {
3264 /*
3265 * If there's only a single token, it can be either...
3266 * endpoint
3267 * host
3268 */
3269 return handle_single_token(to, destination, get_default_outbound, uri);
3270 }
3271
3272 if (slash) {
3273 /*
3274 * If there's a '/', then the form must be one of the following...
3275 * PJSIP/user@endpoint
3276 * endpoint/aor
3277 * endpoint/uri
3278 */
3279 return handle_slash(to, destination, uri, slash, atsign, scheme);
3280 }
3281
3282 if (atsign && !scheme) {
3283 /*
3284 * If there's an '@' but no scheme then it's either following an endpoint name
3285 * and being followed by a domain name (which we discard).
3286 * OR is's a user@host uri without a scheme. It's probably the latter but because
3287 * endpoint@domain looks just like user@host, we'll test for endpoint first.
3288 */
3289 return handle_atsign(to, destination, uri, slash, atsign, scheme, get_default_outbound);
3290 }
3291
3292 /*
3293 * If all else fails, we assume it's a URI or just a hostname.
3294 */
3295 if (scheme) {
3296 *uri = ast_strdup(destination);
3297 if (!(*uri)) {
3298 goto failure;
3299 }
3300 ast_debug(3, "Dest: '%s' Didn't find an endpoint but did find a scheme so using URI '%s'%s\n",
3301 to, *uri, get_default_outbound ? " with default endpoint" : "");
3302 } else {
3303 *uri = ast_malloc(strlen(destination) + strlen("sip:") + 1);
3304 if (!(*uri)) {
3305 goto failure;
3306 }
3307 sprintf(*uri, "sip:%s", destination);
3308 ast_debug(3, "Dest: '%s' Didn't find an endpoint and didn't find scheme so adding scheme and using URI '%s'%s\n",
3309 to, *uri, get_default_outbound ? " with default endpoint" : "");
3310 }
3311 if (get_default_outbound) {
3313 }
3314
3315 return endpoint;
3316
3317failure:
3318 ao2_cleanup(endpoint);
3319 *uri = NULL;
3320 return NULL;
3321}
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
#define ast_debug(level,...)
Log a DEBUG message.
static struct ast_sip_endpoint * handle_slash(const char *to, char *destination, char **uri, char *slash, char *atsign, char *scheme)
Definition: res_pjsip.c:3034
static struct ast_sip_endpoint * handle_single_token(const char *to, char *destination, int get_default_outbound, char **uri)
Definition: res_pjsip.c:2955
static struct ast_sip_endpoint * handle_atsign(const char *to, char *destination, char **uri, char *slash, char *atsign, char *scheme, int get_default_outbound)
Definition: res_pjsip.c:3191
struct ast_sip_endpoint * ast_sip_default_outbound_endpoint(void)
Retrieve the default outbound endpoint.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
An entity with which Asterisk communicates.
Definition: res_pjsip.h:958

References ao2_cleanup, ast_debug, ast_malloc, ast_sip_default_outbound_endpoint(), ast_strdup, ast_strdupa, handle_atsign(), handle_single_token(), handle_slash(), NULL, and S_OR.

Referenced by msg_send(), and refer_send().

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

2481{
2482 if (af == pj_AF_INET() && !ast_strlen_zero(host_ip_ipv4_string)) {
2483 pj_sockaddr_copy_addr(addr, &host_ip_ipv4);
2484 return 0;
2485 } else if (af == pj_AF_INET6() && !ast_strlen_zero(host_ip_ipv6_string)) {
2486 pj_sockaddr_copy_addr(addr, &host_ip_ipv6);
2487 return 0;
2488 }
2489
2490 return -1;
2491}
static pj_sockaddr host_ip_ipv4
Definition: res_pjsip.c:79
static char host_ip_ipv6_string[PJ_INET6_ADDRSTRLEN]
Definition: res_pjsip.c:88
static pj_sockaddr host_ip_ipv6
Definition: res_pjsip.c:85
static char host_ip_ipv4_string[PJ_INET6_ADDRSTRLEN]
Definition: res_pjsip.c:82

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

2494{
2495 if (af == pj_AF_INET()) {
2496 return host_ip_ipv4_string;
2497 } else if (af == pj_AF_INET6()) {
2498 return host_ip_ipv6_string;
2499 }
2500
2501 return NULL;
2502}

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

521{
522 return ast_pjsip_endpoint;
523}
static pjsip_endpoint * ast_pjsip_endpoint
Definition: res_pjsip.c:74

References ast_pjsip_endpoint.

Referenced by acl_on_rx_msg(), aoc_release_pool(), aoc_send_as_xml(), 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_send_stateful_response(), ast_sip_session_defer_termination(), ast_sip_session_resume_reinvite(), authenticate(), cancel_publish_refresh(), cancel_registration(), channel_read_pjsip(), create_out_of_dialog_request(), digest_create_request_with_auth(), distribute(), distributor(), do_cli_dump_endpt(), endpoint_lookup(), endpt_send_request(), endpt_send_request_cb(), exten_state_data_alloc(), exten_state_data_destructor(), exten_state_publisher_cb(), filter_on_tx_message(), find_registrar_aor(), insert_user_in_contact_uri(), keepalive_transport_send_keepalive(), load_module(), logging_on_rx_msg(), logging_on_tx_msg(), notify_task(), on_rx_process_uris(), options_incoming_request(), parse_uri_cb(), pool_destroy_callback(), 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(), 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 698 of file res_pjsip.c.

700{
701 char *host = NULL;
702 static const pj_str_t x_name = { AST_SIP_X_AST_TXP, AST_SIP_X_AST_TXP_LEN };
703 pjsip_param *x_transport;
704
705 if (!ast_strlen_zero(endpoint->transport)) {
706 ast_copy_string(buf, endpoint->transport, buf_len);
707 return 0;
708 }
709
710 x_transport = pjsip_param_find(&sip_uri->other_param, &x_name);
711 if (!x_transport) {
712 return -1;
713 }
714
715 /* Only use x_transport if the uri host is an ip (4 or 6) address */
716 host = ast_alloca(sip_uri->host.slen + 1);
717 ast_copy_pj_str(host, &sip_uri->host, sip_uri->host.slen + 1);
719 return -1;
720 }
721
722 ast_copy_pj_str(buf, &x_transport->value, buf_len);
723
724 return 0;
725}
#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:2201
#define AST_SIP_X_AST_TXP
Definition: res_pjsip.h:1077
#define AST_SIP_X_AST_TXP_LEN
Definition: res_pjsip.h:1078
const ast_string_field transport
Definition: res_pjsip.h:987

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

const int ast_sip_hangup_sip2cause ( int  cause)

Convert SIP hangup causes to Asterisk hangup causes.

Parameters
causeSIP cause
Return values
matchedcause code from causes.h

Definition at line 3531 of file res_pjsip.c.

3532{
3533 /* Possible values taken from causes.h */
3534
3535 switch(cause) {
3536 case 401: /* Unauthorized */
3538 case 403: /* Not found */
3540 case 404: /* Not found */
3541 return AST_CAUSE_UNALLOCATED;
3542 case 405: /* Method not allowed */
3544 case 407: /* Proxy authentication required */
3546 case 408: /* No reaction */
3548 case 409: /* Conflict */
3550 case 410: /* Gone */
3552 case 411: /* Length required */
3554 case 413: /* Request entity too large */
3556 case 414: /* Request URI too large */
3558 case 415: /* Unsupported media type */
3560 case 420: /* Bad extension */
3562 case 480: /* No answer */
3563 return AST_CAUSE_NO_ANSWER;
3564 case 481: /* No answer */
3566 case 482: /* Loop detected */
3568 case 483: /* Too many hops */
3569 return AST_CAUSE_NO_ANSWER;
3570 case 484: /* Address incomplete */
3572 case 485: /* Ambiguous */
3573 return AST_CAUSE_UNALLOCATED;
3574 case 486: /* Busy everywhere */
3575 return AST_CAUSE_BUSY;
3576 case 487: /* Request terminated */
3578 case 488: /* No codecs approved */
3580 case 491: /* Request pending */
3582 case 493: /* Undecipherable */
3584 case 500: /* Server internal failure */
3585 return AST_CAUSE_FAILURE;
3586 case 501: /* Call rejected */
3588 case 502:
3590 case 503: /* Service unavailable */
3591 return AST_CAUSE_CONGESTION;
3592 case 504: /* Gateway timeout */
3594 case 505: /* SIP version not supported */
3596 case 600: /* Busy everywhere */
3597 return AST_CAUSE_USER_BUSY;
3598 case 603: /* Decline */
3600 case 604: /* Does not exist anywhere */
3601 return AST_CAUSE_UNALLOCATED;
3602 case 606: /* Not acceptable */
3604 default:
3605 if (cause < 500 && cause >= 400) {
3606 /* 4xx class error that is unknown - someting wrong with our request */
3608 } else if (cause < 600 && cause >= 500) {
3609 /* 5xx class error - problem in the remote end */
3610 return AST_CAUSE_CONGESTION;
3611 } else if (cause < 700 && cause >= 600) {
3612 /* 6xx - global errors in the 4xx class */
3614 }
3615 return AST_CAUSE_NORMAL;
3616 }
3617 /* Never reached */
3618 return 0;
3619}
#define AST_CAUSE_CONGESTION
Definition: causes.h:153
#define AST_CAUSE_UNALLOCATED
Definition: causes.h:98
#define AST_CAUSE_INTERWORKING
Definition: causes.h:146
#define AST_CAUSE_NUMBER_CHANGED
Definition: causes.h:112
#define AST_CAUSE_BEARERCAPABILITY_NOTAVAIL
Definition: causes.h:130
#define AST_CAUSE_INVALID_NUMBER_FORMAT
Definition: causes.h:116
#define AST_CAUSE_FAILURE
Definition: causes.h:150
#define AST_CAUSE_DESTINATION_OUT_OF_ORDER
Definition: causes.h:115
#define AST_CAUSE_NO_USER_RESPONSE
Definition: causes.h:108
#define AST_CAUSE_NORMAL_TEMPORARY_FAILURE
Definition: causes.h:122
#define AST_CAUSE_NORMAL
Definition: causes.h:151
#define AST_CAUSE_CALL_REJECTED
Definition: causes.h:111
#define AST_CAUSE_FACILITY_REJECTED
Definition: causes.h:117
#define AST_CAUSE_RECOVERY_ON_TIMER_EXPIRE
Definition: causes.h:143
#define AST_CAUSE_NO_ROUTE_DESTINATION
Definition: causes.h:100
#define AST_CAUSE_BUSY
Definition: causes.h:149
#define AST_CAUSE_NO_ANSWER
Definition: causes.h:109
#define AST_CAUSE_USER_BUSY
Definition: causes.h:107

References AST_CAUSE_BEARERCAPABILITY_NOTAVAIL, AST_CAUSE_BUSY, AST_CAUSE_CALL_REJECTED, AST_CAUSE_CONGESTION, AST_CAUSE_DESTINATION_OUT_OF_ORDER, AST_CAUSE_FACILITY_REJECTED, AST_CAUSE_FAILURE, AST_CAUSE_INTERWORKING, AST_CAUSE_INVALID_NUMBER_FORMAT, AST_CAUSE_NO_ANSWER, AST_CAUSE_NO_ROUTE_DESTINATION, AST_CAUSE_NO_USER_RESPONSE, AST_CAUSE_NORMAL, AST_CAUSE_NORMAL_TEMPORARY_FAILURE, AST_CAUSE_NUMBER_CHANGED, AST_CAUSE_RECOVERY_ON_TIMER_EXPIRE, AST_CAUSE_UNALLOCATED, and AST_CAUSE_USER_BUSY.

Referenced by chan_pjsip_incoming_response_update_cause(), chan_pjsip_session_end(), and rfc3326_use_reason_header().

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

331{
332 struct endpoint_identifier_list *iter;
333 struct ast_sip_endpoint *endpoint = NULL;
337 endpoint = iter->identifier->identify_endpoint(rdata);
338 if (endpoint) {
339 break;
340 }
341 }
342 return endpoint;
343}
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:1294
struct ast_sip_endpoint_identifier * identifier
Definition: res_pjsip.c:227

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

int ast_sip_is_allowed_uri ( pjsip_uri *  uri)

Check whether a pjsip_uri is allowed or not.

Since
16.28.0
Parameters
uriThe pjsip_uri to check
Return values
1if allowed
0if not allowed

Definition at line 3472 of file res_pjsip.c.

3473{
3474 return (ast_sip_is_uri_sip_sips(uri) || PJSIP_URI_SCHEME_IS_TEL(uri));
3475}
int ast_sip_is_uri_sip_sips(pjsip_uri *uri)
Check whether a pjsip_uri is SIP/SIPS or not.
Definition: res_pjsip.c:3467

References ast_sip_is_uri_sip_sips().

Referenced by endpoint_lookup(), get_destination(), on_rx_process_uris(), options_on_rx_request(), rx_data_to_ast_msg(), and set_redirecting_reason_by_cause().

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

2249{
2250 pjsip_media_type compare;
2251
2252 if (!content_type) {
2253 return 0;
2254 }
2255
2256 pjsip_media_type_init2(&compare, type, subtype);
2257
2258 return pjsip_media_type_cmp(content_type, &compare, 0) ? 0 : -1;
2259}
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 2228 of file res_pjsip.c.

2229{
2230 int rc = 0;
2231 pjsip_media_type *b = NULL;
2232 va_list ap;
2233
2234 ast_assert(a != NULL);
2235 va_start(ap, a);
2236
2237 while ((b = va_arg(ap, pjsip_media_type *)) != (pjsip_media_type *)SENTINEL) {
2238 if (pjsip_media_type_cmp(a, b, 0) == 0) {
2239 rc = 1;
2240 break;
2241 }
2242 }
2243 va_end(ap);
2244
2245 return rc;
2246}
#define SENTINEL
Definition: compiler.h:87

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

Referenced by check_content_disposition().

◆ ast_sip_is_uri_sip_sips()

int ast_sip_is_uri_sip_sips ( pjsip_uri *  uri)

Check whether a pjsip_uri is SIP/SIPS or not.

Since
16.28.0
Parameters
uriThe pjsip_uri to check
Return values
1if true
0if false

Definition at line 3467 of file res_pjsip.c.

3468{
3469 return (PJSIP_URI_SCHEME_IS_SIP(uri) || PJSIP_URI_SCHEME_IS_SIPS(uri));
3470}

Referenced by ast_sip_is_allowed_uri(), ast_sip_pjsip_uri_get_hostname(), ast_sip_pjsip_uri_get_other_param(), ast_sip_pjsip_uri_get_username(), filter_on_tx_message(), get_endpoint_details(), get_from_header(), publish_request_initial(), pubsub_on_rx_subscribe_request(), and sanitize_tdata().

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

2851{
2852 pjsip_name_addr *id_name_addr;
2853 pjsip_sip_uri *id_uri;
2854
2855 id_name_addr = (pjsip_name_addr *) id_hdr->uri;
2856 id_uri = pjsip_uri_get_uri(id_name_addr->uri);
2857
2858 if (id->name.valid) {
2859 if (!ast_strlen_zero(id->name.str)) {
2860 int name_buf_len = strlen(id->name.str) * 2 + 1;
2861 char *name_buf = ast_alloca(name_buf_len);
2862
2863 ast_escape_quoted(id->name.str, name_buf, name_buf_len);
2864 pj_strdup2(pool, &id_name_addr->display, name_buf);
2865 } else {
2866 pj_strdup2(pool, &id_name_addr->display, NULL);
2867 }
2868 }
2869
2870 if (id->number.valid) {
2871 pj_strdup2(pool, &id_uri->user, id->number.str);
2872 }
2873}
enum queue_result id
Definition: app_queue.c:1638
char * ast_escape_quoted(const char *string, char *outbuf, int buflen)
Escape characters found in a quoted string.
Definition: 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_pjsip_uri_get_hostname()

const pj_str_t * ast_sip_pjsip_uri_get_hostname ( pjsip_uri *  uri)

Get the host portion of the pjsip_uri.

Since
16.28.0
Parameters
uriThe pjsip_uri to get the host from
Note
This function will check what kind of URI it receives and return the host based off of that
Returns
Host string or empty string if not present

Definition at line 3496 of file res_pjsip.c.

3497{
3498 if (ast_sip_is_uri_sip_sips(uri)) {
3499 pjsip_sip_uri *sip_uri = pjsip_uri_get_uri(uri);
3500 if (!sip_uri) {
3501 return &AST_PJ_STR_EMPTY;
3502 }
3503 return &sip_uri->host;
3504 } else if (PJSIP_URI_SCHEME_IS_TEL(uri)) {
3505 return &AST_PJ_STR_EMPTY;
3506 }
3507
3508 return &AST_PJ_STR_EMPTY;
3509}
static const pj_str_t AST_PJ_STR_EMPTY
Definition: res_pjsip.h:111

References AST_PJ_STR_EMPTY, and ast_sip_is_uri_sip_sips().

Referenced by dialog_info_generate_body_content(), find_aor2(), get_endpoint_details(), get_from_header(), and set_sipdomain_variable().

◆ ast_sip_pjsip_uri_get_other_param()

struct pjsip_param * ast_sip_pjsip_uri_get_other_param ( pjsip_uri *  uri,
const pj_str_t *  param_str 
)

Find an 'other' SIP/SIPS URI parameter by name.

Since
16.28.0

A convenience function to find a named parameter from a SIP/SIPS URI. This function will not find the following standard SIP/SIPS URI parameters which are stored separately by PJSIP:

  • user
  • method
  • transport
  • ttl
  • lr
  • maddr
Parameters
uriThe pjsip_uri to get the parameter from
param_strThe name of the parameter to find
Note
This function will check what kind of URI it receives and return the parameter based off of that
Returns
Find parameter or NULL if not present

Definition at line 3511 of file res_pjsip.c.

3512{
3513 if (ast_sip_is_uri_sip_sips(uri)) {
3514 pjsip_sip_uri *sip_uri = pjsip_uri_get_uri(uri);
3515 if (!sip_uri) {
3516 return NULL;
3517 }
3518 return pjsip_param_find(&sip_uri->other_param, param_str);
3519 } else if (PJSIP_URI_SCHEME_IS_TEL(uri)) {
3520 pjsip_tel_uri *tel_uri = pjsip_uri_get_uri(uri);
3521 if (!tel_uri) {
3522 return NULL;
3523 }
3524 return pjsip_param_find(&tel_uri->other_param, param_str);
3525 }
3526
3527 return NULL;
3528}

References ast_sip_is_uri_sip_sips(), and NULL.

Referenced by get_uri_option_line(), and set_redirecting_reason_by_cause().

◆ ast_sip_pjsip_uri_get_username()

const pj_str_t * ast_sip_pjsip_uri_get_username ( pjsip_uri *  uri)

Get the user portion of the pjsip_uri.

Since
16.28.0
Parameters
uriThe pjsip_uri to get the user from
Note
This function will check what kind of URI it receives and return the user based off of that
Returns
User string or empty string if not present

Definition at line 3477 of file res_pjsip.c.

3478{
3479 if (ast_sip_is_uri_sip_sips(uri)) {
3480 pjsip_sip_uri *sip_uri = pjsip_uri_get_uri(uri);
3481 if (!sip_uri) {
3482 return &AST_PJ_STR_EMPTY;
3483 }
3484 return &sip_uri->user;
3485 } else if (PJSIP_URI_SCHEME_IS_TEL(uri)) {
3486 pjsip_tel_uri *tel_uri = pjsip_uri_get_uri(uri);
3487 if (!tel_uri) {
3488 return &AST_PJ_STR_EMPTY;
3489 }
3490 return &tel_uri->number;
3491 }
3492
3493 return &AST_PJ_STR_EMPTY;
3494}

References AST_PJ_STR_EMPTY, and ast_sip_is_uri_sip_sips().

Referenced by add_diversion_header(), endpoint_lookup(), find_aor2(), get_destination(), get_from_header(), options_on_rx_request(), publish_request_initial(), pubsub_on_rx_subscribe_request(), rx_data_to_ast_msg(), set_id_from_hdr(), and sub_persistence_recreate().

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

2138{
2139 /* This method is an onion */
2140 struct sync_task_data std;
2141
2142 memset(&std, 0, sizeof(std));
2143 ast_mutex_init(&std.lock);
2144 ast_cond_init(&std.cond, NULL);
2145 std.task = sip_task;
2146 std.task_data = task_data;
2147
2149 ast_mutex_destroy(&std.lock);
2150 ast_cond_destroy(&std.cond);
2151 return -1;
2152 }
2153
2154 ast_mutex_lock(&std.lock);
2155 while (!std.complete) {
2156 ast_cond_wait(&std.cond, &std.lock);
2157 }
2158 ast_mutex_unlock(&std.lock);
2159
2160 ast_mutex_destroy(&std.lock);
2161 ast_cond_destroy(&std.cond);
2162 return std.fail;
2163}
int ast_sip_push_task(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Pushes a task to SIP servants.
Definition: res_pjsip.c:2099
#define ast_cond_destroy(cond)
Definition: lock.h:202
#define ast_cond_wait(cond, mutex)
Definition: lock.h:205
#define ast_cond_init(cond, attr)
Definition: lock.h:201
#define ast_mutex_init(pmutex)
Definition: lock.h:186
#define ast_mutex_unlock(a)
Definition: lock.h:190
#define ast_mutex_destroy(a)
Definition: lock.h:188
#define ast_mutex_lock(a)
Definition: lock.h:189
static int sync_task(void *data)
Definition: res_pjsip.c:2117
void * task_data
Definition: stasis.c:1279

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

346{
347 pjsip_generic_string_hdr *hdr;
348 pj_str_t hdr_val;
349
350 hdr = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &str, NULL);
351 if (!hdr) {
352 return NULL;
353 }
354
355 pj_strdup_with_null(rdata->tp_info.pool, &hdr_val, &hdr->hvalue);
356
357 return hdr_val.ptr;
358}
const char * str
Definition: app_jack.c:147

References NULL, and str.

Referenced by 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 140 of file res_pjsip.c.

141{
143 ast_log(LOG_WARNING, "Authenticator %p is already registered. Cannot register a new one\n", registered_authenticator);
144 return -1;
145 }
147 ast_debug(1, "Registered SIP authenticator module %p\n", auth);
148
149 return 0;
150}

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

482{
485}
#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 310 of file res_pjsip.c.

311{
313}
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:233

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

235{
236 char *prev, *current, *identifier_order;
237 struct endpoint_identifier_list *iter, *id_list_item;
239
240 id_list_item = ast_calloc(1, sizeof(*id_list_item));
241 if (!id_list_item) {
242 ast_log(LOG_ERROR, "Unable to add endpoint identifier. Out of memory.\n");
243 return -1;
244 }
245 id_list_item->identifier = identifier;
246 id_list_item->name = name;
247
248 ast_debug(1, "Register endpoint identifier %s(%p)\n", name ?: "", identifier);
249
250 if (ast_strlen_zero(name)) {
251 /* if an identifier has no name then place in front */
252 AST_RWLIST_INSERT_HEAD(&endpoint_identifiers, id_list_item, list);
253 return 0;
254 }
255
256 /* see if the name of the identifier is in the global endpoint_identifier_order list */
257 identifier_order = prev = current = ast_sip_get_endpoint_identifier_order();
258
259 if (ast_strlen_zero(identifier_order)) {
260 id_list_item->priority = UINT_MAX;
261 AST_RWLIST_INSERT_TAIL(&endpoint_identifiers, id_list_item, list);
262 ast_free(identifier_order);
263 return 0;
264 }
265
266 id_list_item->priority = 0;
267 while ((current = strchr(current, ','))) {
268 ++id_list_item->priority;
269 if (!strncmp(prev, name, current - prev)
270 && strlen(name) == current - prev) {
271 break;
272 }
273 prev = ++current;
274 }
275
276 if (!current) {
277 /* check to see if it is the only or last item */
278 if (!strcmp(prev, name)) {
279 ++id_list_item->priority;
280 } else {
281 id_list_item->priority = UINT_MAX;
282 }
283 }
284
285 if (id_list_item->priority == UINT_MAX || AST_RWLIST_EMPTY(&endpoint_identifiers)) {
286 /* if not in the endpoint_identifier_order list then consider it less in
287 priority and add it to the end */
288 AST_RWLIST_INSERT_TAIL(&endpoint_identifiers, id_list_item, list);
289 ast_free(identifier_order);
290 return 0;
291 }
292
294 if (id_list_item->priority < iter->priority) {
295 AST_RWLIST_INSERT_BEFORE_CURRENT(id_list_item, list);
296 break;
297 }
298
299 if (!AST_RWLIST_NEXT(iter, list)) {
300 AST_RWLIST_INSERT_AFTER(&endpoint_identifiers, iter, id_list_item, list);
301 break;
302 }
303 }
305
306 ast_free(identifier_order);
307 return 0;
308}
#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:226

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

192{
194 ast_log(LOG_WARNING, "Outbound authenticator %p is already registered. Cannot register a new one\n", registered_outbound_authenticator);
195 return -1;
196 }
198 ast_debug(1, "Registered SIP outbound authenticator module %p\n", auth);
199
200 return 0;
201}

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

118{
120}
int ast_sip_push_task_wait_servant(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Push a task to SIP servants and wait for it to complete.
Definition: res_pjsip.c:2165
static int register_service(void *data)
Definition: res_pjsip.c:102

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

1457{
1458 struct ast_sip_supplement *iter;
1459 int inserted = 0;
1461
1463 if (iter->priority > supplement->priority) {
1465 inserted = 1;
1466 break;
1467 }
1468 }
1470
1471 if (!inserted) {
1473 }
1474}
A supplement to SIP message processing.
Definition: res_pjsip.h:3197
enum ast_sip_supplement_priority priority
Definition: res_pjsip.h:3201
struct ast_sip_supplement * next
Definition: res_pjsip.h:3247

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

164{
166 && !pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_options_method)) {
167 ast_debug(3, "Skipping OPTIONS authentication due to endpoint configuration\n");
168 return 0;
169 }
170
172 ast_log(LOG_WARNING, "No SIP authenticator registered. Assuming authentication is not required\n");
173 return 0;
174 }
175
176 return registered_authenticator->requires_authentication(endpoint, rdata);
177}
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:1251
unsigned int allow_unauthenticated_options
Definition: res_pjsip.h:1059

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

int ast_sip_rewrite_uri_to_local ( pjsip_sip_uri *  uri,
pjsip_tx_data *  tdata 
)

Replace domain and port of SIP URI to point to (external) signaling address of this Asterisk instance.

Parameters
uri
tdata
Return values
0success
-1failure
Note
Uses domain and port in Contact header if it exists, otherwise the local URI of the dialog is used if the message is sent within the context of a dialog. Further, NAT settings are considered - i.e. if the target is not in the localnet, the external_signaling_address and port are used.

Definition at line 605 of file res_pjsip.c.

605 {
606 RAII_VAR(struct ast_sip_transport *, transport, NULL, ao2_cleanup);
607 RAII_VAR(struct ast_sip_transport_state *, transport_state, NULL, ao2_cleanup);
608 struct ast_sip_request_transport_details details = { 0, };
609 pjsip_sip_uri *tmp_uri;
610 pjsip_dialog *dlg;
611 struct ast_sockaddr addr = { { 0, } };
612
613 if ((tmp_uri = ast_sip_get_contact_sip_uri(tdata))) {
614 pj_strdup(tdata->pool, &uri->host, &tmp_uri->host);
615 uri->port = tmp_uri->port;
616 } else if ((dlg = pjsip_tdata_get_dlg(tdata))
617 && (tmp_uri = pjsip_uri_get_uri(dlg->local.info->uri))
618 && (PJSIP_URI_SCHEME_IS_SIP(tmp_uri) || PJSIP_URI_SCHEME_IS_SIPS(tmp_uri))) {
619 pj_strdup(tdata->pool, &uri->host, &tmp_uri->host);
620 uri->port = tmp_uri->port;
621 }
622
623 if (ast_sip_set_request_transport_details(&details, tdata, 1)
624 || !(transport_state = ast_sip_find_transport_state_in_use(&details))
625 || !(transport = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "transport", transport_state->id))) {
626 return 0;
627 }
628
629 if (transport_state->localnet) {
630 ast_sockaddr_parse(&addr, tdata->tp_info.dst_name, PARSE_PORT_FORBID);
631 ast_sockaddr_set_port(&addr, tdata->tp_info.dst_port);
632 if (ast_sip_transport_is_local(transport_state, &addr)) {
633 return 0;
634 }
635 }
636
637 if (!ast_sockaddr_isnull(&transport_state->external_signaling_address)) {
638 pj_strdup2(tdata->pool, &uri->host, ast_sockaddr_stringify_host(&transport_state->external_signaling_address));
639 }
640
641 if (transport->external_signaling_port) {
642 uri->port = transport->external_signaling_port;
643 }
644
645 return 0;
646}
static char * ast_sockaddr_stringify_host(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() to return an address only, suitable for a URL (with brack...
Definition: netsock2.h:327
static int ast_sockaddr_isnull(const struct ast_sockaddr *addr)
Checks if the ast_sockaddr is null. "null" in this sense essentially means uninitialized,...
Definition: netsock2.h:127
#define ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
Definition: netsock2.h:532
struct ast_sip_transport_state * ast_sip_find_transport_state_in_use(struct ast_sip_request_transport_details *details)
Returns the transport state currently in use based on request transport details.
Definition: res_pjsip.c:595
int ast_sip_set_request_transport_details(struct ast_sip_request_transport_details *details, pjsip_tx_data *tdata, int use_ipv6)
Sets request transport details based on tdata.
Definition: res_pjsip.c:648
pjsip_sip_uri * ast_sip_get_contact_sip_uri(pjsip_tx_data *tdata)
Return the SIP URI of the Contact header.
Definition: res_pjsip.c:564
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
#define ast_sip_transport_is_local(transport_state, addr)
Definition: res_pjsip.h:212
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
Structure which contains information about a transport.
Definition: res_pjsip.h:334
Structure for SIP transport information.
Definition: res_pjsip.h:116
Transport to bind to.
Definition: res_pjsip.h:218
Socket address structure.
Definition: netsock2.h:97

References ao2_cleanup, ast_sip_find_transport_state_in_use(), ast_sip_get_contact_sip_uri(), ast_sip_get_sorcery(), ast_sip_set_request_transport_details(), ast_sip_transport_is_local, ast_sockaddr_isnull(), ast_sockaddr_parse(), ast_sockaddr_set_port, ast_sockaddr_stringify_host(), ast_sorcery_retrieve_by_id(), NULL, PARSE_PORT_FORBID, RAII_VAR, and ast_sip_transport_state::transport.

Referenced by refer_on_tx_request().

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

1941{
1942 struct ast_sip_supplement *supplement;
1943 struct send_request_data *req_data;
1944 struct ast_sip_contact *contact;
1945
1946 req_data = send_request_data_alloc(endpoint, token, callback);
1947 if (!req_data) {
1948 pjsip_tx_data_dec_ref(tdata);
1949 return -1;
1950 }
1951
1952 if (endpoint) {
1954 }
1955
1956 contact = ast_sip_mod_data_get(tdata->mod_data, supplement_module.id, MOD_DATA_CONTACT);
1957
1959 AST_LIST_TRAVERSE(&supplements, supplement, next) {
1960 if (supplement->outgoing_request
1961 && does_method_match(&tdata->msg->line.req.method.name, supplement->method)) {
1962 supplement->outgoing_request(endpoint, contact, tdata);
1963 }
1964 }
1966
1967 ast_sip_mod_data_set(tdata->pool, tdata->mod_data, supplement_module.id, MOD_DATA_CONTACT, NULL);
1968 ao2_cleanup(contact);
1969
1970 if (endpt_send_request(endpoint, tdata, timeout, req_data, send_request_cb)
1971 != PJ_SUCCESS) {
1972 ao2_cleanup(req_data);
1973 return -1;
1974 }
1975
1976 return 0;
1977}
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
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:1534
static void send_request_cb(void *token, pjsip_event *e)
Definition: res_pjsip.c:1882
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:1696
static pj_bool_t does_method_match(const pj_str_t *message_method, const char *supplement_method)
Definition: res_pjsip.c:1499
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:2947
Contact associated with an address of record.
Definition: res_pjsip.h:389
struct ast_sip_endpoint * endpoint
Definition: res_pjsip.h:421
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:3240
const char * method
Definition: res_pjsip.h:3199
Structure to hold information about an outbound request.
Definition: res_pjsip.c:1516

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

1982{
1983 ast_assert(tdata->msg->type == PJSIP_REQUEST_MSG);
1984
1985 if (dlg) {
1986 return send_in_dialog_request(tdata, dlg);
1987 } else {
1988 return ast_sip_send_out_of_dialog_request(tdata, endpoint, -1, token, callback);
1989 }
1990}
static int send_in_dialog_request(pjsip_tx_data *tdata, struct pjsip_dialog *dlg)
Definition: res_pjsip.c:1490
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:1938

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(), refer_client_on_evsub_state(), 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 2396 of file res_pjsip.c.

2397{
2398 pj_status_t status;
2399
2400 supplement_outgoing_response(tdata, sip_endpoint);
2401 status = pjsip_endpt_send_response(ast_sip_get_pjsip_endpoint(), res_addr, tdata, NULL, NULL);
2402 if (status != PJ_SUCCESS) {
2403 pjsip_tx_data_dec_ref(tdata);
2404 }
2405
2406 return status == PJ_SUCCESS ? 0 : -1;
2407}
static void supplement_outgoing_response(pjsip_tx_data *tdata, struct ast_sip_endpoint *sip_endpoint)
Definition: res_pjsip.c:2374

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

2425{
2426 pjsip_transaction *tsx;
2427 pj_grp_lock_t *tsx_glock;
2428 pj_pool_t *pool;
2429
2430 /* Create and initialize global lock pool */
2431 pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(), "stateful response", PJSIP_POOL_TSX_LEN, PJSIP_POOL_TSX_INC);
2432 if (!pool){
2433 /* ast_sip_create_response bumps the refcount of the contact and adds it to the tdata.
2434 * We'll leak that reference if we don't get rid of it here.
2435 */
2437 return -1;
2438 }
2439 /* Create with handler so that we can release the pool once the glock derefs out */
2440 if(pj_grp_lock_create_w_handler(pool, NULL, pool, &pool_destroy_callback, &tsx_glock) != PJ_SUCCESS) {
2442 pool_destroy_callback((void *) pool);
2443 return -1;
2444 }
2445 /* We need an additional reference as the qualify thread may destroy this out
2446 * from under us. Add it now before it gets added to the tsx. */
2447 pj_grp_lock_add_ref(tsx_glock);
2448
2449 if (pjsip_tsx_create_uas2(NULL, rdata, tsx_glock, &tsx) != PJ_SUCCESS) {
2451 pj_grp_lock_dec_ref(tsx_glock);
2452 return -1;
2453 }
2454
2455 pjsip_tsx_recv_msg(tsx, rdata);
2456 supplement_outgoing_response(tdata, sip_endpoint);
2457
2458 if (pjsip_tsx_send_msg(tsx, tdata) != PJ_SUCCESS) {
2459 pj_grp_lock_dec_ref(tsx_glock);
2460 pjsip_tx_data_dec_ref(tdata);
2461 return -1;
2462 }
2463
2464 pj_grp_lock_dec_ref(tsx_glock);
2465 return 0;
2466}
static void clean_contact_from_tdata(pjsip_tx_data *tdata)
Definition: res_pjsip.c:2415
static void pool_destroy_callback(void *arg)
Definition: res_pjsip.c:2409

References ast_sip_get_pjsip_endpoint(), clean_contact_from_tdata(), NULL, pool_destroy_callback(), and supplement_outgoing_response().

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

◆ ast_sip_set_id_connected_line()

int ast_sip_set_id_connected_line ( struct pjsip_rx_data *  rdata,
struct ast_party_id id 
)

Set the ID for a connected line update.

Return values
-1on failure, 0 on success

Definition at line 2822 of file res_pjsip.c.

2823{
2824 return !set_id_from_pai(rdata, id) || !set_id_from_rpid(rdata, id) ? 0 : -1;
2825}
static int set_id_from_pai(pjsip_rx_data *rdata, struct ast_party_id *id)
Definition: res_pjsip.c:2710
static int set_id_from_rpid(pjsip_rx_data *rdata, struct ast_party_id *id)
Definition: res_pjsip.c:2751

References set_id_from_pai(), and set_id_from_rpid().

Referenced by update_incoming_connected_line().

◆ ast_sip_set_id_from_invite()

int ast_sip_set_id_from_invite ( struct pjsip_rx_data *  rdata,
struct ast_party_id id,
struct ast_party_id default_id,
int  trust_inbound 
)

Set the ID from an INVITE.

Parameters
rdata
idID structure to fill
default_idDefault ID structure with data to use (for non-trusted endpoints)
trust_inboundWhether or not the endpoint is trusted (controls whether PAI or RPID can be used)
Return values
-1on failure, 0 on success

Definition at line 2827 of file res_pjsip.c.

2828{
2829 if (trust_inbound && (!set_id_from_pai(rdata, id) || !set_id_from_rpid(rdata, id))) {
2830 /* Trusted: Check PAI and RPID */
2831 ast_free(id->tag);
2832 id->tag = ast_strdup(default_id->tag);
2833 return 0;
2834 }
2835 /* Not trusted: check the endpoint config or use From. */
2836 ast_party_id_copy(id, default_id);
2837 if (!default_id->number.valid) {
2838 set_id_from_from(rdata, id);
2839 }
2840 return 0;
2841}
void ast_party_id_copy(struct ast_party_id *dest, const struct ast_party_id *src)
Copy the source party id information to the destination party id.
Definition: channel.c:1784
static int set_id_from_from(struct pjsip_rx_data *rdata, struct ast_party_id *id)
Definition: res_pjsip.c:2803
char * tag
User-set "tag".
Definition: channel.h:356
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:344
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:299

References ast_free, ast_party_id_copy(), ast_strdup, id, ast_party_id::number, set_id_from_from(), set_id_from_pai(), set_id_from_rpid(), ast_party_id::tag, and ast_party_number::valid.

Referenced by caller_id_incoming_request(), and fetch_callerid_num().

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

1993{
1994 pjsip_route_hdr *route;
1995 static const pj_str_t ROUTE_HNAME = { "Route", 5 };
1996 pj_str_t tmp;
1997
1998 pj_strdup2_with_null(tdata->pool, &tmp, proxy);
1999 if (!(route = pjsip_parse_hdr(tdata->pool, &ROUTE_HNAME, tmp.ptr, tmp.slen, NULL))) {
2000 return -1;
2001 }
2002
2003 pj_list_insert_nodes_before(&tdata->msg->hdr, (pjsip_hdr*)route);
2004
2005 return 0;
2006}

References NULL, and tmp().

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

◆ ast_sip_set_request_transport_details()

int ast_sip_set_request_transport_details ( struct ast_sip_request_transport_details details,
pjsip_tx_data *  tdata,
int  use_ipv6 
)

Sets request transport details based on tdata.

Parameters
detailspre-allocated request transport details to set
tdata
use_ipv6if non-zero, ipv6 transports will be considered
Return values
0success
-1failure

Definition at line 648 of file res_pjsip.c.

649 {
650 pjsip_sip_uri *uri;
651 pjsip_via_hdr *via;
652 long transport_type;
653
654 if (!details || !tdata) {
655 return -1;
656 }
657
658 /* If IPv6 should be considered, un-set Bit 7 to make TCP6 equal to TCP and TLS6 equal to TLS */
659 transport_type = use_ipv6 ? tdata->tp_info.transport->key.type & ~(PJSIP_TRANSPORT_IPV6)
660 : tdata->tp_info.transport->key.type;
661
662 if (tdata->tp_sel.type == PJSIP_TPSELECTOR_TRANSPORT) {
663 details->transport = tdata->tp_sel.u.transport;
664 } else if (tdata->tp_sel.type == PJSIP_TPSELECTOR_LISTENER) {
665 details->factory = tdata->tp_sel.u.listener;
666 } else if (transport_type == PJSIP_TRANSPORT_UDP || transport_type == PJSIP_TRANSPORT_UDP6) {
667 /* Connectionless uses the same transport for all requests */
668 details->type = AST_TRANSPORT_UDP;
669 details->transport = tdata->tp_info.transport;
670 } else {
671 if (transport_type == PJSIP_TRANSPORT_TCP) {
672 details->type = AST_TRANSPORT_TCP;
673 } else if (transport_type == PJSIP_TRANSPORT_TLS) {
674 details->type = AST_TRANSPORT_TLS;
675 } else {
676 /* Unknown transport type, we can't map. */
677 return -1;
678 }
679
680 if ((uri = ast_sip_get_contact_sip_uri(tdata))) {
681 details->local_address = uri->host;
682 details->local_port = uri->port;
683 } else if ((tdata->msg->type == PJSIP_REQUEST_MSG) &&
684 (via = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA, NULL))) {
685 details->local_address = via->sent_by.host;
686 details->local_port = via->sent_by.port;
687 } else {
688 return -1;
689 }
690
691 if (!details->local_port) {
692 details->local_port = (details->type == AST_TRANSPORT_TLS) ? 5061 : 5060;
693 }
694 }
695 return 0;
696}
if(!yyg->yy_init)
Definition: ast_expr2f.c:854
@ AST_TRANSPORT_UDP
Definition: netsock2.h:60
@ AST_TRANSPORT_TLS
Definition: netsock2.h:62
@ AST_TRANSPORT_TCP
Definition: netsock2.h:61
int local_port
Local port for transport.
Definition: res_pjsip.h:344
pjsip_transport * transport
Potential pointer to the transport itself, if UDP.
Definition: res_pjsip.h:338
enum ast_transport type
Type of transport.
Definition: res_pjsip.h:336
pjsip_tpfactory * factory
Potential pointer to the transport factory itself, if TCP/TLS.
Definition: res_pjsip.h:340
pj_str_t local_address
Local address for transport.
Definition: res_pjsip.h:342

References ast_sip_get_contact_sip_uri(), AST_TRANSPORT_TCP, AST_TRANSPORT_TLS, AST_TRANSPORT_UDP, ast_sip_request_transport_details::factory, if(), ast_sip_request_transport_details::local_address, ast_sip_request_transport_details::local_port, NULL, ast_sip_request_transport_details::transport, and ast_sip_request_transport_details::type.

Referenced by ast_sip_rewrite_uri_to_local(), and process_nat().

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

913{
914 char transport_name[128];
915
916 if (ast_sip_get_transport_name(endpoint, sip_uri, transport_name, sizeof(transport_name))) {
917 return 0;
918 }
919
920 return ast_sip_set_tpselector_from_transport_name(transport_name, selector);
921}
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:698
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:893

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

844{
845 int res = 0;
846 struct ast_sip_transport_state *transport_state;
847
849 if (!transport_state) {
850 ast_log(LOG_ERROR, "Unable to retrieve PJSIP transport state for '%s'\n",
852 return -1;
853 }
854
855 /* Only flows maintain dynamic state which needs protection */
856 if (transport_state->flow) {
857 ao2_lock(transport_state);
858 }
859
860 if (transport_state->transport) {
861 selector->type = PJSIP_TPSELECTOR_TRANSPORT;
862 selector->u.transport = transport_state->transport;
863 pjsip_transport_add_ref(selector->u.transport);
864 } else if (transport_state->factory) {
865 selector->type = PJSIP_TPSELECTOR_LISTENER;
866 selector->u.listener = transport_state->factory;
867 } else if (transport->type == AST_TRANSPORT_WS || transport->type == AST_TRANSPORT_WSS) {
868 /* The WebSocket transport has no factory as it can not create outgoing connections, so
869 * even if an endpoint is locked to a WebSocket transport we let the PJSIP logic
870 * find the existing connection if available and use it.
871 */
872 } else if (transport->flow) {
873 /* This is a child of another transport, so we need to establish a new connection */
874#ifdef HAVE_PJSIP_TRANSPORT_DISABLE_CONNECTION_REUSE
875 selector->disable_connection_reuse = PJ_TRUE;
876#else
877 ast_log(LOG_WARNING, "Connection reuse could not be disabled on transport '%s' as support is not available\n",
879#endif
880 } else {
881 res = -1;
882 }
883
884 if (transport_state->flow) {
885 ao2_unlock(transport_state);
886 }
887
888 ao2_ref(transport_state, -1);
889
890 return res;
891}
#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.
struct pjsip_tpfactory * factory
Transport factory.
Definition: res_pjsip.h:120
struct pjsip_transport * transport
Transport itself.
Definition: res_pjsip.h:118

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

894{
895 RAII_VAR(struct ast_sip_transport *, transport, NULL, ao2_cleanup);
896
897 if (ast_strlen_zero(transport_name)) {
898 return 0;
899 }
900
901 transport = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "transport", transport_name);
902 if (!transport) {
903 ast_log(LOG_ERROR, "Unable to retrieve PJSIP transport '%s'\n",
904 transport_name);
905 return -1;
906 }
907
908 return ast_sip_set_tpselector_from_transport(transport, selector);
909}
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:843

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

int ast_sip_str2rc ( const char *  name)

Convert name to SIP response code.

Parameters
nameSIP response code name matching one of the enum names defined in "enum pjsip_status_code" defined in sip_msg.h. May be specified with or without the PJSIP_SC_ prefix.
Return values
SIPresponse code
-1if matching code not found

Definition at line 3714 of file res_pjsip.c.

3715{
3716 int i;
3717
3718 if (ast_strlen_zero(name)) {
3719 return -1;
3720 }
3721
3722 for (i = 0; i < ARRAY_LEN(rc_map); i++) {
3723 if (strcasecmp(rc_map[i].short_name, name) == 0 ||
3724 strcasecmp(rc_map[i].long_name, name) == 0) {
3725 return rc_map[i].code;
3726 }
3727 }
3728
3729 return -1;
3730}
static const struct response_code_map rc_map[]
Definition: res_pjsip.c:3634
#define ARRAY_LEN(a)
Definition: utils.h:666

References ARRAY_LEN, ast_strlen_zero(), response_code_map::code, response_code_map::long_name, name, rc_map, and response_code_map::short_name.

Referenced by response_code_validator().

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

2534{
2535 int result = -1;
2536
2537 if (!strcasecmp(dtmf_mode, "info")) {
2539 } else if (!strcasecmp(dtmf_mode, "rfc4733")) {
2541 } else if (!strcasecmp(dtmf_mode, "inband")) {
2543 } else if (!strcasecmp(dtmf_mode, "none")) {
2545 } else if (!strcasecmp(dtmf_mode, "auto")) {
2547 } else if (!strcasecmp(dtmf_mode, "auto_info")) {
2549 }
2550
2551 return result;
2552}
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 3462 of file res_pjsip.c.

3463{
3464 return sip_threadpool;
3465}
static struct ast_threadpool * sip_threadpool
Definition: res_pjsip.c:76

References sip_threadpool.

Referenced by load_module().

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

3458{
3460}
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 923 of file res_pjsip.c.

924{
925 if (selector->type == PJSIP_TPSELECTOR_TRANSPORT && selector->u.transport) {
926 pjsip_transport_dec_ref(selector->u.transport);
927 }
928}

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

153{
154 if (registered_authenticator != auth) {
155 ast_log(LOG_WARNING, "Trying to unregister authenticator %p but authenticator %p registered\n",
157 return;
158 }
160 ast_debug(1, "Unregistered SIP authenticator %p\n", auth);
161}

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

Referenced by unload_module().

◆ ast_sip_unregister_endpoint_formatter()

void ast_sip_unregister_endpoint_formatter ( struct ast_sip_endpoint_formatter obj)

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

316{
317 struct endpoint_identifier_list *iter;
320 if (iter->identifier == identifier) {
322 ast_free(iter);
323 ast_debug(1, "Unregistered endpoint identifier %p\n", identifier);
324 break;
325 }
326 }
328}

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

204{
206 ast_log(LOG_WARNING, "Trying to unregister outbound authenticator %p but outbound authenticator %p registered\n",
208 return;
209 }
211 ast_debug(1, "Unregistered SIP outbound authenticator %p\n", auth);
212}

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

Referenced by unload_module().

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

134{
136}
static int unregister_service(void *data)
Definition: res_pjsip.c:122

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

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

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

1477{
1478 struct ast_sip_supplement *iter;
1480
1482 if (supplement == iter) {
1484 break;
1485 }
1486 }
1488}

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

Referenced by ast_res_pjsip_cleanup_message_filter(), and unload_module().

◆ ast_sip_update_from()

int ast_sip_update_from ( pjsip_tx_data *  tdata,
char *  from 
)

Overwrite fields in the outbound 'From' header.

The outbound 'From' header is created/added in ast_sip_create_request with default data. If available that data may be info specified in the 'from_user' and 'from_domain' options found on the endpoint. That information will be overwritten with data in the given 'from' parameter.

Parameters
tdatathe outbound message data structure
frominfo to copy into the header. Can be either a SIP URI, or in the format user[@domain]
Return values
0success, -1: failure

Definition at line 3383 of file res_pjsip.c.

3384{
3385 pjsip_name_addr *name_addr;
3386 pjsip_sip_uri *uri;
3387 pjsip_name_addr *parsed_name_addr;
3388 pjsip_from_hdr *from_hdr;
3389
3390 if (ast_strlen_zero(from)) {
3391 return 0;
3392 }
3393
3394 from_hdr = PJSIP_MSG_FROM_HDR(tdata->msg);
3395 if (!from_hdr) {
3396 return -1;
3397 }
3398 name_addr = (pjsip_name_addr *) from_hdr->uri;
3399 uri = pjsip_uri_get_uri(name_addr);
3400
3401 parsed_name_addr = (pjsip_name_addr *) pjsip_parse_uri(tdata->pool, from,
3402 strlen(from), PJSIP_PARSE_URI_AS_NAMEADDR);
3403 if (parsed_name_addr) {
3404 pjsip_sip_uri *parsed_uri;
3405
3406 if (!PJSIP_URI_SCHEME_IS_SIP(parsed_name_addr->uri)
3407 && !PJSIP_URI_SCHEME_IS_SIPS(parsed_name_addr->uri)) {
3408 ast_log(LOG_WARNING, "From address '%s' is not a valid SIP/SIPS URI\n", from);
3409 return -1;
3410 }
3411
3412 parsed_uri = pjsip_uri_get_uri(parsed_name_addr->uri);
3413
3414 if (pj_strlen(&parsed_name_addr->display)) {
3415 pj_strdup(tdata->pool, &name_addr->display, &parsed_name_addr->display);
3416 }
3417
3418 /* Unlike the To header, we only want to replace the user, host and port */
3419 pj_strdup(tdata->pool, &uri->user, &parsed_uri->user);
3420 pj_strdup(tdata->pool, &uri->host, &parsed_uri->host);
3421 uri->port = parsed_uri->port;
3422
3423 return 0;
3424 } else {
3425 /* assume it is 'user[@domain]' format */
3426 char *domain = strchr(from, '@');
3427
3428 if (domain) {
3429 pj_str_t pj_from;
3430
3431 pj_strset3(&pj_from, from, domain);
3432 pj_strdup(tdata->pool, &uri->user, &pj_from);
3433
3434 pj_strdup2(tdata->pool, &uri->host, domain + 1);
3435 } else {
3436 pj_strdup2(tdata->pool, &uri->user, from);
3437 }
3438
3439 return 0;
3440 }
3441
3442 return -1;
3443}

References ast_log, ast_strlen_zero(), and LOG_WARNING.

Referenced by msg_send(), and refer_send().

◆ ast_sip_update_to_uri()

int ast_sip_update_to_uri ( pjsip_tx_data *  tdata,
const char *  to 
)

Replace the To URI in the tdata with the supplied one.

Parameters
tdatathe outbound message data structure
toURI to replace the To URI with. Must be a valid SIP URI.
Return values
0success, -1: failure

Definition at line 3323 of file res_pjsip.c.

3324{
3325 pjsip_name_addr *parsed_name_addr;
3326 pjsip_sip_uri *sip_uri;
3327 pjsip_name_addr *tdata_name_addr;
3328 pjsip_sip_uri *tdata_sip_uri;
3329 pjsip_to_hdr *to_hdr;
3330 char *buf = NULL;
3331#define DEBUG_BUF_SIZE 256
3332
3333 parsed_name_addr = (pjsip_name_addr *) pjsip_parse_uri(tdata->pool, (char*)to, strlen(to),
3334 PJSIP_PARSE_URI_AS_NAMEADDR);
3335
3336 if (!parsed_name_addr || (!PJSIP_URI_SCHEME_IS_SIP(parsed_name_addr->uri)
3337 && !PJSIP_URI_SCHEME_IS_SIPS(parsed_name_addr->uri))) {
3338 ast_log(LOG_WARNING, "To address '%s' is not a valid SIP/SIPS URI\n", to);
3339 return -1;
3340 }
3341
3342 sip_uri = pjsip_uri_get_uri(parsed_name_addr->uri);
3343 if (DEBUG_ATLEAST(3)) {
3345 pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, sip_uri, buf, DEBUG_BUF_SIZE);
3346 ast_debug(3, "Parsed To: %.*s %s\n", (int)parsed_name_addr->display.slen,
3347 parsed_name_addr->display.ptr, buf);
3348 }
3349
3350 to_hdr = PJSIP_MSG_TO_HDR(tdata->msg);
3351 tdata_name_addr = to_hdr ? (pjsip_name_addr *) to_hdr->uri : NULL;
3352 if (!tdata_name_addr || (!PJSIP_URI_SCHEME_IS_SIP(tdata_name_addr->uri)
3353 && !PJSIP_URI_SCHEME_IS_SIPS(tdata_name_addr->uri))) {
3354 /* Highly unlikely but we have to check */
3355 ast_log(LOG_WARNING, "tdata To address '%s' is not a valid SIP/SIPS URI\n", to);
3356 return -1;
3357 }
3358
3359 tdata_sip_uri = pjsip_uri_get_uri(tdata_name_addr->uri);
3360 if (DEBUG_ATLEAST(3)) {
3361 buf[0] = '\0';
3362 pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, tdata_sip_uri, buf, DEBUG_BUF_SIZE);
3363 ast_debug(3, "Original tdata To: %.*s %s\n", (int)tdata_name_addr->display.slen,
3364 tdata_name_addr->display.ptr, buf);
3365 }
3366
3367 /* Replace the uri */
3368 pjsip_sip_uri_assign(tdata->pool, tdata_sip_uri, sip_uri);
3369 /* The display name isn't part of the URI so we need to replace it separately */
3370 pj_strdup(tdata->pool, &tdata_name_addr->display, &parsed_name_addr->display);
3371
3372 if (DEBUG_ATLEAST(3)) {
3373 buf[0] = '\0';
3374 pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, tdata_sip_uri, buf, 256);
3375 ast_debug(3, "New tdata To: %.*s %s\n", (int)tdata_name_addr->display.slen,
3376 tdata_name_addr->display.ptr, buf);
3377 }
3378
3379 return 0;
3380#undef DEBUG_BUF_SIZE
3381}
#define DEBUG_ATLEAST(level)
#define DEBUG_BUF_SIZE

References ast_alloca, ast_debug, ast_log, buf, DEBUG_ATLEAST, DEBUG_BUF_SIZE, if(), LOG_WARNING, and NULL.

Referenced by msg_send(), and refer_send().

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

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

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

1840{
1841 struct ast_sip_endpoint *endpoint;
1842 pjsip_transaction *tsx;
1843 pjsip_tx_data *tdata;
1844 int res = 0;
1845
1846 if (!(endpoint = ao2_bump(req_data->endpoint))) {
1847 return 0;
1848 }
1849
1850 tsx = e->body.tsx_state.tsx;
1851
1852 switch (tsx->status_code) {
1853 case 401:
1854 case 407:
1855 /* Resend the request with a challenge response if we are challenged. */
1856 res = ++req_data->challenge_count < MAX_RX_CHALLENGES /* Not in a challenge loop */
1858 e->body.tsx_state.src.rdata, tsx->last_tx, &tdata);
1859 break;
1860 case 408:
1861 case 503:
1862 if ((res = ast_sip_failover_request(tsx->last_tx))) {
1863 tdata = tsx->last_tx;
1864 /*
1865 * Bump the ref since it will be on a new transaction and
1866 * we don't want it to go away along with the old transaction.
1867 */
1868 pjsip_tx_data_add_ref(tdata);
1869 }
1870 break;
1871 }
1872
1873 if (res) {
1874 res = endpt_send_request(endpoint, tdata, -1,
1875 req_data, send_request_cb) == PJ_SUCCESS;
1876 }
1877
1878 ao2_ref(endpoint, -1);
1879 return res;
1880}
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:214
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:1816
#define MAX_RX_CHALLENGES
Definition: res_pjsip.h:107
struct ast_sip_auth_vector outbound_auths
Definition: res_pjsip.h:1005
struct ast_sip_endpoint * endpoint
Definition: res_pjsip.c:1518
unsigned int challenge_count
Definition: res_pjsip.c:1524

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

◆ clean_contact_from_tdata()

static void clean_contact_from_tdata ( pjsip_tx_data *  tdata)
static

Definition at line 2415 of file res_pjsip.c.

2416{
2417 struct ast_sip_contact *contact;
2418 contact = ast_sip_mod_data_get(tdata->mod_data, supplement_module.id, MOD_DATA_CONTACT);
2419 ao2_cleanup(contact);
2420 ast_sip_mod_data_set(tdata->pool, tdata->mod_data, supplement_module.id, MOD_DATA_CONTACT, NULL);
2421 pjsip_tx_data_dec_ref(tdata);
2422}

References ao2_cleanup, ast_sip_mod_data_get, ast_sip_mod_data_set, MOD_DATA_CONTACT, NULL, and supplement_module.

Referenced by ast_sip_send_stateful_response().

◆ cli_dump_endpt()

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

Definition at line 371 of file res_pjsip.c.

372{
373 switch (cmd) {
374 case CLI_INIT:
375#ifdef AST_DEVMODE
376 e->command = "pjsip dump endpt [details]";
377 e->usage =
378 "Usage: pjsip dump endpt [details]\n"
379 " Dump the res_pjsip endpt internals.\n"
380 "\n"
381 "Warning: PJPROJECT documents that the function used by this\n"
382 "CLI command may cause a crash when asking for details because\n"
383 "it tries to access all active memory pools.\n";
384#else
385 /*
386 * In non-developer mode we will not document or make easily accessible
387 * the details option even though it is still available. The user has
388 * to know it exists to use it. Presumably they would also be aware of
389 * the potential crash warning.
390 */
391 e->command = "pjsip dump endpt";
392 e->usage =
393 "Usage: pjsip dump endpt\n"
394 " Dump the res_pjsip endpt internals.\n";
395#endif /* AST_DEVMODE */
396 return NULL;
397 case CLI_GENERATE:
398 return NULL;
399 }
400
401 if (4 < a->argc
402 || (a->argc == 4 && strcasecmp(a->argv[3], "details"))) {
403 return CLI_SHOWUSAGE;
404 }
405
407
408 return CLI_SUCCESS;
409}
#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:360
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 411 of file res_pjsip.c.

412{
413#define ENDPOINT_IDENTIFIER_FORMAT "%-20.20s\n"
414 struct endpoint_identifier_list *iter;
415
416 switch (cmd) {
417 case CLI_INIT:
418 e->command = "pjsip show identifiers";
419 e->usage = "Usage: pjsip show identifiers\n"
420 " List all registered endpoint identifiers\n";
421 return NULL;
422 case CLI_GENERATE:
423 return NULL;
424 }
425
426 if (a->argc != 3) {
427 return CLI_SHOWUSAGE;
428 }
429
430 ast_cli(a->fd, ENDPOINT_IDENTIFIER_FORMAT, "Identifier Names:");
431 {
435 iter->name ? iter->name : "name not specified");
436 }
437 }
438 return CLI_SUCCESS;
439#undef ENDPOINT_IDENTIFIER_FORMAT
440}
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 442 of file res_pjsip.c.

443{
445
446 switch (cmd) {
447 case CLI_INIT:
448 e->command = "pjsip show settings";
449 e->usage = "Usage: pjsip show settings\n"
450 " Show global and system configuration options\n";
451 return NULL;
452 case CLI_GENERATE:
453 return NULL;
454 }
455
456 context.output_buffer = ast_str_create(256);
457 if (!context.output_buffer) {
458 ast_cli(a->fd, "Could not allocate output buffer.\n");
459 return CLI_FAILURE;
460 }
461
463 ast_free(context.output_buffer);
464 ast_cli(a->fd, "Error retrieving settings.\n");
465 return CLI_FAILURE;
466 }
467
468 ast_cli(a->fd, "%s", ast_str_buffer(context.output_buffer));
469 ast_free(context.output_buffer);
470 return CLI_SUCCESS;
471}
#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:659
CLI Formatter Context passed to all formatters.
Definition: res_pjsip_cli.h:34

References a, ast_cli(), ast_free, ast_str_buffer(), ast_str_create, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, voicemailpwcheck::context, NULL, sip_cli_print_global(), sip_cli_print_system(), and ast_cli_entry::usage.

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

1120{
1121 pjsip_dialog *dlg;
1122 pj_str_t contact;
1123 pjsip_transport_type_e type = rdata->tp_info.transport->key.type;
1124 pjsip_tpselector selector = { .type = PJSIP_TPSELECTOR_NONE, };
1125 pjsip_transport *transport;
1126 pjsip_contact_hdr *contact_hdr;
1127
1129
1130 contact_hdr = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT, NULL);
1131 if (!contact_hdr || ast_sip_set_tpselector_from_ep_or_uri(endpoint, pjsip_uri_get_uri(contact_hdr->uri),
1132 &selector)) {
1133 return NULL;
1134 }
1135
1136 transport = rdata->tp_info.transport;
1137 if (selector.type == PJSIP_TPSELECTOR_TRANSPORT) {
1138 transport = selector.u.transport;
1139 }
1140 type = transport->key.type;
1141
1142 contact.ptr = pj_pool_alloc(rdata->tp_info.pool, PJSIP_MAX_URL_SIZE);
1143 contact.slen = pj_ansi_snprintf(contact.ptr, PJSIP_MAX_URL_SIZE,
1144 "<%s:%s%s%s%.*s%s:%d%s%s>",
1145 uas_use_sips_contact(rdata) ? "sips" : "sip",
1146 S_OR(endpoint->contact_user, ""),
1147 (!ast_strlen_zero(endpoint->contact_user)) ? "@" : "",
1148 (type & PJSIP_TRANSPORT_IPV6) ? "[" : "",
1149 (int)transport->local_name.host.slen,
1150 transport->local_name.host.ptr,
1151 (type & PJSIP_TRANSPORT_IPV6) ? "]" : "",
1152 transport->local_name.port,
1153 (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? ";transport=" : "",
1154 (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? pjsip_transport_get_type_name(type) : "");
1155
1156 *status = create_fun(pjsip_ua_instance(), rdata, &contact, &dlg);
1157 if (*status != PJ_SUCCESS) {
1158 char err[PJ_ERR_MSG_SIZE];
1159
1160 pj_strerror(*status, err, sizeof(err));
1161 ast_log(LOG_ERROR, "Could not create dialog with endpoint %s. %s\n",
1162 ast_sorcery_object_get_id(endpoint), err);
1163 ast_sip_tpselector_unref(&selector);
1164 return NULL;
1165 }
1166
1167 dlg->sess_count++;
1168 pjsip_dlg_set_transport(dlg, &selector);
1169 dlg->sess_count--;
1170
1171 ast_sip_tpselector_unref(&selector);
1172
1173 return dlg;
1174}
static int uas_use_sips_contact(pjsip_rx_data *rdata)
Determine if a SIPS Contact header is required.
Definition: res_pjsip.c:1089

References ast_assert, ast_log, 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, LOG_ERROR, NULL, S_OR, 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 1307 of file res_pjsip.c.

1308{
1309 if (pjsip_dlg_create_request(dlg, method, -1, tdata) != PJ_SUCCESS) {
1310 ast_log(LOG_WARNING, "Unable to create in-dialog request.\n");
1311 return -1;
1312 }
1313
1314 return 0;
1315}

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

1327{
1328 RAII_VAR(struct ast_sip_contact *, contact, ao2_bump(provided_contact), ao2_cleanup);
1329 pj_str_t remote_uri;
1330 pj_str_t from;
1331 pj_pool_t *pool;
1332 pjsip_tpselector selector = { .type = PJSIP_TPSELECTOR_NONE, };
1333 pjsip_uri *sip_uri;
1334 const char *fromuser;
1335
1336 if (ast_strlen_zero(uri)) {
1337 if (!endpoint && (!contact || ast_strlen_zero(contact->uri))) {
1338 ast_log(LOG_ERROR, "An endpoint and/or uri must be specified\n");
1339 return -1;
1340 }
1341
1342 if (!contact) {
1344 }
1345 if (!contact || ast_strlen_zero(contact->uri)) {
1346 ast_log(LOG_WARNING, "Unable to retrieve contact for endpoint %s\n",
1347 ast_sorcery_object_get_id(endpoint));
1348 return -1;
1349 }
1350
1351 pj_cstr(&remote_uri, contact->uri);
1352 } else {
1353 pj_cstr(&remote_uri, uri);
1354 }
1355
1356 pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(), "Outbound request", 256, 256);
1357
1358 if (!pool) {
1359 ast_log(LOG_ERROR, "Unable to create PJLIB memory pool\n");
1360 return -1;
1361 }
1362
1363 sip_uri = pjsip_parse_uri(pool, remote_uri.ptr, remote_uri.slen, 0);
1364 if (!sip_uri || (!PJSIP_URI_SCHEME_IS_SIP(sip_uri) && !PJSIP_URI_SCHEME_IS_SIPS(sip_uri))) {
1365 ast_log(LOG_ERROR, "Unable to create outbound %.*s request to endpoint %s as URI '%s' is not valid\n",
1366 (int) pj_strlen(&method->name), pj_strbuf(&method->name),
1367 endpoint ? ast_sorcery_object_get_id(endpoint) : "<none>",
1368 pj_strbuf(&remote_uri));
1369 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
1370 return -1;
1371 }
1372
1373 ast_sip_set_tpselector_from_ep_or_uri(endpoint, pjsip_uri_get_uri(sip_uri), &selector);
1374
1375 fromuser = endpoint ? (!ast_strlen_zero(endpoint->fromuser) ? endpoint->fromuser : ast_sorcery_object_get_id(endpoint)) : NULL;
1376 if (sip_dialog_create_from(pool, &from, fromuser,
1377 endpoint ? endpoint->fromdomain : NULL, &remote_uri, &selector)) {
1378 ast_log(LOG_ERROR, "Unable to create From header for %.*s request to endpoint %s\n",
1379 (int) pj_strlen(&method->name), pj_strbuf(&method->name),
1380 endpoint ? ast_sorcery_object_get_id(endpoint) : "<none>");
1381 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
1382 ast_sip_tpselector_unref(&selector);
1383 return -1;
1384 }
1385
1386 if (pjsip_endpt_create_request(ast_sip_get_pjsip_endpoint(), method, &remote_uri,
1387 &from, &remote_uri, &from, NULL, -1, NULL, tdata) != PJ_SUCCESS) {
1388 ast_log(LOG_ERROR, "Unable to create outbound %.*s request to endpoint %s\n",
1389 (int) pj_strlen(&method->name), pj_strbuf(&method->name),
1390 endpoint ? ast_sorcery_object_get_id(endpoint) : "<none>");
1391 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
1392 ast_sip_tpselector_unref(&selector);
1393 return -1;
1394 }
1395
1396 pjsip_tx_data_set_transport(*tdata, &selector);
1397
1398 ast_sip_tpselector_unref(&selector);
1399
1400 if (endpoint && !ast_strlen_zero(endpoint->contact_user)){
1401 pjsip_contact_hdr *contact_hdr;
1402 pjsip_sip_uri *contact_uri;
1403 static const pj_str_t HCONTACT = { "Contact", 7 };
1404 static const pj_str_t HCONTACTSHORT = { "m", 1 };
1405
1406 contact_hdr = pjsip_msg_find_hdr_by_names((*tdata)->msg, &HCONTACT, &HCONTACTSHORT, NULL);
1407 if (contact_hdr) {
1408 contact_uri = pjsip_uri_get_uri(contact_hdr->uri);
1409 pj_strdup2((*tdata)->pool, &contact_uri->user, endpoint->contact_user);
1410 }
1411 }
1412
1413 /* Add the user=phone parameter if applicable */
1414 ast_sip_add_usereqphone(endpoint, (*tdata)->pool, (*tdata)->msg->line.req.uri);
1415
1416 /* If an outbound proxy is specified on the endpoint apply it to this request */
1417 if (endpoint && !ast_strlen_zero(endpoint->outbound_proxy) &&
1418 ast_sip_set_outbound_proxy((*tdata), endpoint->outbound_proxy)) {
1419 ast_log(LOG_ERROR, "Unable to apply outbound proxy on request %.*s to endpoint %s as outbound proxy URI '%s' is not valid\n",
1420 (int) pj_strlen(&method->name), pj_strbuf(&method->name), ast_sorcery_object_get_id(endpoint),
1421 endpoint->outbound_proxy);
1422 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
1423 return -1;
1424 }
1425
1426 ast_sip_mod_data_set((*tdata)->pool, (*tdata)->mod_data, supplement_module.id, MOD_DATA_CONTACT, ao2_bump(contact));
1427
1428 /* We can release this pool since request creation copied all the necessary
1429 * data into the outbound request's pool
1430 */
1431 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
1432 return 0;
1433}
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:1992
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:987

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

361{
362 struct ast_cli_args *a = v_a;
363
365 pjsip_endpt_dump(ast_sip_get_pjsip_endpoint(), a->argc == 4 ? PJ_TRUE : PJ_FALSE);
367
368 return 0;
369}
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 1499 of file res_pjsip.c.

1500{
1501 pj_str_t method;
1502
1503 if (ast_strlen_zero(supplement_method)) {
1504 return PJ_TRUE;
1505 }
1506
1507 pj_cstr(&method, supplement_method);
1508
1509 return pj_stristr(&method, message_method) ? PJ_TRUE : PJ_FALSE;
1510}
static const pjsip_method message_method
Definition: res_pjsip.c:1275

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

1698{
1699 struct send_request_wrapper *req_wrapper;
1700 pj_status_t ret_val;
1701 pjsip_endpoint *endpt = ast_sip_get_pjsip_endpoint();
1702
1703 if (!cb && token) {
1704 /* Silly. Without a callback we cannot do anything with token. */
1705 pjsip_tx_data_dec_ref(tdata);
1706 return PJ_EINVAL;
1707 }
1708
1709 /* Create wrapper to detect if the callback was actually called on an error. */
1710 req_wrapper = ao2_alloc(sizeof(*req_wrapper), send_request_wrapper_destructor);
1711 if (!req_wrapper) {
1712 pjsip_tx_data_dec_ref(tdata);
1713 return PJ_ENOMEM;
1714 }
1715
1716 ast_debug(2, "%p: Wrapper created\n", req_wrapper);
1717
1718 req_wrapper->token = token;
1719 req_wrapper->callback = cb;
1720 req_wrapper->timeout = timeout;
1721 req_wrapper->timeout_timer = NULL;
1722 req_wrapper->tdata = tdata;
1723 /* Add a reference to tdata. The wrapper destructor cleans it up. */
1724 pjsip_tx_data_add_ref(tdata);
1725
1726 if (timeout > 0) {
1727 pj_time_val timeout_timer_val = { timeout / 1000, timeout % 1000 };
1728
1729 req_wrapper->timeout_timer = PJ_POOL_ALLOC_T(tdata->pool, pj_timer_entry);
1730
1731 ast_debug(2, "%p: Set timer to %d msec\n", req_wrapper, timeout);
1732
1733 pj_timer_entry_init(req_wrapper->timeout_timer, TIMEOUT_TIMER2,
1734 req_wrapper, send_request_timer_callback);
1735
1736 /* We need to insure that the wrapper and tdata are available if/when the
1737 * timer callback is executed.
1738 */
1739 ao2_ref(req_wrapper, +1);
1740 ret_val = pj_timer_heap_schedule(pjsip_endpt_get_timer_heap(endpt),
1741 req_wrapper->timeout_timer, &timeout_timer_val);
1742 if (ret_val != PJ_SUCCESS) {
1744 "Failed to set timer. Not sending %.*s request to endpoint %s.\n",
1745 (int) pj_strlen(&tdata->msg->line.req.method.name),
1746 pj_strbuf(&tdata->msg->line.req.method.name),
1747 endpoint ? ast_sorcery_object_get_id(endpoint) : "<unknown>");
1748 ao2_t_ref(req_wrapper, -2, "Drop timer and routine ref");
1749 pjsip_tx_data_dec_ref(tdata);
1750 return ret_val;
1751 }
1752 }
1753
1754 /* We need to insure that the wrapper and tdata are available when the
1755 * transaction callback is executed.
1756 */
1757 ao2_ref(req_wrapper, +1);
1758 ret_val = pjsip_endpt_send_request(endpt, tdata, -1, req_wrapper, endpt_send_request_cb);
1759 if (ret_val != PJ_SUCCESS) {
1760 char errmsg[PJ_ERR_MSG_SIZE];
1761
1762 if (!req_wrapper->send_cb_called) {
1763 /* endpt_send_request_cb is not expected to ever be called now. */
1764 ao2_ref(req_wrapper, -1);
1765 }
1766
1767 /* Complain of failure to send the request. */
1768 pj_strerror(ret_val, errmsg, sizeof(errmsg));
1769 ast_log(LOG_ERROR, "Error %d '%s' sending %.*s request to endpoint %s\n",
1770 (int) ret_val, errmsg, (int) pj_strlen(&tdata->msg->line.req.method.name),
1771 pj_strbuf(&tdata->msg->line.req.method.name),
1772 endpoint ? ast_sorcery_object_get_id(endpoint) : "<unknown>");
1773
1774 if (timeout > 0) {
1775 int timers_cancelled;
1776
1777 ao2_lock(req_wrapper);
1778 timers_cancelled = pj_timer_heap_cancel_if_active(
1779 pjsip_endpt_get_timer_heap(endpt),
1780 req_wrapper->timeout_timer, TIMER_INACTIVE);
1781 if (timers_cancelled > 0) {
1782 ao2_ref(req_wrapper, -1);
1783 }
1784
1785 /* Was the callback called? */
1786 if (req_wrapper->cb_called) {
1787 /*
1788 * Yes so we cannot report any error. The callback
1789 * has already freed any resources associated with
1790 * token.
1791 */
1792 ret_val = PJ_SUCCESS;
1793 } else {
1794 /*
1795 * No so we claim it is called so our caller can free
1796 * any resources associated with token because of
1797 * failure.
1798 */
1799 req_wrapper->cb_called = 1;
1800 }
1801 ao2_unlock(req_wrapper);
1802 } else if (req_wrapper->cb_called) {
1803 /*
1804 * We cannot report any error. The callback has
1805 * already freed any resources associated with
1806 * token.
1807 */
1808 ret_val = PJ_SUCCESS;
1809 }
1810 }
1811
1812 ao2_ref(req_wrapper, -1);
1813 return ret_val;
1814}
#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:1648
static void send_request_wrapper_destructor(void *obj)
Definition: res_pjsip.c:1688
static void endpt_send_request_cb(void *token, pjsip_event *e)
Definition: res_pjsip.c:1573
#define TIMER_INACTIVE
Definition: res_pjsip.c:1512
#define TIMEOUT_TIMER2
Definition: res_pjsip.c:1513
pj_int32_t timeout
Definition: res_pjsip.c:1564
unsigned int send_cb_called
Definition: res_pjsip.c:1560
pjsip_tx_data * tdata
Definition: res_pjsip.c:1566
unsigned int cb_called
Definition: res_pjsip.c:1558
pj_timer_entry * timeout_timer
Definition: res_pjsip.c:1562
void(* callback)(void *token, pjsip_event *e)
Definition: res_pjsip.c:1556

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

1574{
1575 struct send_request_wrapper *req_wrapper = token;
1576 unsigned int cb_called;
1577
1578 /*
1579 * Needed because we cannot otherwise tell if this callback was
1580 * called when pjsip_endpt_send_request() returns error.
1581 */
1582 req_wrapper->send_cb_called = 1;
1583
1584 if (e->body.tsx_state.type == PJSIP_EVENT_TIMER) {
1585 ast_debug(2, "%p: PJSIP tsx timer expired\n", req_wrapper);
1586
1587 if (req_wrapper->timeout_timer
1588 && req_wrapper->timeout_timer->id != TIMEOUT_TIMER2) {
1589 ast_debug(3, "%p: Timeout already handled\n", req_wrapper);
1590 ao2_ref(req_wrapper, -1);
1591 return;
1592 }
1593 } else {
1594 ast_debug(2, "%p: PJSIP tsx response received\n", req_wrapper);
1595 }
1596
1597 ao2_lock(req_wrapper);
1598
1599 /* It's possible that our own timer was already processing while
1600 * we were waiting on the lock so check the timer id. If it's
1601 * still TIMER2 then we still need to process.
1602 */
1603 if (req_wrapper->timeout_timer
1604 && req_wrapper->timeout_timer->id == TIMEOUT_TIMER2) {
1605 int timers_cancelled = 0;
1606
1607 ast_debug(3, "%p: Cancelling timer\n", req_wrapper);
1608
1609 timers_cancelled = pj_timer_heap_cancel_if_active(
1610 pjsip_endpt_get_timer_heap(ast_sip_get_pjsip_endpoint()),
1611 req_wrapper->timeout_timer, TIMER_INACTIVE);
1612 if (timers_cancelled > 0) {
1613 /* If the timer was cancelled the callback will never run so
1614 * clean up its reference to the wrapper.
1615 */
1616 ast_debug(3, "%p: Timer cancelled\n", req_wrapper);
1617 ao2_ref(req_wrapper, -1);
1618 } else {
1619 /*
1620 * If it wasn't cancelled, it MAY be in the callback already
1621 * waiting on the lock. When we release the lock, it will
1622 * now know not to proceed.
1623 */
1624 ast_debug(3, "%p: Timer already expired\n", req_wrapper);
1625 }
1626 }
1627
1628 cb_called = req_wrapper->cb_called;
1629 req_wrapper->cb_called = 1;
1630 ao2_unlock(req_wrapper);
1631
1632 /* It's possible that our own timer expired and called the callbacks
1633 * so no need to call them again.
1634 */
1635 if (!cb_called && req_wrapper->callback) {
1636 req_wrapper->callback(req_wrapper->token, e);
1637 ast_debug(2, "%p: Callbacks executed\n", req_wrapper);
1638 }
1639
1640 ao2_ref(req_wrapper, -1);
1641}

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

◆ find_transport_state_in_use()

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

Callback function for finding the transport the request is going out on.

Definition at line 576 of file res_pjsip.c.

577{
578 struct ast_sip_transport_state *transport_state = obj;
579 struct ast_sip_request_transport_details *details = arg;
580
581 /* If an explicit transport or factory matches then this is what is in use, if we are unavailable
582 * to compare based on that we make sure that the type is the same and the source IP address/port are the same
583 */
584 if (transport_state && ((details->transport && details->transport == transport_state->transport) ||
585 (details->factory && details->factory == transport_state->factory) ||
586 ((details->type == transport_state->type) && (transport_state->factory) &&
587 !pj_strcmp(&transport_state->factory->addr_name.host, &details->local_address) &&
588 transport_state->factory->addr_name.port == details->local_port))) {
589 return CMP_MATCH | CMP_STOP;
590 }
591
592 return 0;
593}
@ CMP_MATCH
Definition: astobj2.h:1027
@ CMP_STOP
Definition: astobj2.h:1028
enum ast_transport type
Definition: res_pjsip.h:130

References CMP_MATCH, CMP_STOP, ast_sip_transport_state::factory, ast_sip_request_transport_details::factory, ast_sip_request_transport_details::local_address, ast_sip_request_transport_details::local_port, ast_sip_transport_state::transport, ast_sip_request_transport_details::transport, ast_sip_transport_state::type, and ast_sip_request_transport_details::type.

Referenced by ast_sip_find_transport_state_in_use().

◆ get_id_header()

static pjsip_fromto_hdr * get_id_header ( pjsip_rx_data *  rdata,
const pj_str_t *  header_name 
)
static

Definition at line 2673 of file res_pjsip.c.

2674{
2675 static const pj_str_t from = { "From", 4 };
2676 pj_str_t header_content;
2677 pjsip_fromto_hdr *parsed_hdr;
2678 pjsip_generic_string_hdr *ident = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg,
2679 header_name, NULL);
2680 int parsed_len;
2681
2682 if (!ident) {
2683 return NULL;
2684 }
2685
2686 pj_strdup_with_null(rdata->tp_info.pool, &header_content, &ident->hvalue);
2687
2688 parsed_hdr = pjsip_parse_hdr(rdata->tp_info.pool, &from, header_content.ptr,
2689 pj_strlen(&header_content), &parsed_len);
2690
2691 if (!parsed_hdr) {
2692 return NULL;
2693 }
2694
2695 return parsed_hdr;
2696}

References NULL.

Referenced by set_id_from_pai(), and set_id_from_rpid().

◆ get_pjsip_method()

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

Definition at line 1296 of file res_pjsip.c.

1297{
1298 int i;
1299 for (i = 0; i < ARRAY_LEN(methods); ++i) {
1300 if (!strcmp(method, methods[i].method)) {
1301 return methods[i].pmethod;
1302 }
1303 }
1304 return NULL;
1305}
static struct @450 methods[]

References ARRAY_LEN, method, methods, and NULL.

Referenced by ast_sip_create_request().

◆ handle_atsign()

static struct ast_sip_endpoint * handle_atsign ( const char *  to,
char *  destination,
char **  uri,
char *  slash,
char *  atsign,
char *  scheme,
int  get_default_outbound 
)
static

Definition at line 3191 of file res_pjsip.c.

3193{
3194 char *endpoint_name = NULL;
3195 struct ast_sip_endpoint *endpoint = NULL;
3196 struct ast_sip_contact *contact = NULL;
3197 char *afterat = atsign + 1;
3198
3199 *atsign = '\0';
3200 endpoint_name = destination;
3201
3202 /* Apparently there may be ';<user_options>' after the endpoint name ??? */
3205 if (!endpoint) {
3206 /*
3207 * It's probably a uri with a user but without a scheme but we don't have a way to tell.
3208 * We're going to assume it is and prepend it with a scheme.
3209 */
3210 *uri = ast_malloc(strlen(to) + strlen("sip:") + 1);
3211 if (!(*uri)) {
3212 goto failure;
3213 }
3214 sprintf(*uri, "sip:%s", to);
3215 if (get_default_outbound) {
3217 }
3218 ast_debug(3, "Dest: '%s' Didn't find endpoint before the '@' so using URI '%s'%s\n",
3219 to, *uri, get_default_outbound ? " with default endpoint" : "");
3220 return endpoint;
3221 }
3222
3223 /*
3224 * OK, it's an endpoint and a domain (which we ignore)
3225 */
3227 if (!contact) {
3228 ast_log(LOG_WARNING, "Dest: '%s'. Found endpoint '%s' but didn't find contact\n",
3229 to, endpoint_name);
3230 goto failure;
3231 }
3232
3233 *uri = ast_strdup(contact->uri);
3234 ao2_cleanup(contact);
3235 if (!(*uri)) {
3236 goto failure;
3237 }
3238 ast_debug(3, "Dest: '%s' Found endpoint '%s' and found contact with URI '%s' (discarding domain %s)\n",
3239 to, endpoint_name, *uri, afterat);
3240
3241 return endpoint;
3242
3243failure:
3245 *uri = NULL;
3246 return NULL;
3247}
#define AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(str)
Truncate the URI user field options string if enabled.
Definition: res_pjsip.h:3350
const ast_string_field uri
Definition: res_pjsip.h:411
const ast_string_field endpoint_name
Definition: res_pjsip.h:411

References ao2_cleanup, ast_sip_endpoint::aors, ast_debug, ast_log, ast_malloc, ast_sip_default_outbound_endpoint(), ast_sip_get_sorcery(), ast_sip_location_retrieve_contact_from_aor_list(), AST_SIP_USER_OPTIONS_TRUNCATE_CHECK, ast_sorcery_retrieve_by_id(), ast_strdup, ast_sip_contact::endpoint, ast_sip_contact::endpoint_name, LOG_WARNING, NULL, and ast_sip_contact::uri.

Referenced by ast_sip_get_endpoint().

◆ handle_single_token()

static struct ast_sip_endpoint * handle_single_token ( const char *  to,
char *  destination,
int  get_default_outbound,
char **  uri 
)
static

Definition at line 2955 of file res_pjsip.c.

2955 {
2956 RAII_VAR(struct ast_sip_contact*, contact, NULL, ao2_cleanup);
2957 char *endpoint_name = NULL;
2958 struct ast_sip_endpoint *endpoint = NULL;
2959
2960 /*
2961 * If "destination" is just one token, it could be an endpoint name
2962 * or a hostname without a scheme.
2963 */
2964
2965 endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", destination);
2966 if (!endpoint) {
2967 /*
2968 * We can only assume it's a hostname.
2969 */
2970 char *temp_uri = ast_malloc(strlen(destination) + strlen("sip:") + 1);
2971 if (!temp_uri) {
2972 goto failure;
2973 }
2974 sprintf(temp_uri, "sip:%s", destination);
2975 *uri = temp_uri;
2976 if (get_default_outbound) {
2978 }
2979 ast_debug(3, "Dest: '%s' Didn't find endpoint so adding scheme and using URI '%s'%s\n",
2980 to, *uri, get_default_outbound ? " with default endpoint" : "");
2981 return endpoint;
2982 }
2983
2984 /*
2985 * It's an endpoint
2986 */
2987
2988 endpoint_name = destination;
2990 if (!contact) {
2991 ast_log(LOG_WARNING, "Dest: '%s'. Found endpoint '%s' but didn't find an aor/contact for it\n",
2992 to, endpoint_name);
2993 ao2_cleanup(endpoint);
2994 goto failure;
2995 }
2996
2997 *uri = ast_strdup(contact->uri);
2998 if (!(*uri)) {
2999 ao2_cleanup(endpoint);
3000 goto failure;
3001 }
3002
3003 ast_debug(3, "Dest: '%s' Found endpoint '%s' and found contact with URI '%s'\n",
3004 to, endpoint_name, *uri);
3005 return endpoint;
3006
3007failure:
3008 *uri = NULL;
3009 return NULL;
3010}

References ao2_cleanup, ast_sip_endpoint::aors, ast_debug, ast_log, ast_malloc, ast_sip_default_outbound_endpoint(), ast_sip_get_sorcery(), ast_sip_location_retrieve_contact_from_aor_list(), ast_sorcery_retrieve_by_id(), ast_strdup, LOG_WARNING, NULL, and RAII_VAR.

Referenced by ast_sip_get_endpoint().

◆ handle_slash()

static struct ast_sip_endpoint * handle_slash ( const char *  to,
char *  destination,
char **  uri,
char *  slash,
char *  atsign,
char *  scheme 
)
static

Definition at line 3034 of file res_pjsip.c.

3036{
3037 char *endpoint_name = NULL;
3038 struct ast_sip_endpoint *endpoint = NULL;
3039 struct ast_sip_contact *contact = NULL;
3040 char *user = NULL;
3041 char *afterslash = slash + 1;
3042 struct ast_sip_aor *aor;
3043
3044 if (ast_begins_with(destination, "PJSIP/")) {
3045 ast_debug(3, "Dest: '%s' Dialplan format'\n", to);
3046 /*
3047 * This has to be the form PJSIP/user@endpoint
3048 */
3049 if (!atsign || strchr(afterslash, '/')) {
3050 /*
3051 * If there's no "user@" or there's a slash somewhere after
3052 * "PJSIP/" then we go no further.
3053 */
3055 "Dest: '%s'. Destinations beginning with 'PJSIP/' must be in the form of 'PJSIP/user@endpoint'\n",
3056 to);
3057 goto failure;
3058 }
3059 *atsign = '\0';
3060 user = afterslash;
3061 endpoint_name = atsign + 1;
3062 ast_debug(3, "Dest: '%s' User: '%s' Endpoint: '%s'\n", to, user, endpoint_name);
3063 } else {
3064 /*
3065 * Either...
3066 * endpoint/aor
3067 * endpoint/uri
3068 */
3069 *slash = '\0';
3070 endpoint_name = destination;
3071 ast_debug(3, "Dest: '%s' Endpoint: '%s'\n", to, endpoint_name);
3072 }
3073
3074 endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", endpoint_name);
3075 if (!endpoint) {
3076 ast_log(LOG_WARNING, "Dest: '%s'. Didn't find endpoint with name '%s'\n",
3077 to, endpoint_name);
3078 goto failure;
3079 }
3080
3081 if (scheme) {
3082 /*
3083 * If we found a scheme, then everything after the slash MUST be a URI.
3084 * We don't need to do any further modification.
3085 */
3086 *uri = ast_strdup(afterslash);
3087 if (!(*uri)) {
3088 goto failure;
3089 }
3090 ast_debug(3, "Dest: '%s' Found endpoint '%s' and found URI '%s' after '/'\n",
3091 to, endpoint_name, *uri);
3092 return endpoint;
3093 }
3094
3095 if (user) {
3096 /*
3097 * This has to be the form PJSIP/user@endpoint
3098 */
3099 int rc;
3100
3101 /*
3102 * Set the return URI to be the endpoint's contact URI with the user
3103 * portion set to the user that was specified before the endpoint name.
3104 */
3105 rc = insert_user_in_contact_uri(to, endpoint_name, endpoint->aors, user, uri);
3106 if (rc != 0) {
3107 /*
3108 * insert_user_in_contact_uri prints the warning message.
3109 */
3110 goto failure;
3111 }
3112 ast_debug(3, "Dest: '%s' User: '%s' Endpoint: '%s' URI: '%s'\n", to, user,
3113 endpoint_name, *uri);
3114
3115 return endpoint;
3116 }
3117
3118 /*
3119 * We're now left with two possibilities...
3120 * endpoint/aor
3121 * endpoint/uri-without-scheme
3122 */
3123 aor = ast_sip_location_retrieve_aor(afterslash);
3124 if (!aor) {
3125 /*
3126 * It's probably a URI without a scheme but we don't have a way to tell
3127 * for sure. We're going to assume it is and prepend it with a scheme.
3128 */
3129 *uri = ast_malloc(strlen(afterslash) + strlen("sip:") + 1);
3130 if (!(*uri)) {
3131 goto failure;
3132 }
3133 sprintf(*uri, "sip:%s", afterslash);
3134 ast_debug(3, "Dest: '%s' Found endpoint '%s' but didn't find aor after '/' so using URI '%s'\n",
3135 to, endpoint_name, *uri);
3136 return endpoint;
3137 }
3138
3139 /*
3140 * Only one possibility left... There was an aor name after the slash.
3141 */
3142 ast_debug(3, "Dest: '%s' Found endpoint '%s' and found aor '%s' after '/'\n",
3143 to, endpoint_name, ast_sorcery_object_get_id(aor));
3144
3146 if (!contact) {
3147 ast_log(LOG_WARNING, "Dest: '%s'. Found endpoint '%s' but didn't find contact for aor '%s'\n",
3148 to, endpoint_name, ast_sorcery_object_get_id(aor));
3149 ao2_cleanup(aor);
3150 goto failure;
3151 }
3152
3153 *uri = ast_strdup(contact->uri);
3154 ao2_cleanup(contact);
3155 ao2_cleanup(aor);
3156 if (!(*uri)) {
3157 goto failure;
3158 }
3159
3160 ast_debug(3, "Dest: '%s' Found endpoint '%s' and found contact with URI '%s' for aor '%s'\n",
3161 to, endpoint_name, *uri, ast_sorcery_object_get_id(aor));
3162
3163 return endpoint;
3164
3165failure:
3166 ao2_cleanup(endpoint);
3167 *uri = NULL;
3168 return NULL;
3169}
static int insert_user_in_contact_uri(const char *to, const char *endpoint_name, const char *aors, const char *user, char **uri)
Find a contact and insert a "user@" into its URI.
Definition: res_pjsip.c:2890
struct ast_sip_aor * ast_sip_location_retrieve_aor(const char *aor_name)
Retrieve a named AOR.
Definition: location.c:147
struct ast_sip_contact * ast_sip_location_retrieve_first_aor_contact(const struct ast_sip_aor *aor)
Retrieve the first bound contact for an AOR.
Definition: location.c:194
A SIP address of record.
Definition: res_pjsip.h:475
structure to hold users read from users.conf

References ao2_cleanup, ast_sip_endpoint::aors, ast_begins_with(), ast_debug, ast_log, ast_malloc, ast_sip_get_sorcery(), ast_sip_location_retrieve_aor(), ast_sip_location_retrieve_first_aor_contact(), ast_sorcery_object_get_id(), ast_sorcery_retrieve_by_id(), ast_strdup, insert_user_in_contact_uri(), LOG_WARNING, NULL, and ast_sip_contact::uri.

Referenced by ast_sip_get_endpoint().

◆ insert_user_in_contact_uri()

static int insert_user_in_contact_uri ( const char *  to,
const char *  endpoint_name,
const char *  aors,
const char *  user,
char **  uri 
)
static

Find a contact and insert a "user@" into its URI.

Parameters
toOriginal destination (for error messages only)
endpoint_nameEndpoint name (for error messages only)
aorsCommand separated list of AORs
userThe user to insert in the contact URI
uriPointer to buffer in which to return the URI. Must be freed by caller.
Returns
0 Success
-1 Fail
Note
If the contact URI found for the endpoint already has a user in its URI, it will be replaced by the user passed as an argument to this function.

Definition at line 2890 of file res_pjsip.c.

2892{
2893 RAII_VAR(struct ast_sip_contact *, contact, NULL, ao2_cleanup);
2894 pj_pool_t *pool;
2895 pjsip_name_addr *name_addr;
2896 pjsip_sip_uri *sip_uri;
2897 int err = 0;
2898
2900 if (!contact) {
2901 ast_log(LOG_WARNING, "Dest: '%s'. Couldn't find contact for endpoint '%s'\n",
2902 to, endpoint_name);
2903 return -1;
2904 }
2905
2906 pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(), "uri-user-insert", 128, 128);
2907 if (!pool) {
2908 ast_log(LOG_WARNING, "Failed to allocate ParseUri endpoint pool.\n");
2909 return -1;
2910 }
2911
2912 name_addr = (pjsip_name_addr *) pjsip_parse_uri(pool, (char*)contact->uri, strlen(contact->uri), PJSIP_PARSE_URI_AS_NAMEADDR);
2913 if (!name_addr || (!PJSIP_URI_SCHEME_IS_SIP(name_addr->uri) && !PJSIP_URI_SCHEME_IS_SIPS(name_addr->uri))) {
2914 ast_log(LOG_WARNING, "Failed to parse URI '%s'\n", contact->uri);
2915 err = -1;
2916 goto out;
2917 }
2918
2919 ast_debug(3, "Dest: '%s' User: '%s' Endpoint: '%s' ContactURI: '%s'\n", to, user, endpoint_name, contact->uri);
2920
2921 sip_uri = pjsip_uri_get_uri(name_addr->uri);
2922 pj_strset2(&sip_uri->user, (char*)user);
2923
2924 *uri = ast_malloc(PJSIP_MAX_URL_SIZE);
2925 if (!(*uri)) {
2926 err = -1;
2927 goto out;
2928 }
2929 pjsip_uri_print(PJSIP_URI_IN_REQ_URI, name_addr, *uri, PJSIP_MAX_URL_SIZE);
2930
2931out:
2932 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
2933
2934 return err;
2935}
FILE * out
Definition: utils/frame.c:33

References ao2_cleanup, ast_debug, ast_log, ast_malloc, ast_sip_get_pjsip_endpoint(), ast_sip_location_retrieve_contact_from_aor_list(), ast_sip_contact::endpoint_name, LOG_WARNING, NULL, out, RAII_VAR, and ast_sip_contact::uri.

Referenced by handle_slash().

◆ load_module()

static int load_module ( void  )
static

Definition at line 3922 of file res_pjsip.c.

3923{
3925
3926 /* pjproject and config_system need to be initialized before all else */
3927 if (pj_init() != PJ_SUCCESS) {
3929 }
3930
3931 if (pjlib_util_init() != PJ_SUCCESS) {
3932 goto error;
3933 }
3934
3935 /* Register PJMEDIA error codes for SDP parsing errors */
3936 if (pj_register_strerror(PJMEDIA_ERRNO_START, PJ_ERRNO_SPACE_SIZE, pjmedia_strerror)
3937 != PJ_SUCCESS) {
3938 ast_log(LOG_WARNING, "Failed to register pjmedia error codes. Codes will not be decoded.\n");
3939 }
3940
3941 /* Initialize common media types */
3942 pjsip_media_type_init2(&pjsip_media_type_application_json, "application", "json");
3943 pjsip_media_type_init2(&pjsip_media_type_application_media_control_xml, "application", "media_control+xml");
3944 pjsip_media_type_init2(&pjsip_media_type_application_pidf_xml, "application", "pidf+xml");
3945 pjsip_media_type_init2(&pjsip_media_type_application_xpidf_xml, "application", "xpidf+xml");
3946 pjsip_media_type_init2(&pjsip_media_type_application_cpim_xpidf_xml, "application", "cpim-xpidf+xml");
3947 pjsip_media_type_init2(&pjsip_media_type_application_rlmi_xml, "application", "rlmi+xml");
3948 pjsip_media_type_init2(&pjsip_media_type_application_sdp, "application", "sdp");
3949 pjsip_media_type_init2(&pjsip_media_type_application_simple_message_summary, "application", "simple-message-summary");
3950 pjsip_media_type_init2(&pjsip_media_type_multipart_alternative, "multipart", "alternative");
3951 pjsip_media_type_init2(&pjsip_media_type_multipart_mixed, "multipart", "mixed");
3952 pjsip_media_type_init2(&pjsip_media_type_multipart_related, "multipart", "related");
3953 pjsip_media_type_init2(&pjsip_media_type_text_plain, "text", "plain");
3954
3955
3957 ast_log(LOG_ERROR, "Failed to initialize SIP 'system' configuration section. Aborting load\n");
3958 goto error;
3959 }
3960
3961 /* The serializer needs threadpool and threadpool needs pjproject to be initialized so it's next */
3963 options.thread_start = sip_thread_start;
3965 if (!sip_threadpool) {
3966 goto error;
3967 }
3968
3970 "pjsip/default", SERIALIZER_POOL_SIZE, sip_threadpool, -1);
3971 if (!sip_serializer_pool) {
3972 ast_log(LOG_ERROR, "Failed to create SIP serializer pool. Aborting load\n");
3973 goto error;
3974 }
3975
3977 ast_log(LOG_ERROR, "Failed to start scheduler. Aborting load\n");
3978 goto error;
3979 }
3980
3981 /* Now load all the pjproject infrastructure. */
3982 if (load_pjsip()) {
3983 goto error;
3984 }
3985
3987 ast_log(LOG_ERROR, "Failed to initialize SIP transport monitor. Aborting load\n");
3988 goto error;
3989 }
3990
3993
3995 ast_log(LOG_ERROR, "Failed to pre-initialize OPTIONS handling. Aborting load\n");
3996 goto error;
3997 }
3998
4000 ast_log(LOG_ERROR, "Failed to initialize SIP configuration. Aborting load\n");
4001 goto error;
4002 }
4003
4006
4008 ast_log(LOG_ERROR, "Failed to initialize SIP transport management. Aborting load\n");
4009 goto error;
4010 }
4011
4013 ast_log(LOG_ERROR, "Failed to register distributor module. Aborting load\n");
4014 goto error;
4015 }
4016
4018 ast_log(LOG_ERROR, "Failed to initialize supplement hooks. Aborting load\n");
4019 goto error;
4020 }
4021
4023 ast_log(LOG_ERROR, "Failed to initialize OPTIONS handling. Aborting load\n");
4024 goto error;
4025 }
4026
4027 /*
4028 * It is OK to prune the contacts now that
4029 * ast_res_pjsip_init_options_handling() has added the contact observer
4030 * of res/res_pjsip/pjsip_options.c to sorcery (to ensure that any
4031 * pruned contacts are removed from this module's data structure).
4032 */
4034
4036 ast_log(LOG_ERROR, "Failed to initialize message IP updating. Aborting load\n");
4037 goto error;
4038 }
4039
4041
4042 AST_TEST_REGISTER(xml_sanitization_end_null);
4043 AST_TEST_REGISTER(xml_sanitization_exceeds_buffer);
4044
4046
4047error:
4049
4050 /* These functions all check for NULLs and are safe to call at any time */
4054
4056}
#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:3798
pjsip_media_type pjsip_media_type_application_media_control_xml
Definition: res_pjsip.c:3910
static struct ast_cli_entry cli_commands[]
Definition: res_pjsip.c:473
pjsip_media_type pjsip_media_type_application_json
Definition: res_pjsip.c:3909
int ast_sip_register_service(pjsip_module *module)
Register a SIP service in Asterisk.
Definition: res_pjsip.c:117
pjsip_media_type pjsip_media_type_application_sdp
Definition: res_pjsip.c:3916
pjsip_media_type pjsip_media_type_text_plain
Definition: res_pjsip.c:3920
pjsip_media_type pjsip_media_type_application_pidf_xml
Definition: res_pjsip.c:3911
static void sip_thread_start(void)
Definition: res_pjsip.c:2285
#define SERIALIZER_POOL_SIZE
Definition: res_pjsip.c:69
pjsip_media_type pjsip_media_type_application_simple_message_summary
Definition: res_pjsip.c:3915
pjsip_media_type pjsip_media_type_application_rlmi_xml
Definition: res_pjsip.c:3914
pjsip_media_type pjsip_media_type_multipart_mixed
Definition: res_pjsip.c:3918
pjsip_media_type pjsip_media_type_application_xpidf_xml
Definition: res_pjsip.c:3912
pjsip_media_type pjsip_media_type_multipart_alternative
Definition: res_pjsip.c:3917
static int load_pjsip(void)
Definition: res_pjsip.c:3842
pjsip_media_type pjsip_media_type_application_cpim_xpidf_xml
Definition: res_pjsip.c:3913
pjsip_media_type pjsip_media_type_multipart_related
Definition: res_pjsip.c:3919
static struct ast_serializer_pool * sip_serializer_pool
Definition: res_pjsip.c:72
void ast_sip_location_prune_boot_contacts(void)
Prune the prune_on_boot contacts.
Definition: location.c:469
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_location_prune_boot_contacts(), 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 3842 of file res_pjsip.c.

3843{
3844 const unsigned int flags = 0; /* no port, no brackets */
3845 pj_status_t status;
3846
3847 /* The third parameter is just copied from
3848 * example code from PJLIB. This can be adjusted
3849 * if necessary.
3850 */
3852 if (pjsip_endpt_create(&caching_pool.factory, "SIP", &ast_pjsip_endpoint) != PJ_SUCCESS) {
3853 ast_log(LOG_ERROR, "Failed to create PJSIP endpoint structure. Aborting load\n");
3854 goto error;
3855 }
3856
3857 /* PJSIP will automatically try to add a Max-Forwards header. Since we want to control that,
3858 * we need to stop PJSIP from doing it automatically
3859 */
3861
3862 memory_pool = pj_pool_create(&caching_pool.factory, "SIP", 1024, 1024, NULL);
3863 if (!memory_pool) {
3864 ast_log(LOG_ERROR, "Failed to create memory pool for SIP. Aborting load\n");
3865 goto error;
3866 }
3867
3868 if (!pj_gethostip(pj_AF_INET(), &host_ip_ipv4)) {
3869 pj_sockaddr_print(&host_ip_ipv4, host_ip_ipv4_string, sizeof(host_ip_ipv4_string), flags);
3870 ast_verb(3, "Local IPv4 address determined to be: %s\n", host_ip_ipv4_string);
3871 }
3872
3873 if (!pj_gethostip(pj_AF_INET6(), &host_ip_ipv6)) {
3874 pj_sockaddr_print(&host_ip_ipv6, host_ip_ipv6_string, sizeof(host_ip_ipv6_string), flags);
3875 ast_verb(3, "Local IPv6 address determined to be: %s\n", host_ip_ipv6_string);
3876 }
3877
3878 pjsip_tsx_layer_init_module(ast_pjsip_endpoint);
3879 pjsip_ua_init_module(ast_pjsip_endpoint, NULL);
3880
3881 monitor_continue = 1;
3882 status = pj_thread_create(memory_pool, "SIP", (pj_thread_proc *) &monitor_thread_exec,
3883 NULL, PJ_THREAD_DEFAULT_STACK_SIZE * 2, 0, &monitor_thread);
3884 if (status != PJ_SUCCESS) {
3885 ast_log(LOG_ERROR, "Failed to start SIP monitor thread. Aborting load\n");
3886 goto error;
3887 }
3888
3890
3891error:
3893}
#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.
pj_pool_t * memory_pool
Definition: res_pjsip.c:2262
pj_thread_t * monitor_thread
Definition: res_pjsip.c:2263
static void * monitor_thread_exec(void *endpt)
Definition: res_pjsip.c:2266
static int monitor_continue
Definition: res_pjsip.c:2264
static void remove_request_headers(pjsip_endpoint *endpt)
Definition: res_pjsip.c:3445
pj_caching_pool caching_pool
Definition: res_pjsip.c:2261

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

2267{
2268 while (monitor_continue) {
2269 const pj_time_val delay = {0, 10};
2270 pjsip_endpt_handle_events(ast_pjsip_endpoint, &delay);
2271 }
2272 return NULL;
2273}

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

3904{
3905 pjmedia_strerror(0, NULL, 0);
3906}

References NULL.

◆ pool_destroy_callback()

static void pool_destroy_callback ( void *  arg)
static

Definition at line 2409 of file res_pjsip.c.

2410{
2411 pj_pool_t *pool = (pj_pool_t *)arg;
2412 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
2413}

References ast_sip_get_pjsip_endpoint().

Referenced by ast_sip_send_stateful_response().

◆ register_service()

static int register_service ( void *  data)
static

Definition at line 102 of file res_pjsip.c.

103{
104 pjsip_module **module = data;
105 if (!ast_pjsip_endpoint) {
106 ast_log(LOG_ERROR, "There is no PJSIP endpoint. Unable to register services\n");
107 return -1;
108 }
109 if (pjsip_endpt_register_module(ast_pjsip_endpoint, *module) != PJ_SUCCESS) {
110 ast_log(LOG_ERROR, "Unable to register module %.*s\n", (int) pj_strlen(&(*module)->name), pj_strbuf(&(*module)->name));
111 return -1;
112 }
113 ast_debug(1, "Registered SIP service %.*s (%p)\n", (int) pj_strlen(&(*module)->name), pj_strbuf(&(*module)->name), *module);
114 return 0;
115}

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

◆ reload_module()

static int reload_module ( void  )
static

Definition at line 4058 of file