Asterisk - The Open Source Telephony Project GIT-master-5467495
Loading...
Searching...
No Matches
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/taskpool.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
 

Macros

#define DEBUG_BUF_SIZE   256
 
#define ENDPOINT_IDENTIFIER_FORMAT   "%-20.20s\n"
 
#define MOD_DATA_CONTACT   "contact"
 
#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

int __ast_sip_push_task (struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data, const char *file, int line, const char *function)
 Pushes a task to SIP servants.
 
int __ast_sip_push_task_synchronous (struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data, const char *file, int line, const char *function)
 Push a task to SIP servants and wait for it to complete.
 
static int __ast_sip_push_task_wait (struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data, const char *file, int line, const char *function)
 
int __ast_sip_push_task_wait_serializer (struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data, const char *file, int line, const char *function)
 Push a task to the serializer and wait for it to complete.
 
int __ast_sip_push_task_wait_servant (struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data, const char *file, int line, const char *function)
 Push a task to SIP servants and wait for it to complete.
 
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.
 
int ast_copy_pj_str2 (char **dest, const pj_str_t *src)
 Create and copy a pj_str_t into a standard character buffer.
 
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.
 
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.
 
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.
 
int ast_sip_add_header (pjsip_tx_data *tdata, const char *name, const char *value)
 Add a header to an outbound SIP message.
 
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.
 
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.
 
int ast_sip_append_body (pjsip_tx_data *tdata, const char *body_text)
 Append body data to a SIP message.
 
int ast_sip_are_media_types_equal (pjsip_media_type *a, pjsip_media_type *b)
 Compare pjsip media types.
 
const char * ast_sip_call_codec_pref_to_str (struct ast_flags pref)
 Convert the call codec preference flags to a string.
 
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.
 
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.
 
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.
 
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.
 
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.
 
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.
 
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.
 
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.
 
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.
 
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.
 
struct ast_taskprocessorast_sip_create_serializer (const char *name)
 Create a new serializer for SIP tasks.
 
struct ast_taskprocessorast_sip_create_serializer_group (const char *name, struct ast_serializer_shutdown_group *shutdown_group)
 Create a new serializer for SIP tasks.
 
void * ast_sip_dict_get (void *ht, const char *key)
 Retrieves the value associated with the given key.
 
void * ast_sip_dict_set (pj_pool_t *pool, void *ht, const char *key, void *val)
 Set the value for the given key.
 
int ast_sip_dlg_set_transport (const struct ast_sip_endpoint *endpoint, pjsip_dialog *dlg, pjsip_tpselector *selector)
 Set the transport on a dialog.
 
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.
 
int ast_sip_failover_request (pjsip_tx_data *tdata)
 Set a request to use the next value in the list of resolved addresses.
 
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.
 
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.
 
pjsip_sip_uri * ast_sip_get_contact_sip_uri (pjsip_tx_data *tdata)
 Return the SIP URI of the Contact header.
 
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.
 
int ast_sip_get_host_ip (int af, pj_sockaddr *addr)
 Retrieve the local host address in IP form.
 
const char * ast_sip_get_host_ip_string (int af)
 Retrieve the local host address in string form.
 
pjsip_endpoint * ast_sip_get_pjsip_endpoint (void)
 Get a pointer to the PJSIP endpoint.
 
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.
 
const int ast_sip_hangup_sip2cause (int cause)
 Convert SIP hangup causes to Asterisk hangup causes.
 
struct ast_sip_endpointast_sip_identify_endpoint (pjsip_rx_data *rdata)
 Determine the endpoint that has sent a SIP message.
 
int ast_sip_is_allowed_uri (pjsip_uri *uri)
 Check whether a pjsip_uri is allowed or not.
 
int ast_sip_is_content_type (pjsip_media_type *content_type, char *type, char *subtype)
 Checks if the given content type matches type/subtype.
 
int ast_sip_is_media_type_in (pjsip_media_type *a,...)
 Check if a media type is in a list of others.
 
int ast_sip_is_uri_sip_sips (pjsip_uri *uri)
 Check whether a pjsip_uri is SIP/SIPS or not.
 
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.
 
float ast_sip_parse_qvalue (const char *q_value)
 Parses a string representing a q_value to a float.
 
const pj_str_t * ast_sip_pjsip_uri_get_hostname (pjsip_uri *uri)
 Get the host portion of the pjsip_uri.
 
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.
 
const pj_str_t * ast_sip_pjsip_uri_get_username (pjsip_uri *uri)
 Get the user portion of the pjsip_uri.
 
int ast_sip_push_task (struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
 
int ast_sip_push_task_synchronous (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)
 
int ast_sip_push_task_wait_servant (struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
 
char * ast_sip_rdata_get_header_value (pjsip_rx_data *rdata, const pj_str_t str)
 Get a specific header value from rdata.
 
int ast_sip_register_authenticator (struct ast_sip_authenticator *auth)
 Register a SIP authenticator.
 
void ast_sip_register_endpoint_formatter (struct ast_sip_endpoint_formatter *obj)
 Register an endpoint formatter.
 
int ast_sip_register_endpoint_identifier (struct ast_sip_endpoint_identifier *identifier)
 Register a SIP endpoint identifier.
 
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.
 
int ast_sip_register_outbound_authenticator (struct ast_sip_outbound_authenticator *auth)
 Register an outbound SIP authenticator.
 
int ast_sip_register_service (pjsip_module *module)
 Register a SIP service in Asterisk.
 
void ast_sip_register_supplement (struct ast_sip_supplement *supplement)
 Register a supplement to SIP out of dialog processing.
 
int ast_sip_requires_authentication (struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata)
 Determine if an incoming request requires authentication.
 
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.
 
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.
 
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.
 
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.
 
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.
 
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.
 
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.
 
int ast_sip_set_outbound_proxy (pjsip_tx_data *tdata, const char *proxy)
 Set the outbound proxy for an outbound SIP message.
 
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.
 
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.
 
int ast_sip_set_tpselector_from_transport (const struct ast_sip_transport *transport, pjsip_tpselector *selector)
 Sets pjsip_tpselector from ast_sip_transport.
 
int ast_sip_set_tpselector_from_transport_name (const char *transport_name, pjsip_tpselector *selector)
 Sets pjsip_tpselector from ast_sip_transport.
 
int ast_sip_str2rc (const char *name)
 Convert name to SIP response code.
 
int ast_sip_str_to_dtmf (const char *dtmf_mode)
 Convert the DTMF mode name into an enum.
 
struct ast_taskpoolast_sip_taskpool (void)
 Retrieve the SIP taskpool object.
 
long ast_sip_taskpool_queue_size (void)
 Return the size of the SIP taskpool's task queue.
 
int ast_sip_thread_is_servant (void)
 Determine if the current thread is a SIP servant thread.
 
void ast_sip_tpselector_unref (pjsip_tpselector *selector)
 Unreference a pjsip_tpselector.
 
void ast_sip_unregister_authenticator (struct ast_sip_authenticator *auth)
 Unregister a SIP authenticator.
 
void ast_sip_unregister_endpoint_formatter (struct ast_sip_endpoint_formatter *obj)
 Unregister an endpoint formatter.
 
void ast_sip_unregister_endpoint_identifier (struct ast_sip_endpoint_identifier *identifier)
 Unregister a SIP endpoint identifier.
 
void ast_sip_unregister_outbound_authenticator (struct ast_sip_outbound_authenticator *auth)
 Unregister an outbound SIP authenticator.
 
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.
 
int ast_sip_update_from (pjsip_tx_data *tdata, char *from)
 Overwrite fields in the outbound 'From' header.
 
int ast_sip_update_to_uri (pjsip_tx_data *tdata, const char *to)
 Replace the To URI in the tdata with the supplied one.
 
int ast_sip_will_uri_survive_restart (pjsip_sip_uri *uri, struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata)
 
 AST_THREADSTORAGE_CUSTOM_SCOPE (pj_thread_storage, NULL, ast_free_ptr, static)
 
 AST_THREADSTORAGE_CUSTOM_SCOPE (servant_id_storage, NULL, ast_free_ptr, static)
 
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.
 
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.
 
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 uas_use_sips_contact (pjsip_rx_data *rdata)
 Determine if a SIPS Contact header is required.
 
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 = ASTERISK_GPL_KEY , .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 = AST_RWLIST_HEAD_INIT_VALUE
 
static struct endpoint_identifiers endpoint_identifiers = AST_RWLIST_HEAD_INIT_VALUE
 
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
 
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_taskpoolsip_taskpool
 
static pjsip_module supplement_module
 
struct supplements supplements = AST_RWLIST_HEAD_INIT_VALUE
 

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.

◆ SIP_SERVANT_ID

#define SIP_SERVANT_ID   0x5E2F1D

Definition at line 2258 of file res_pjsip.c.

◆ TIMEOUT_TIMER2

#define TIMEOUT_TIMER2   5

Definition at line 1511 of file res_pjsip.c.

◆ TIMER_INACTIVE

#define TIMER_INACTIVE   0

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

Function Documentation

◆ __ast_sip_push_task_wait()

static int __ast_sip_push_task_wait ( struct ast_taskprocessor serializer,
int(*)(void *)  sip_task,
void *  task_data,
const char *  file,
int  line,
const char *  function 
)
static

Definition at line 2141 of file res_pjsip.c.

2143{
2144 if (!serializer) {
2145 return __ast_taskpool_push_wait(sip_taskpool, sip_task, task_data, file, line, function);
2146 }
2147 return __ast_taskpool_serializer_push_wait(serializer, sip_task, task_data, file, line, function);
2148}
static struct ast_taskpool * sip_taskpool
Definition res_pjsip.c:70
userdata associated with baseline taskprocessor test
int __ast_taskpool_push_wait(struct ast_taskpool *pool, int(*task)(void *data), void *data, const char *file, int line, const char *function) attribute_warn_unused_result
Push a task to the taskpool, and wait for completion.
Definition taskpool.c:635
int __ast_taskpool_serializer_push_wait(struct ast_taskprocessor *serializer, int(*task)(void *data), void *data, const char *file, int line, const char *function) attribute_warn_unused_result
Push a task to a serializer, and wait for completion.
Definition taskpool.c:882

References __ast_taskpool_push_wait(), __ast_taskpool_serializer_push_wait(), and sip_taskpool.

Referenced by __ast_sip_push_task_wait_servant().

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 4083 of file res_pjsip.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

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

2038{
2039 pj_str_t type;
2040 pj_str_t subtype;
2041 pj_str_t body_text;
2042
2043 pj_cstr(&type, body->type);
2044 pj_cstr(&subtype, body->subtype);
2045 pj_cstr(&body_text, body->body_text);
2046
2047 return pjsip_msg_body_create(pool, &type, &subtype, &body_text);
2048}
static const char type[]
const char * type
Definition res_pjsip.h:2477
const char * body_text
Definition res_pjsip.h:2481
const char * subtype
Definition res_pjsip.h:2479

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

2177{
2178 size_t chars_to_copy = MIN(size - 1, pj_strlen(src));
2179 memcpy(dest, pj_strbuf(src), chars_to_copy);
2180 dest[chars_to_copy] = '\0';
2181}
#define MIN(a, b)
Definition utils.h:252

References MIN.

Referenced by apply_dtls_attrib(), apply_negotiated_sdp_stream(), 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(), change_outgoing_sdp_stream_media_address(), channel_read_pjsip(), cli_complete_subscription_common(), cli_list_subscriptions_detail(), cli_show_subscriptions_detail(), copy_string(), determine_sip_publish_type(), dialog_info_generate_body_content(), endpoint_lookup(), evaluate_like(), extract_contact_addr(), extract_contact_addr(), extract_oli(), find_aor2(), find_aor_name(), find_authorization(), 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(), 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_ari_request(), refer_incoming_blind_request(), refer_incoming_refer_request(), register_aor_core(), 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_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 2183 of file res_pjsip.c.

2184{
2185 int res = ast_asprintf(dest, "%.*s", (int)pj_strlen(src), pj_strbuf(src));
2186
2187 if (res < 0) {
2188 *dest = NULL;
2189 }
2190
2191 return res;
2192}
#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 4083 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 2050 of file res_pjsip.c.

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

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

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

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

85{
86 char date[256];
87 struct tm tm;
88 time_t t = time(NULL);
89
90 gmtime_r(&t, &tm);
91 strftime(date, sizeof(date), "%a, %d %b %Y %T GMT", &tm);
92
93 ast_sip_add_header(tdata, "Date", date);
94}
int ast_sip_add_header(pjsip_tx_data *tdata, const char *name, const char *value)
Add a header to an outbound SIP message.
Definition res_pjsip.c:2006

References ast_sip_add_header(), and NULL.

Referenced by add_date_header(), and register_aor_core().

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

2007{
2008 pj_str_t hdr_name;
2009 pj_str_t hdr_value;
2010 pjsip_generic_string_hdr *hdr;
2011
2012 pj_cstr(&hdr_name, name);
2013 pj_cstr(&hdr_value, value);
2014
2015 hdr = pjsip_generic_string_hdr_create(tdata->pool, &hdr_name, &hdr_value);
2016
2017 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *) hdr);
2018 return 0;
2019}
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(), outgoing_request(), rfc3326_add_reason_header(), send_options_response(), sip_publication_respond(), transfer_refer(), vars_to_headers(), 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 2021 of file res_pjsip.c.

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

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

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

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

2074{
2075 size_t combined_size = strlen(body_text) + tdata->msg->body->len;
2076 struct ast_str *body_buffer = ast_str_alloca(combined_size);
2077
2078 ast_str_set(&body_buffer, 0, "%.*s%s", (int) tdata->msg->body->len, (char *) tdata->msg->body->data, body_text);
2079
2080 tdata->msg->body->data = pj_pool_alloc(tdata->pool, combined_size);
2081 pj_memcpy(tdata->msg->body->data, ast_str_buffer(body_buffer), combined_size);
2082 tdata->msg->body->len = combined_size;
2083
2084 return 0;
2085}
#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
char *attribute_pure ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition strings.h:761
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 2194 of file res_pjsip.c.

2195{
2196 int rc = 0;
2197 if (a != NULL && b != NULL) {
2198 rc = pjsip_media_type_cmp(a, b, 0) ? 0 : 1;
2199 }
2200 return rc;
2201}
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 2529 of file res_pjsip.c.

2530{
2531 const char *value;
2532
2533 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)) {
2534 value = "local";
2535 } 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)) {
2536 value = "local_merge";
2537 } 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)) {
2538 value = "local_first";
2539 } 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)) {
2540 value = "remote";
2541 } 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)) {
2542 value = "remote_merge";
2543 } 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)) {
2544 value = "remote_first";
2545 } else {
2546 value = "unknown";
2547 }
2548
2549 return value;
2550}
#define ast_sip_call_codec_pref_test(__param, __codec_pref)
Returns true if the preference is set in the parameter.
Definition res_pjsip.h:799

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

2553{
2554 pref->flags = 0;
2555
2556 if (strcmp(pref_str, "local") == 0) {
2558 } else if (is_outgoing && strcmp(pref_str, "local_merge") == 0) {
2560 } else if (strcmp(pref_str, "local_first") == 0) {
2562 } else if (strcmp(pref_str, "remote") == 0) {
2564 } else if (is_outgoing && strcmp(pref_str, "remote_merge") == 0) {
2566 } else if (strcmp(pref_str, "remote_first") == 0) {
2568 } else {
2569 return -1;
2570 }
2571
2572 return 0;
2573}
@ AST_SIP_CALL_CODEC_PREF_ALL
Definition res_pjsip.h:779
@ AST_SIP_CALL_CODEC_PREF_LOCAL
Definition res_pjsip.h:785
@ AST_SIP_CALL_CODEC_PREF_REMOTE
Definition res_pjsip.h:787
@ AST_SIP_CALL_CODEC_PREF_UNION
Definition res_pjsip.h:775
@ AST_SIP_CALL_CODEC_PREF_FIRST
Definition res_pjsip.h:781
@ AST_SIP_CALL_CODEC_PREF_INTERSECT
Definition res_pjsip.h:773
unsigned int flags
Definition utils.h:221
#define ast_set_flag(p, flag)
Definition utils.h:71

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

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

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

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

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

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

1175{
1176#ifdef HAVE_PJSIP_DLG_CREATE_UAS_AND_INC_LOCK
1177 pjsip_dialog *dlg;
1178
1179 dlg = create_dialog_uas(endpoint, rdata, status, pjsip_dlg_create_uas_and_inc_lock);
1180 if (dlg) {
1181 pjsip_dlg_dec_lock(dlg);
1182 }
1183
1184 return dlg;
1185#else
1186 return create_dialog_uas(endpoint, rdata, status, pjsip_dlg_create_uas);
1187#endif
1188}
jack_status_t status
Definition app_jack.c:149
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:1116

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

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

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

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

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

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

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

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

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

210{
212 ast_log(LOG_WARNING, "No SIP outbound authenticator registered. Cannot respond to authentication challenge\n");
213 return -1;
214 }
215 return registered_outbound_authenticator->create_request_with_auth(auths, challenge, old_request, new_request);
216}
static struct ast_sip_outbound_authenticator * registered_outbound_authenticator
Definition res_pjsip.c:183
static void challenge(const char *endpoint_id, struct ast_sip_auth *auth, pjsip_tx_data *tdata, const pjsip_rx_data *rdata, int is_stale, const pjsip_auth_algorithm *algorithm)
Send a WWW-Authenticate challenge.
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:1420

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

2445{
2446 int res = pjsip_endpt_create_response(ast_sip_get_pjsip_endpoint(), rdata, st_code, NULL, tdata);
2447
2448 if (!res) {
2449 ast_sip_mod_data_set((*tdata)->pool, (*tdata)->mod_data, supplement_module.id, MOD_DATA_CONTACT, ao2_bump(contact));
2450 }
2451
2452 return res;
2453}
#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:518
static pjsip_module supplement_module
Definition res_pjsip.c:1316
#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:3130

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

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

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

2303{
2304 unsigned int hval = 0;
2305
2306 if (!ht) {
2307 return NULL;
2308 }
2309
2310 return pj_hash_get(ht, key, PJ_HASH_KEY_STRING, &hval);
2311}

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

2315{
2316 if (!ht) {
2317 ht = pj_hash_create(pool, 11);
2318 }
2319
2320 pj_hash_set(pool, ht, key, PJ_HASH_KEY_STRING, 0, val);
2321
2322 return ht;
2323}

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

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

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

2481{
2482 switch (dtmf) {
2483 case AST_SIP_DTMF_NONE:
2484 ast_copy_string(buf, "none", buf_len);
2485 break;
2487 ast_copy_string(buf, "rfc4733", buf_len);
2488 break;
2490 ast_copy_string(buf, "inband", buf_len);
2491 break;
2492 case AST_SIP_DTMF_INFO:
2493 ast_copy_string(buf, "info", buf_len);
2494 break;
2495 case AST_SIP_DTMF_AUTO:
2496 ast_copy_string(buf, "auto", buf_len);
2497 break;
2499 ast_copy_string(buf, "auto_info", buf_len);
2500 break;
2501 default:
2502 buf[0] = '\0';
2503 return -1;
2504 }
2505 return 0;
2506}
char buf[BUFSIZE]
Definition eagi_proxy.c:66
@ AST_SIP_DTMF_NONE
Definition res_pjsip.h:549
@ AST_SIP_DTMF_AUTO_INFO
Definition res_pjsip.h:560
@ AST_SIP_DTMF_AUTO
Definition res_pjsip.h:558
@ AST_SIP_DTMF_INBAND
Definition res_pjsip.h:554
@ AST_SIP_DTMF_INFO
Definition res_pjsip.h:556
@ AST_SIP_DTMF_RFC_4733
Definition res_pjsip.h:552

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

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

References NULL, and send_request_wrapper::tdata.

Referenced by check_request_status(), 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 593 of file res_pjsip.c.

593 {
595
597 return NULL;
598 }
599
601}
#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:574
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:981

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

501{
502 int res = 0;
505 *count = 0;
507 if (i->format_ami && ((res = i->format_ami(endpoint, ami)) < 0)) {
508 return res;
509 }
510
511 if (!res) {
512 (*count)++;
513 }
514 }
515 return 0;
516}
ast_mutex_t lock
Definition app_sla.c:337
#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.
#define AST_RWLIST_TRAVERSE
#define SCOPED_LOCK(varname, lock, lockfunc, unlockfunc)
Scoped Locks.
Definition lock.h:590
An entity responsible formatting endpoint information.
Definition res_pjsip.h:3257
struct ast_sip_endpoint_formatter * next
Definition res_pjsip.h:3263
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:3261

References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_sip_endpoint_formatter::format_ami, lock, ast_sip_endpoint_formatter::next, 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 562 of file res_pjsip.c.

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

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

3225{
3226 char *destination;
3227 char *slash = NULL;
3228 char *atsign = NULL;
3229 char *scheme = NULL;
3230 struct ast_sip_endpoint *endpoint = NULL;
3231
3232 destination = ast_strdupa(to);
3233
3234 slash = strchr(destination, '/');
3235 atsign = strchr(destination, '@');
3236 scheme = S_OR(strstr(destination, "sip:"), strstr(destination, "sips:"));
3237
3238 if (!slash && !atsign && !scheme) {
3239 /*
3240 * If there's only a single token, it can be either...
3241 * endpoint
3242 * host
3243 */
3244 return handle_single_token(to, destination, get_default_outbound, uri);
3245 }
3246
3247 if (slash) {
3248 /*
3249 * If there's a '/', then the form must be one of the following...
3250 * PJSIP/user@endpoint
3251 * endpoint/aor
3252 * endpoint/uri
3253 */
3254 return handle_slash(to, destination, uri, slash, atsign, scheme);
3255 }
3256
3257 if (atsign && !scheme) {
3258 /*
3259 * If there's an '@' but no scheme then it's either following an endpoint name
3260 * and being followed by a domain name (which we discard).
3261 * OR is's a user@host uri without a scheme. It's probably the latter but because
3262 * endpoint@domain looks just like user@host, we'll test for endpoint first.
3263 */
3264 return handle_atsign(to, destination, uri, slash, atsign, scheme, get_default_outbound);
3265 }
3266
3267 /*
3268 * If all else fails, we assume it's a URI or just a hostname.
3269 */
3270 if (scheme) {
3271 *uri = ast_strdup(destination);
3272 if (!(*uri)) {
3273 goto failure;
3274 }
3275 ast_debug(3, "Dest: '%s' Didn't find an endpoint but did find a scheme so using URI '%s'%s\n",
3276 to, *uri, get_default_outbound ? " with default endpoint" : "");
3277 } else {
3278 *uri = ast_malloc(strlen(destination) + strlen("sip:") + 1);
3279 if (!(*uri)) {
3280 goto failure;
3281 }
3282 sprintf(*uri, "sip:%s", destination);
3283 ast_debug(3, "Dest: '%s' Didn't find an endpoint and didn't find scheme so adding scheme and using URI '%s'%s\n",
3284 to, *uri, get_default_outbound ? " with default endpoint" : "");
3285 }
3286 if (get_default_outbound) {
3288 }
3289
3290 return endpoint;
3291
3292failure:
3293 ao2_cleanup(endpoint);
3294 *uri = NULL;
3295 return NULL;
3296}
#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:3009
static struct ast_sip_endpoint * handle_single_token(const char *to, char *destination, int get_default_outbound, char **uri)
Definition res_pjsip.c:2930
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:3166
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:1067

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

2456{
2457 if (af == pj_AF_INET() && !ast_strlen_zero(host_ip_ipv4_string)) {
2458 pj_sockaddr_copy_addr(addr, &host_ip_ipv4);
2459 return 0;
2460 } else if (af == pj_AF_INET6() && !ast_strlen_zero(host_ip_ipv6_string)) {
2461 pj_sockaddr_copy_addr(addr, &host_ip_ipv6);
2462 return 0;
2463 }
2464
2465 return -1;
2466}
static pj_sockaddr host_ip_ipv4
Definition res_pjsip.c:73
static char host_ip_ipv6_string[PJ_INET6_ADDRSTRLEN]
Definition res_pjsip.c:82
static pj_sockaddr host_ip_ipv6
Definition res_pjsip.c:79
static char host_ip_ipv4_string[PJ_INET6_ADDRSTRLEN]
Definition res_pjsip.c:76

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

2469{
2470 if (af == pj_AF_INET()) {
2471 return host_ip_ipv4_string;
2472 } else if (af == pj_AF_INET6()) {
2473 return host_ip_ipv6_string;
2474 }
2475
2476 return NULL;
2477}

References host_ip_ipv4_string, host_ip_ipv6_string, and NULL.

Referenced by create_local_sdp(), create_outgoing_sdp_stream(), 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 518 of file res_pjsip.c.

519{
520 return ast_pjsip_endpoint;
521}
static pjsip_endpoint * ast_pjsip_endpoint
Definition res_pjsip.c:68

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(), load_module(), load_module(), load_module(), load_module(), load_module(), load_module(), logging_on_rx_msg(), logging_on_tx_msg(), maintenance_on_rx_request(), 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(), register_aor_core(), 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 696 of file res_pjsip.c.

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

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

3526{
3527 /* Possible values taken from causes.h */
3528 switch(cause) {
3529 case 302: /* Redirect */
3531 case 401: /* Unauthorized */
3533 case 403: /* Not found */
3535 case 404: /* Not found */
3536 return AST_CAUSE_UNALLOCATED;
3537 case 405: /* Method not allowed */
3539 case 407: /* Proxy authentication required */
3541 case 408: /* No reaction */
3543 case 409: /* Conflict */
3545 case 410: /* Gone */
3547 case 411: /* Length required */
3549 case 413: /* Request entity too large */
3551 case 414: /* Request URI too large */
3553 case 415: /* Unsupported media type */
3555 case 420: /* Bad extension */
3557 case 480: /* No answer */
3558 return AST_CAUSE_NO_ANSWER;
3559 case 481: /* No answer */
3561 case 482: /* Loop detected */
3563 case 483: /* Too many hops */
3564 return AST_CAUSE_NO_ANSWER;
3565 case 484: /* Address incomplete */
3567 case 485: /* Ambiguous */
3568 return AST_CAUSE_UNALLOCATED;
3569 case 486: /* Busy everywhere */
3570 return AST_CAUSE_BUSY;
3571 case 487: /* Request terminated */
3573 case 488: /* No codecs approved */
3575 case 491: /* Request pending */
3577 case 493: /* Undecipherable */
3579 case 500: /* Server internal failure */
3580 return AST_CAUSE_FAILURE;
3581 case 501: /* Call rejected */
3583 case 502:
3585 case 503: /* Service unavailable */
3586 return AST_CAUSE_CONGESTION;
3587 case 504: /* Gateway timeout */
3589 case 505: /* SIP version not supported */
3591 case 600: /* Busy everywhere */
3592 return AST_CAUSE_USER_BUSY;
3593 case 603: /* Decline */
3595 case 604: /* Does not exist anywhere */
3596 return AST_CAUSE_UNALLOCATED;
3597 case 606: /* Not acceptable */
3599 default:
3600 if (cause < 500 && cause >= 400) {
3601 /* 4xx class error that is unknown - someting wrong with our request */
3603 } else if (cause < 600 && cause >= 500) {
3604 /* 5xx class error - problem in the remote end */
3605 return AST_CAUSE_CONGESTION;
3606 } else if (cause < 700 && cause >= 600) {
3607 /* 6xx - global errors in the 4xx class */
3609 }
3610 return AST_CAUSE_NORMAL;
3611 }
3612 /* Never reached */
3613 return 0;
3614}
#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_REDIRECTED_TO_NEW_DESTINATION
Definition causes.h:113
#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_REDIRECTED_TO_NEW_DESTINATION, 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 324 of file res_pjsip.c.

325{
326 struct endpoint_identifier_list *iter;
327 struct ast_sip_endpoint *endpoint = NULL;
331 endpoint = iter->identifier->identify_endpoint(rdata);
332 if (endpoint) {
333 break;
334 }
335 }
336 return endpoint;
337}
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:1432
struct ast_sip_endpoint_identifier * identifier
Definition res_pjsip.c:221

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

3448{
3449 return (ast_sip_is_uri_sip_sips(uri) || PJSIP_URI_SCHEME_IS_TEL(uri));
3450}
int ast_sip_is_uri_sip_sips(pjsip_uri *uri)
Check whether a pjsip_uri is SIP/SIPS or not.
Definition res_pjsip.c:3442

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

2224{
2225 pjsip_media_type compare;
2226
2227 if (!content_type) {
2228 return 0;
2229 }
2230
2231 pjsip_media_type_init2(&compare, type, subtype);
2232
2233 return pjsip_media_type_cmp(content_type, &compare, 0) ? 0 : -1;
2234}
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 2203 of file res_pjsip.c.

2204{
2205 int rc = 0;
2206 pjsip_media_type *b = NULL;
2207 va_list ap;
2208
2209 ast_assert(a != NULL);
2210 va_start(ap, a);
2211
2212 while ((b = va_arg(ap, pjsip_media_type *)) != (pjsip_media_type *)SENTINEL) {
2213 if (pjsip_media_type_cmp(a, b, 0) == 0) {
2214 rc = 1;
2215 break;
2216 }
2217 }
2218 va_end(ap);
2219
2220 return rc;
2221}
#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 3442 of file res_pjsip.c.

3443{
3444 return (PJSIP_URI_SCHEME_IS_SIP(uri) || PJSIP_URI_SCHEME_IS_SIPS(uri));
3445}

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

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

2826{
2827 pjsip_name_addr *id_name_addr;
2828 pjsip_sip_uri *id_uri;
2829
2830 id_name_addr = (pjsip_name_addr *) id_hdr->uri;
2831 id_uri = pjsip_uri_get_uri(id_name_addr->uri);
2832
2833 if (id->name.valid) {
2834 if (!ast_strlen_zero(id->name.str)) {
2835 int name_buf_len = strlen(id->name.str) * 2 + 1;
2836 char *name_buf = ast_alloca(name_buf_len);
2837
2838 ast_escape_quoted(id->name.str, name_buf, name_buf_len);
2839 pj_strdup2(pool, &id_name_addr->display, name_buf);
2840 } else {
2841 pj_strdup2(pool, &id_name_addr->display, NULL);
2842 }
2843 }
2844
2845 if (id->number.valid) {
2846 pj_strdup2(pool, &id_uri->user, id->number.str);
2847 }
2848}
enum queue_result id
Definition app_queue.c:1790
char * ast_escape_quoted(const char *string, char *outbuf, int buflen)
Escape characters found in a quoted string.
Definition utils.c:815

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

float ast_sip_parse_qvalue ( const char *  q_value)

Parses a string representing a q_value to a float.

Valid q values must be in the range from 0.0 to 1.0 inclusively.

Parameters
q_valueString representing a floating point value
Return values
Theparsed qvalue or -1.0 on failure.

Definition at line 3505 of file res_pjsip.c.

3505 {
3506 char *end = NULL;
3507 float ret = strtof(q_value, &end);
3508
3509 if (end == q_value) {
3510 return -1.0f; /* Not a number. */
3511 }
3512 if ('\0' != *end) {
3513 return -1.0f; /* Extra characters at end of input. */
3514 }
3515 if (!isfinite(ret)) {
3516 return -1.0f; /* NaN or Infinity. */
3517 }
3518 if (ret > 1.0f || ret < 0.0f) {
3519 return -1.0f; /* Out of valid range. */
3520 }
3521 return ret;
3522}
char * end
Definition eagi_proxy.c:73

References end, and NULL.

Referenced by ast_sip_str_to_security_mechanism(), and extract_q_value().

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

3472{
3473 if (ast_sip_is_uri_sip_sips(uri)) {
3474 pjsip_sip_uri *sip_uri = pjsip_uri_get_uri(uri);
3475 if (!sip_uri) {
3476 return &AST_PJ_STR_EMPTY;
3477 }
3478 return &sip_uri->host;
3479 } else if (PJSIP_URI_SCHEME_IS_TEL(uri)) {
3480 return &AST_PJ_STR_EMPTY;
3481 }
3482
3483 return &AST_PJ_STR_EMPTY;
3484}
static const pj_str_t AST_PJ_STR_EMPTY
Definition res_pjsip.h:112

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

3487{
3488 if (ast_sip_is_uri_sip_sips(uri)) {
3489 pjsip_sip_uri *sip_uri = pjsip_uri_get_uri(uri);
3490 if (!sip_uri) {
3491 return NULL;
3492 }
3493 return pjsip_param_find(&sip_uri->other_param, param_str);
3494 } else if (PJSIP_URI_SCHEME_IS_TEL(uri)) {
3495 pjsip_tel_uri *tel_uri = pjsip_uri_get_uri(uri);
3496 if (!tel_uri) {
3497 return NULL;
3498 }
3499 return pjsip_param_find(&tel_uri->other_param, param_str);
3500 }
3501
3502 return NULL;
3503}

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

3453{
3454 if (ast_sip_is_uri_sip_sips(uri)) {
3455 pjsip_sip_uri *sip_uri = pjsip_uri_get_uri(uri);
3456 if (!sip_uri) {
3457 return &AST_PJ_STR_EMPTY;
3458 }
3459 return &sip_uri->user;
3460 } else if (PJSIP_URI_SCHEME_IS_TEL(uri)) {
3461 pjsip_tel_uri *tel_uri = pjsip_uri_get_uri(uri);
3462 if (!tel_uri) {
3463 return &AST_PJ_STR_EMPTY;
3464 }
3465 return &tel_uri->number;
3466 }
3467
3468 return &AST_PJ_STR_EMPTY;
3469}

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

int ast_sip_push_task ( struct ast_taskprocessor serializer,
int(*)(void *)  sip_task,
void *  task_data 
)

Definition at line 2111 of file res_pjsip.c.

2112{
2113 return __ast_sip_push_task(serializer, sip_task, task_data, NULL, 0, NULL);
2114}
int __ast_sip_push_task(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data, const char *file, int line, const char *function)
Pushes a task to SIP servants.
Definition res_pjsip.c:2100

References __ast_sip_push_task(), and NULL.

◆ ast_sip_push_task_synchronous()

int ast_sip_push_task_synchronous ( struct ast_taskprocessor serializer,
int(*)(void *)  sip_task,
void *  task_data 
)

Definition at line 2128 of file res_pjsip.c.

2129{
2131}
int __ast_sip_push_task_synchronous(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data, const char *file, int line, const char *function)
Push a task to SIP servants and wait for it to complete.
Definition res_pjsip.c:2160

References __ast_sip_push_task_synchronous(), and NULL.

◆ ast_sip_push_task_wait_serializer()

int ast_sip_push_task_wait_serializer ( struct ast_taskprocessor serializer,
int(*)(void *)  sip_task,
void *  task_data 
)

Definition at line 2136 of file res_pjsip.c.

2137{
2139}
int __ast_sip_push_task_wait_serializer(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data, const char *file, int line, const char *function)
Push a task to the serializer and wait for it to complete.
Definition res_pjsip.c:2166

References __ast_sip_push_task_wait_serializer(), and NULL.

◆ ast_sip_push_task_wait_servant()

int ast_sip_push_task_wait_servant ( struct ast_taskprocessor serializer,
int(*)(void *)  sip_task,
void *  task_data 
)

Definition at line 2120 of file res_pjsip.c.

2121{
2123}
int __ast_sip_push_task_wait_servant(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data, const char *file, int line, const char *function)
Push a task to SIP servants and wait for it to complete.
Definition res_pjsip.c:2150

References __ast_sip_push_task_wait_servant(), and NULL.

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

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

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

135{
137 ast_log(LOG_WARNING, "Authenticator %p is already registered. Cannot register a new one\n", registered_authenticator);
138 return -1;
139 }
141 ast_debug(1, "Registered SIP authenticator module %p\n", auth);
142
143 return 0;
144}

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

480{
483}
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition linkedlists.h:52
#define AST_RWLIST_INSERT_TAIL

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

305{
307}
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:227

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

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

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, endpoint_identifier_list::list, lock, LOG_ERROR, name, endpoint_identifier_list::name, endpoint_identifier_list::priority, and SCOPED_LOCK.

Referenced by ast_sip_register_endpoint_identifier(), load_module(), load_module(), 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 185 of file res_pjsip.c.

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

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

112{
114}
#define ast_sip_push_task_wait_servant(serializer, sip_task, task_data)
Definition res_pjsip.h:2139
static int register_service(void *data)
Definition res_pjsip.c:96

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

1455{
1456 struct ast_sip_supplement *iter;
1457 int inserted = 0;
1459
1461 if (iter->priority > supplement->priority) {
1463 inserted = 1;
1464 break;
1465 }
1466 }
1468
1469 if (!inserted) {
1471 }
1472}
A supplement to SIP message processing.
Definition res_pjsip.h:3382
enum ast_sip_supplement_priority priority
Definition res_pjsip.h:3386
struct ast_sip_supplement * next
Definition res_pjsip.h:3432

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

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

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

603 {
604 RAII_VAR(struct ast_sip_transport *, transport, NULL, ao2_cleanup);
605 RAII_VAR(struct ast_sip_transport_state *, transport_state, NULL, ao2_cleanup);
606 struct ast_sip_request_transport_details details = { 0, };
607 pjsip_sip_uri *tmp_uri;
608 pjsip_dialog *dlg;
609 struct ast_sockaddr addr = { { 0, } };
610
611 if ((tmp_uri = ast_sip_get_contact_sip_uri(tdata))) {
612 pj_strdup(tdata->pool, &uri->host, &tmp_uri->host);
613 uri->port = tmp_uri->port;
614 } else if ((dlg = pjsip_tdata_get_dlg(tdata))
615 && (tmp_uri = pjsip_uri_get_uri(dlg->local.info->uri))
616 && (PJSIP_URI_SCHEME_IS_SIP(tmp_uri) || PJSIP_URI_SCHEME_IS_SIPS(tmp_uri))) {
617 pj_strdup(tdata->pool, &uri->host, &tmp_uri->host);
618 uri->port = tmp_uri->port;
619 }
620
621 if (ast_sip_set_request_transport_details(&details, tdata, 1)
622 || !(transport_state = ast_sip_find_transport_state_in_use(&details))
623 || !(transport = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "transport", transport_state->id))) {
624 return 0;
625 }
626
627 if (transport_state->localnet) {
628 ast_sockaddr_parse(&addr, tdata->tp_info.dst_name, PARSE_PORT_FORBID);
629 ast_sockaddr_set_port(&addr, tdata->tp_info.dst_port);
630 if (ast_sip_transport_is_local(transport_state, &addr)) {
631 return 0;
632 }
633 }
634
635 if (!ast_sockaddr_isnull(&transport_state->external_signaling_address)) {
636 pj_strdup2(tdata->pool, &uri->host, ast_sockaddr_stringify_host(&transport_state->external_signaling_address));
637 }
638
639 if (transport->external_signaling_port) {
640 uri->port = transport->external_signaling_port;
641 }
642
643 return 0;
644}
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:593
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:646
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:562
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:213
void * ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
Retrieve an object using its unique identifier.
Definition sorcery.c:1917
Structure which contains information about a transport.
Definition res_pjsip.h:337
Structure for SIP transport information.
Definition res_pjsip.h:117
Transport to bind to.
Definition res_pjsip.h:219
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 1936 of file res_pjsip.c.

1939{
1940 struct ast_sip_supplement *supplement;
1941 struct send_request_data *req_data;
1942 struct ast_sip_contact *contact;
1943
1944 req_data = send_request_data_alloc(endpoint, token, callback);
1945 if (!req_data) {
1946 pjsip_tx_data_dec_ref(tdata);
1947 return -1;
1948 }
1949
1950 if (endpoint) {
1952 }
1953
1954 contact = ast_sip_mod_data_get(tdata->mod_data, supplement_module.id, MOD_DATA_CONTACT);
1955
1957 AST_LIST_TRAVERSE(&supplements, supplement, next) {
1958 if (supplement->outgoing_request
1959 && does_method_match(&tdata->msg->line.req.method.name, supplement->method)) {
1960 supplement->outgoing_request(endpoint, contact, tdata);
1961 }
1962 }
1964
1965 ast_sip_mod_data_set(tdata->pool, tdata->mod_data, supplement_module.id, MOD_DATA_CONTACT, NULL);
1966 ao2_cleanup(contact);
1967
1968 if (endpt_send_request(endpoint, tdata, timeout, req_data, send_request_cb)
1969 != PJ_SUCCESS) {
1970 ao2_cleanup(req_data);
1971 return -1;
1972 }
1973
1974 return 0;
1975}
static struct ast_channel * callback(struct ast_channelstorage_instance *driver, ao2_callback_data_fn *cb_fn, void *arg, void *data, int ao2_flags, int rdlock)
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
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:1532
static void send_request_cb(void *token, pjsip_event *e)
Definition res_pjsip.c:1880
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:1694
static pj_bool_t does_method_match(const pj_str_t *message_method, const char *supplement_method)
Definition res_pjsip.c:1497
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:3098
Contact associated with an address of record.
Definition res_pjsip.h:392
struct ast_sip_endpoint * endpoint
Definition res_pjsip.h:424
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:3425
const char * method
Definition res_pjsip.h:3384
Structure to hold information about an outbound request.
Definition res_pjsip.c:1514

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

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

References ast_assert, ast_sip_send_out_of_dialog_request(), callback(), 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_message_to_uri(), send_unsolicited_mwi_notify_to_contact(), and sendtext().

◆ ast_sip_send_response()

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

Send a response to an out of dialog request.

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

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

Definition at line 2371 of file res_pjsip.c.

2372{
2373 pj_status_t status;
2374
2375 supplement_outgoing_response(tdata, sip_endpoint);
2376 status = pjsip_endpt_send_response(ast_sip_get_pjsip_endpoint(), res_addr, tdata, NULL, NULL);
2377 if (status != PJ_SUCCESS) {
2378 pjsip_tx_data_dec_ref(tdata);
2379 }
2380
2381 return status == PJ_SUCCESS ? 0 : -1;
2382}
static void supplement_outgoing_response(pjsip_tx_data *tdata, struct ast_sip_endpoint *sip_endpoint)
Definition res_pjsip.c:2349

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

2400{
2401 pjsip_transaction *tsx;
2402 pj_grp_lock_t *tsx_glock;
2403 pj_pool_t *pool;
2404
2405 /* Create and initialize global lock pool */
2406 pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(), "stateful response", PJSIP_POOL_TSX_LEN, PJSIP_POOL_TSX_INC);
2407 if (!pool){
2408 /* ast_sip_create_response bumps the refcount of the contact and adds it to the tdata.
2409 * We'll leak that reference if we don't get rid of it here.
2410 */
2412 return -1;
2413 }
2414 /* Create with handler so that we can release the pool once the glock derefs out */
2415 if(pj_grp_lock_create_w_handler(pool, NULL, pool, &pool_destroy_callback, &tsx_glock) != PJ_SUCCESS) {
2417 pool_destroy_callback((void *) pool);
2418 return -1;
2419 }
2420 /* We need an additional reference as the qualify thread may destroy this out
2421 * from under us. Add it now before it gets added to the tsx. */
2422 pj_grp_lock_add_ref(tsx_glock);
2423
2424 if (pjsip_tsx_create_uas2(NULL, rdata, tsx_glock, &tsx) != PJ_SUCCESS) {
2426 pj_grp_lock_dec_ref(tsx_glock);
2427 return -1;
2428 }
2429
2430 pjsip_tsx_recv_msg(tsx, rdata);
2431 supplement_outgoing_response(tdata, sip_endpoint);
2432
2433 if (pjsip_tsx_send_msg(tsx, tdata) != PJ_SUCCESS) {
2434 pj_grp_lock_dec_ref(tsx_glock);
2435 pjsip_tx_data_dec_ref(tdata);
2436 return -1;
2437 }
2438
2439 pj_grp_lock_dec_ref(tsx_glock);
2440 return 0;
2441}
static void clean_contact_from_tdata(pjsip_tx_data *tdata)
Definition res_pjsip.c:2390
static void pool_destroy_callback(void *arg)
Definition res_pjsip.c:2384

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

2798{
2799 return !set_id_from_pai(rdata, id) || !set_id_from_rpid(rdata, id) ? 0 : -1;
2800}
static int set_id_from_pai(pjsip_rx_data *rdata, struct ast_party_id *id)
Definition res_pjsip.c:2685
static int set_id_from_rpid(pjsip_rx_data *rdata, struct ast_party_id *id)
Definition res_pjsip.c:2726

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

2803{
2804 if (trust_inbound && (!set_id_from_pai(rdata, id) || !set_id_from_rpid(rdata, id))) {
2805 /* Trusted: Check PAI and RPID */
2806 ast_free(id->tag);
2807 id->tag = ast_strdup(default_id->tag);
2808 return 0;
2809 }
2810 /* Not trusted: check the endpoint config or use From. */
2811 ast_party_id_copy(id, default_id);
2812 if (!default_id->number.valid) {
2813 set_id_from_from(rdata, id);
2814 }
2815 return 0;
2816}
void ast_party_id_copy(struct ast_party_id *dest, const struct ast_party_id *src)
Copy the source party id information to the destination party id.
Definition channel.c:1752
static int set_id_from_from(struct pjsip_rx_data *rdata, struct ast_party_id *id)
Definition res_pjsip.c:2778
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 1990 of file res_pjsip.c.

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

References NULL.

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

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

References ast_sip_get_contact_sip_uri(), AST_TRANSPORT_TCP, AST_TRANSPORT_TLS, AST_TRANSPORT_UDP, ast_sip_request_transport_details::factory, 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 909 of file res_pjsip.c.

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

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

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

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

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

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

3710{
3711 int i;
3712
3713 if (ast_strlen_zero(name)) {
3714 return -1;
3715 }
3716
3717 for (i = 0; i < ARRAY_LEN(rc_map); i++) {
3718 if (strcasecmp(rc_map[i].short_name, name) == 0 ||
3719 strcasecmp(rc_map[i].long_name, name) == 0) {
3720 return rc_map[i].code;
3721 }
3722 }
3723
3724 return -1;
3725}
static const struct response_code_map rc_map[]
Definition res_pjsip.c:3629
#define ARRAY_LEN(a)
Definition utils.h:706

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

2509{
2510 int result = -1;
2511
2512 if (!strcasecmp(dtmf_mode, "info")) {
2514 } else if (!strcasecmp(dtmf_mode, "rfc4733")) {
2516 } else if (!strcasecmp(dtmf_mode, "inband")) {
2518 } else if (!strcasecmp(dtmf_mode, "none")) {
2520 } else if (!strcasecmp(dtmf_mode, "auto")) {
2522 } else if (!strcasecmp(dtmf_mode, "auto_info")) {
2524 }
2525
2526 return result;
2527}
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_taskpool()

struct ast_taskpool * ast_sip_taskpool ( void  )

Retrieve the SIP taskpool object.

Definition at line 3437 of file res_pjsip.c.

3438{
3439 return sip_taskpool;
3440}

References sip_taskpool.

Referenced by load_module().

◆ ast_sip_taskpool_queue_size()

long ast_sip_taskpool_queue_size ( void  )

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

Since
13.7.0

Definition at line 3432 of file res_pjsip.c.

3433{
3435}
long ast_taskpool_queue_size(struct ast_taskpool *pool)
Get the current number of queued tasks in the taskpool.
Definition taskpool.c:464

References ast_taskpool_queue_size(), and sip_taskpool.

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

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

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

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

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

310{
311 struct endpoint_identifier_list *iter;
314 if (iter->identifier == identifier) {
316 ast_free(iter);
317 ast_debug(1, "Unregistered endpoint identifier %p\n", identifier);
318 break;
319 }
320 }
322}

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, endpoint_identifier_list::list, lock, and SCOPED_LOCK.

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

198{
200 ast_log(LOG_WARNING, "Trying to unregister outbound authenticator %p but outbound authenticator %p registered\n",
202 return;
203 }
205 ast_debug(1, "Unregistered SIP outbound authenticator %p\n", auth);
206}

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

128{
130}
static int unregister_service(void *data)
Definition res_pjsip.c:116

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(), load_module(), load_module(), load_module(), load_module(), unload_module(), unload_module(), unload_module(), unload_module(), unload_module(), unload_module(), unload_module(), unload_module(), unload_module(), unload_module(), unload_module(), unload_module(), unload_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 1474 of file res_pjsip.c.

1475{
1476 struct ast_sip_supplement *iter;
1478
1480 if (supplement == iter) {
1482 break;
1483 }
1484 }
1486}

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

3359{
3360 pjsip_name_addr *name_addr;
3361 pjsip_sip_uri *uri;
3362 pjsip_name_addr *parsed_name_addr;
3363 pjsip_from_hdr *from_hdr;
3364
3365 if (ast_strlen_zero(from)) {
3366 return 0;
3367 }
3368
3369 from_hdr = PJSIP_MSG_FROM_HDR(tdata->msg);
3370 if (!from_hdr) {
3371 return -1;
3372 }
3373 name_addr = (pjsip_name_addr *) from_hdr->uri;
3374 uri = pjsip_uri_get_uri(name_addr);
3375
3376 parsed_name_addr = (pjsip_name_addr *) pjsip_parse_uri(tdata->pool, from,
3377 strlen(from), PJSIP_PARSE_URI_AS_NAMEADDR);
3378 if (parsed_name_addr) {
3379 pjsip_sip_uri *parsed_uri;
3380
3381 if (!PJSIP_URI_SCHEME_IS_SIP(parsed_name_addr->uri)
3382 && !PJSIP_URI_SCHEME_IS_SIPS(parsed_name_addr->uri)) {
3383 ast_log(LOG_WARNING, "From address '%s' is not a valid SIP/SIPS URI\n", from);
3384 return -1;
3385 }
3386
3387 parsed_uri = pjsip_uri_get_uri(parsed_name_addr->uri);
3388
3389 if (pj_strlen(&parsed_name_addr->display)) {
3390 pj_strdup(tdata->pool, &name_addr->display, &parsed_name_addr->display);
3391 }
3392
3393 /* Unlike the To header, we only want to replace the user, host and port */
3394 pj_strdup(tdata->pool, &uri->user, &parsed_uri->user);
3395 pj_strdup(tdata->pool, &uri->host, &parsed_uri->host);
3396 uri->port = parsed_uri->port;
3397
3398 return 0;
3399 } else {
3400 /* assume it is 'user[@domain]' format */
3401 char *domain = strchr(from, '@');
3402
3403 if (domain) {
3404 pj_str_t pj_from;
3405
3406 pj_strset3(&pj_from, from, domain);
3407 pj_strdup(tdata->pool, &uri->user, &pj_from);
3408
3409 pj_strdup2(tdata->pool, &uri->host, domain + 1);
3410 } else {
3411 pj_strdup2(tdata->pool, &uri->user, from);
3412 }
3413
3414 return 0;
3415 }
3416
3417 return -1;
3418}

References ast_log, ast_strlen_zero(), and LOG_WARNING.

Referenced by msg_send(), refer_send(), and send_message_to_uri().

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

3299{
3300 pjsip_name_addr *parsed_name_addr;
3301 pjsip_sip_uri *sip_uri;
3302 pjsip_name_addr *tdata_name_addr;
3303 pjsip_sip_uri *tdata_sip_uri;
3304 pjsip_to_hdr *to_hdr;
3305 char *buf = NULL;
3306#define DEBUG_BUF_SIZE 256
3307
3308 parsed_name_addr = (pjsip_name_addr *) pjsip_parse_uri(tdata->pool, (char*)to, strlen(to),
3309 PJSIP_PARSE_URI_AS_NAMEADDR);
3310
3311 if (!parsed_name_addr || (!PJSIP_URI_SCHEME_IS_SIP(parsed_name_addr->uri)
3312 && !PJSIP_URI_SCHEME_IS_SIPS(parsed_name_addr->uri))) {
3313 ast_log(LOG_WARNING, "To address '%s' is not a valid SIP/SIPS URI\n", to);
3314 return -1;
3315 }
3316
3317 sip_uri = pjsip_uri_get_uri(parsed_name_addr->uri);
3318 if (DEBUG_ATLEAST(3)) {
3320 pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, sip_uri, buf, DEBUG_BUF_SIZE);
3321 ast_debug(3, "Parsed To: %.*s %s\n", (int)parsed_name_addr->display.slen,
3322 parsed_name_addr->display.ptr, buf);
3323 }
3324
3325 to_hdr = PJSIP_MSG_TO_HDR(tdata->msg);
3326 tdata_name_addr = to_hdr ? (pjsip_name_addr *) to_hdr->uri : NULL;
3327 if (!tdata_name_addr || (!PJSIP_URI_SCHEME_IS_SIP(tdata_name_addr->uri)
3328 && !PJSIP_URI_SCHEME_IS_SIPS(tdata_name_addr->uri))) {
3329 /* Highly unlikely but we have to check */
3330 ast_log(LOG_WARNING, "tdata To address '%s' is not a valid SIP/SIPS URI\n", to);
3331 return -1;
3332 }
3333
3334 tdata_sip_uri = pjsip_uri_get_uri(tdata_name_addr->uri);
3335 if (DEBUG_ATLEAST(3)) {
3336 buf[0] = '\0';
3337 pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, tdata_sip_uri, buf, DEBUG_BUF_SIZE);
3338 ast_debug(3, "Original tdata To: %.*s %s\n", (int)tdata_name_addr->display.slen,
3339 tdata_name_addr->display.ptr, buf);
3340 }
3341
3342 /* Replace the uri */
3343 pjsip_sip_uri_assign(tdata->pool, tdata_sip_uri, sip_uri);
3344 /* The display name isn't part of the URI so we need to replace it separately */
3345 pj_strdup(tdata->pool, &tdata_name_addr->display, &parsed_name_addr->display);
3346
3347 if (DEBUG_ATLEAST(3)) {
3348 buf[0] = '\0';
3349 pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, tdata_sip_uri, buf, 256);
3350 ast_debug(3, "New tdata To: %.*s %s\n", (int)tdata_name_addr->display.slen,
3351 tdata_name_addr->display.ptr, buf);
3352 }
3353
3354 return 0;
3355#undef DEBUG_BUF_SIZE
3356}
#define DEBUG_ATLEAST(level)
#define DEBUG_BUF_SIZE

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

Referenced by msg_send(), refer_send(), and send_message_to_uri().

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

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

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

Referenced by register_aor_core(), and subscription_persistence_update().

◆ AST_THREADSTORAGE_CUSTOM_SCOPE() [1/2]

AST_THREADSTORAGE_CUSTOM_SCOPE ( pj_thread_storage  ,
NULL  ,
ast_free_ptr  ,
static   
)

◆ AST_THREADSTORAGE_CUSTOM_SCOPE() [2/2]

AST_THREADSTORAGE_CUSTOM_SCOPE ( servant_id_storage  ,
NULL  ,
ast_free_ptr  ,
static   
)

◆ check_request_status()

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

Definition at line 1837 of file res_pjsip.c.

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

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

2391{
2392 struct ast_sip_contact *contact;
2393 contact = ast_sip_mod_data_get(tdata->mod_data, supplement_module.id, MOD_DATA_CONTACT);
2394 ao2_cleanup(contact);
2395 ast_sip_mod_data_set(tdata->pool, tdata->mod_data, supplement_module.id, MOD_DATA_CONTACT, NULL);
2396 pjsip_tx_data_dec_ref(tdata);
2397}

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

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

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

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

References a, ast_cli(), ast_free, ast_str_buffer(), ast_str_create, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, 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 1116 of file res_pjsip.c.

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

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

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

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

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

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

355{
356 struct ast_cli_args *a = v_a;
357
359 pj_log_set_level(3);
360 }
362 pjsip_endpt_dump(ast_sip_get_pjsip_endpoint(), a->argc == 4 ? PJ_TRUE : PJ_FALSE);
364 pj_log_set_level(ast_option_pjproject_log_level);
365
366 return 0;
367}
int ast_option_pjproject_log_level
Definition options.c:75
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_option_pjproject_log_level, 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 1497 of file res_pjsip.c.

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

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

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

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

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

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

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

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

2649{
2650 static const pj_str_t from = { "From", 4 };
2651 pj_str_t header_content;
2652 pjsip_fromto_hdr *parsed_hdr;
2653 pjsip_generic_string_hdr *ident = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg,
2654 header_name, NULL);
2655 int parsed_len;
2656
2657 if (!ident) {
2658 return NULL;
2659 }
2660
2661 pj_strdup_with_null(rdata->tp_info.pool, &header_content, &ident->hvalue);
2662
2663 parsed_hdr = pjsip_parse_hdr(rdata->tp_info.pool, &from, header_content.ptr,
2664 pj_strlen(&header_content), &parsed_len);
2665
2666 if (!parsed_hdr) {
2667 return NULL;
2668 }
2669
2670 return parsed_hdr;
2671}

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

1295{
1296 int i;
1297 for (i = 0; i < ARRAY_LEN(methods); ++i) {
1298 if (!strcmp(method, methods[i].method)) {
1299 return methods[i].pmethod;
1300 }
1301 }
1302 return NULL;
1303}
static struct @486 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 3166 of file res_pjsip.c.

3168{
3169 char *endpoint_name = NULL;
3170 struct ast_sip_endpoint *endpoint = NULL;
3171 struct ast_sip_contact *contact = NULL;
3172 char *afterat = atsign + 1;
3173
3174 *atsign = '\0';
3175 endpoint_name = destination;
3176
3177 /* Apparently there may be ';<user_options>' after the endpoint name ??? */
3180 if (!endpoint) {
3181 /*
3182 * It's probably a uri with a user but without a scheme but we don't have a way to tell.
3183 * We're going to assume it is and prepend it with a scheme.
3184 */
3185 *uri = ast_malloc(strlen(to) + strlen("sip:") + 1);
3186 if (!(*uri)) {
3187 goto failure;
3188 }
3189 sprintf(*uri, "sip:%s", to);
3190 if (get_default_outbound) {
3192 }
3193 ast_debug(3, "Dest: '%s' Didn't find endpoint before the '@' so using URI '%s'%s\n",
3194 to, *uri, get_default_outbound ? " with default endpoint" : "");
3195 return endpoint;
3196 }
3197
3198 /*
3199 * OK, it's an endpoint and a domain (which we ignore)
3200 */
3202 if (!contact) {
3203 ast_log(LOG_WARNING, "Dest: '%s'. Found endpoint '%s' but didn't find contact\n",
3204 to, endpoint_name);
3205 goto failure;
3206 }
3207
3208 *uri = ast_strdup(contact->uri);
3209 ao2_cleanup(contact);
3210 if (!(*uri)) {
3211 goto failure;
3212 }
3213 ast_debug(3, "Dest: '%s' Found endpoint '%s' and found contact with URI '%s' (discarding domain %s)\n",
3214 to, endpoint_name, *uri, afterat);
3215
3216 return endpoint;
3217
3218failure:
3220 *uri = NULL;
3221 return NULL;
3222}
#define AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(str)
Truncate the URI user field options string if enabled.
Definition res_pjsip.h:3535
const ast_string_field uri
Definition res_pjsip.h:414
const ast_string_field endpoint_name
Definition res_pjsip.h:414

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

2930 {
2931 RAII_VAR(struct ast_sip_contact*, contact, NULL, ao2_cleanup);
2932 char *endpoint_name = NULL;
2933 struct ast_sip_endpoint *endpoint = NULL;
2934
2935 /*
2936 * If "destination" is just one token, it could be an endpoint name
2937 * or a hostname without a scheme.
2938 */
2939
2940 endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", destination);
2941 if (!endpoint) {
2942 /*
2943 * We can only assume it's a hostname.
2944 */
2945 char *temp_uri = ast_malloc(strlen(destination) + strlen("sip:") + 1);
2946 if (!temp_uri) {
2947 goto failure;
2948 }
2949 sprintf(temp_uri, "sip:%s", destination);
2950 *uri = temp_uri;
2951 if (get_default_outbound) {
2953 }
2954 ast_debug(3, "Dest: '%s' Didn't find endpoint so adding scheme and using URI '%s'%s\n",
2955 to, *uri, get_default_outbound ? " with default endpoint" : "");
2956 return endpoint;
2957 }
2958
2959 /*
2960 * It's an endpoint
2961 */
2962
2963 endpoint_name = destination;
2965 if (!contact) {
2966 ast_log(LOG_WARNING, "Dest: '%s'. Found endpoint '%s' but didn't find an aor/contact for it\n",
2967 to, endpoint_name);
2968 ao2_cleanup(endpoint);
2969 goto failure;
2970 }
2971
2972 *uri = ast_strdup(contact->uri);
2973 if (!(*uri)) {
2974 ao2_cleanup(endpoint);
2975 goto failure;
2976 }
2977
2978 ast_debug(3, "Dest: '%s' Found endpoint '%s' and found contact with URI '%s'\n",
2979 to, endpoint_name, *uri);
2980 return endpoint;
2981
2982failure:
2983 *uri = NULL;
2984 return NULL;
2985}

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

3011{
3012 char *endpoint_name = NULL;
3013 struct ast_sip_endpoint *endpoint = NULL;
3014 struct ast_sip_contact *contact = NULL;
3015 char *user = NULL;
3016 char *afterslash = slash + 1;
3017 struct ast_sip_aor *aor;
3018
3019 if (ast_begins_with(destination, "PJSIP/")) {
3020 ast_debug(3, "Dest: '%s' Dialplan format'\n", to);
3021 /*
3022 * This has to be the form PJSIP/user@endpoint
3023 */
3024 if (!atsign || strchr(afterslash, '/')) {
3025 /*
3026 * If there's no "user@" or there's a slash somewhere after
3027 * "PJSIP/" then we go no further.
3028 */
3030 "Dest: '%s'. Destinations beginning with 'PJSIP/' must be in the form of 'PJSIP/user@endpoint'\n",
3031 to);
3032 goto failure;
3033 }
3034 *atsign = '\0';
3035 user = afterslash;
3036 endpoint_name = atsign + 1;
3037 ast_debug(3, "Dest: '%s' User: '%s' Endpoint: '%s'\n", to, user, endpoint_name);
3038 } else {
3039 /*
3040 * Either...
3041 * endpoint/aor
3042 * endpoint/uri
3043 */
3044 *slash = '\0';
3045 endpoint_name = destination;
3046 ast_debug(3, "Dest: '%s' Endpoint: '%s'\n", to, endpoint_name);
3047 }
3048
3049 endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", endpoint_name);
3050 if (!endpoint) {
3051 ast_log(LOG_WARNING, "Dest: '%s'. Didn't find endpoint with name '%s'\n",
3052 to, endpoint_name);
3053 goto failure;
3054 }
3055
3056 if (scheme) {
3057 /*
3058 * If we found a scheme, then everything after the slash MUST be a URI.
3059 * We don't need to do any further modification.
3060 */
3061 *uri = ast_strdup(afterslash);
3062 if (!(*uri)) {
3063 goto failure;
3064 }
3065 ast_debug(3, "Dest: '%s' Found endpoint '%s' and found URI '%s' after '/'\n",
3066 to, endpoint_name, *uri);
3067 return endpoint;
3068 }
3069
3070 if (user) {
3071 /*
3072 * This has to be the form PJSIP/user@endpoint
3073 */
3074 int rc;
3075
3076 /*
3077 * Set the return URI to be the endpoint's contact URI with the user
3078 * portion set to the user that was specified before the endpoint name.
3079 */
3080 rc = insert_user_in_contact_uri(to, endpoint_name, endpoint->aors, user, uri);
3081 if (rc != 0) {
3082 /*
3083 * insert_user_in_contact_uri prints the warning message.
3084 */
3085 goto failure;
3086 }
3087 ast_debug(3, "Dest: '%s' User: '%s' Endpoint: '%s' URI: '%s'\n", to, user,
3088 endpoint_name, *uri);
3089
3090 return endpoint;
3091 }
3092
3093 /*
3094 * We're now left with two possibilities...
3095 * endpoint/aor
3096 * endpoint/uri-without-scheme
3097 */
3098 aor = ast_sip_location_retrieve_aor(afterslash);
3099 if (!aor) {
3100 /*
3101 * It's probably a URI without a scheme but we don't have a way to tell
3102 * for sure. We're going to assume it is and prepend it with a scheme.
3103 */
3104 *uri = ast_malloc(strlen(afterslash) + strlen("sip:") + 1);
3105 if (!(*uri)) {
3106 goto failure;
3107 }
3108 sprintf(*uri, "sip:%s", afterslash);
3109 ast_debug(3, "Dest: '%s' Found endpoint '%s' but didn't find aor after '/' so using URI '%s'\n",
3110 to, endpoint_name, *uri);
3111 return endpoint;
3112 }
3113
3114 /*
3115 * Only one possibility left... There was an aor name after the slash.
3116 */
3117 ast_debug(3, "Dest: '%s' Found endpoint '%s' and found aor '%s' after '/'\n",
3118 to, endpoint_name, ast_sorcery_object_get_id(aor));
3119
3121 if (!contact) {
3122 ast_log(LOG_WARNING, "Dest: '%s'. Found endpoint '%s' but didn't find contact for aor '%s'\n",
3123 to, endpoint_name, ast_sorcery_object_get_id(aor));
3124 ao2_cleanup(aor);
3125 goto failure;
3126 }
3127
3128 *uri = ast_strdup(contact->uri);
3129 ao2_cleanup(contact);
3130 ao2_cleanup(aor);
3131 if (!(*uri)) {
3132 goto failure;
3133 }
3134
3135 ast_debug(3, "Dest: '%s' Found endpoint '%s' and found contact with URI '%s' for aor '%s'\n",
3136 to, endpoint_name, *uri, ast_sorcery_object_get_id(aor));
3137
3138 return endpoint;
3139
3140failure:
3141 ao2_cleanup(endpoint);
3142 *uri = NULL;
3143 return NULL;
3144}
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:2865
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:480
structure to hold users read from phoneprov_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 2865 of file res_pjsip.c.

2867{
2868 RAII_VAR(struct ast_sip_contact *, contact, NULL, ao2_cleanup);
2869 pj_pool_t *pool;
2870 pjsip_name_addr *name_addr;
2871 pjsip_sip_uri *sip_uri;
2872 int err = 0;
2873
2875 if (!contact) {
2876 ast_log(LOG_WARNING, "Dest: '%s'. Couldn't find contact for endpoint '%s'\n",
2877 to, endpoint_name);
2878 return -1;
2879 }
2880
2881 pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(), "uri-user-insert", 128, 128);
2882 if (!pool) {
2883 ast_log(LOG_WARNING, "Failed to allocate ParseUri endpoint pool.\n");
2884 return -1;
2885 }
2886
2887 name_addr = (pjsip_name_addr *) pjsip_parse_uri(pool, (char*)contact->uri, strlen(contact->uri), PJSIP_PARSE_URI_AS_NAMEADDR);
2888 if (!name_addr || (!PJSIP_URI_SCHEME_IS_SIP(name_addr->uri) && !PJSIP_URI_SCHEME_IS_SIPS(name_addr->uri))) {
2889 ast_log(LOG_WARNING, "Failed to parse URI '%s'\n", contact->uri);
2890 err = -1;
2891 goto out;
2892 }
2893
2894 ast_debug(3, "Dest: '%s' User: '%s' Endpoint: '%s' ContactURI: '%s'\n", to, user, endpoint_name, contact->uri);
2895
2896 sip_uri = pjsip_uri_get_uri(name_addr->uri);
2897 pj_strset2(&sip_uri->user, (char*)user);
2898
2899 *uri = ast_malloc(PJSIP_MAX_URL_SIZE);
2900 if (!(*uri)) {
2901 err = -1;
2902 goto out;
2903 }
2904 pjsip_uri_print(PJSIP_URI_IN_REQ_URI, name_addr, *uri, PJSIP_MAX_URL_SIZE);
2905
2906out:
2907 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
2908
2909 return err;
2910}
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 3917 of file res_pjsip.c.

3918{
3920
3921 /* pjproject and config_system need to be initialized before all else */
3922 if (pj_init() != PJ_SUCCESS) {
3924 }
3925
3926 if (pjlib_util_init() != PJ_SUCCESS) {
3927 goto error;
3928 }
3929
3930 /* Register PJMEDIA error codes for SDP parsing errors */
3931 if (pj_register_strerror(PJMEDIA_ERRNO_START, PJ_ERRNO_SPACE_SIZE, pjmedia_strerror)
3932 != PJ_SUCCESS) {
3933 ast_log(LOG_WARNING, "Failed to register pjmedia error codes. Codes will not be decoded.\n");
3934 }
3935
3936 /* Initialize common media types */
3937 pjsip_media_type_init2(&pjsip_media_type_application_json, "application", "json");
3938 pjsip_media_type_init2(&pjsip_media_type_application_media_control_xml, "application", "media_control+xml");
3939 pjsip_media_type_init2(&pjsip_media_type_application_pidf_xml, "application", "pidf+xml");
3940 pjsip_media_type_init2(&pjsip_media_type_application_xpidf_xml, "application", "xpidf+xml");
3941 pjsip_media_type_init2(&pjsip_media_type_application_cpim_xpidf_xml, "application", "cpim-xpidf+xml");
3942 pjsip_media_type_init2(&pjsip_media_type_application_rlmi_xml, "application", "rlmi+xml");
3943 pjsip_media_type_init2(&pjsip_media_type_application_sdp, "application", "sdp");
3944 pjsip_media_type_init2(&pjsip_media_type_application_simple_message_summary, "application", "simple-message-summary");
3945 pjsip_media_type_init2(&pjsip_media_type_multipart_alternative, "multipart", "alternative");
3946 pjsip_media_type_init2(&pjsip_media_type_multipart_mixed, "multipart", "mixed");
3947 pjsip_media_type_init2(&pjsip_media_type_multipart_related, "multipart", "related");
3948 pjsip_media_type_init2(&pjsip_media_type_text_plain, "text", "plain");
3949
3950
3952 ast_log(LOG_ERROR, "Failed to initialize SIP 'system' configuration section. Aborting load\n");
3953 goto error;
3954 }
3955
3956 /* The serializer needs taskpool and taskpool needs pjproject to be initialized so it's next */
3958 options.thread_start = sip_thread_start;
3960 if (!sip_taskpool) {
3961 goto error;
3962 }
3963
3965 ast_log(LOG_ERROR, "Failed to start scheduler. Aborting load\n");
3966 goto error;
3967 }
3968
3969 /* Now load all the pjproject infrastructure. */
3970 if (load_pjsip()) {
3971 goto error;
3972 }
3973
3975 ast_log(LOG_ERROR, "Failed to initialize SIP transport monitor. Aborting load\n");
3976 goto error;
3977 }
3978
3981
3983 ast_log(LOG_ERROR, "Failed to pre-initialize OPTIONS handling. Aborting load\n");
3984 goto error;
3985 }
3986
3988 ast_log(LOG_ERROR, "Failed to initialize SIP configuration. Aborting load\n");
3989 goto error;
3990 }
3991
3994
3996 ast_log(LOG_ERROR, "Failed to initialize SIP transport management. Aborting load\n");
3997 goto error;
3998 }
3999
4001 ast_log(LOG_ERROR, "Failed to register distributor module. Aborting load\n");
4002 goto error;
4003 }
4004
4006 ast_log(LOG_ERROR, "Failed to initialize supplement hooks. Aborting load\n");
4007 goto error;
4008 }
4009
4011 ast_log(LOG_ERROR, "Failed to initialize OPTIONS handling. Aborting load\n");
4012 goto error;
4013 }
4014
4015 /*
4016 * It is OK to prune the contacts now that
4017 * ast_res_pjsip_init_options_handling() has added the contact observer
4018 * of res/res_pjsip/pjsip_options.c to sorcery (to ensure that any
4019 * pruned contacts are removed from this module's data structure).
4020 */
4022
4024 ast_log(LOG_ERROR, "Failed to initialize message IP updating. Aborting load\n");
4025 goto error;
4026 }
4027
4029
4030 AST_TEST_REGISTER(xml_sanitization_end_null);
4031 AST_TEST_REGISTER(xml_sanitization_exceeds_buffer);
4032
4034
4035error:
4037
4038 /* These functions all check for NULLs and are safe to call at any time */
4041
4043}
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition cli.h:265
void sip_get_taskpool_options(struct ast_taskpool_options *taskpool_options)
int ast_sip_initialize_system(void)
void ast_sip_initialize_dns(void)
@ 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:3793
pjsip_media_type pjsip_media_type_application_media_control_xml
Definition res_pjsip.c:3905
static struct ast_cli_entry cli_commands[]
Definition res_pjsip.c:471
pjsip_media_type pjsip_media_type_application_json
Definition res_pjsip.c:3904
int ast_sip_register_service(pjsip_module *module)
Register a SIP service in Asterisk.
Definition res_pjsip.c:111
pjsip_media_type pjsip_media_type_application_sdp
Definition res_pjsip.c:3911
pjsip_media_type pjsip_media_type_text_plain
Definition res_pjsip.c:3915
pjsip_media_type pjsip_media_type_application_pidf_xml
Definition res_pjsip.c:3906
static void sip_thread_start(void)
Definition res_pjsip.c:2260
pjsip_media_type pjsip_media_type_application_simple_message_summary
Definition res_pjsip.c:3910
pjsip_media_type pjsip_media_type_application_rlmi_xml
Definition res_pjsip.c:3909
pjsip_media_type pjsip_media_type_multipart_mixed
Definition res_pjsip.c:3913
pjsip_media_type pjsip_media_type_application_xpidf_xml
Definition res_pjsip.c:3907
pjsip_media_type pjsip_media_type_multipart_alternative
Definition res_pjsip.c:3912
static int load_pjsip(void)
Definition res_pjsip.c:3837
pjsip_media_type pjsip_media_type_application_cpim_xpidf_xml
Definition res_pjsip.c:3908
pjsip_media_type pjsip_media_type_multipart_related
Definition res_pjsip.c:3914
void ast_sip_location_prune_boot_contacts(void)
Prune the prune_on_boot contacts.
Definition location.c:470
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)
void ast_taskpool_shutdown(struct ast_taskpool *pool)
Shut down a taskpool and remove the underlying taskprocessors.
Definition taskpool.c:675
struct ast_taskpool * ast_taskpool_create(const char *name, const struct ast_taskpool_options *options)
Create a new taskpool.
Definition taskpool.c:324
#define AST_TEST_REGISTER(cb)
Definition test.h:127
static struct test_options options
int error(const char *format,...)

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_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_taskpool_create(), ast_taskpool_shutdown(), AST_TEST_REGISTER, 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, sip_get_taskpool_options(), sip_taskpool, sip_thread_start(), supplement_module, and unload_pjsip().

◆ load_pjsip()

static int load_pjsip ( void  )
static

Definition at line 3837 of file res_pjsip.c.

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

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

2242{
2243 while (monitor_continue) {
2244 const pj_time_val delay = {0, 10};
2245 pjsip_endpt_handle_events(ast_pjsip_endpoint, &delay);
2246 }
2247 return NULL;
2248}

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

3899{
3900 pjmedia_strerror(0, NULL, 0);
3901}

References NULL.

◆ pool_destroy_callback()

static void pool_destroy_callback ( void *  arg)
static

Definition at line 2384 of file res_pjsip.c.

2385{
2386 pj_pool_t *pool = (pj_pool_t *)arg;
2387 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
2388}

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

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

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

4046{
4047 /*
4048 * We must wait for the reload to complete so multiple
4049 * reloads cannot happen at the same time.
4050 */
4052 ast_log(LOG_WARNING, "Failed to reload PJSIP\n");
4053 return -1;
4054 }
4055
4056 return 0;
4057}
static int reload_configuration_task(void *obj)
Definition res_pjsip.c:3785

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

◆ remove_request_headers()

static void remove_request_headers ( pjsip_endpoint *  endpt)
static

Definition at line 3420 of file res_pjsip.c.

3421{
3422 const pjsip_hdr *request_headers = pjsip_endpt_get_request_headers(endpt);
3423 pjsip_hdr *iter = request_headers->next;
3424
3425 while (iter != request_headers) {
3426 pjsip_hdr *to_erase = iter;
3427 iter = iter->next;
3428 pj_list_erase(to_erase);
3429 }
3430}
static struct header_list request_headers

References request_headers.

Referenced by load_pjsip().

◆ send_in_dialog_request()

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

Definition at line 1488 of file res_pjsip.c.

1489{
1490 if (pjsip_dlg_send_request(dlg, tdata, -1, NULL) != PJ_SUCCESS) {
1491 ast_log(LOG_WARNING, "Unable to send in-dialog request.\n");
1492 return -1;
1493 }
1494 return 0;
1495}

References ast_log, LOG_WARNING, and NULL.

Referenced by ast_sip_send_request().

◆ send_request_cb()

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

Definition at line 1880 of file res_pjsip.c.

1881{
1882 struct send_request_data *req_data = token;
1883 pjsip_rx_data *challenge;
1884 struct ast_sip_supplement *supplement;
1885
1886 if (e->type == PJSIP_EVENT_TSX_STATE) {
1887 switch(e->body.tsx_state.type) {
1888 case PJSIP_EVENT_TRANSPORT_ERROR:
1889 case PJSIP_EVENT_TIMER:
1890 /*
1891 * Check the request status on transport error or timeout. A transport
1892 * error can occur when a TCP socket closes and that can be the result
1893 * of a 503. Also we may need to failover on a timeout (408).
1894 */
1895 if (check_request_status(req_data, e)) {
1896 return;
1897 }
1898 break;
1899 case PJSIP_EVENT_RX_MSG:
1900 challenge = e->body.tsx_state.src.rdata;
1901
1902 /*
1903 * Call any supplements that want to know about a response
1904 * with any received data.
1905 */
1907 AST_LIST_TRAVERSE(&supplements, supplement, next) {
1908 if (supplement->incoming_response
1909 && does_method_match(&challenge->msg_info.cseq->method.name,
1910 supplement->method)) {
1911 supplement->incoming_response(req_data->endpoint, challenge);
1912 }
1913 }
1915
1916 if (check_request_status(req_data, e)) {
1917 /*
1918 * Request with challenge response or failover sent.
1919 * Passed our req_data ref to the new request.
1920 */
1921 return;
1922 }
1923 break;
1924 default:
1925 ast_log(LOG_ERROR, "Unexpected PJSIP event %u\n", e->body.tsx_state.type);
1926 break;
1927 }
1928 }
1929
1930 if (req_data->callback) {
1931 req_data->callback(req_data->token, e);
1932 }
1933 ao2_ref(req_data, -1);
1934}
static int check_request_status(struct send_request_data *req_data, pjsip_event *e)
Definition res_pjsip.c:1837
void(* incoming_response)(struct ast_sip_endpoint *endpoint, struct pjsip_rx_data *rdata)
Called on an incoming SIP response This method is always called from a SIP servant thread.
Definition res_pjsip.h:3420
void(* callback)(void *token, pjsip_event *e)
Definition res_pjsip.c:1520

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

Referenced by ast_sip_send_out_of_dialog_request(), and check_request_status().

◆ send_request_data_alloc()

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

Definition at line 1532 of file res_pjsip.c.

1534{
1535 struct send_request_data *req_data;
1536
1537 req_data = ao2_alloc_options(sizeof(*req_data), send_request_data_destroy,
1539 if (!req_data) {
1540 return NULL;
1541 }
1542
1543 req_data->endpoint = ao2_bump(endpoint);
1544 req_data->token = token;
1545 req_data->callback = callback;
1546
1547 return req_data;
1548}
@ AO2_ALLOC_OPT_LOCK_NOLOCK
Definition astobj2.h:367
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition astobj2.h:404
static void send_request_data_destroy(void *obj)
Definition res_pjsip.c:1525

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

Referenced by ast_sip_send_out_of_dialog_request().

◆ send_request_data_destroy()

static void send_request_data_destroy ( void *  obj)
static

Definition at line 1525 of file res_pjsip.c.

1526{
1527 struct send_request_data *req_data = obj;
1528
1529 ao2_cleanup(req_data->endpoint);
1530}

References ao2_cleanup, and send_request_data::endpoint.

Referenced by send_request_data_alloc().

◆ send_request_timer_callback()

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

Definition at line 1646 of file res_pjsip.c.

1647{
1648 struct send_request_wrapper *req_wrapper = entry->user_data;
1649 unsigned int cb_called;
1650
1651 ast_debug(2, "%p: Internal tsx timer expired after %d msec\n",
1652 req_wrapper, req_wrapper->timeout);
1653
1654 ao2_lock(req_wrapper);
1655 /*
1656 * If the id is not TIMEOUT_TIMER2 then the timer was cancelled
1657 * before we got the lock or it was already handled so just clean up.
1658 */
1659 if (entry->id != TIMEOUT_TIMER2) {
1660 ao2_unlock(req_wrapper);
1661 ast_debug(3, "%p: Timeout already handled\n", req_wrapper);
1662 ao2_ref(req_wrapper, -1);
1663 return;
1664 }
1665 entry->id = TIMER_INACTIVE;
1666
1667 ast_debug(3, "%p: Timer handled here\n", req_wrapper);
1668
1669 cb_called = req_wrapper->cb_called;
1670 req_wrapper->cb_called = 1;
1671 ao2_unlock(req_wrapper);
1672
1673 if (!cb_called && req_wrapper->callback) {
1674 pjsip_event event;
1675
1676 PJSIP_EVENT_INIT_TX_MSG(event, req_wrapper->tdata);
1677 event.body.tsx_state.type = PJSIP_EVENT_TIMER;
1678
1679 req_wrapper->callback(req_wrapper->token, &event);
1680 ast_debug(2, "%p: Callbacks executed\n", req_wrapper);
1681 }
1682
1683 ao2_ref(req_wrapper, -1);
1684}

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

Referenced by endpt_send_request().

◆ send_request_wrapper_destructor()

static void send_request_wrapper_destructor ( void *  obj)
static

Definition at line 1686 of file res_pjsip.c.

1687{
1688 struct send_request_wrapper *req_wrapper = obj;
1689
1690 pjsip_tx_data_dec_ref(req_wrapper->tdata);
1691 ast_debug(2, "%p: wrapper destroyed\n", req_wrapper);
1692}

References ast_debug, and send_request_wrapper::tdata.

Referenced by endpt_send_request().

◆ set_id_from_from()

static int set_id_from_from ( struct pjsip_rx_data *  rdata,
struct ast_party_id id 
)
static

Definition at line 2778 of file res_pjsip.c.

2779{
2780 pjsip_fromto_hdr *from = pjsip_msg_find_hdr(rdata->msg_info.msg,
2781 PJSIP_H_FROM, rdata->msg_info.msg->hdr.next);
2782
2783 if (!from) {
2784 /* This had better not happen */
2785 return -1;
2786 }
2787
2788 set_id_from_hdr(from, id);
2789
2790 if (!id->number.valid) {
2791 return -1;
2792 }
2793
2794 return 0;
2795}
static void set_id_from_hdr(pjsip_fromto_hdr *hdr, struct ast_party_id *id)
Definition res_pjsip.c:2581

References id, and set_id_from_hdr().

Referenced by ast_sip_set_id_from_invite().

◆ set_id_from_hdr()

static void set_id_from_hdr ( pjsip_fromto_hdr *  hdr,
struct ast_party_id id 
)
static

Definition at line 2581 of file res_pjsip.c.

2582{
2583 char cid_name[AST_CHANNEL_NAME];
2584 char cid_num[AST_CHANNEL_NAME];
2585 size_t cid_name_size = AST_CHANNEL_NAME;
2586 pjsip_name_addr *id_name_addr = (pjsip_name_addr *) hdr->uri;
2587 char *semi;
2589
2590 ast_copy_pj_str(cid_num, ast_sip_pjsip_uri_get_username(hdr->uri), sizeof(cid_num));
2591 /* Always truncate caller-id number at a semicolon. */
2592 semi = strchr(cid_num, ';');
2593 if (semi) {
2594 /*
2595 * We need to be able to handle URI's looking like
2596 * "sip:1235557890;phone-context=national@x.x.x.x;user=phone"
2597 *
2598 * Where the uri->user field will result in:
2599 * "1235557890;phone-context=national"
2600 *
2601 * People don't care about anything after the semicolon
2602 * showing up on their displays even though the RFC
2603 * allows the semicolon.
2604 */
2605 *semi = '\0';
2606 }
2607
2608 /*
2609 * It's safe to pass a NULL or empty string as the source.
2610 * The result will be an empty string assuming the destination
2611 * size was at least 1.
2612 */
2613 result = ast_utf8_replace_invalid_chars(cid_name, &cid_name_size,
2614 id_name_addr->display.ptr, id_name_addr->display.slen);
2615
2617 ast_log(LOG_WARNING, "CallerID Name '" PJSTR_PRINTF_SPEC
2618 "' for number '%s' has invalid UTF-8 characters which "
2619 "were replaced",
2620 PJSTR_PRINTF_VAR(id_name_addr->display), cid_num);
2621 }
2622
2623 ast_free(id->name.str);
2624 id->name.str = ast_strdup(cid_name);
2625 if (!ast_strlen_zero(cid_name)) {
2626 id->name.valid = 1;
2627 }
2628 ast_free(id->number.str);
2629 id->number.str = ast_strdup(cid_num);
2630 if (!ast_strlen_zero(cid_num)) {
2631 id->number.valid = 1;
2632 }
2633}
#define AST_CHANNEL_NAME
Definition channel.h:173
const pj_str_t * ast_sip_pjsip_uri_get_username(pjsip_uri *uri)
Get the user portion of the pjsip_uri.
Definition res_pjsip.c:3452
#define PJSTR_PRINTF_VAR(_v)
Definition res_pjsip.h:72
#define PJSTR_PRINTF_SPEC
Definition res_pjsip.h:71
ast_utf8_replace_result
Definition utf8.h:70
@ AST_UTF8_REPLACE_VALID
Source contained fully valid UTF-8.
Definition utf8.h:76
enum ast_utf8_replace_result ast_utf8_replace_invalid_chars(char *dst, size_t *dst_size, const char *src, size_t src_len)
Copy a string safely replacing any invalid UTF-8 sequences.
Definition utf8.c:173

References AST_CHANNEL_NAME, ast_copy_pj_str(), ast_free, ast_log, ast_sip_pjsip_uri_get_username(), ast_strdup, ast_strlen_zero(), ast_utf8_replace_invalid_chars(), AST_UTF8_REPLACE_VALID, id, LOG_WARNING, PJSTR_PRINTF_SPEC, PJSTR_PRINTF_VAR, and result.

Referenced by set_id_from_from(), set_id_from_pai(), and set_id_from_rpid().

◆ set_id_from_pai()

static int set_id_from_pai ( pjsip_rx_data *  rdata,
struct ast_party_id id 
)
static

Definition at line 2685 of file res_pjsip.c.

2686{
2687 static const pj_str_t pai_str = { "P-Asserted-Identity", 19 };
2688 static const pj_str_t privacy_str = { "Privacy", 7 };
2689 pjsip_fromto_hdr *pai_hdr = get_id_header(rdata, &pai_str);
2690 pjsip_generic_string_hdr *privacy;
2691
2692 if (!pai_hdr) {
2693 return -1;
2694 }
2695
2696 set_id_from_hdr(pai_hdr, id);
2697
2698 if (!id->number.valid) {
2699 return -1;
2700 }
2701
2702 privacy = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &privacy_str, NULL);
2703 if (!privacy || !pj_stricmp2(&privacy->hvalue, "none")) {
2704 id->number.presentation = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
2705 id->name.presentation = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
2706 } else {
2707 id->number.presentation = AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED;
2708 id->name.presentation = AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED;
2709 }
2710
2711 return 0;
2712}
#define AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED
Definition callerid.h:449
#define AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED
Definition callerid.h:437
static pjsip_fromto_hdr * get_id_header(pjsip_rx_data *rdata, const pj_str_t *header_name)
Definition res_pjsip.c:2648

References AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED, AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED, get_id_header(), id, NULL, and set_id_from_hdr().

Referenced by ast_sip_set_id_connected_line(), and ast_sip_set_id_from_invite().

◆ set_id_from_rpid()

static int set_id_from_rpid ( pjsip_rx_data *  rdata,
struct ast_party_id id 
)
static

Definition at line 2726 of file res_pjsip.c.

2727{
2728 static const pj_str_t rpid_str = { "Remote-Party-ID", 15 };
2729 static const pj_str_t privacy_str = { "privacy", 7 };
2730 static const pj_str_t screen_str = { "screen", 6 };
2731 pjsip_fromto_hdr *rpid_hdr = get_id_header(rdata, &rpid_str);
2732 pjsip_param *screen;
2733 pjsip_param *privacy;
2734
2735 if (!rpid_hdr) {
2736 return -1;
2737 }
2738
2739 set_id_from_hdr(rpid_hdr, id);
2740
2741 if (!id->number.valid) {
2742 return -1;
2743 }
2744
2745 privacy = pjsip_param_find(&rpid_hdr->other_param, &privacy_str);
2746 screen = pjsip_param_find(&rpid_hdr->other_param, &screen_str);
2747 if (privacy && !pj_stricmp2(&privacy->value, "full")) {
2748 id->number.presentation = AST_PRES_RESTRICTED;
2749 id->name.presentation = AST_PRES_RESTRICTED;
2750 } else {
2751 id->number.presentation = AST_PRES_ALLOWED;
2752 id->name.presentation = AST_PRES_ALLOWED;
2753 }
2754 if (screen && !pj_stricmp2(&screen->value, "yes")) {
2755 id->number.presentation |= AST_PRES_USER_NUMBER_PASSED_SCREEN;
2756 id->name.presentation |= AST_PRES_USER_NUMBER_PASSED_SCREEN;
2757 } else {
2758 id->number.presentation |= AST_PRES_USER_NUMBER_UNSCREENED;
2759 id->name.presentation |= AST_PRES_USER_NUMBER_UNSCREENED;
2760 }
2761
2762 return 0;
2763}
#define AST_PRES_USER_NUMBER_UNSCREENED
Definition callerid.h:426
#define AST_PRES_USER_NUMBER_PASSED_SCREEN
Definition callerid.h:427
#define AST_PRES_RESTRICTED
Definition callerid.h:433
#define AST_PRES_ALLOWED
Definition callerid.h:432

References AST_PRES_ALLOWED, AST_PRES_RESTRICTED, AST_PRES_USER_NUMBER_PASSED_SCREEN, AST_PRES_USER_NUMBER_UNSCREENED, get_id_header(), id, and set_id_from_hdr().

Referenced by ast_sip_set_id_connected_line(), and ast_sip_set_id_from_invite().

◆ sip_dialog_create_from()

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

Definition at line 747 of file res_pjsip.c.

749{
750 pj_str_t tmp, local_addr;
751 pjsip_uri *uri;
752 pjsip_sip_uri *sip_uri;
753 pjsip_transport_type_e type;
754 int local_port;
755 char default_user[PJSIP_MAX_URL_SIZE];
756
757 if (ast_strlen_zero(user)) {
758 ast_sip_get_default_from_user(default_user, sizeof(default_user));
759 user = default_user;
760 }
761
762 /* Parse the provided target URI so we can determine what transport it will end up using */
763 pj_strdup_with_null(pool, &tmp, target);
764
765 if (!(uri = pjsip_parse_uri(pool, tmp.ptr, tmp.slen, 0)) ||
766 (!PJSIP_URI_SCHEME_IS_SIP(uri) && !PJSIP_URI_SCHEME_IS_SIPS(uri))) {
767 return -1;
768 }
769
770 sip_uri = pjsip_uri_get_uri(uri);
771
772 /* Determine the transport type to use */
773 type = pjsip_transport_get_type_from_name(&sip_uri->transport_param);
774 if (PJSIP_URI_SCHEME_IS_SIPS(sip_uri)) {
775 if (type == PJSIP_TRANSPORT_UNSPECIFIED
776 || !(pjsip_transport_get_flag_from_type(type) & PJSIP_TRANSPORT_SECURE)) {
777 type = PJSIP_TRANSPORT_TLS;
778 }
779 } else if (!sip_uri->transport_param.slen) {
780 type = PJSIP_TRANSPORT_UDP;
781 } else if (type == PJSIP_TRANSPORT_UNSPECIFIED) {
782 return -1;
783 }
784
785 /* If the host is IPv6 turn the transport into an IPv6 version */
786 if (pj_strchr(&sip_uri->host, ':')) {
787 type |= PJSIP_TRANSPORT_IPV6;
788 }
789
790 /* In multidomain scenario, username may contain @ with domain info */
791 if (!ast_sip_get_disable_multi_domain() && strchr(user, '@')) {
792 from->ptr = pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE);
793 from->slen = pj_ansi_snprintf(from->ptr, PJSIP_MAX_URL_SIZE,
794 "<sip:%s%s%s>",
795 user,
796 (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? ";transport=" : "",
797 (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? pjsip_transport_get_type_name(type) : "");
798 return 0;
799 }
800
801 if (!ast_strlen_zero(domain)) {
802 from->ptr = pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE);
803 from->slen = pj_ansi_snprintf(from->ptr, PJSIP_MAX_URL_SIZE,
804 "<sip:%s@%s%s%s>",
805 user,
806 domain,
807 (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? ";transport=" : "",
808 (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? pjsip_transport_get_type_name(type) : "");
809 return 0;
810 }
811
812 /* Get the local bound address for the transport that will be used when communicating with the provided URI */
813 if (pjsip_tpmgr_find_local_addr(pjsip_endpt_get_tpmgr(ast_sip_get_pjsip_endpoint()), pool, type, selector,
814 &local_addr, &local_port) != PJ_SUCCESS) {
815
816 /* If no local address can be retrieved using the transport manager use the host one */
817 pj_strdup(pool, &local_addr, pj_gethostname());
818 local_port = pjsip_transport_get_default_port_for_type(PJSIP_TRANSPORT_UDP);
819 }
820
821 /* If IPv6 was specified in the transport, set the proper type */
822 if (pj_strchr(&local_addr, ':')) {
823 type |= PJSIP_TRANSPORT_IPV6;
824 }
825
826 from->ptr = pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE);
827 from->slen = pj_ansi_snprintf(from->ptr, PJSIP_MAX_URL_SIZE,
828 "<sip:%s@%s%.*s%s:%d%s%s>",
829 user,
830 (type & PJSIP_TRANSPORT_IPV6) ? "[" : "",
831 (int)local_addr.slen,
832 local_addr.ptr,
833 (type & PJSIP_TRANSPORT_IPV6) ? "]" : "",
834 local_port,
835 (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? ";transport=" : "",
836 (type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? pjsip_transport_get_type_name(type) : "");
837
838 return 0;
839}
unsigned int ast_sip_get_disable_multi_domain(void)
Retrieve the system setting 'disable multi domain'.
void ast_sip_get_default_from_user(char *from_user, size_t size)
Retrieve the global default from user.

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

Referenced by ast_sip_create_dialog_uac(), and create_out_of_dialog_request().

◆ sip_thread_start()

static void sip_thread_start ( void  )
static

Definition at line 2260 of file res_pjsip.c.

2261{
2262 pj_thread_desc *desc;
2263 pj_thread_t *thread;
2264 uint32_t *servant_id;
2265
2266 servant_id = ast_threadstorage_get(&servant_id_storage, sizeof(*servant_id));
2267 if (!servant_id) {
2268 ast_log(LOG_ERROR, "Could not set SIP servant ID in thread-local storage.\n");
2269 return;
2270 }
2271 *servant_id = SIP_SERVANT_ID;
2272
2273 desc = ast_threadstorage_get(&pj_thread_storage, sizeof(pj_thread_desc));
2274 if (!desc) {
2275 ast_log(LOG_ERROR, "Could not get thread desc from thread-local storage. Expect awful things to occur\n");
2276 return;
2277 }
2278 pj_bzero(*desc, sizeof(*desc));
2279
2280 if (pj_thread_register("Asterisk Thread", *desc, &thread) != PJ_SUCCESS) {
2281 ast_log(LOG_ERROR, "Couldn't register thread with PJLIB.\n");
2282 }
2283}
pthread_t thread
Definition app_sla.c:335
static const char desc[]
Definition cdr_radius.c:84
#define SIP_SERVANT_ID
Definition res_pjsip.c:2258
void * ast_threadstorage_get(struct ast_threadstorage *ts, size_t init_size)
Retrieve thread storage.

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

Referenced by load_module().

◆ stop_monitor_thread()

static void stop_monitor_thread ( void  )
static

Definition at line 2250 of file res_pjsip.c.

2251{
2252 monitor_continue = 0;
2253 pj_thread_join(monitor_thread);
2254}

References monitor_continue, and monitor_thread.

Referenced by unload_pjsip().

◆ supplement_on_rx_request()

static pj_bool_t supplement_on_rx_request ( pjsip_rx_data *  rdata)
static

Definition at line 2325 of file res_pjsip.c.

2326{
2327 struct ast_sip_supplement *supplement;
2328
2329 if (pjsip_rdata_get_dlg(rdata)) {
2330 return PJ_FALSE;
2331 }
2332
2334 AST_LIST_TRAVERSE(&supplements, supplement, next) {
2335 if (supplement->incoming_request
2336 && does_method_match(&rdata->msg_info.msg->line.req.method.name, supplement->method)) {
2337 struct ast_sip_endpoint *endpoint;
2338
2339 endpoint = ast_pjsip_rdata_get_endpoint(rdata);
2340 supplement->incoming_request(endpoint, rdata);
2341 ao2_cleanup(endpoint);
2342 }
2343 }
2345
2346 return PJ_FALSE;
2347}
struct ast_sip_endpoint * ast_pjsip_rdata_get_endpoint(pjsip_rx_data *rdata)
Get the looked-up endpoint on an out-of dialog request or response.
int(* incoming_request)(struct ast_sip_endpoint *endpoint, struct pjsip_rx_data *rdata)
Called on incoming SIP request This method can indicate a failure in processing in its return....
Definition res_pjsip.h:3404

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

◆ supplement_outgoing_response()

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

Definition at line 2349 of file res_pjsip.c.

2350{
2351 struct ast_sip_supplement *supplement;
2352 pjsip_cseq_hdr *cseq = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CSEQ, NULL);
2353 struct ast_sip_contact *contact = ast_sip_mod_data_get(tdata->mod_data, supplement_module.id, MOD_DATA_CONTACT);
2354
2355 if (sip_endpoint) {
2356 ast_sip_message_apply_transport(sip_endpoint->transport, tdata);
2357 }
2358
2360 AST_LIST_TRAVERSE(&supplements, supplement, next) {
2361 if (supplement->outgoing_response && does_method_match(&cseq->method.name, supplement->method)) {
2362 supplement->outgoing_response(sip_endpoint, contact, tdata);
2363 }
2364 }
2366
2367 ast_sip_mod_data_set(tdata->pool, tdata->mod_data, supplement_module.id, MOD_DATA_CONTACT, NULL);
2368 ao2_cleanup(contact);
2369}
void(* outgoing_response)(struct ast_sip_endpoint *endpoint, struct ast_sip_contact *contact, struct pjsip_tx_data *tdata)
Called on an outgoing SIP response This method is always called from a SIP servant thread.
Definition res_pjsip.h:3430

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

Referenced by ast_sip_send_response(), and ast_sip_send_stateful_response().

◆ uas_use_sips_contact()

static int uas_use_sips_contact ( pjsip_rx_data *  rdata)
static

Determine if a SIPS Contact header is required.

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

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

Definition at line 1087 of file res_pjsip.c.

1088{
1089 pjsip_rr_hdr *record_route;
1090
1091 if (PJSIP_URI_SCHEME_IS_SIPS(rdata->msg_info.msg->line.req.uri)) {
1092 return 1;
1093 }
1094
1095 record_route = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_RECORD_ROUTE, NULL);
1096 if (record_route) {
1097 if (PJSIP_URI_SCHEME_IS_SIPS(&record_route->name_addr)) {
1098 return 1;
1099 }
1100 } else {
1101 pjsip_contact_hdr *contact;
1102
1103 contact = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT, NULL);
1104 ast_assert(contact != NULL);
1105 if (PJSIP_URI_SCHEME_IS_SIPS(contact->uri)) {
1106 return 1;
1107 }
1108 }
1109
1110 return 0;
1111}

References ast_assert, and NULL.

Referenced by create_dialog_uas().

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 4059 of file res_pjsip.c.

4060{
4061 AST_TEST_UNREGISTER(xml_sanitization_end_null);
4062 AST_TEST_UNREGISTER(xml_sanitization_exceeds_buffer);
4064
4065 /* The thread this is called from cannot call PJSIP/PJLIB functions,
4066 * so we have to push the work to the taskpool to handle
4067 */
4071
4072 return 0;
4073}
void ast_cli_unregister_multiple(void)
Definition ael_main.c:408
#define AST_TEST_UNREGISTER(cb)
Definition test.h:128

References ARRAY_LEN, ast_cli_unregister_multiple(), ast_sip_destroy_scheduler(), ast_sip_push_task_wait_servant, ast_taskpool_shutdown(), AST_TEST_UNREGISTER, cli_commands, NULL, sip_taskpool, and unload_pjsip().

◆ unload_pjsip()

static int unload_pjsip ( void *  data)
static

Definition at line 3793 of file res_pjsip.c.

3794{
3795 /*
3796 * These calls need the pjsip endpoint and serializer to clean up.
3797 * If they're not set, then there's nothing to clean up anyway.
3798 */
3799 if (ast_pjsip_endpoint) {
3809 }
3810
3811 if (monitor_thread) {
3814 }
3815
3816 if (memory_pool) {
3817 /* This mimics the behavior of pj_pool_safe_release
3818 * which was introduced in pjproject 2.6.
3819 */
3820 pj_pool_t *temp_pool = memory_pool;
3821
3822 memory_pool = NULL;
3823 pj_pool_release(temp_pool);
3824 }
3825
3827
3828 if (caching_pool.lock) {
3830 }
3831
3832 pj_shutdown();
3833
3834 return 0;
3835}
void ast_sip_destroy_system(void)
void ast_pjproject_caching_pool_destroy(pj_caching_pool *cp)
Destroy caching pool factory and all cached pools.
void ast_sip_unregister_service(pjsip_module *module)
Definition res_pjsip.c:127
static void stop_monitor_thread(void)
Definition res_pjsip.c:2250
void ast_res_pjsip_cleanup_options_handling(void)
void ast_sip_destroy_transport_management(void)
void ast_sip_destroy_distributor(void)
void ast_sip_destroy_global_headers(void)
void ast_res_pjsip_destroy_configuration(void)
void ast_sip_destroy_transport_events(void)
void ast_res_pjsip_cleanup_message_filter(void)

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

Referenced by load_module(), and unload_module().

◆ unregister_service()

static int unregister_service ( void *  data)
static

Definition at line 116 of file res_pjsip.c.

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

References ast_debug, and ast_pjsip_endpoint.

Referenced by ast_sip_unregister_service().

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "Basic SIP resource" , .key = ASTERISK_GPL_KEY , .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

Definition at line 4083 of file res_pjsip.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 4083 of file res_pjsip.c.

◆ ast_pjsip_endpoint

pjsip_endpoint* ast_pjsip_endpoint
static

◆ caching_pool

pj_caching_pool caching_pool

Definition at line 2236 of file res_pjsip.c.

Referenced by load_pjsip(), and unload_pjsip().

◆ cli_commands

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

Definition at line 471 of file res_pjsip.c.

471 {
472 AST_CLI_DEFINE(cli_dump_endpt, "Dump the res_pjsip endpt internals"),
473 AST_CLI_DEFINE(cli_show_settings, "Show global and system configuration options"),
474 AST_CLI_DEFINE(cli_show_endpoint_identifiers, "List registered endpoint identifiers")
475};
#define AST_CLI_DEFINE(fn, txt,...)
Definition cli.h:197

Referenced by load_module(), and unload_module().

◆ endpoint_formatters

◆ endpoint_identifiers

◆ host_ip_ipv4

pj_sockaddr host_ip_ipv4
static

Local host address for IPv4

Definition at line 73 of file res_pjsip.c.

Referenced by ast_sip_get_host_ip(), and load_pjsip().

◆ host_ip_ipv4_string

char host_ip_ipv4_string[PJ_INET6_ADDRSTRLEN]
static

Local host address for IPv4 (string form)

Definition at line 76 of file res_pjsip.c.

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

◆ host_ip_ipv6

pj_sockaddr host_ip_ipv6
static

Local host address for IPv6

Definition at line 79 of file res_pjsip.c.

Referenced by ast_sip_get_host_ip(), and load_pjsip().

◆ host_ip_ipv6_string

char host_ip_ipv6_string[PJ_INET6_ADDRSTRLEN]
static

Local host address for IPv6 (string form)

Definition at line 82 of file res_pjsip.c.

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

◆ info_method

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

Definition at line 1272 of file res_pjsip.c.

1272{PJSIP_OTHER_METHOD, {"INFO", 4} };

◆ memory_pool

pj_pool_t* memory_pool

Definition at line 2237 of file res_pjsip.c.

Referenced by load_pjsip(), and unload_pjsip().

◆ message_method

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

Definition at line 1273 of file res_pjsip.c.

1273{PJSIP_OTHER_METHOD, {"MESSAGE", 7} };

Referenced by does_method_match(), and does_method_match().

◆ method

const char* method

Definition at line 1277 of file res_pjsip.c.

Referenced by apply_method_filter(), ari_handle_websocket(), ast_ari_callback(), ast_ari_invoke(), ast_geoloc_eprofile_create_from_profile(), ast_geoloc_eprofile_dup(), ast_geoloc_eprofile_refresh_location(), ast_get_http_method(), ast_get_http_method_from_string(), ast_http_send(), ast_sip_create_request(), ast_sip_session_refresh(), ast_websocket_uri_cb(), auth_http_callback(), auth_manager_http_callback(), auth_mxml_http_callback(), auth_rawman_http_callback(), caldav_request(), create_in_dialog_request(), create_out_of_dialog_request(), delay_request(), delayed_method2str(), delayed_request_alloc(), does_method_match(), does_method_match(), exchangecal_request(), follow_redirect_methods_handler(), generic_http_callback(), geoloc_config_load(), geoloc_eprofile_create_from_xslt_result(), geoloc_profile_write(), get_pjsip_method(), handle_uri(), has_supplement(), http_callback(), http_callback(), http_post_callback(), httpd_process_request(), httpstatus_callback(), ident_handler(), ident_to_str(), incoming_ws_http_callback(), is_allowed_tel_uri_request(), maintenance_on_rx_request(), manager_add_filter(), manager_http_callback(), method_logging_info_alloc(), mxml_http_callback(), phoneprov_callback(), pjsip_enable_logger_method(), pjsip_log_test_filter(), rawman_http_callback(), res_sdp_crypto_parse_offer(), send_topology_change_refresh(), sip_endpoint_identifier_str2type(), sip_endpoint_identifier_type2str(), sip_session_refresh(), sorcery_function_read(), static_callback(), and update_connected_line_information().

◆ [struct]

struct { ... } methods[]

◆ monitor_continue

int monitor_continue
static

Definition at line 2239 of file res_pjsip.c.

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

◆ monitor_thread

pj_thread_t* monitor_thread

◆ pjsip_media_type_application_cpim_xpidf_xml

pjsip_media_type pjsip_media_type_application_cpim_xpidf_xml

Definition at line 3908 of file res_pjsip.c.

Referenced by load_module().

◆ pjsip_media_type_application_json

pjsip_media_type pjsip_media_type_application_json

Common media types used throughout res_pjsip and pjproject

Definition at line 3904 of file res_pjsip.c.

Referenced by load_module().

◆ pjsip_media_type_application_media_control_xml

pjsip_media_type pjsip_media_type_application_media_control_xml

Definition at line 3905 of file res_pjsip.c.

Referenced by load_module(), and video_info_incoming_request().

◆ pjsip_media_type_application_pidf_xml

pjsip_media_type pjsip_media_type_application_pidf_xml

Definition at line 3906 of file res_pjsip.c.

Referenced by add_eprofile_to_tdata(), find_pidf(), and load_module().

◆ pjsip_media_type_application_rlmi_xml

pjsip_media_type pjsip_media_type_application_rlmi_xml

Definition at line 3909 of file res_pjsip.c.

Referenced by load_module().

◆ pjsip_media_type_application_sdp

pjsip_media_type pjsip_media_type_application_sdp

Definition at line 3911 of file res_pjsip.c.

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

◆ pjsip_media_type_application_simple_message_summary

pjsip_media_type pjsip_media_type_application_simple_message_summary

Definition at line 3910 of file res_pjsip.c.

Referenced by load_module().

◆ pjsip_media_type_application_xpidf_xml

pjsip_media_type pjsip_media_type_application_xpidf_xml

Definition at line 3907 of file res_pjsip.c.

Referenced by load_module().

◆ pjsip_media_type_multipart_alternative

pjsip_media_type pjsip_media_type_multipart_alternative

Definition at line 3912 of file res_pjsip.c.

Referenced by check_content_disposition(), and load_module().

◆ pjsip_media_type_multipart_mixed

pjsip_media_type pjsip_media_type_multipart_mixed

◆ pjsip_media_type_multipart_related

pjsip_media_type pjsip_media_type_multipart_related

Definition at line 3914 of file res_pjsip.c.

Referenced by load_module().

◆ pjsip_media_type_text_plain

pjsip_media_type pjsip_media_type_text_plain

Definition at line 3915 of file res_pjsip.c.

Referenced by load_module().

◆ pmethod

const pjsip_method* pmethod

Definition at line 1278 of file res_pjsip.c.

Referenced by ast_sip_create_request().

◆ rc_map

const struct response_code_map rc_map[]
static

Definition at line 3629 of file res_pjsip.c.

3629 {
3630 { PJSIP_SC_NULL, "PJSIP_SC_NULL", "NULL" },
3631 { PJSIP_SC_TRYING, "PJSIP_SC_TRYING", "TRYING" },
3632 { PJSIP_SC_RINGING, "PJSIP_SC_RINGING", "RINGING" },
3633 { PJSIP_SC_CALL_BEING_FORWARDED, "PJSIP_SC_CALL_BEING_FORWARDED", "CALL_BEING_FORWARDED" },
3634 { PJSIP_SC_QUEUED, "PJSIP_SC_QUEUED", "QUEUED" },
3635 { PJSIP_SC_PROGRESS, "PJSIP_SC_PROGRESS", "PROGRESS" },
3636 { PJSIP_SC_EARLY_DIALOG_TERMINATED, "PJSIP_SC_EARLY_DIALOG_TERMINATED", "EARLY_DIALOG_TERMINATED" },
3637 { PJSIP_SC_OK, "PJSIP_SC_OK", "OK" },
3638 { PJSIP_SC_ACCEPTED, "PJSIP_SC_ACCEPTED", "ACCEPTED" },
3639 { PJSIP_SC_NO_NOTIFICATION, "PJSIP_SC_NO_NOTIFICATION", "NO_NOTIFICATION" },
3640 { PJSIP_SC_MULTIPLE_CHOICES, "PJSIP_SC_MULTIPLE_CHOICES", "MULTIPLE_CHOICES" },
3641 { PJSIP_SC_MOVED_PERMANENTLY, "PJSIP_SC_MOVED_PERMANENTLY", "MOVED_PERMANENTLY" },
3642 { PJSIP_SC_MOVED_TEMPORARILY, "PJSIP_SC_MOVED_TEMPORARILY", "MOVED_TEMPORARILY" },
3643 { PJSIP_SC_USE_PROXY, "PJSIP_SC_USE_PROXY", "USE_PROXY" },
3644 { PJSIP_SC_ALTERNATIVE_SERVICE, "PJSIP_SC_ALTERNATIVE_SERVICE", "ALTERNATIVE_SERVICE" },
3645 { PJSIP_SC_BAD_REQUEST, "PJSIP_SC_BAD_REQUEST", "BAD_REQUEST" },
3646 { PJSIP_SC_UNAUTHORIZED, "PJSIP_SC_UNAUTHORIZED", "UNAUTHORIZED" },
3647 { PJSIP_SC_PAYMENT_REQUIRED, "PJSIP_SC_PAYMENT_REQUIRED", "PAYMENT_REQUIRED" },
3648 { PJSIP_SC_FORBIDDEN, "PJSIP_SC_FORBIDDEN", "FORBIDDEN" },
3649 { PJSIP_SC_NOT_FOUND, "PJSIP_SC_NOT_FOUND", "NOT_FOUND" },
3650 { PJSIP_SC_METHOD_NOT_ALLOWED, "PJSIP_SC_METHOD_NOT_ALLOWED", "METHOD_NOT_ALLOWED" },
3651 { PJSIP_SC_NOT_ACCEPTABLE, "PJSIP_SC_NOT_ACCEPTABLE", "NOT_ACCEPTABLE" },
3652 { PJSIP_SC_PROXY_AUTHENTICATION_REQUIRED, "PJSIP_SC_PROXY_AUTHENTICATION_REQUIRED", "PROXY_AUTHENTICATION_REQUIRED" },
3653 { PJSIP_SC_REQUEST_TIMEOUT, "PJSIP_SC_REQUEST_TIMEOUT", "REQUEST_TIMEOUT" },
3654 { PJSIP_SC_CONFLICT, "PJSIP_SC_CONFLICT", "CONFLICT" },
3655 { PJSIP_SC_GONE, "PJSIP_SC_GONE", "GONE" },
3656 { PJSIP_SC_LENGTH_REQUIRED, "PJSIP_SC_LENGTH_REQUIRED", "LENGTH_REQUIRED" },
3657 { PJSIP_SC_CONDITIONAL_REQUEST_FAILED, "PJSIP_SC_CONDITIONAL_REQUEST_FAILED", "CONDITIONAL_REQUEST_FAILED" },
3658 { PJSIP_SC_REQUEST_ENTITY_TOO_LARGE, "PJSIP_SC_REQUEST_ENTITY_TOO_LARGE", "REQUEST_ENTITY_TOO_LARGE" },
3659 { PJSIP_SC_REQUEST_URI_TOO_LONG, "PJSIP_SC_REQUEST_URI_TOO_LONG", "REQUEST_URI_TOO_LONG" },
3660 { PJSIP_SC_UNSUPPORTED_MEDIA_TYPE, "PJSIP_SC_UNSUPPORTED_MEDIA_TYPE", "UNSUPPORTED_MEDIA_TYPE" },
3661 { PJSIP_SC_UNSUPPORTED_URI_SCHEME, "PJSIP_SC_UNSUPPORTED_URI_SCHEME", "UNSUPPORTED_URI_SCHEME" },
3662 { PJSIP_SC_UNKNOWN_RESOURCE_PRIORITY, "PJSIP_SC_UNKNOWN_RESOURCE_PRIORITY", "UNKNOWN_RESOURCE_PRIORITY" },
3663 { PJSIP_SC_BAD_EXTENSION, "PJSIP_SC_BAD_EXTENSION", "BAD_EXTENSION" },
3664 { PJSIP_SC_EXTENSION_REQUIRED, "PJSIP_SC_EXTENSION_REQUIRED", "EXTENSION_REQUIRED" },
3665 { PJSIP_SC_SESSION_TIMER_TOO_SMALL, "PJSIP_SC_SESSION_TIMER_TOO_SMALL", "SESSION_TIMER_TOO_SMALL" },
3666 { PJSIP_SC_INTERVAL_TOO_BRIEF, "PJSIP_SC_INTERVAL_TOO_BRIEF", "INTERVAL_TOO_BRIEF" },
3667 { PJSIP_SC_BAD_LOCATION_INFORMATION, "PJSIP_SC_BAD_LOCATION_INFORMATION", "BAD_LOCATION_INFORMATION" },
3668 { PJSIP_SC_USE_IDENTITY_HEADER, "PJSIP_SC_USE_IDENTITY_HEADER", "USE_IDENTITY_HEADER" },
3669 { PJSIP_SC_PROVIDE_REFERRER_HEADER, "PJSIP_SC_PROVIDE_REFERRER_HEADER", "PROVIDE_REFERRER_HEADER" },
3670 { PJSIP_SC_FLOW_FAILED, "PJSIP_SC_FLOW_FAILED", "FLOW_FAILED" },
3671 { PJSIP_SC_ANONIMITY_DISALLOWED, "PJSIP_SC_ANONIMITY_DISALLOWED", "ANONIMITY_DISALLOWED" },
3672 { PJSIP_SC_BAD_IDENTITY_INFO, "PJSIP_SC_BAD_IDENTITY_INFO", "BAD_IDENTITY_INFO" },
3673 { PJSIP_SC_UNSUPPORTED_CERTIFICATE, "PJSIP_SC_UNSUPPORTED_CERTIFICATE", "UNSUPPORTED_CERTIFICATE" },
3674 { PJSIP_SC_INVALID_IDENTITY_HEADER, "PJSIP_SC_INVALID_IDENTITY_HEADER", "INVALID_IDENTITY_HEADER" },
3675 { PJSIP_SC_FIRST_HOP_LACKS_OUTBOUND_SUPPORT, "PJSIP_SC_FIRST_HOP_LACKS_OUTBOUND_SUPPORT", "FIRST_HOP_LACKS_OUTBOUND_SUPPORT" },
3676 { PJSIP_SC_MAX_BREADTH_EXCEEDED, "PJSIP_SC_MAX_BREADTH_EXCEEDED", "MAX_BREADTH_EXCEEDED" },
3677 { PJSIP_SC_BAD_INFO_PACKAGE, "PJSIP_SC_BAD_INFO_PACKAGE", "BAD_INFO_PACKAGE" },
3678 { PJSIP_SC_CONSENT_NEEDED, "PJSIP_SC_CONSENT_NEEDED", "CONSENT_NEEDED" },
3679 { PJSIP_SC_TEMPORARILY_UNAVAILABLE, "PJSIP_SC_TEMPORARILY_UNAVAILABLE", "TEMPORARILY_UNAVAILABLE" },
3680 { PJSIP_SC_CALL_TSX_DOES_NOT_EXIST, "PJSIP_SC_CALL_TSX_DOES_NOT_EXIST", "CALL_TSX_DOES_NOT_EXIST" },
3681 { PJSIP_SC_LOOP_DETECTED, "PJSIP_SC_LOOP_DETECTED", "LOOP_DETECTED" },
3682 { PJSIP_SC_TOO_MANY_HOPS, "PJSIP_SC_TOO_MANY_HOPS", "TOO_MANY_HOPS" },
3683 { PJSIP_SC_ADDRESS_INCOMPLETE, "PJSIP_SC_ADDRESS_INCOMPLETE", "ADDRESS_INCOMPLETE" },
3684 { PJSIP_SC_BUSY_HERE, "PJSIP_SC_BUSY_HERE", "BUSY_HERE" },
3685 { PJSIP_SC_REQUEST_TERMINATED, "PJSIP_SC_REQUEST_TERMINATED", "REQUEST_TERMINATED" },
3686 { PJSIP_SC_NOT_ACCEPTABLE_HERE, "PJSIP_SC_NOT_ACCEPTABLE_HERE", "NOT_ACCEPTABLE_HERE" },
3687 { PJSIP_SC_BAD_EVENT, "PJSIP_SC_BAD_EVENT", "BAD_EVENT" },
3688 { PJSIP_SC_REQUEST_UPDATED, "PJSIP_SC_REQUEST_UPDATED", "REQUEST_UPDATED" },
3689 { PJSIP_SC_REQUEST_PENDING, "PJSIP_SC_REQUEST_PENDING", "REQUEST_PENDING" },
3690 { PJSIP_SC_UNDECIPHERABLE, "PJSIP_SC_UNDECIPHERABLE", "UNDECIPHERABLE" },
3691 { PJSIP_SC_SECURITY_AGREEMENT_NEEDED, "PJSIP_SC_SECURITY_AGREEMENT_NEEDED", "SECURITY_AGREEMENT_NEEDED" },
3692 { PJSIP_SC_INTERNAL_SERVER_ERROR, "PJSIP_SC_INTERNAL_SERVER_ERROR", "INTERNAL_SERVER_ERROR" },
3693 { PJSIP_SC_NOT_IMPLEMENTED, "PJSIP_SC_NOT_IMPLEMENTED", "NOT_IMPLEMENTED" },
3694 { PJSIP_SC_BAD_GATEWAY, "PJSIP_SC_BAD_GATEWAY", "BAD_GATEWAY" },
3695 { PJSIP_SC_SERVICE_UNAVAILABLE, "PJSIP_SC_SERVICE_UNAVAILABLE", "SERVICE_UNAVAILABLE" },
3696 { PJSIP_SC_SERVER_TIMEOUT, "PJSIP_SC_SERVER_TIMEOUT", "SERVER_TIMEOUT" },
3697 { PJSIP_SC_VERSION_NOT_SUPPORTED, "PJSIP_SC_VERSION_NOT_SUPPORTED", "VERSION_NOT_SUPPORTED" },
3698 { PJSIP_SC_MESSAGE_TOO_LARGE, "PJSIP_SC_MESSAGE_TOO_LARGE", "MESSAGE_TOO_LARGE" },
3699 { PJSIP_SC_PUSH_NOTIFICATION_SERVICE_NOT_SUPPORTED, "PJSIP_SC_PUSH_NOTIFICATION_SERVICE_NOT_SUPPORTED", "PUSH_NOTIFICATION_SERVICE_NOT_SUPPORTED" },
3700 { PJSIP_SC_PRECONDITION_FAILURE, "PJSIP_SC_PRECONDITION_FAILURE", "PRECONDITION_FAILURE" },
3701 { PJSIP_SC_BUSY_EVERYWHERE, "PJSIP_SC_BUSY_EVERYWHERE", "BUSY_EVERYWHERE" },
3702 { PJSIP_SC_DECLINE, "PJSIP_SC_DECLINE", "DECLINE" },
3703 { PJSIP_SC_DOES_NOT_EXIST_ANYWHERE, "PJSIP_SC_DOES_NOT_EXIST_ANYWHERE", "DOES_NOT_EXIST_ANYWHERE" },
3704 { PJSIP_SC_NOT_ACCEPTABLE_ANYWHERE, "PJSIP_SC_NOT_ACCEPTABLE_ANYWHERE", "NOT_ACCEPTABLE_ANYWHERE" },
3705 { PJSIP_SC_UNWANTED, "PJSIP_SC_UNWANTED", "UNWANTED" },
3706 { PJSIP_SC_REJECTED, "PJSIP_SC_REJECTED", "REJECTED" },
3707};

Referenced by ast_sip_str2rc().

◆ refer_method

const pjsip_method refer_method = {PJSIP_OTHER_METHOD, {"REFER", 5} }
static

Definition at line 1274 of file res_pjsip.c.

1274{PJSIP_OTHER_METHOD, {"REFER", 5} };

◆ registered_authenticator

struct ast_sip_authenticator* registered_authenticator
static

◆ registered_outbound_authenticator

struct ast_sip_outbound_authenticator* registered_outbound_authenticator
static

◆ sip_taskpool

struct ast_taskpool* sip_taskpool
static

◆ supplement_module

pjsip_module supplement_module
static

Definition at line 1316 of file res_pjsip.c.

1316 {
1317 .name = { "Out of dialog supplement hook", 29 },
1318 .id = -1,
1319 .priority = PJSIP_MOD_PRIORITY_APPLICATION - 1,
1320 .on_rx_request = supplement_on_rx_request,
1321};
static pj_bool_t supplement_on_rx_request(pjsip_rx_data *rdata)
Definition res_pjsip.c:2325

Referenced by ast_sip_create_response(), ast_sip_send_out_of_dialog_request(), clean_contact_from_tdata(), create_out_of_dialog_request(), load_module(), supplement_outgoing_response(), and unload_pjsip().

◆ supplements