#include "asterisk.h"
#include <signal.h>
#include <sys/signal.h>
#include <regex.h>
#include <inttypes.h>
#include "asterisk/network.h"
#include "asterisk/paths.h"
#include "asterisk/lock.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/rtp_engine.h"
#include "asterisk/udptl.h"
#include "asterisk/acl.h"
#include "asterisk/manager.h"
#include "asterisk/callerid.h"
#include "asterisk/cli.h"
#include "asterisk/musiconhold.h"
#include "asterisk/dsp.h"
#include "asterisk/features.h"
#include "asterisk/srv.h"
#include "asterisk/astdb.h"
#include "asterisk/causes.h"
#include "asterisk/utils.h"
#include "asterisk/file.h"
#include "asterisk/astobj2.h"
#include "asterisk/dnsmgr.h"
#include "asterisk/devicestate.h"
#include "asterisk/monitor.h"
#include "asterisk/netsock2.h"
#include "asterisk/localtime.h"
#include "asterisk/abstract_jb.h"
#include "asterisk/threadstorage.h"
#include "asterisk/translate.h"
#include "asterisk/ast_version.h"
#include "asterisk/event.h"
#include "asterisk/cel.h"
#include "asterisk/data.h"
#include "asterisk/aoc.h"
#include "asterisk/message.h"
#include "sip/include/sip.h"
#include "sip/include/globals.h"
#include "sip/include/config_parser.h"
#include "sip/include/reqresp_parser.h"
#include "sip/include/sip_utils.h"
#include "sip/include/srtp.h"
#include "sip/include/sdp_crypto.h"
#include "asterisk/ccss.h"
#include "asterisk/xml.h"
#include "sip/include/dialog.h"
#include "sip/include/dialplan_functions.h"
#include "sip/include/security_events.h"
Go to the source code of this file.
Data Structures | |
| struct | ast_register_list |
| The register list: Other SIP proxies we register with and receive calls from. More... | |
| struct | ast_subscription_mwi_list |
| The MWI subscription list. More... | |
| struct | cfalias |
| Structure for conversion between compressed SIP and "normal" SIP headers. More... | |
| struct | cfsip_methods |
| The core structure to setup dialogs. We parse incoming messages by using structure and then route the messages according to the type. More... | |
| struct | cfsubscription_types |
Subscription types that we support. We support
| |
| struct | domain_list |
| struct | epa_static_data_list |
| struct | event_state_compositor |
| The Event State Compositors. More... | |
| struct | invstate2stringtable |
| Readable descriptions of device states. More... | |
| struct | match_req_args |
| struct | sip_history_head |
| struct | sip_reasons |
| Diversion header reasons. More... | |
Object counters @{ | |
| |
| #define | append_history(p, event, fmt, args...) append_history_full(p, "%-15s " fmt, event, ## args) |
| Append to SIP dialog history. | |
| #define | check_request_transport(peer, tmpl) |
| generic function for determining if a correct transport is being used to contact a peer | |
| #define | CONTAINER_UNLINK(container, obj, tag) |
| Unlink the given object from the container and return TRUE if it was in the container. | |
| #define | DATA_EXPORT_SIP_PEER(MEMBER) |
| #define | FORMAT "%-15.15s %-15.15s %-15.15s %-15.15s %-3.3s %-3.3s %-15.15s %-10.10s %-10.10s\n" |
| #define | FORMAT "%-30.30s %-12.12s %-10.10s %-10.10s\n" |
| #define | FORMAT "%-15.15s %-11.11s %-8.8s %-10.10u%-1.1s %-10.10u (%5.2f%%) %-6.4lf %-10.10u%-1.1s %-10.10u (%5.2f%%) %-6.4lf\n" |
| #define | FORMAT "%-39.39s %-6.6s %-12.12s %8d %-20.20s %-25.25s\n" |
| #define | FORMAT "%-40.40s %-20.20s %-16.16s\n" |
| #define | FORMAT "%-25.25s %-15.15s %-15.15s %-15.15s %-5.5s%-10.10s\n" |
| #define | FORMAT "%-47.47s %-9.9s %-6.6s\n" |
| #define | FORMAT "%-25.25s %-15.15s %-15.15s \n" |
| #define | FORMAT2 "%-15.15s %-15.15s %-15.15s %-15.15s %-7.7s %-15.15s %-10.10s %-10.10s\n" |
| #define | FORMAT2 "%-15.15s %-11.11s %-8.8s %-10.10s %-10.10s ( %%) %-6.6s %-10.10s %-10.10s ( %%) %-6.6s\n" |
| #define | FORMAT2 "%-39.39s %-6.6s %-12.12s %8.8s %-20.20s %-25.25s\n" |
| #define | FORMAT2 "%-25.25s %-39.39s %-3.3s %-10.10s %-3.3s %-8s %-11s %-32.32s %s\n" |
| #define | FORMAT2 "%-47.47s %9.9s %6.6s\n" |
| #define | FORMAT2 "%-25.25s %-15.15s %-15.15s \n" |
| #define | FORMAT3 "%-15.15s %-15.15s %-15.15s %-15.15s %-13.13s %-15.15s %-10.10s %-6.6s\n" |
| #define | FORMAT4 "%-15.15s %-15.15s %-15.15s %-15.15s %-13.13s %-15.15s %-10.10s %-6.6d\n" |
| #define | sip_pvt_lock(x) ao2_lock(x) |
| #define | sip_pvt_trylock(x) ao2_trylock(x) |
| #define | sip_pvt_unlock(x) ao2_unlock(x) |
| #define | UNLINK(element, head, prev) |
| enum | match_req_res { SIP_REQ_MATCH, SIP_REQ_NOT_MATCH, SIP_REQ_LOOP_DETECTED, SIP_REQ_FORKED } |
| enum | peer_unlink_flag_t { SIP_PEERS_MARKED, SIP_PEERS_ALL } |
| static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Session Initiation Protocol (SIP)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DRIVER, .nonoptreq = "res_crypto,chan_local", } |
| static struct cfalias | aliases [] |
| static struct _map_x_s | allowoverlapstr [] |
| static int | apeerobjs = 0 |
| static char * | app_dtmfmode = "SIPDtmfMode" |
| static char * | app_sipaddheader = "SIPAddHeader" |
| static char * | app_sipremoveheader = "SIPRemoveHeader" |
| static struct ast_module_info * | ast_module_info = &__mod_info |
| static struct sip_auth_container * | authl = NULL |
| Authentication container for realm authentication. | |
| static ast_mutex_t | authl_lock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 } |
| Global authentication container protection while adjusting the references. | |
| static struct _map_x_s | autopeermodes [] |
| struct ast_sockaddr | bindaddr |
| static struct epa_static_data | cc_epa_static_data |
| static struct ast_custom_function | checksipdomain_function |
| static struct ast_cli_entry | cli_sip [] |
| SIP Cli commands definition. | |
| static struct ast_sockaddr | debugaddr |
| static const int | DEFAULT_PUBLISH_EXPIRES = 3600 |
| static struct ast_tls_config | default_tls_cfg |
| Default TLS connection configuration. | |
| static struct ao2_container * | dialogs |
| struct ao2_container * | dialogs_needdestroy |
| struct ao2_container * | dialogs_rtpcheck |
| static struct _map_x_s | dtmfstr [] |
| mapping between dtmf flags and strings | |
| static int | esc_etag_counter |
| static const int | ESC_MAX_BUCKETS = 37 |
| static struct event_state_compositor | event_state_compositors [] |
| The Event State Compositors. | |
| static struct ast_sockaddr | externaddr |
| our external IP address/port for SIP sessions. externaddr.sin_addr is only set when we know we might be behind a NAT, and this is done using a variety of (mutually exclusive) ways from the config file: | |
| static time_t | externexpire |
| static char | externhost [MAXHOSTNAMELEN] |
| static int | externrefresh = 10 |
| static uint16_t | externtcpport |
| static uint16_t | externtlsport |
| static struct _map_x_s | faxecmodes [] |
| static struct ast_flags | global_flags [3] = {{0}} |
| static int | global_t38_maxdatagram |
| static const int | HASH_DIALOG_SIZE = 563 |
| static const int | HASH_PEER_SIZE = 563 |
| static struct _map_x_s | insecurestr [] |
| static struct ast_sockaddr | internip |
| our (internal) default address/port to put in SIP/SDP messages internip is initialized picking a suitable address from one of the interfaces, and the same port number we bind to. It is used as the default address/port in SIP messages, and as the default address (but not port) in SDP messages. | |
| static struct io_context * | io |
| static struct ast_ha * | localaddr |
| List of local networks We store "localnet" addresses from the config file into an access list, marked as 'DENY', so the call to ast_apply_ha() will return AST_SENSE_DENY for 'local' addresses, and AST_SENSE_ALLOW for 'non local' (i.e. presumably public) addresses. | |
| static struct ast_sockaddr | media_address |
| static pthread_t | monitor_thread = AST_PTHREADT_NULL |
| This is the thread for the monitor which checks for input on the channels which are not currently in use. | |
| static ast_mutex_t | monlock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 } |
| Protect the monitoring thread, so only one process can kill or start it, and not when it's doing something critical. | |
| static ast_mutex_t | netlock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 } |
| static int | network_change_event_sched_id = -1 |
| static struct ast_event_sub * | network_change_event_subscription |
| static struct ast_config * | notify_types = NULL |
| static int | ourport_tcp |
| static int | ourport_tls |
| static struct ao2_container * | peers |
| The peer list: Users, Peers and Friends. | |
| static struct ao2_container * | peers_by_ip |
| static struct ast_data_handler | peers_data_provider |
| static struct _map_x_s | referstatusstrings [] |
| static struct ast_register_list | regl |
| The register list: Other SIP proxies we register with and receive calls from. | |
| static int | regobjs = 0 |
| static struct _map_x_s | regstatestrings [] |
| static int | rpeerobjs = 0 |
| struct ast_sched_context * | sched |
| static struct ast_cc_agent_callbacks | sip_cc_agent_callbacks |
| static struct ast_cc_monitor_callbacks | sip_cc_monitor_callbacks |
| struct { | |
| enum sip_cc_notify_state state | |
| const char * state_string | |
| } | sip_cc_notify_state_map [] |
| struct { | |
| enum ast_cc_service_type service | |
| const char * service_string | |
| } | sip_cc_service_map [] |
| static struct ast_data_entry | sip_data_providers [] |
| static struct ast_custom_function | sip_header_function |
| struct ao2_container * | sip_monitor_instances |
| static struct ast_threadstorage | sip_msg_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_sip_msg_buf , .custom_init = NULL , } |
| static struct ast_msg_tech | sip_msg_tech |
| static ast_mutex_t | sip_reload_lock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 } |
| static int | sip_reloading = FALSE |
| static enum channelreloadreason | sip_reloadreason |
| static struct ast_rtp_glue | sip_rtp_glue |
| static struct ast_tcptls_session_args | sip_tcp_desc |
| The TCP server definition. | |
| struct ast_channel_tech | sip_tech |
| Definition of this channel for PBX channel registration. | |
| struct ast_channel_tech | sip_tech_info |
| This version of the sip channel tech has no send_digit_begin callback so that the core knows that the channel does not want DTMF BEGIN frames. The struct is initialized just before registering the channel driver, and is for use with channels using SIP INFO DTMF. | |
| static struct ast_tls_config | sip_tls_cfg |
| Working TLS connection configuration. | |
| static struct ast_tcptls_session_args | sip_tls_desc |
| The TCP/TLS server definition. | |
| static struct ast_udptl_protocol | sip_udptl |
| Interface structure with callbacks used to connect to UDPTL module. | |
| static struct ast_custom_function | sipchaninfo_function |
| Structure to declare a dialplan function: SIPCHANINFO. | |
| static enum sip_debug_e | sipdebug |
| static int | sipdebug_text |
| extra debugging for 'text' related events. At the moment this is set together with sip_debug_console. | |
| static struct ast_custom_function | sippeer_function |
| Structure to declare a dialplan function: SIPPEER. | |
| static int | sipsock = -1 |
| Main socket for UDP SIP communication. | |
| static int * | sipsock_read_id |
| static int | speerobjs = 0 |
| static struct _map_x_s | stmodes [] |
| Report Peer status in character string. | |
| static struct _map_x_s | strefreshers [] |
| static struct ast_subscription_mwi_list | submwil |
| The MWI subscription list. | |
| static struct ao2_container * | threadt |
| The table of TCP threads. | |
| static struct ast_threadstorage | ts_temp_pvt = { .once = PTHREAD_ONCE_INIT , .key_init = __init_ts_temp_pvt , .custom_init = temp_pvt_init , } |
| static char | used_context [AST_MAX_CONTEXT] |
| static const char * | __get_header (const struct sip_request *req, const char *name, int *start) |
| static void | __init_sip_msg_buf (void) |
| static void | __init_ts_temp_pvt (void) |
| A per-thread temporary pvt structure. | |
| static void | __reg_module (void) |
| static int | __set_address_from_contact (const char *fullcontact, struct ast_sockaddr *addr, int tcp) |
| int | __sip_ack (struct sip_pvt *p, uint32_t seqno, int resp, int sipmethod) |
| Acknowledges receipt of a packet and stops retransmission called with p locked. | |
| static int | __sip_autodestruct (const void *data) |
| Kill a SIP dialog (called only by the scheduler) The scheduler has a reference to this dialog when p->autokillid != -1, and we are called using that reference. So if the event is not rescheduled, we need to call dialog_unref(). | |
| void | __sip_destroy (struct sip_pvt *p, int lockowner, int lockdialoglist) |
| Execute destruction of SIP dialog structure, release memory. | |
| static int | __sip_do_register (struct sip_registry *r) |
| Register with SIP proxy. | |
| void | __sip_pretend_ack (struct sip_pvt *p) |
| Pretend to ack all packets called with p locked. | |
| static int | __sip_reliable_xmit (struct sip_pvt *p, uint32_t seqno, int resp, struct ast_str *data, int fatal, int sipmethod) |
| int | __sip_semi_ack (struct sip_pvt *p, uint32_t seqno, int resp, int sipmethod) |
| Acks receipt of packet, keep it around (used for provisional responses). | |
| static int | __sip_subscribe_mwi_do (struct sip_subscription_mwi *mwi) |
| Actually setup an MWI subscription or resubscribe. | |
| static int | __sip_xmit (struct sip_pvt *p, struct ast_str *data) |
| static int | __transmit_response (struct sip_pvt *p, const char *msg, const struct sip_request *req, enum xmittype reliable) |
| Base transmit response function. | |
| static void | __unreg_module (void) |
| static char * | _sip_qualify_peer (int type, int fd, struct mansession *s, const struct message *m, int argc, const char *argv[]) |
| Send qualify message to peer from cli or manager. Mostly for debugging. | |
| static char * | _sip_show_peer (int type, int fd, struct mansession *s, const struct message *m, int argc, const char *argv[]) |
| Show one peer in detail (main function). | |
| static char * | _sip_show_peers (int fd, int *total, struct mansession *s, const struct message *m, int argc, const char *argv[]) |
| Execute sip show peers command. | |
| static void * | _sip_tcp_helper_thread (struct sip_pvt *pvt, struct ast_tcptls_session_instance *tcptls_session) |
| SIP TCP thread management function This function reads from the socket, parses the packet into a request. | |
| static void | add_blank (struct sip_request *req) |
| add a blank line if no body | |
| static void | add_cc_call_info_to_response (struct sip_pvt *p, struct sip_request *resp) |
| static void | add_codec_to_sdp (const struct sip_pvt *p, struct ast_format *format, struct ast_str **m_buf, struct ast_str **a_buf, int debug, int *min_packet_size) |
| Add codec offer to SDP offer/answer body in INVITE or 200 OK. | |
| static int | add_content (struct sip_request *req, const char *line) |
| Add content (not header) to SIP message. | |
| static int | add_digit (struct sip_request *req, char digit, unsigned int duration, int mode) |
| Add DTMF INFO tone to sip message Mode = 0 for application/dtmf-relay (Cisco) 1 for application/dtmf. | |
| static void | add_diversion_header (struct sip_request *req, struct sip_pvt *pvt) |
| Add "Diversion" header to outgoing message. | |
| static int | add_header (struct sip_request *req, const char *var, const char *value) |
| Add header to SIP message. | |
| static int | add_header_max_forwards (struct sip_pvt *dialog, struct sip_request *req) |
| Add 'Max-Forwards' header to SIP message. | |
| static void | add_msg_header (struct sip_pvt *pvt, const char *hdr_name, const char *hdr_value) |
| static void | add_noncodec_to_sdp (const struct sip_pvt *p, int format, struct ast_str **m_buf, struct ast_str **a_buf, int debug) |
| Add RFC 2833 DTMF offer to SDP. | |
| static void | add_peer_mailboxes (struct sip_peer *peer, const char *value) |
| static void | add_peer_mwi_subs (struct sip_peer *peer) |
| static void | add_realm_authentication (struct sip_auth_container **credentials, const char *configuration, int lineno) |
| static void | add_route (struct sip_request *req, struct sip_route *route) |
| Add route header into request per learned route. | |
| static int | add_rpid (struct sip_request *req, struct sip_pvt *p) |
| Add Remote-Party-ID header to SIP message. | |
| static enum sip_result | add_sdp (struct sip_request *resp, struct sip_pvt *p, int oldsdp, int add_audio, int add_t38) |
| Add Session Description Protocol message. | |
| static int | add_sip_domain (const char *domain, const enum domain_mode mode, const char *context) |
| Add SIP domain to list of domains we are responsible for. | |
| static int | add_supported_header (struct sip_pvt *pvt, struct sip_request *req) |
| Add "Supported" header to sip message. Since some options may be disabled in the config, the sip_pvt must be inspected to determine what is supported for this dialog. | |
| static void | add_tcodec_to_sdp (const struct sip_pvt *p, struct ast_format *format, struct ast_str **m_buf, struct ast_str **a_buf, int debug, int *min_packet_size) |
| Add text codec offer to SDP offer/answer body in INVITE or 200 OK. | |
| static int | add_text (struct sip_request *req, struct sip_pvt *p) |
| Add text body to SIP message. | |
| static struct ast_variable * | add_var (const char *buf, struct ast_variable *list) |
| implement the setvar config line | |
| static void | add_vcodec_to_sdp (const struct sip_pvt *p, struct ast_format *format, struct ast_str **m_buf, struct ast_str **a_buf, int debug, int *min_packet_size) |
| Add video codec offer to SDP offer/answer body in INVITE or 200 OK. | |
| static int | add_vidupdate (struct sip_request *req) |
| add XML encoded media control with update | |
| static const char * | allowoverlap2str (int mode) |
| Convert AllowOverlap setting to printable string. | |
| static void | append_date (struct sip_request *req) |
| Append date to SIP message. | |
| static void | append_history_full (struct sip_pvt *p, const char *fmt,...) |
| Append to SIP dialog history with arg list. | |
| static void | append_history_va (struct sip_pvt *p, const char *fmt, va_list ap) |
| Append to SIP dialog history with arg list. | |
| static int | apply_directmedia_ha (struct sip_pvt *p, const char *op) |
| AST_DATA_STRUCTURE (sip_peer, DATA_EXPORT_SIP_PEER) | |
| static void | ast_quiet_chan (struct ast_channel *chan) |
| Turn off generator data XXX Does this function belong in the SIP channel? | |
| static void | ast_sip_ouraddrfor (const struct ast_sockaddr *them, struct ast_sockaddr *us, struct sip_pvt *p) |
| NAT fix - decide which IP address to use for Asterisk server? | |
| static int | ast_sockaddr_resolve_first (struct ast_sockaddr *addr, const char *name, int flag) |
| Return the first entry from ast_sockaddr_resolve filtered by family of binddaddr. | |
| static int | ast_sockaddr_resolve_first_af (struct ast_sockaddr *addr, const char *name, int flag, int family) |
| Return the first entry from ast_sockaddr_resolve filtered by address family. | |
| static int | attempt_transfer (struct sip_dual *transferer, struct sip_dual *target) |
| Attempt transfer of SIP call This fix for attended transfers on a local PBX. | |
| static int | auto_congest (const void *arg) |
| Scheduled congestion on a call. Only called by the scheduler, must return the reference when done. | |
| static const char * | autocreatepeer2str (enum autocreatepeer_mode r) |
| static int | block_msg_header (const char *header_name) |
| static void | build_callid_pvt (struct sip_pvt *pvt) |
| Build SIP Call-ID value for a non-REGISTER transaction. | |
| static void | build_callid_registry (struct sip_registry *reg, const struct ast_sockaddr *ourip, const char *fromdomain) |
| Build SIP Call-ID value for a REGISTER transaction. | |
| static void | build_contact (struct sip_pvt *p) |
| Build contact header - the contact header we send out. | |
| static struct sip_peer * | build_peer (const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime, int devstate_only) |
| Build peer from configuration (file or realtime static/dynamic). | |
| static int | build_reply_digest (struct sip_pvt *p, int method, char *digest, int digest_len) |
| Build reply digest. | |
| static void | build_route (struct sip_pvt *p, struct sip_request *req, int backwards) |
| Build route list from Record-Route header. | |
| static void | build_via (struct sip_pvt *p) |
| Build a Via header for a request. | |
| static int | cb_extensionstate (const char *context, const char *exten, enum ast_extension_states state, void *data) |
| Callback for the devicestate notification (SUBSCRIBE) support subsystem. | |
| static void | cb_extensionstate_destroy (int id, void *data) |
| static void | cc_epa_destructor (void *data) |
| static void | cc_handle_publish_error (struct sip_pvt *pvt, const int resp, struct sip_request *req, struct sip_epa_entry *epa_entry) |
| static void | change_callid_pvt (struct sip_pvt *pvt, const char *callid) |
| static void | change_hold_state (struct sip_pvt *dialog, struct sip_request *req, int holdstate, int sendonly) |
| Change hold state for a call. | |
| static void | change_redirecting_information (struct sip_pvt *p, struct sip_request *req, struct ast_party_redirecting *redirecting, struct ast_set_party_redirecting *update_redirecting, int set_call_forward) |
| update redirecting information for a channel based on headers | |
| static void | change_t38_state (struct sip_pvt *p, int state) |
| Change the T38 state on a SIP dialog. | |
| static enum check_auth_result | check_auth (struct sip_pvt *p, struct sip_request *req, const char *username, const char *secret, const char *md5secret, int sipmethod, const char *uri, enum xmittype reliable, int ignore) |
| Check user authorization from peer definition Some actions, like REGISTER and INVITEs from peers require authentication (if peer have secret set). | |
| static enum check_auth_result | check_peer_ok (struct sip_pvt *p, char *of, struct sip_request *req, int sipmethod, struct ast_sockaddr *addr, struct sip_peer **authpeer, enum xmittype reliable, char *calleridname, char *uri2) |
| Validate device authentication. | |
| static void | check_pendings (struct sip_pvt *p) |
| Check pending actions on SIP call. | |
| static int | check_rtp_timeout (struct sip_pvt *dialog, time_t t) |
| helper function for the monitoring thread -- seems to be called with the assumption that the dialog is locked | |
| static int | check_sip_domain (const char *domain, char *context, size_t len) |
| check_sip_domain: Check if domain part of uri is local to our server | |
| static int | check_user (struct sip_pvt *p, struct sip_request *req, int sipmethod, const char *uri, enum xmittype reliable, struct ast_sockaddr *addr) |
| Find user If we get a match, this will add a reference pointer to the user object in ASTOBJ, that needs to be unreferenced. | |
| static enum check_auth_result | check_user_full (struct sip_pvt *p, struct sip_request *req, int sipmethod, const char *uri, enum xmittype reliable, struct ast_sockaddr *addr, struct sip_peer **authpeer) |
| Check if matching user or peer is defined Match user on From: user name and peer on IP/port This is used on first invite (not re-invites) and subscribe requests. | |
| static void | check_via (struct sip_pvt *p, struct sip_request *req) |
| check Via: header for hostname, port and rport request/answer | |
| static attribute_unused void | check_via_response (struct sip_pvt *p, struct sip_request *req) |
| check received= and rport= in a SIP response. If we get a response with received= and/or rport= in the Via: line, use them as 'p->ourip' (see RFC 3581 for rport, and RFC 3261 for received). Using these two fields SIP can produce the correct address and port in the SIP headers without the need for STUN. The address part is also reused for the media sessions. Note that ast_sip_ouraddrfor() still rewrites p->ourip if you specify externaddr/seternaddr/. | |
| static void | cleanup_all_regs (void) |
| static void | cleanup_stale_contexts (char *new, char *old) |
| Destroy disused contexts between reloads Only used in reload_config so the code for regcontext doesn't get ugly. | |
| static void | clear_peer_mailboxes (struct sip_peer *peer) |
| static void | clear_sip_domains (void) |
| Clear our domain list (at reload). | |
| static char * | complete_sip_peer (const char *word, int state, int flags2) |
| Do completion on peer name. | |
| static char * | complete_sip_registered_peer (const char *word, int state, int flags2) |
| Do completion on registered peer name. | |
| static char * | complete_sip_show_history (const char *line, const char *word, int pos, int state) |
| Support routine for 'sip show history' CLI. | |
| static char * | complete_sip_show_peer (const char *line, const char *word, int pos, int state) |
| Support routine for 'sip show peer' CLI. | |
| static char * | complete_sip_show_user (const char *line, const char *word, int pos, int state) |
| Support routine for 'sip show user' CLI. | |
| static char * | complete_sip_unregister (const char *line, const char *word, int pos, int state) |
| Support routine for 'sip unregister' CLI. | |
| static char * | complete_sip_user (const char *word, int state) |
| Do completion on user name. | |
| static char * | complete_sipch (const char *line, const char *word, int pos, int state) |
| Support routine for 'sip show channel' and 'sip show history' CLI This is in charge of generating all strings that match a prefix in the given position. As many functions of this kind, each invokation has O(state) time complexity so be careful in using it. | |
| static char * | complete_sipnotify (const char *line, const char *word, int pos, int state) |
| Support routine for 'sip notify' CLI. | |
| static int | construct_pidf_body (enum sip_cc_publish_state state, char *pidf_body, size_t size, const char *presentity) |
| static int | copy_all_header (struct sip_request *req, const struct sip_request *orig, const char *field) |
| Copy all headers from one request to another. | |
| static int | copy_header (struct sip_request *req, const struct sip_request *orig, const char *field) |
| Copy one header field from one request to another. | |
| static void | copy_request (struct sip_request *dst, const struct sip_request *src) |
| copy SIP request (mostly used to save request for responses) | |
| static void | copy_socket_data (struct sip_socket *to_sock, const struct sip_socket *from_sock) |
| static struct ast_variable * | copy_vars (struct ast_variable *src) |
| duplicate a list of channel variables, | |
| static int | copy_via_headers (struct sip_pvt *p, struct sip_request *req, const struct sip_request *orig, const char *field) |
| Copy SIP VIA Headers from the request to the response. | |
| static int | create_addr (struct sip_pvt *dialog, const char *opeer, struct ast_sockaddr *addr, int newdialog, struct ast_sockaddr *remote_address) |
| create address structure from device name Or, if peer not found, find it in the global DNS returns TRUE (-1) on failure, FALSE on success | |
| static int | create_addr_from_peer (struct sip_pvt *dialog, struct sip_peer *peer) |
| Create address structure from peer reference. This function copies data from peer to the dialog, so we don't have to look up the peer again from memory or database during the life time of the dialog. | |
| static struct sip_epa_entry * | create_epa_entry (const char *const event_package, const char *const destination) |
| static struct sip_esc_entry * | create_esc_entry (struct event_state_compositor *esc, struct sip_request *req, const int expires) |
| static void | create_new_sip_etag (struct sip_esc_entry *esc_entry, int is_linked) |
| static int | default_sip_port (enum sip_transport type) |
| The default sip port for the given transport. | |
| static void | deinit_req (struct sip_request *req) |
| Deinitialize SIP response/request. | |
| static void | destroy_association (struct sip_peer *peer) |
| Remove registration data from realtime database or AST/DB when registration expires. | |
| static void | destroy_escs (void) |
| static void | destroy_mailbox (struct sip_mailbox *mailbox) |
| static void | destroy_msg_headers (struct sip_pvt *pvt) |
| static void | destroy_realm_authentication (void *obj) |
| static int | determine_firstline_parts (struct sip_request *req) |
| Parse first line of incoming SIP request. | |
| static enum sip_publish_type | determine_sip_publish_type (struct sip_request *req, const char *const event, const char *const etag, const char *const expires, int *expires_int) |
| static int | dialog_checkrtp_cb (void *dialogobj, void *arg, int flags) |
| Check RTP Timeout on dialogs. | |
| static int | dialog_cmp_cb (void *obj, void *arg, int flags) |
| static int | dialog_dump_func (void *userobj, void *arg, int flags) |
| static int | dialog_find_multiple (void *obj, void *arg, int flags) |
| static int | dialog_hash_cb (const void *obj, const int flags) |
| static int | dialog_initialize_rtp (struct sip_pvt *dialog) |
| Initialize RTP portion of a dialog. | |
| static int | dialog_needdestroy (void *dialogobj, void *arg, int flags) |
| Match dialogs that need to be destroyed. | |
| struct sip_pvt * | dialog_ref_debug (struct sip_pvt *p, const char *tag, char *file, int line, const char *func) |
| void | dialog_unlink_all (struct sip_pvt *dialog) |
| Unlink a dialog from the dialogs container, as well as any other places that it may be currently stored. | |
| struct sip_pvt * | dialog_unref_debug (struct sip_pvt *p, const char *tag, char *file, int line, const char *func) |
| static void | disable_dsp_detect (struct sip_pvt *p) |
| static void | display_nat_warning (const char *cat, int reason, struct ast_flags *flags) |
| static int | do_magic_pickup (struct ast_channel *channel, const char *extension, const char *context) |
| static int | do_message_auth (struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, uint32_t seqno) |
| static void * | do_monitor (void *data) |
| The SIP monitoring thread. | |
| static int | do_proxy_auth (struct sip_pvt *p, struct sip_request *req, enum sip_auth_type code, int sipmethod, int init) |
| Add authentication on outbound SIP packet. | |
| static int | do_register_auth (struct sip_pvt *p, struct sip_request *req, enum sip_auth_type code) |
| Authenticate for outbound registration. | |
| static void | do_setnat (struct sip_pvt *p) |
| Set nat mode on the various data sockets. | |
| static const char * | domain_mode_to_text (const enum domain_mode mode) |
| Print domain mode to cli. | |
| static const char * | dtmfmode2str (int mode) |
| Convert DTMF mode to printable string. | |
| static void | enable_dsp_detect (struct sip_pvt *p) |
| static int | esc_cmp_fn (void *obj, void *arg, int flags) |
| static void | esc_entry_destructor (void *obj) |
| static int | esc_hash_fn (const void *obj, const int flags) |
| static int | expire_register (const void *data) |
| Expire registration of SIP peer. | |
| static void | extract_host_from_hostport (char **hostport) |
| Terminate a host:port at the ':'. | |
| static void | extract_uri (struct sip_pvt *p, struct sip_request *req) |
| Check Contact: URI of SIP message. | |
| static const char * | faxec2str (int faxec) |
| static int | finalize_content (struct sip_request *req) |
| Add 'Content-Length' header and content to SIP message. | |
| static const char * | find_alias (const char *name, const char *_default) |
| Find compressed SIP alias. | |
| static int | find_by_callid_helper (void *obj, void *arg, int flags) |
| static int | find_by_name (void *obj, void *arg, void *data, int flags) |
| static int | find_by_notify_uri_helper (void *obj, void *arg, int flags) |
| static int | find_by_subscribe_uri_helper (void *obj, void *arg, int flags) |
| static struct sip_pvt * | find_call (struct sip_request *req, struct ast_sockaddr *addr, const int intended_method) |
| find or create a dialog structure for an incoming SIP message. Connect incoming SIP message to current dialog or create new dialog structure Returns a reference to the sip_pvt object, remember to give it back once done. Called by handle_request_do | |
| static int | find_calling_channel (void *obj, void *arg, void *data, int flags) |
| Find the channel that is causing the RINGING update. | |
| const char * | find_closing_quote (const char *start, const char *lim) |
| Locate closing quote in a string, skipping escaped quotes. optionally with a limit on the search. start must be past the first quote. | |
| static const char * | find_full_alias (const char *name, const char *_default) |
| Find full SIP alias. | |
| static struct sip_auth * | find_realm_authentication (struct sip_auth_container *credentials, const char *realm) |
| static int | find_sdp (struct sip_request *req) |
| Determine whether a SIP message contains an SDP in its body. | |
| static struct ast_cc_agent * | find_sip_cc_agent_by_notify_uri (const char *const uri) |
| static struct ast_cc_agent * | find_sip_cc_agent_by_original_callid (struct sip_pvt *pvt) |
| static struct ast_cc_agent * | find_sip_cc_agent_by_subscribe_uri (const char *const uri) |
| static int | find_sip_method (const char *msg) |
| find_sip_method: Find SIP method from header | |
| static int | find_sip_monitor_instance_by_subscription_pvt (void *obj, void *arg, int flags) |
| static int | find_sip_monitor_instance_by_suspension_entry (void *obj, void *arg, int flags) |
| static struct epa_static_data * | find_static_data (const char *const event_package) |
| static struct cfsubscription_types * | find_subscription_type (enum subscriptiontype subtype) |
| Find subscription type in array. | |
| static void | forked_invite_init (struct sip_request *req, const char *new_theirtag, struct sip_pvt *original, struct ast_sockaddr *addr) |
| This function creates a dialog to handle a forked request. This dialog exists only to properly terminiate the the forked request immediately. | |
| static void | free_old_route (struct sip_route *route) |
| Remove route from route list. | |
| static int | func_check_sipdomain (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len) |
| Dial plan function to check if domain is local. | |
| static int | func_header_read (struct ast_channel *chan, const char *function, char *data, char *buf, size_t len) |
| Read SIP header (dialplan function). | |
| static int | function_sipchaninfo_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len) |
| ${SIPCHANINFO()} Dialplan function - reads sip channel data | |
| static int | function_sippeer (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len) |
| ${SIPPEER()} Dialplan function - reads peer data | |
| static char * | generate_random_string (char *buf, size_t size) |
| Generate 32 byte random string for callid's etc. | |
| static char * | generate_uri (struct sip_pvt *pvt, char *buf, size_t size) |
| static int | get_address_family_filter (const struct ast_sockaddr *addr) |
| Helper for dns resolution to filter by address family. | |
| static int | get_also_info (struct sip_pvt *p, struct sip_request *oreq) |
| Call transfer support (old way, deprecated by the IETF). | |
| static char * | get_body (struct sip_request *req, char *name, char delimiter) |
| Get a specific line from the message body. | |
| static char * | get_body_by_line (const char *line, const char *name, int nameLen, char delimiter) |
| Reads one line of SIP message body. | |
| static int | get_cached_mwi (struct sip_peer *peer, int *new, int *old) |
| Get cached MWI info. | |
| static void | get_crypto_attrib (struct sip_pvt *p, struct sip_srtp *srtp, const char **a_crypto) |
| static enum sip_get_dest_result | get_destination (struct sip_pvt *p, struct sip_request *oreq, int *cc_recall_core_id) |
| Find out who the call is for. | |
| static int | get_domain (const char *str, char *domain, int len) |
| Extract domain from SIP To/From header. | |
| static struct event_state_compositor * | get_esc (const char *const event_package) |
| static struct sip_esc_entry * | get_esc_entry (const char *entity_tag, struct event_state_compositor *esc) |
| static struct ast_variable * | get_insecure_variable_from_config (struct ast_config *config) |
| static struct ast_variable * | get_insecure_variable_from_sippeers (const char *column, const char *value) |
| static struct ast_variable * | get_insecure_variable_from_sipregs (const char *column, const char *value, struct ast_variable **var) |
| static int | get_ip_and_port_from_sdp (struct sip_request *req, const enum media_type media, struct ast_sockaddr *addr) |
| static int | get_msg_text (char *buf, int len, struct sip_request *req) |
| Get message body from a SIP request. | |
| static int | get_msg_text2 (struct ast_str **buf, struct sip_request *req) |
| static const char * | get_name_from_variable (const struct ast_variable *var) |
| static void | get_our_media_address (struct sip_pvt *p, int needvideo, int needtext, struct ast_sockaddr *addr, struct ast_sockaddr *vaddr, struct ast_sockaddr *taddr, struct ast_sockaddr *dest, struct ast_sockaddr *vdest, struct ast_sockaddr *tdest) |
| Set all IP media addresses for this call. | |
| static int | get_pai (struct sip_pvt *p, struct sip_request *req) |
| Parse the parts of the P-Asserted-Identity header on an incoming packet. Returns 1 if a valid header is found and it is different from the current caller id. | |
| static int | get_rdnis (struct sip_pvt *p, struct sip_request *oreq, char **name, char **number, int *reason) |
| Get referring dnis. | |
| static void | get_realm (struct sip_pvt *p, const struct sip_request *req) |
| Choose realm based on From header and then To header or use globaly configured realm. Realm from From/To header should be listed among served domains in config file: domain=... | |
| static int | get_refer_info (struct sip_pvt *transferer, struct sip_request *outgoing_req) |
| Call transfer support (the REFER method) Extracts Refer headers into pvt dialog structure. | |
| static int | get_rpid (struct sip_pvt *p, struct sip_request *oreq) |
| Get name, number and presentation from remote party id header, returns true if a valid header was found and it was different from the current caller id. | |
| static const char * | get_sdp_iterate (int *start, struct sip_request *req, const char *name) |
| Lookup 'name' in the SDP starting at the 'start' line. Returns the matching line, and 'start' is updated with the next line number. | |
| static char | get_sdp_line (int *start, int stop, struct sip_request *req, const char **value) |
| Fetches the next valid SDP line between the 'start' line (inclusive) and the 'stop' line (exclusive). Returns the type ('a', 'c', ...) and matching line in reference 'start' is updated with the next line number. | |
| static struct sip_pvt * | get_sip_pvt_byid_locked (const char *callid, const char *totag, const char *fromtag) |
| Lock dialog lock and find matching pvt lock. | |
| static const char * | get_srv_protocol (enum sip_transport t) |
| Return protocol string for srv dns query. | |
| static const char * | get_srv_service (enum sip_transport t) |
| Return service string for srv dns query. | |
| static const char * | get_transport_list (unsigned int transports) |
| Return configuration of transports for a device. | |
| static const char * | get_transport_pvt (struct sip_pvt *p) |
| Return transport of dialog. | |
| static int | get_transport_str2enum (const char *transport) |
| Return int representing a bit field of transport types found in const char *transport. | |
| static const char * | gettag (const struct sip_request *req, const char *header, char *tagbuf, int tagbufsize) |
| Get tag from packet. | |
| static int | handle_cc_notify (struct sip_pvt *pvt, struct sip_request *req) |
| static int | handle_cc_subscribe (struct sip_pvt *p, struct sip_request *req) |
| static int | handle_common_options (struct ast_flags *flags, struct ast_flags *mask, struct ast_variable *v) |
| Handle flag-type options common to configuration of devices - peers. | |
| static int | handle_incoming (struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, int *recount, int *nounlock) |
| Handle incoming SIP requests (methods). | |
| static int | handle_invite_replaces (struct sip_pvt *p, struct sip_request *req, int debug, uint32_t seqno, struct ast_sockaddr *addr, int *nounlock) |
| Handle the transfer part of INVITE with a replaces: header, meaning a target pickup or an attended transfer. Used only once. XXX 'ignore' is unused. | |
| static int | handle_request_bye (struct sip_pvt *p, struct sip_request *req) |
| Handle incoming BYE request. | |
| static int | handle_request_cancel (struct sip_pvt *p, struct sip_request *req) |
| Handle incoming CANCEL request. | |
| static int | handle_request_do (struct sip_request *req, struct ast_sockaddr *addr) |
| Handle incoming SIP message - request or response. | |
| static void | handle_request_info (struct sip_pvt *p, struct sip_request *req) |
| Receive SIP INFO Message. | |
| static int | handle_request_invite (struct sip_pvt *p, struct sip_request *req, int debug, uint32_t seqno, struct ast_sockaddr *addr, int *recount, const char *e, int *nounlock) |
| Handle incoming INVITE request. | |
| static int | handle_request_message (struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, const char *e) |
| Handle incoming MESSAGE request. | |
| static int | handle_request_notify (struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, uint32_t seqno, const char *e) |
| Handle incoming notifications. | |
| static int | handle_request_options (struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, const char *e) |
| Handle incoming OPTIONS request An OPTIONS request should be answered like an INVITE from the same UA, including SDP. | |
| static int | handle_request_publish (struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, const uint32_t seqno, const char *uri) |
| static int | handle_request_refer (struct sip_pvt *p, struct sip_request *req, int debug, uint32_t seqno, int *nounlock) |
| static int | handle_request_register (struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, const char *e) |
| Handle incoming REGISTER request. | |
| static int | handle_request_subscribe (struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, uint32_t seqno, const char *e) |
| Handle incoming SUBSCRIBE request. | |
| static int | handle_request_update (struct sip_pvt *p, struct sip_request *req) |
| bare-bones support for SIP UPDATE | |
| static void | handle_response (struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, uint32_t seqno) |
| Handle SIP response in dialogue. | |
| static void | handle_response_info (struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, uint32_t seqno) |
| static void | handle_response_invite (struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, uint32_t seqno) |
| Handle SIP response to INVITE dialogue. | |
| static void | handle_response_message (struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, uint32_t seqno) |
| static void | handle_response_notify (struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, uint32_t seqno) |
| static void | handle_response_peerpoke (struct sip_pvt *p, int resp, struct sip_request *req) |
| Handle qualification responses (OPTIONS). | |
| static void | handle_response_publish (struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, uint32_t seqno) |
| static void | handle_response_refer (struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, uint32_t seqno) |
| static int | handle_response_register (struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, uint32_t seqno) |
| Handle responses on REGISTER to services. | |
| static void | handle_response_subscribe (struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, uint32_t seqno) |
| static void | handle_response_update (struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, uint32_t seqno) |
| Handle authentication challenge for SIP UPDATE. | |
| static int | handle_sip_publish_initial (struct sip_pvt *p, struct sip_request *req, struct event_state_compositor *esc, const int expires) |
| static int | handle_sip_publish_modify (struct sip_pvt *p, struct sip_request *req, struct event_state_compositor *esc, const char *const etag, const int expires) |
| static int | handle_sip_publish_refresh (struct sip_pvt *p, struct sip_request *req, struct event_state_compositor *esc, const char *const etag, const int expires) |
| static int | handle_sip_publish_remove (struct sip_pvt *p, struct sip_request *req, struct event_state_compositor *esc, const char *const etag) |
| static int | handle_t38_options (struct ast_flags *flags, struct ast_flags *mask, struct ast_variable *v, int *maxdatagram) |
| Handle T.38 configuration options common to users and peers. | |
| const char * | hangup_cause2sip (int cause) |
| Convert Asterisk hangup causes to SIP codes. | |
| int | hangup_sip2cause (int cause) |
| Convert SIP hangup causes to Asterisk hangup causes. | |
| static int | init_req (struct sip_request *req, int sipmethod, const char *recip) |
| Initialize SIP request. | |
| static int | init_resp (struct sip_request *resp, const char *msg) |
| Initialize SIP response, based on SIP request. | |
| static int | initialize_escs (void) |
| static void | initialize_initreq (struct sip_pvt *p, struct sip_request *req) |
| Initialize the initital request packet in the pvt structure. This packet is used for creating replies and future requests in a dialog. | |
| static int | initialize_udptl (struct sip_pvt *p) |
| static void | initreqprep (struct sip_request *req, struct sip_pvt *p, int sipmethod, const char *const explicit_uri) |
| Initiate new SIP request to peer/user. | |
| static const char * | insecure2str (int mode) |
| Convert Insecure setting to printable string. | |
| static int | interpret_t38_parameters (struct sip_pvt *p, const struct ast_control_t38_parameters *parameters) |
| Helper function which updates T.38 capability information and triggers a reinvite. | |
| static int | is_method_allowed (unsigned int *allowed_methods, enum sipmethod method) |
| Check if method is allowed for a device or a dialog. | |
| static void | list_route (struct sip_route *route) |
| List all routes - mostly for debugging. | |
| static int | load_module (void) |
| PBX load module - initialization. | |
| static int | local_attended_transfer (struct sip_pvt *transferer, struct sip_dual *current, struct sip_request *req, uint32_t seqno, int *nounlock) |
| Find all call legs and bridge transferee with target called from handle_request_refer. | |
| static void | lws2sws (struct ast_str *data) |
| Parse multiline SIP headers into one header This is enabled if pedanticsipchecking is enabled. | |
| static void | make_our_tag (char *tagbuf, size_t len) |
| Make our SIP dialog tag. | |
| static int | manager_show_registry (struct mansession *s, const struct message *m) |
| Show SIP registrations in the manager API. | |
| static int | manager_sip_qualify_peer (struct mansession *s, const struct message *m) |
| Qualify SIP peers in the manager API. | |
| static int | manager_sip_show_peer (struct mansession *s, const struct message *m) |
| Show SIP peers in the manager API. | |
| static int | manager_sip_show_peers (struct mansession *s, const struct message *m) |
| Show SIP peers in the manager API. | |
| static int | manager_sipnotify (struct mansession *s, const struct message *m) |
| static int | map_s_x (const struct _map_x_s *table, const char *s, int errorvalue) |
| map from a string to an integer value, case insensitive. If no match is found, return errorvalue. | |
| static const char * | map_x_s (const struct _map_x_s *table, int x, const char *errorstring) |
| map from an integer value to a string. If no match is found, return errorstring | |
| static void | mark_method_allowed (unsigned int *allowed_methods, enum sipmethod method) |
| static void | mark_method_unallowed (unsigned int *allowed_methods, enum sipmethod method) |
| static void | mark_parsed_methods (unsigned int *methods, char *methods_str) |
| static int | match_and_cleanup_peer_sched (void *peerobj, void *arg, int flags) |
| static enum match_req_res | match_req_to_dialog (struct sip_pvt *sip_pvt_ptr, struct match_req_args *arg) |
| static int | method_match (enum sipmethod id, const char *name) |
| returns true if 'name' (with optional trailing whitespace) matches the sip method 'id'. Strictly speaking, SIP methods are case SENSITIVE, but we do a case-insensitive comparison to be more tolerant. following Jon Postel's rule: Be gentle in what you accept, strict with what you send | |
| static void | mwi_event_cb (const struct ast_event *event, void *userdata) |
| Receive MWI events that we have subscribed to. | |
| static void | network_change_event_cb (const struct ast_event *, void *) |
| static int | network_change_event_sched_cb (const void *data) |
| static void | network_change_event_subscribe (void) |
| static void | network_change_event_unsubscribe (void) |
| static struct sip_proxy * | obproxy_get (struct sip_pvt *dialog, struct sip_peer *peer) |
| Get default outbound proxy or global proxy. | |
| static void | on_dns_update_mwi (struct ast_sockaddr *old, struct ast_sockaddr *new, void *data) |
| static void | on_dns_update_peer (struct ast_sockaddr *old, struct ast_sockaddr *new, void *data) |
| static void | on_dns_update_registry (struct ast_sockaddr *old, struct ast_sockaddr *new, void *data) |
| static unsigned int | parse_allowed_methods (struct sip_request *req) |
| parse the Allow header to see what methods the endpoint we are communicating with allows. | |
| static void | parse_copy (struct sip_request *dst, const struct sip_request *src) |
| Copy SIP request, parse it. | |
| static int | parse_minse (const char *p_hdrval, int *const p_interval) |
| Session-Timers: Function for parsing Min-SE header. | |
| static void | parse_moved_contact (struct sip_pvt *p, struct sip_request *req, char **name, char **number, int set_call_forward) |
| Parse 302 Moved temporalily response. | |
| static int | parse_ok_contact (struct sip_pvt *pvt, struct sip_request *req) |
| Save contact header for 200 OK on INVITE. | |
| static enum parse_register_result | parse_register_contact (struct sip_pvt *pvt, struct sip_peer *peer, struct sip_request *req) |
| Parse contact header and save registration (peer registration). | |
| static int | parse_request (struct sip_request *req) |
| Parse a SIP message. | |
| static int | parse_session_expires (const char *p_hdrval, int *const p_interval, enum st_refresher *const p_ref) |
| Session-Timers: Function for parsing Session-Expires header. | |
| static int | parse_uri_legacy_check (char *uri, const char *scheme, char **user, char **pass, char **hostport, char **transport) |
| parse uri in a way that allows semicolon stripping if legacy mode is enabled | |
| static int | peer_cmp_cb (void *obj, void *arg, int flags) |
| static int | peer_dump_func (void *userobj, void *arg, int flags) |
| static int | peer_hash_cb (const void *obj, const int flags) |
| static int | peer_ipcmp_cb (void *obj, void *arg, int flags) |
| static int | peer_ipcmp_cb_full (void *obj, void *arg, void *data, int flags) |
| static int | peer_iphash_cb (const void *obj, const int flags) |
| static void | peer_mailboxes_to_str (struct ast_str **mailbox_str, struct sip_peer *peer) |
| list peer mailboxes to CLI | |
| static int | peer_markall_func (void *device, void *arg, int flags) |
| static void | peer_sched_cleanup (struct sip_peer *peer) |
| static int | peer_status (struct sip_peer *peer, char *status, int statuslen) |
| int | peercomparefunc (const void *a, const void *b) |
| static int | peers_data_provider_get (const struct ast_data_search *search, struct ast_data *data_root) |
| unsigned int | port_str2int (const char *pt, unsigned int standard) |
| converts ascii port to int representation. If no pt buffer is provided or the pt has errors when being converted to an int value, the port provided as the standard is used. | |
| static void | print_codec_to_cli (int fd, struct ast_codec_pref *pref) |
| Print codec list from preference to CLI/manager. | |
| static void | print_group (int fd, ast_group_t group, int crlf) |
| Print call group and pickup group. | |
| static void | proc_422_rsp (struct sip_pvt *p, struct sip_request *rsp) |
| Handle 422 response to INVITE with session-timer requested. | |
| static int | proc_session_timer (const void *vp) |
| Session-Timers: Process session refresh timeout event. | |
| static int | process_crypto (struct sip_pvt *p, struct ast_rtp_instance *rtp, struct sip_srtp **srtp, const char *a) |
| static int | process_sdp (struct sip_pvt *p, struct sip_request *req, int t38action) |
| Process SIP SDP offer, select formats and activate RTP channels If offer is rejected, we will not change any properties of the call Return 0 on success, a negative value on errors. Must be called after find_sdp(). | |
| static int | process_sdp_a_audio (const char *a, struct sip_pvt *p, struct ast_rtp_codecs *newaudiortp, int *last_rtpmap_codec) |
| static int | process_sdp_a_image (const char *a, struct sip_pvt *p) |
| static int | process_sdp_a_sendonly (const char *a, int *sendonly) |
| static int | process_sdp_a_text (const char *a, struct sip_pvt *p, struct ast_rtp_codecs *newtextrtp, char *red_fmtp, int *red_num_gen, int *red_data_pt, int *last_rtpmap_codec) |
| static int | process_sdp_a_video (const char *a, struct sip_pvt *p, struct ast_rtp_codecs *newvideortp, int *last_rtpmap_codec) |
| static int | process_sdp_c (const char *c, struct ast_sockaddr *addr) |
| static int | process_sdp_o (const char *o, struct sip_pvt *p) |
| static int | process_via (struct sip_pvt *p, const struct sip_request *req) |
| Process the Via header according to RFC 3261 section 18.2.2. | |
| static int | proxy_update (struct sip_proxy *proxy) |
| static int | publish_expire (const void *data) |
| static void | pvt_set_needdestroy (struct sip_pvt *pvt, const char *reason) |
| static struct sip_peer * | realtime_peer (const char *newpeername, struct ast_sockaddr *addr, char *callbackexten, int devstate_only, int which_objects) |
| realtime_peer: Get peer from realtime storage Checks the "sippeers" realtime family from extconfig.conf Checks the "sipregs" realtime family from extconfig.conf if it's configured. This returns a pointer to a peer and because we use build_peer, we can rest assured that the refcount is bumped. | |
| static int | realtime_peer_by_addr (const char **name, struct ast_sockaddr *addr, const char *ipaddr, const char *callbackexten, struct ast_variable **var, struct ast_variable **varregs) |
| static int | realtime_peer_by_name (const char *const *name, struct ast_sockaddr *addr, const char *ipaddr, struct ast_variable **var, struct ast_variable **varregs) |
| static struct ast_variable * | realtime_peer_get_sippeer_helper (const char **name, struct ast_variable **varregs) |
| static void | realtime_update_peer (const char *peername, struct ast_sockaddr *addr, const char *defaultuser, const char *fullcontact, const char *useragent, int expirey, unsigned short deprecated_username, int lastms) |
| Update peer object in realtime storage If the Asterisk system name is set in asterisk.conf, we will use that name and store that in the "regserver" field in the sippeers table to facilitate multi-server setups. | |
| static void | receive_message (struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, const char *e) |
| Receive SIP MESSAGE method messages. | |
| static void | ref_proxy (struct sip_pvt *pvt, struct sip_proxy *proxy) |
| maintain proper refcounts for a sip_pvt's outboundproxy | |
| static const char * | referstatus2str (enum referstatus rstatus) |
| Convert transfer status to string. | |
| static void | reg_source_db (struct sip_peer *peer) |
| Get registration details from Asterisk DB. | |
| static void | register_peer_exten (struct sip_peer *peer, int onoff) |
| Automatically add peer extension to dial plan. | |
| static int | register_realtime_peers_with_callbackextens (void) |
| static enum check_auth_result | register_verify (struct sip_pvt *p, struct ast_sockaddr *addr, struct sip_request *req, const char *uri) |
Verify registration of user
| |
| static struct sip_registry * | registry_addref (struct sip_registry *reg, char *tag) |
| Add object reference to SIP registry. | |
| static void * | registry_unref (struct sip_registry *reg, char *tag) |
| static const char * | regstate2str (enum sipregistrystate regstate) |
| Convert registration state status to string. | |
| static int | reload (void) |
| Part of Asterisk module interface. | |
| static int | reload_config (enum channelreloadreason reason) |
| Re-read SIP.conf config file. | |
| static char * | remove_uri_parameters (char *uri) |
| static int | reply_digest (struct sip_pvt *p, struct sip_request *req, char *header, int sipmethod, char *digest, int digest_len) |
| reply to authentication for outbound registrations | |
| static int | reqprep (struct sip_request *req, struct sip_pvt *p, int sipmethod, uint32_t seqno, int newbranch) |
| Initialize a SIP request message (not the initial one in a dialog). | |
| static int | resp_needs_contact (const char *msg, enum sipmethod method) |
| Test if this response needs a contact header. | |
| static int | respprep (struct sip_request *resp, struct sip_pvt *p, const char *msg, const struct sip_request *req) |
| Prepare SIP response packet. | |
| static int | restart_monitor (void) |
| Start the channel monitor thread. | |
| static void | restart_session_timer (struct sip_pvt *p) |
| Session-Timers: Restart session timer. | |
| static int | retrans_pkt (const void *data) |
| Retransmit SIP message if no answer (Called from scheduler). | |
| static int | send_provisional_keepalive (const void *data) |
| static int | send_provisional_keepalive_full (struct sip_pvt *pvt, int with_sdp) |
| static int | send_provisional_keepalive_with_sdp (const void *data) |
| static int | send_request (struct sip_pvt *p, struct sip_request *req, enum xmittype reliable, uint32_t seqno) |
| static int | send_response (struct sip_pvt *p, struct sip_request *req, enum xmittype reliable, uint32_t seqno) |
| Transmit response on SIP request. | |
| static enum ast_cc_service_type | service_string_to_service_type (const char *const service_string) |
| static int | set_address_from_contact (struct sip_pvt *pvt) |
| Change the other partys IP address based on given contact. | |
| static void | set_destination (struct sip_pvt *p, char *uri) |
| Set destination from SIP URI. | |
| static void | set_insecure_flags (struct ast_flags *flags, const char *value, int lineno) |
| Parse insecure= setting in sip.conf and set flags according to setting. | |
| static int | set_message_vars_from_req (struct ast_msg *msg, struct sip_request *req) |
| static void | set_nonce_randdata (struct sip_pvt *p, int forceupdate) |
| builds the sip_pvt's randdata field which is used for the nonce challenge. When forceupdate is not set, the nonce is only updated if the current one is stale. In this case, a stalenonce is one which has already received a response, if a nonce has not received a response it is not always necessary or beneficial to create a new one. | |
| static void | set_peer_defaults (struct sip_peer *peer) |
| Set peer defaults before configuring specific configurations. | |
| static unsigned int | set_pvt_allowed_methods (struct sip_pvt *pvt, struct sip_request *req) |
| static void | set_socket_transport (struct sip_socket *socket, int transport) |
| static void | set_t38_capabilities (struct sip_pvt *p) |
| Set the global T38 capabilities on a SIP dialog structure. | |
| static int | setup_srtp (struct sip_srtp **srtp) |
| static int | show_channels_cb (void *__cur, void *__arg, int flags) |
| callback for show channel|subscription | |
| static int | show_chanstats_cb (void *__cur, void *__arg, int flags) |
| Callback for show_chanstats. | |
| static int | sip_addheader (struct ast_channel *chan, const char *data) |
| Add a SIP header to an outbound INVITE. | |
| struct sip_pvt * | sip_alloc (ast_string_field callid, struct ast_sockaddr *addr, int useglobal_nat, const int intended_method, struct sip_request *req) |
| Allocate sip_pvt structure, set defaults and link in the container. Returns a reference to the object so whoever uses it later must remember to release the reference. | |
| static void | sip_alreadygone (struct sip_pvt *dialog) |
| Encapsulate setting of SIP_ALREADYGONE to be able to trace it with debugging. | |
| static int | sip_answer (struct ast_channel *ast) |
| sip_answer: Answer SIP call , send 200 OK on Invite Part of PBX interface | |
| void | sip_auth_headers (enum sip_auth_type code, char **header, char **respheader) |
| return the request and response header for a 401 or 407 code | |
| static int | sip_call (struct ast_channel *ast, const char *dest, int timeout) |
| Initiate SIP call from PBX used from the dial() application. | |
| int | sip_cancel_destroy (struct sip_pvt *p) |
| Cancel destruction of SIP dialog. Be careful as this also absorbs the reference - if you call it from within the scheduler, this might be the last reference. | |
| static void | sip_cc_agent_destructor (struct ast_cc_agent *agent) |
| static int | sip_cc_agent_init (struct ast_cc_agent *agent, struct ast_channel *chan) |
| static int | sip_cc_agent_recall (struct ast_cc_agent *agent) |
| static void | sip_cc_agent_respond (struct ast_cc_agent *agent, enum ast_cc_agent_response_reason reason) |
| static int | sip_cc_agent_start_monitoring (struct ast_cc_agent *agent) |
| static int | sip_cc_agent_start_offer_timer (struct ast_cc_agent *agent) |
| static int | sip_cc_agent_status_request (struct ast_cc_agent *agent) |
| static int | sip_cc_agent_stop_offer_timer (struct ast_cc_agent *agent) |
| static int | sip_cc_monitor_cancel_available_timer (struct ast_cc_monitor *monitor, int *sched_id) |
| static void | sip_cc_monitor_destructor (void *private_data) |
| static int | sip_cc_monitor_request_cc (struct ast_cc_monitor *monitor, int *available_timer_id) |
| static int | sip_cc_monitor_suspend (struct ast_cc_monitor *monitor) |
| static int | sip_cc_monitor_unsuspend (struct ast_cc_monitor *monitor) |
| static int | sip_check_authtimeout (time_t start) |
| Check if the authtimeout has expired. | |
| static char * | sip_cli_notify (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| Cli command to send SIP notify to peer. | |
| static int | sip_debug_test_addr (const struct ast_sockaddr *addr) |
| See if we pass debug IP filter. | |
| static int | sip_debug_test_pvt (struct sip_pvt *p) |
| Test PVT for debugging output. | |
| struct sip_pvt * | sip_destroy (struct sip_pvt *p) |
| Destroy SIP call structure. Make it return NULL so the caller can do things like foo = sip_destroy(foo); and reduce the chance of bugs due to dangling pointers. | |
| static void | sip_destroy_fn (void *p) |
| static void | sip_destroy_peer (struct sip_peer *peer) |
| Destroy peer object from memory. | |
| static void | sip_destroy_peer_fn (void *peer) |
| static int | sip_devicestate (const char *data) |
| Part of PBX channel interface. | |
| void | sip_digest_parser (char *c, struct digestkeys *keys) |
| Takes the digest response and parses it. | |
| static char * | sip_do_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| Turn on SIP debugging (CLI command). | |
| static char * | sip_do_debug_ip (int fd, const char *arg) |
| Enable SIP Debugging for a single IP. | |
| static char * | sip_do_debug_peer (int fd, const char *arg) |
| Turn on SIP debugging for a given peer. | |
| static int | sip_do_reload (enum channelreloadreason reason) |
| Reload module. | |
| static int | sip_dtmfmode (struct ast_channel *chan, const char *data) |
| Set the DTMFmode for an outbound SIP call (application). | |
| static void | sip_dump_history (struct sip_pvt *dialog) |
| Dump SIP history to debug log file at end of lifespan for SIP dialog. | |
| static int | sip_epa_register (const struct epa_static_data *static_data) |
| static void | sip_epa_unregister_all (void) |
| struct sip_peer * | sip_find_peer (const char *peer, struct ast_sockaddr *addr, int realtime, int which_objects, int devstate_only, int transport) |
| Locate device by name or ip address. | |
| static struct sip_peer * | sip_find_peer_by_ip_and_exten (struct ast_sockaddr *addr, char *callbackexten, int transport) |
| static struct sip_peer * | sip_find_peer_full (const char *peer, struct ast_sockaddr *addr, char *callbackexten, int realtime, int which_objects, int devstate_only, int transport) |
| static int | sip_fixup (struct ast_channel *oldchan, struct ast_channel *newchan) |
| sip_fixup: Fix up a channel: If a channel is consumed, this is called. Basically update any ->owner links | |
| static const char * | sip_get_callid (struct ast_channel *chan) |
| Deliver SIP call ID for the call. | |
| static int | sip_get_cc_information (struct sip_request *req, char *subscribe_uri, size_t size, enum ast_cc_service_type *service) |
| static void | sip_get_codec (struct ast_channel *chan, struct ast_format_cap *result) |
| const char * | sip_get_header (const struct sip_request *req, const char *name) |
| Get header from SIP request. | |
| static enum ast_rtp_glue_result | sip_get_rtp_peer (struct ast_channel *chan, struct ast_rtp_instance **instance) |
| const char * | sip_get_transport (enum sip_transport t) |
| Return transport as string. | |
| static enum ast_rtp_glue_result | sip_get_trtp_peer (struct ast_channel *chan, struct ast_rtp_instance **instance) |
| static struct ast_udptl * | sip_get_udptl_peer (struct ast_channel *chan) |
| static enum ast_rtp_glue_result | sip_get_vrtp_peer (struct ast_channel *chan, struct ast_rtp_instance **instance) |
| static void | sip_handle_cc (struct sip_pvt *pvt, struct sip_request *req, enum ast_cc_service_type service) |
| static int | sip_hangup (struct ast_channel *ast) |
| sip_hangup: Hangup SIP call Part of PBX interface, called from ast_hangup | |
| static int | sip_indicate (struct ast_channel *ast, int condition, const void *data, size_t datalen) |
| Play indication to user With SIP a lot of indications is sent as messages, letting the device play the indication - busy signal, congestion etc. | |
| static int | sip_is_xml_parsable (void) |
| static int | sip_monitor_instance_cmp_fn (void *obj, void *arg, int flags) |
| static void | sip_monitor_instance_destructor (void *data) |
| static int | sip_monitor_instance_hash_fn (const void *obj, const int flags) |
| static struct sip_monitor_instance * | sip_monitor_instance_init (int core_id, const char *const subscribe_uri, const char *const peername, const char *const device_name) |
| static int | sip_msg_send (const struct ast_msg *msg, const char *to, const char *from) |
| static const char * | sip_nat_mode (const struct sip_pvt *p) |
| Display SIP nat mode. | |
| static struct ast_channel * | sip_new (struct sip_pvt *i, int state, const char *title, const char *linkedid) |
| Initiate a call in the SIP channel. | |
| static int | sip_notify_allocate (struct sip_pvt *p) |
| Allocate SIP refer structure. | |
| static int | sip_offer_timer_expire (const void *data) |
| static int | sip_park (struct ast_channel *chan1, struct ast_channel *chan2, struct sip_request *req, uint32_t seqno, const char *park_exten, const char *park_context) |
| static void * | sip_park_thread (void *stuff) |
| Park SIP call support function Starts in a new thread, then parks the call XXX Should we add a wait period after streaming audio and before hangup?? Sometimes the audio can't be heard before hangup. | |
| static void | sip_peer_hold (struct sip_pvt *p, int hold) |
| Change onhold state of a peer using a pvt structure. | |
| static int | sip_pickup (struct ast_channel *chan) |
| Pickup a call using the subsystem in features.c This is executed in a separate thread. | |
| static void * | sip_pickup_thread (void *stuff) |
| SIP pickup support function Starts in a new thread, then pickup the call. | |
| static void | sip_poke_all_peers (void) |
| Send a poke to all known peers. | |
| static int | sip_poke_noanswer (const void *data) |
| React to lack of answer to Qualify poke. | |
| static int | sip_poke_peer (struct sip_peer *peer, int force) |
| Check availability of peer, also keep NAT open. | |
| static int | sip_poke_peer_s (const void *data) |
| Poke peer (send qualify to check if peer is alive and well). | |
| static int | sip_prepare_socket (struct sip_pvt *p) |
| static char * | sip_prune_realtime (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| Remove temporary realtime objects from memory (CLI). | |
| static struct ast_channel * | sip_pvt_lock_full (struct sip_pvt *pvt) |
| static char * | sip_qualify_peer (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| Send an OPTIONS packet to a SIP peer. | |
| static int | sip_queryoption (struct ast_channel *chan, int option, void *data, int *datalen) |
| Query an option on a SIP dialog. | |
| static struct ast_frame * | sip_read (struct ast_channel *ast) |
| Read SIP RTP from channel. | |
| static struct ast_sockaddr * | sip_real_dst (const struct sip_pvt *p) |
| The real destination address for a write. | |
| static const char * | sip_reason_code_to_str (enum AST_REDIRECTING_REASON code) |
| static enum AST_REDIRECTING_REASON | sip_reason_str_to_code (const char *text) |
| struct sip_peer * | sip_ref_peer (struct sip_peer *peer, char *tag) |
| static int | sip_refer_allocate (struct sip_pvt *p) |
| Allocate SIP refer structure. | |
| static int | sip_reg_timeout (const void *data) |
| Registration timeout, register again Registered as a timeout handler during transmit_register(), to retransmit the packet if a reply does not come back. This is called by the scheduler so the event is not pending anymore when we are called. | |
| static int | sip_register (const char *value, int lineno) |
| create sip_registry object from register=> line in sip.conf and link into reg container | |
| static void | sip_register_tests (void) |
| SIP test registration. | |
| static void | sip_registry_destroy (struct sip_registry *reg) |
| Destroy registry object Objects created with the register= statement in static configuration. | |
| static int | sip_reinvite_retry (const void *data) |
| Reset the NEEDREINVITE flag after waiting when we get 491 on a Re-invite to avoid race conditions between asterisk servers. Called from the scheduler. | |
| static char * | sip_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| Force reload of module from cli. | |
| static int | sip_removeheader (struct ast_channel *chan, const char *data) |
| Remove SIP headers added previously with SipAddHeader application. | |
| static struct ast_channel * | sip_request_call (const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *dest, int *cause) |
| PBX interface function -build SIP pvt structure SIP calls initiated by the PBX arrive here. | |
| static int | sip_reregister (const void *data) |
| Update registration with SIP Proxy. Called from the scheduler when the previous registration expires, so we don't have to cancel the pending event. We assume the reference so the sip_registry is valid, since it is stored in the scheduled event anyways. | |
| static struct ast_frame * | sip_rtp_read (struct ast_channel *ast, struct sip_pvt *p, int *faxdetect) |
| Read RTP from network. | |
| static const char * | sip_sanitized_host (const char *host) |
| void | sip_scheddestroy (struct sip_pvt *p, int ms) |
| Schedule destruction of SIP dialog. | |
| void | sip_scheddestroy_final (struct sip_pvt *p, int ms) |
| Schedule final destruction of SIP dialog. This can not be canceled. This function is used to keep a dialog around for a period of time in order to properly respond to any retransmits. | |
| static void | sip_send_all_mwi_subscriptions (void) |
| Send all MWI subscriptions. | |
| static void | sip_send_all_registers (void) |
| Send all known registrations. | |
| static int | sip_send_mwi_to_peer (struct sip_peer *peer, int cache_only) |
| Send message waiting indication to alert peer that they've got voicemail. | |
| static int | sip_senddigit_begin (struct ast_channel *ast, char digit) |
| static int | sip_senddigit_end (struct ast_channel *ast, char digit, unsigned int duration) |
| Send DTMF character on SIP channel within one call, we're able to transmit in many methods simultaneously. | |
| static int | sip_sendhtml (struct ast_channel *chan, int subclass, const char *data, int datalen) |
| Send message with Access-URL header, if this is an HTML URL only! | |
| static int | sip_sendtext (struct ast_channel *ast, const char *text) |
| static void | sip_set_default_format_capabilities (struct ast_format_cap *cap) |
| static char * | sip_set_history (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| Enable/Disable SIP History logging (CLI). | |
| static void | sip_set_redirstr (struct sip_pvt *p, char *reason) |
| Translate referring cause. | |
| static int | sip_set_rtp_peer (struct ast_channel *chan, struct ast_rtp_instance *instance, struct ast_rtp_instance *vinstance, struct ast_rtp_instance *tinstance, const struct ast_format_cap *cap, int nat_active) |
| static int | sip_set_udptl_peer (struct ast_channel *chan, struct ast_udptl *udptl) |
| static int | sip_setoption (struct ast_channel *chan, int option, void *data, int datalen) |
| Set an option on a SIP dialog. | |
| static char * | sip_show_channel (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| Show details of one active dialog. | |
| static char * | sip_show_channels (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| CLI for show channels or subscriptions. This is a new-style CLI handler so a single function contains the prototype for the function, the 'generator' to produce multiple entries in case it is required, and the actual handler for the command. | |
| static char * | sip_show_channelstats (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| SIP show channelstats CLI (main function). | |
| static char * | sip_show_domains (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| CLI command to list local domains. | |
| static char * | sip_show_history (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| Show history details of one dialog. | |
| static char * | sip_show_inuse (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| CLI Command to show calls within limits set by call_limit. | |
| static char * | sip_show_mwi (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | sip_show_objects (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| List all allocated SIP Objects (realtime or static). | |
| static char * | sip_show_peer (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| Show one peer in detail. | |
| static char * | sip_show_peers (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| CLI Show Peers command. | |
| static char * | sip_show_registry (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| Show SIP Registry (registrations with other SIP proxies. | |
| static char * | sip_show_sched (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | sip_show_settings (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| List global settings for the SIP channel. | |
| static char * | sip_show_tcp (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| Show active TCP connections. | |
| static char * | sip_show_user (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| Show one user in detail. | |
| static char * | sip_show_users (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| CLI Command 'SIP Show Users'. | |
| static int | sip_sipredirect (struct sip_pvt *p, const char *dest) |
| Transfer call before connect with a 302 redirect. | |
| static struct sip_st_dlg * | sip_st_alloc (struct sip_pvt *const p) |
| Allocate Session-Timers struct w/in dialog. | |
| static int | sip_standard_port (enum sip_transport type, int port) |
| Returns the port to use for this socket. | |
| static int | sip_subscribe_mwi (const char *value, int lineno) |
| Parse mwi=> line in sip.conf and add to list. | |
| static void | sip_subscribe_mwi_destroy (struct sip_subscription_mwi *mwi) |
| Destroy MWI subscription object. | |
| static int | sip_subscribe_mwi_do (const void *data) |
| Send a subscription or resubscription for MWI. | |
| static int | sip_t38_abort (const void *data) |
| Called to deny a T38 reinvite if the core does not respond to our request. | |
| static struct ast_tcptls_session_instance * | sip_tcp_locate (struct ast_sockaddr *s) |
| Find thread for TCP/TLS session (based on IP/Port. | |
| static void * | sip_tcp_worker_fn (void *data) |
| SIP TCP connection handler. | |
| static void | sip_tcptls_client_args_destructor (void *obj) |
| static int | sip_tcptls_write (struct ast_tcptls_session_instance *tcptls_session, const void *buf, size_t len) |
| used to indicate to a tcptls thread that data is ready to be written | |
| static struct sip_threadinfo * | sip_threadinfo_create (struct ast_tcptls_session_instance *tcptls_session, int transport) |
| creates a sip_threadinfo object and links it into the threadt table. | |
| static void | sip_threadinfo_destructor (void *obj) |
| static int | sip_transfer (struct ast_channel *ast, const char *dest) |
| Transfer SIP call. | |
| void * | sip_unref_peer (struct sip_peer *peer, char *tag) |
| static char * | sip_unregister (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| Unregister (force expiration) a SIP peer in the registry via CLI. | |
| static void | sip_unregister_tests (void) |
| SIP test registration. | |
| static int | sip_write (struct ast_channel *ast, struct ast_frame *frame) |
| Send frame to media channel (rtp). | |
| static int | sipsock_read (int *id, int fd, short events, void *ignore) |
| Read data from SIP UDP socket. | |
| static int | sockaddr_is_null_or_any (const struct ast_sockaddr *addr) |
| static enum st_mode | st_get_mode (struct sip_pvt *p, int no_cached) |
| Get the session-timer mode. | |
| static enum st_refresher | st_get_refresher (struct sip_pvt *p) |
| Get the entity (UAC or UAS) that's acting as the session-timer refresher. | |
| static int | st_get_se (struct sip_pvt *p, int max) |
| Get Max or Min SE (session timer expiry). | |
| static void | start_session_timer (struct sip_pvt *p) |
| Session-Timers: Start session timer. | |
| static void | state_notify_build_xml (int state, int full, const char *exten, const char *context, struct ast_str **tmp, struct sip_pvt *p, int subscribed, const char *mfrom, const char *mto) |
| Builds XML portion of NOTIFY messages for presence or dialog updates. | |
| static const char * | stmode2str (enum st_mode m) |
| static void | stop_media_flows (struct sip_pvt *p) |
| Immediately stop RTP, VRTP and UDPTL as applicable. | |
| static void | stop_session_timer (struct sip_pvt *p) |
| Session-Timers: Stop session timer. | |
| static int | str2dtmfmode (const char *str) |
| maps a string to dtmfmode, returns -1 on error | |
| static enum st_mode | str2stmode (const char *s) |
| static enum st_refresher | str2strefresher (const char *s) |
| static const char * | strefresher2str (enum st_refresher r) |
| static const char * | subscription_type2str (enum subscriptiontype subtype) |
| Show subscription type in string format. | |
| static unsigned int | t38_get_rate (enum ast_control_t38_rate rate) |
| Get Max T.38 Transmission rate from T38 capabilities. | |
| static void | tcptls_packet_destructor (void *obj) |
| static struct sip_peer * | temp_peer (const char *name) |
| Create temporary peer (used in autocreatepeer mode). | |
| static void | temp_pvt_cleanup (void *) |
| static int | temp_pvt_init (void *) |
| static char * | terminate_uri (char *uri) |
| static int | threadinfo_locate_cb (void *obj, void *arg, int flags) |
| static int | threadt_cmp_cb (void *obj, void *arg, int flags) |
| static int | threadt_hash_cb (const void *obj, const int flags) |
| static char * | transfermode2str (enum transfermodes mode) |
| Convert transfer mode to text string. | |
| static int | transmit_cc_notify (struct ast_cc_agent *agent, struct sip_pvt *subscription, enum sip_cc_notify_state state) |
| static void | transmit_fake_auth_response (struct sip_pvt *p, int sipmethod, struct sip_request *req, enum xmittype reliable) |
| Send a fake 401 Unauthorized response when the administrator wants to hide the names of local devices from fishers. | |
| static int | transmit_info_with_aoc (struct sip_pvt *p, struct ast_aoc_decoded *decoded) |
| Send SIP INFO advice of charge message. | |
| static int | transmit_info_with_digit (struct sip_pvt *p, const char digit, unsigned int duration) |
| Send SIP INFO dtmf message, see Cisco documentation on cisco.com. | |
| static int | transmit_info_with_vidupdate (struct sip_pvt *p) |
| Send SIP INFO with video update request. | |
| static int | transmit_invite (struct sip_pvt *p, int sipmethod, int sdp, int init, const char *const explicit_uri) |
| Build REFER/INVITE/OPTIONS/SUBSCRIBE message and transmit it. | |
| static int | transmit_message (struct sip_pvt *p, int init, int auth) |
| Transmit with SIP MESSAGE method. | |
| static int | transmit_notify_with_mwi (struct sip_pvt *p, int newmsgs, int oldmsgs, const char *vmexten) |
| Notify user of messages waiting in voicemail (RFC3842). | |
| static int | transmit_notify_with_sipfrag (struct sip_pvt *p, int cseq, char *message, int terminate) |
| Notify a transferring party of the status of transfer (RFC3515). | |
| static int | transmit_provisional_response (struct sip_pvt *p, const char *msg, const struct sip_request *req, int with_sdp) |
| static int | transmit_publish (struct sip_epa_entry *epa_entry, enum sip_publish_type publish_type, const char *const explicit_uri) |
| static int | transmit_refer (struct sip_pvt *p, const char *dest) |
| Transmit SIP REFER message (initiated by the transfer() dialplan application. | |
| static int | transmit_register (struct sip_registry *r, int sipmethod, const char *auth, const char *authheader) |
| Transmit register to SIP proxy or UA auth = NULL on the initial registration (from sip_reregister()). | |
| static int | transmit_reinvite_with_sdp (struct sip_pvt *p, int t38version, int oldsdp) |
| Transmit reinvite with SDP. | |
| static int | transmit_request (struct sip_pvt *p, int sipmethod, uint32_t seqno, enum xmittype reliable, int newbranch) |
| Transmit generic SIP request returns XMIT_ERROR if transmit failed with a critical error (don't retry). | |
| static int | transmit_request_with_auth (struct sip_pvt *p, int sipmethod, uint32_t seqno, enum xmittype reliable, int newbranch) |
| Transmit SIP request, auth added. | |
| static int | transmit_response (struct sip_pvt *p, const char *msg, const struct sip_request *req) |
| Transmit response, no retransmits. | |
| static int | transmit_response_reliable (struct sip_pvt *p, const char *msg, const struct sip_request *req) |
| Transmit response, Make sure you get an ACK This is only used for responses to INVITEs, where we need to make sure we get an ACK. | |
| static int | transmit_response_using_temp (ast_string_field callid, struct ast_sockaddr *addr, int useglobal_nat, const int intended_method, const struct sip_request *req, const char *msg) |
| Transmit response, no retransmits, using a temporary pvt structure. | |
| static int | transmit_response_with_allow (struct sip_pvt *p, const char *msg, const struct sip_request *req, enum xmittype reliable) |
| Append Accept header, content length before transmitting response. | |
| static int | transmit_response_with_auth (struct sip_pvt *p, const char *msg, const struct sip_request *req, const char *randdata, enum xmittype reliable, const char *header, int stale) |
| Respond with authorization request. | |
| static int | transmit_response_with_date (struct sip_pvt *p, const char *msg, const struct sip_request *req) |
| Append date and content length before transmitting response. | |
| static int | transmit_response_with_minexpires (struct sip_pvt *p, const char *msg, const struct sip_request *req) |
| Append Min-Expires header, content length before transmitting response. | |
| static int | transmit_response_with_minse (struct sip_pvt *p, const char *msg, const struct sip_request *req, int minse_int) |
| Transmit 422 response with Min-SE header (Session-Timers). | |
| static int | transmit_response_with_retry_after (struct sip_pvt *p, const char *msg, const struct sip_request *req, const char *seconds) |
| Append Retry-After header field when transmitting response. | |
| static int | transmit_response_with_sdp (struct sip_pvt *p, const char *msg, const struct sip_request *req, enum xmittype reliable, int oldsdp, int rpid) |
| Used for 200 OK and 183 early media. | |
| static int | transmit_response_with_sip_etag (struct sip_pvt *p, const char *msg, const struct sip_request *req, struct sip_esc_entry *esc_entry, int need_new_etag) |
| static int | transmit_response_with_t38_sdp (struct sip_pvt *p, char *msg, struct sip_request *req, int retrans) |
| Used for 200 OK and 183 early media. | |
| static int | transmit_response_with_unsupported (struct sip_pvt *p, const char *msg, const struct sip_request *req, const char *unsupported) |
| Transmit response, no retransmits. | |
| static int | transmit_state_notify (struct sip_pvt *p, int state, int full, int timeout) |
| Used in the SUBSCRIBE notification subsystem (RFC3265). | |
| static void | try_suggested_sip_codec (struct sip_pvt *p) |
| Try setting codec suggested by the SIP_CODEC channel variable. | |
| static void | unlink_all_peers_from_tables (void) |
| static void | unlink_marked_peers_from_tables (void) |
| static void | unlink_peer_from_tables (struct sip_peer *peer) |
| static void | unlink_peers_from_tables (peer_unlink_flag_t flag) |
| static int | unload_module (void) |
| PBX unload module API. | |
| static int | update_call_counter (struct sip_pvt *fup, int event) |
| update_call_counter: Handle call_limit for SIP devices Setting a call-limit will cause calls above the limit not to be accepted. | |
| static void | update_connectedline (struct sip_pvt *p, const void *data, size_t datalen) |
| Notify peer that the connected line has changed. | |
| static void | update_peer (struct sip_peer *p, int expire) |
| Update peer data in database (if used). | |
| static void | update_provisional_keepalive (struct sip_pvt *pvt, int with_sdp) |
| static void | update_redirecting (struct sip_pvt *p, const void *data, size_t datalen) |
| Send a provisional response indicating that a call was redirected. | |
Defines | |
| #define | SIP_PEDANTIC_DECODE(str) |
Variables | |
| static int | authlimit = DEFAULT_AUTHLIMIT |
| static int | authtimeout = DEFAULT_AUTHTIMEOUT |
| static int | can_parse_xml |
| static unsigned int | chan_idx |
| static const char | config [] = "sip.conf" |
| static int | default_expiry = DEFAULT_DEFAULT_EXPIRY |
| static struct ast_jb_conf | default_jbconf |
| Global jitterbuffer configuration - by default, jb is disabled. | |
| static unsigned int | dumphistory |
| static int | global_authfailureevents |
| static unsigned int | global_autoframing |
| static int | global_callcounter |
| static unsigned int | global_cos_audio |
| static unsigned int | global_cos_sip |
| static unsigned int | global_cos_text |
| static unsigned int | global_cos_video |
| static int | global_dynamic_exclude_static = 0 |
| static struct ast_jb_conf | global_jbconf |
| static int | global_match_auth_username |
| static int | global_max_se |
| static int | global_min_se |
| static int | global_prematuremediafilter |
| static int | global_qualify_gap |
| static int | global_qualify_peers |
| static int | global_qualifyfreq |
| static int | global_reg_timeout |
| static int | global_regattempts_max |
| static int | global_relaxdtmf |
| static int | global_rtpholdtimeout |
| static int | global_rtpkeepalive |
| static int | global_rtptimeout |
| static char | global_sdpowner [AST_MAX_EXTENSION] |
| static char | global_sdpsession [AST_MAX_EXTENSION] |
| static int | global_shrinkcallerid |
| static enum st_mode | global_st_mode |
| static enum st_refresher | global_st_refresher |
| static int | global_store_sip_cause |
| static int | global_t1 |
| static int | global_t1min |
| static int | global_timer_b |
| static unsigned int | global_tos_audio |
| static unsigned int | global_tos_sip |
| static unsigned int | global_tos_text |
| static unsigned int | global_tos_video |
| static char | global_useragent [AST_MAX_EXTENSION] |
| static struct invstate2stringtable | invitestate2string [] |
| Readable descriptions of device states. | |
| static int | max_expiry = DEFAULT_MAX_EXPIRY |
| static int | min_expiry = DEFAULT_MIN_EXPIRY |
| static int | mwi_expiry = DEFAULT_MWI_EXPIRY |
| static const char | notify_config [] = "sip_notify.conf" |
| static unsigned int | recordhistory |
| static struct sip_settings | sip_cfg |
| static struct cfsip_methods | sip_methods [] |
| The core structure to setup dialogs. We parse incoming messages by using structure and then route the messages according to the type. | |
| static struct sip_reasons | sip_reason_table [] |
| Diversion header reasons. | |
| static struct cfsubscription_types | subscription_types [] |
Subscription types that we support. We support
| |
| static int | unauth_sessions = 0 |
DefaultSettings | |
| static char | default_callerid [AST_MAX_EXTENSION] |
| static char | default_engine [256] |
| static char | default_fromdomain [AST_MAX_EXTENSION] |
| static int | default_fromdomainport |
| static char | default_language [MAX_LANGUAGE] |
| static int | default_maxcallbitrate |
| static char | default_mohinterpret [MAX_MUSICCLASS] |
| static char | default_mohsuggest [MAX_MUSICCLASS] |
| static char | default_mwi_from [80] |
| static char | default_notifymime [AST_MAX_EXTENSION] |
| static char | default_parkinglot [AST_MAX_CONTEXT] |
| static struct ast_codec_pref | default_prefs |
| static unsigned int | default_primary_transport |
| static int | default_qualify |
| static unsigned int | default_transports |
| static char | default_vmexten [AST_MAX_EXTENSION] |
| static char | default_zone [MAX_TONEZONE_COUNTRY] |
See Also: Implementation of RFC 3261 - without S/MIME, and experimental TCP and TLS support Configuration file sip.conf
********** IMPORTANT *
A new INVITE is sent to handle_request_invite(), that will end up starting a new channel in the PBX, the new channel after that executing in a separate channel thread. This is an incoming "call". When the call is answered, either by a bridged channel or the PBX itself the sip_answer() function is called.
The actual media - Video or Audio - is mostly handled by the RTP subsystem in rtp.c
Definition in file chan_sip.c.
| #define append_history | ( | p, | |||
| event, | |||||
| fmt, | |||||
| args... | ) | append_history_full(p, "%-15s " fmt, event, ## args) |
Append to SIP dialog history.
Definition at line 2234 of file chan_sip.c.
Referenced by __sip_autodestruct(), __sip_reliable_xmit(), auto_congest(), build_reply_digest(), cb_extensionstate(), change_hold_state(), check_auth(), do_message_auth(), do_register_auth(), handle_invite_replaces(), handle_request_bye(), handle_request_do(), handle_request_invite(), handle_request_refer(), handle_request_register(), handle_request_subscribe(), handle_response(), handle_response_invite(), local_attended_transfer(), obproxy_get(), pvt_set_needdestroy(), retrans_pkt(), send_request(), send_response(), sip_cancel_destroy(), sip_fixup(), sip_hangup(), sip_new(), sip_park_thread(), sip_reregister(), sip_scheddestroy(), sip_set_rtp_peer(), transmit_register(), transmit_reinvite_with_sdp(), transmit_response_with_auth(), and update_connectedline().
| #define check_request_transport | ( | peer, | |||
| tmpl | ) |
generic function for determining if a correct transport is being used to contact a peer
this is done as a macro so that the "tmpl" var can be passed either a sip_request or a sip_peer
Definition at line 2321 of file chan_sip.c.
Referenced by create_addr_from_peer(), and register_verify().
| #define CONTAINER_UNLINK | ( | container, | |||
| obj, | |||||
| tag | ) |
Unlink the given object from the container and return TRUE if it was in the container.
Definition at line 7699 of file chan_sip.c.
Referenced by change_callid_pvt().
| #define DATA_EXPORT_SIP_PEER | ( | MEMBER | ) |
Definition at line 31228 of file chan_sip.c.
| #define FORMAT "%-15.15s %-15.15s %-15.15s %-15.15s %-3.3s %-3.3s %-15.15s %-10.10s %-10.10s\n" |
Definition at line 19016 of file chan_sip.c.
| #define FORMAT "%-30.30s %-12.12s %-10.10s %-10.10s\n" |
Definition at line 19016 of file chan_sip.c.
| #define FORMAT "%-15.15s %-11.11s %-8.8s %-10.10u%-1.1s %-10.10u (%5.2f%%) %-6.4lf %-10.10u%-1.1s %-10.10u (%5.2f%%) %-6.4lf\n" |
Definition at line 19016 of file chan_sip.c.
| #define FORMAT "%-39.39s %-6.6s %-12.12s %8d %-20.20s %-25.25s\n" |
Definition at line 19016 of file chan_sip.c.
| #define FORMAT "%-40.40s %-20.20s %-16.16s\n" |
Definition at line 19016 of file chan_sip.c.
| #define FORMAT "%-25.25s %-15.15s %-15.15s %-15.15s %-5.5s%-10.10s\n" |
Definition at line 19016 of file chan_sip.c.
| #define FORMAT "%-47.47s %-9.9s %-6.6s\n" |
Definition at line 19016 of file chan_sip.c.
| #define FORMAT "%-25.25s %-15.15s %-15.15s \n" |
Definition at line 19016 of file chan_sip.c.
| #define FORMAT2 "%-15.15s %-15.15s %-15.15s %-15.15s %-7.7s %-15.15s %-10.10s %-10.10s\n" |
Definition at line 19015 of file chan_sip.c.
| #define FORMAT2 "%-15.15s %-11.11s %-8.8s %-10.10s %-10.10s ( %%) %-6.6s %-10.10s %-10.10s ( %%) %-6.6s\n" |
Definition at line 19015 of file chan_sip.c.
| #define FORMAT2 "%-39.39s %-6.6s %-12.12s %8.8s %-20.20s %-25.25s\n" |
Definition at line 19015 of file chan_sip.c.
| #define FORMAT2 "%-25.25s %-39.39s %-3.3s %-10.10s %-3.3s %-8s %-11s %-32.32s %s\n" |
Definition at line 19015 of file chan_sip.c.
| #define FORMAT2 "%-47.47s %9.9s %6.6s\n" |
Definition at line 19015 of file chan_sip.c.
| #define FORMAT2 "%-25.25s %-15.15s %-15.15s \n" |
Definition at line 19015 of file chan_sip.c.
| #define FORMAT3 "%-15.15s %-15.15s %-15.15s %-15.15s %-13.13s %-15.15s %-10.10s %-6.6s\n" |
| #define FORMAT4 "%-15.15s %-15.15s %-15.15s %-15.15s %-13.13s %-15.15s %-10.10s %-6.6d\n" |
| #define SIP_PEDANTIC_DECODE | ( | str | ) |
Value:
if (sip_cfg.pedanticsipchecking && !ast_strlen_zero(str)) { \ ast_uri_decode(str, ast_uri_sip_user); \ } \
Definition at line 707 of file chan_sip.c.
Referenced by check_user_full(), get_also_info(), get_destination(), get_refer_info(), register_verify(), and sip_msg_send().
| #define sip_pvt_lock | ( | x | ) | ao2_lock(x) |
Definition at line 1118 of file chan_sip.c.
Referenced by __sip_ack(), __sip_autodestruct(), auto_congest(), cb_extensionstate(), complete_sipch(), get_sip_pvt_byid_locked(), handle_incoming(), handle_invite_replaces(), handle_request_bye(), handle_request_invite(), handle_request_refer(), local_attended_transfer(), proc_session_timer(), retrans_pkt(), sip_answer(), sip_call(), sip_cc_agent_destructor(), sip_cc_agent_init(), sip_cc_agent_recall(), sip_cc_agent_respond(), sip_cc_monitor_request_cc(), sip_dtmfmode(), sip_fixup(), sip_get_rtp_peer(), sip_get_trtp_peer(), sip_get_udptl_peer(), sip_get_vrtp_peer(), sip_hangup(), sip_indicate(), sip_monitor_instance_destructor(), sip_msg_send(), sip_new(), sip_park_thread(), sip_pvt_lock_full(), sip_queryoption(), sip_read(), sip_reg_timeout(), sip_reinvite_retry(), sip_request_call(), sip_send_mwi_to_peer(), sip_senddigit_begin(), sip_senddigit_end(), sip_sendtext(), sip_set_rtp_peer(), sip_set_udptl_peer(), sip_setoption(), sip_show_channel(), sip_show_history(), sip_t38_abort(), sip_transfer(), sip_write(), transmit_publish(), and update_call_counter().
| #define sip_pvt_trylock | ( | x | ) | ao2_trylock(x) |
Definition at line 1119 of file chan_sip.c.
Referenced by dialog_checkrtp_cb(), dialog_needdestroy(), and sip_hangup().
| #define sip_pvt_unlock | ( | x | ) | ao2_unlock(x) |
Definition at line 1120 of file chan_sip.c.
Referenced by __sip_ack(), __sip_autodestruct(), auto_congest(), cb_extensionstate(), complete_sipch(), dialog_checkrtp_cb(), dialog_needdestroy(), dialog_unlink_all(), get_sip_pvt_byid_locked(), handle_incoming(), handle_invite_replaces(), handle_request_bye(), handle_request_do(), handle_request_invite(), handle_request_refer(), local_attended_transfer(), proc_session_timer(), retrans_pkt(), send_provisional_keepalive_full(), sip_answer(), sip_call(), sip_cc_agent_destructor(), sip_cc_agent_init(), sip_cc_agent_recall(), sip_cc_agent_respond(), sip_cc_monitor_request_cc(), sip_dtmfmode(), sip_fixup(), sip_get_rtp_peer(), sip_get_trtp_peer(), sip_get_udptl_peer(), sip_get_vrtp_peer(), sip_hangup(), sip_indicate(), sip_monitor_instance_destructor(), sip_msg_send(), sip_new(), sip_park_thread(), sip_pvt_lock_full(), sip_queryoption(), sip_read(), sip_reg_timeout(), sip_reinvite_retry(), sip_request_call(), sip_send_mwi_to_peer(), sip_senddigit_begin(), sip_senddigit_end(), sip_sendtext(), sip_set_rtp_peer(), sip_set_udptl_peer(), sip_setoption(), sip_show_channel(), sip_show_history(), sip_t38_abort(), sip_transfer(), sip_write(), transmit_publish(), and update_call_counter().
| #define UNLINK | ( | element, | |||
| head, | |||||
| prev | ) |
some list management macros.
Definition at line 1218 of file chan_sip.c.
Referenced by __sip_ack(), handle_request_cancel(), and retrans_pkt().
| enum match_req_res |
Definition at line 8000 of file chan_sip.c.
08000 { 08001 SIP_REQ_MATCH, 08002 SIP_REQ_NOT_MATCH, 08003 SIP_REQ_LOOP_DETECTED, /* multiple incoming requests with same call-id but different branch parameters have been detected */ 08004 SIP_REQ_FORKED, /* An outgoing request has been forked as result of receiving two differing 200ok responses. */ 08005 };
| enum peer_unlink_flag_t |
Definition at line 2886 of file chan_sip.c.
02886 { 02887 SIP_PEERS_MARKED, 02888 SIP_PEERS_ALL, 02889 } peer_unlink_flag_t;
| static const char * __get_header | ( | const struct sip_request * | req, | |
| const char * | name, | |||
| int * | start | |||
| ) | [static] |
Definition at line 7460 of file chan_sip.c.
References ast_skip_blanks(), find_alias(), len(), match(), and sip_cfg.
07461 { 07462 /* 07463 * Technically you can place arbitrary whitespace both before and after the ':' in 07464 * a header, although RFC3261 clearly says you shouldn't before, and place just 07465 * one afterwards. If you shouldn't do it, what absolute idiot decided it was 07466 * a good idea to say you can do it, and if you can do it, why in the hell would. 07467 * you say you shouldn't. 07468 * Anyways, pedanticsipchecking controls whether we allow spaces before ':', 07469 * and we always allow spaces after that for compatibility. 07470 */ 07471 const char *sname = find_alias(name, NULL); 07472 int x, len = strlen(name), slen = (sname ? 1 : 0); 07473 for (x = *start; x < req->headers; x++) { 07474 const char *header = REQ_OFFSET_TO_STR(req, header[x]); 07475 int smatch = 0, match = !strncasecmp(header, name, len); 07476 if (slen) { 07477 smatch = !strncasecmp(header, sname, slen); 07478 } 07479 if (match || smatch) { 07480 /* skip name */ 07481 const char *r = header + (match ? len : slen ); 07482 if (sip_cfg.pedanticsipchecking) { 07483 r = ast_skip_blanks(r); 07484 } 07485 07486 if (*r == ':') { 07487 *start = x+1; 07488 return ast_skip_blanks(r+1); 07489 } 07490 } 07491 } 07492 07493 /* Don't return NULL, so sip_get_header is always a valid pointer */ 07494 return ""; 07495 }
| static void __init_sip_msg_buf | ( | void | ) | [static] |
| static void __init_ts_temp_pvt | ( | void | ) | [static] |
| static void __reg_module | ( | void | ) | [static] |
Definition at line 31726 of file chan_sip.c.
| static int __set_address_from_contact | ( | const char * | fullcontact, | |
| struct ast_sockaddr * | addr, | |||
| int | tcp | |||
| ) | [static] |
Definition at line 14335 of file chan_sip.c.
References ast_copy_string(), ast_log(), ast_sockaddr_port, ast_sockaddr_resolve_first(), ast_sockaddr_set_port, ast_strlen_zero(), get_transport_str2enum(), LOG_WARNING, and parse_uri_legacy_check().
Referenced by build_peer(), and set_address_from_contact().
14336 { 14337 char *hostport, *transport; 14338 char contact_buf[256]; 14339 char *contact; 14340 14341 /* Work on a copy */ 14342 ast_copy_string(contact_buf, fullcontact, sizeof(contact_buf)); 14343 contact = contact_buf; 14344 14345 /* 14346 * We have only the part in <brackets> here so we just need to parse a SIP URI. 14347 * 14348 * Note: The outbound proxy could be using UDP between the proxy and Asterisk. 14349 * We still need to be able to send to the remote agent through the proxy. 14350 */ 14351 14352 if (parse_uri_legacy_check(contact, "sip:,sips:", &contact, NULL, &hostport, 14353 &transport)) { 14354 ast_log(LOG_WARNING, "Invalid contact uri %s (missing sip: or sips:), attempting to use anyway\n", fullcontact); 14355 } 14356 14357 /* XXX This could block for a long time XXX */ 14358 /* We should only do this if it's a name, not an IP */ 14359 /* \todo - if there's no PORT number in contact - we are required to check NAPTR/SRV records 14360 to find transport, port address and hostname. If there's a port number, we have to 14361 assume that the hostport part is a host name and only look for an A/AAAA record in DNS. 14362 */ 14363 14364 /* If we took in an invalid URI, hostport may not have been initialized */ 14365 /* ast_sockaddr_resolve requires an initialized hostport string. */ 14366 if (ast_strlen_zero(hostport)) { 14367 ast_log(LOG_WARNING, "Invalid URI: parse_uri failed to acquire hostport\n"); 14368 return -1; 14369 } 14370 14371 if (ast_sockaddr_resolve_first(addr, hostport, 0)) { 14372 ast_log(LOG_WARNING, "Invalid host name in Contact: (can't " 14373 "resolve in DNS) : '%s'\n", hostport); 14374 return -1; 14375 } 14376 14377 /* set port */ 14378 if (!ast_sockaddr_port(addr)) { 14379 ast_sockaddr_set_port(addr, 14380 (get_transport_str2enum(transport) == 14381 SIP_TRANSPORT_TLS || 14382 !strncasecmp(fullcontact, "sips", 4)) ? 14383 STANDARD_TLS_PORT : STANDARD_SIP_PORT); 14384 } 14385 14386 return 0; 14387 }
| int __sip_ack | ( | struct sip_pvt * | p, | |
| uint32_t | seqno, | |||
| int | resp, | |||
| int | sipmethod | |||
| ) |
Acknowledges receipt of a packet and stops retransmission called with p locked.
Definition at line 3993 of file chan_sip.c.
References ast_debug, ast_free, ast_sched_del(), FALSE, ref_proxy(), sip_pvt_lock, sip_pvt_unlock, TRUE, and UNLINK.
Referenced by __sip_pretend_ack(), handle_incoming(), handle_request_invite(), handle_request_publish(), and handle_response().
03994 { 03995 struct sip_pkt *cur, *prev = NULL; 03996 const char *msg = "Not Found"; /* used only for debugging */ 03997 int res = FALSE; 03998 03999 /* If we have an outbound proxy for this dialog, then delete it now since 04000 the rest of the requests in this dialog needs to follow the routing. 04001 If obforcing is set, we will keep the outbound proxy during the whole 04002 dialog, regardless of what the SIP rfc says 04003 */ 04004 if (p->outboundproxy && !p->outboundproxy->force){ 04005 ref_proxy(p, NULL); 04006 } 04007 04008 for (cur = p->packets; cur; prev = cur, cur = cur->next) { 04009 if (cur->seqno != seqno || cur->is_resp != resp) { 04010 continue; 04011 } 04012 if (cur->is_resp || cur->method == sipmethod) { 04013 res = TRUE; 04014 msg = "Found"; 04015 if (!resp && (seqno == p->pendinginvite)) { 04016 ast_debug(1, "Acked pending invite %u\n", p->pendinginvite); 04017 p->pendinginvite = 0; 04018 } 04019 if (cur->retransid > -1) { 04020 if (sipdebug) 04021 ast_debug(4, "** SIP TIMER: Cancelling retransmit of packet (reply received) Retransid #%d\n", cur->retransid); 04022 } 04023 /* This odd section is designed to thwart a 04024 * race condition in the packet scheduler. There are 04025 * two conditions under which deleting the packet from the 04026 * scheduler can fail. 04027 * 04028 * 1. The packet has been removed from the scheduler because retransmission 04029 * is being attempted. The problem is that if the packet is currently attempting 04030 * retransmission and we are at this point in the code, then that MUST mean 04031 * that retrans_pkt is waiting on p's lock. Therefore we will relinquish the 04032 * lock temporarily to allow retransmission. 04033 * 04034 * 2. The packet has reached its maximum number of retransmissions and has 04035 * been permanently removed from the packet scheduler. If this is the case, then 04036 * the packet's retransid will be set to -1. The atomicity of the setting and checking 04037 * of the retransid to -1 is ensured since in both cases p's lock is held. 04038 */ 04039 while (cur->retransid > -1 && ast_sched_del(sched, cur->retransid)) { 04040 sip_pvt_unlock(p); 04041 usleep(1); 04042 sip_pvt_lock(p); 04043 } 04044 UNLINK(cur, p->packets, prev); 04045 dialog_unref(cur->owner, "unref pkt cur->owner dialog from sip ack before freeing pkt"); 04046 if (cur->data) { 04047 ast_free(cur->data); 04048 } 04049 ast_free(cur); 04050 break; 04051 } 04052 } 04053 ast_debug(1, "Stopping retransmission on '%s' of %s %u: Match %s\n", 04054 p->callid, resp ? "Response" : "Request", seqno, msg); 04055 return res; 04056 }
| static int __sip_autodestruct | ( | const void * | data | ) | [static] |
Kill a SIP dialog (called only by the scheduler) The scheduler has a reference to this dialog when p->autokillid != -1, and we are called using that reference. So if the event is not rescheduled, we need to call dialog_unref().
Definition at line 3857 of file chan_sip.c.
References __sip_pretend_ack(), append_history, AST_CAUSE_PROTOCOL_ERROR, ast_channel_unlock, ast_channel_unref, ast_debug, AST_EXTENSION_DEACTIVATED, ast_log(), ast_queue_hangup_with_cause(), dialog_unlink_all(), LOG_WARNING, method_match(), NONE, pvt_set_needdestroy(), sip_methods, sip_pvt_lock, sip_pvt_lock_full(), sip_pvt_unlock, sip_scheddestroy(), stop_media_flows(), cfsip_methods::text, transmit_request_with_auth(), transmit_state_notify(), and TRUE.
Referenced by sip_scheddestroy(), and sip_show_sched().
03858 { 03859 struct sip_pvt *p = (struct sip_pvt *)data; 03860 struct ast_channel *owner; 03861 03862 /* If this is a subscription, tell the phone that we got a timeout */ 03863 if (p->subscribed && p->subscribed != MWI_NOTIFICATION && p->subscribed != CALL_COMPLETION) { 03864 transmit_state_notify(p, AST_EXTENSION_DEACTIVATED, 1, TRUE); /* Send last notification */ 03865 p->subscribed = NONE; 03866 append_history(p, "Subscribestatus", "timeout"); 03867 ast_debug(3, "Re-scheduled destruction of SIP subscription %s\n", p->callid ? p->callid : "<unknown>"); 03868 return 10000; /* Reschedule this destruction so that we know that it's gone */ 03869 } 03870 03871 /* If there are packets still waiting for delivery, delay the destruction */ 03872 if (p->packets) { 03873 if (!p->needdestroy) { 03874 char method_str[31]; 03875 ast_debug(3, "Re-scheduled destruction of SIP call %s\n", p->callid ? p->callid : "<unknown>"); 03876 append_history(p, "ReliableXmit", "timeout"); 03877 if (sscanf(p->lastmsg, "Tx: %30s", method_str) == 1 || sscanf(p->lastmsg, "Rx: %30s", method_str) == 1) { 03878 if (method_match(SIP_CANCEL, method_str) || method_match(SIP_BYE, method_str)) { 03879 pvt_set_needdestroy(p, "autodestruct"); 03880 } 03881 } 03882 return 10000; 03883 } else { 03884 /* They've had their chance to respond. Time to bail */ 03885 __sip_pretend_ack(p); 03886 } 03887 } 03888 03889 /* Reset schedule ID */ 03890 p->autokillid = -1; 03891 03892 03893 /* 03894 * Lock both the pvt and the channel safely so that we can queue up a frame. 03895 */ 03896 owner = sip_pvt_lock_full(p); 03897 if (owner) { 03898 ast_log(LOG_WARNING, "Autodestruct on dialog '%s' with owner in place (Method: %s)\n", p->callid, sip_methods[p->method].text); 03899 ast_queue_hangup_with_cause(owner, AST_CAUSE_PROTOCOL_ERROR); 03900 ast_channel_unlock(owner); 03901 ast_channel_unref(owner); 03902 } else if (p->refer && !p->alreadygone) { 03903 ast_debug(3, "Finally hanging up channel after transfer: %s\n", p->callid); 03904 stop_media_flows(p); 03905 transmit_request_with_auth(p, SIP_BYE, 0, XMIT_RELIABLE, 1); 03906 append_history(p, "ReferBYE", "Sending BYE on transferer call leg %s", p->callid); 03907 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 03908 } else { 03909 append_history(p, "AutoDestroy", "%s", p->callid); 03910 ast_debug(3, "Auto destroying SIP dialog '%s'\n", p->callid); 03911 sip_pvt_unlock(p); 03912 dialog_unlink_all(p); /* once it's unlinked and unrefd everywhere, it'll be freed automagically */ 03913 sip_pvt_lock(p); 03914 /* dialog_unref(p, "unref dialog-- no other matching conditions"); -- unlink all now should finish off the dialog's references and free it. */ 03915 /* sip_destroy(p); */ /* Go ahead and destroy dialog. All attempts to recover is done */ 03916 /* sip_destroy also absorbs the reference */ 03917 } 03918 03919 sip_pvt_unlock(p); 03920 03921 dialog_unref(p, "The ref to a dialog passed to this sched callback is going out of scope; unref it."); 03922 03923 return 0; 03924 }
| void __sip_destroy | ( | struct sip_pvt * | p, | |
| int | lockowner, | |||
| int | lockdialoglist | |||
| ) |
Execute destruction of SIP dialog structure, release memory.
Definition at line 5821 of file chan_sip.c.
References ao2_ref, ao2_t_ref, ast_cc_config_params_destroy(), ast_channel_lock, ast_channel_name(), ast_channel_unlock, ast_debug, ast_format_cap_destroy(), ast_free, ast_free_ha(), AST_LIST_REMOVE_HEAD, ast_rtp_instance_destroy(), AST_SOFTHANGUP_DEV, ast_string_field_free_memory, ast_test_flag, ast_udptl_destroy(), ast_variables_destroy(), ast_verbose, deinit_req(), destroy_msg_headers(), free_old_route(), registry_unref(), sip_debug_test_pvt(), sip_dump_history(), sip_methods, sip_srtp_destroy(), sip_unref_peer(), stop_session_timer(), cfsip_methods::text, and update_call_counter().
Referenced by sip_destroy().
05822 { 05823 struct sip_request *req; 05824 05825 /* Destroy Session-Timers if allocated */ 05826 if (p->stimer) { 05827 p->stimer->quit_flag = 1; 05828 stop_session_timer(p); 05829 ast_free(p->stimer); 05830 p->stimer = NULL; 05831 } 05832 05833 if (sip_debug_test_pvt(p)) 05834 ast_verbose("Really destroying SIP dialog '%s' Method: %s\n", p->callid, sip_methods[p->method].text); 05835 05836 if (ast_test_flag(&p->flags[0], SIP_INC_COUNT) || ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD)) { 05837 update_call_counter(p, DEC_CALL_LIMIT); 05838 ast_debug(2, "This call did not properly clean up call limits. Call ID %s\n", p->callid); 05839 } 05840 05841 /* Unlink us from the owner if we have one */ 05842 if (p->owner) { 05843 if (lockowner) 05844 ast_channel_lock(p->owner); 05845 ast_debug(1, "Detaching from %s\n", ast_channel_name(p->owner)); 05846 p->owner->tech_pvt = NULL; 05847 /* Make sure that the channel knows its backend is going away */ 05848 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 05849 if (lockowner) 05850 ast_channel_unlock(p->owner); 05851 /* Give the channel a chance to react before deallocation */ 05852 usleep(1); 05853 } 05854 05855 /* Remove link from peer to subscription of MWI */ 05856 if (p->relatedpeer && p->relatedpeer->mwipvt) 05857 p->relatedpeer->mwipvt = dialog_unref(p->relatedpeer->mwipvt, "delete ->relatedpeer->mwipvt"); 05858 if (p->relatedpeer && p->relatedpeer->call == p) 05859 p->relatedpeer->call = dialog_unref(p->relatedpeer->call, "unset the relatedpeer->call field in tandem with relatedpeer field itself"); 05860 05861 if (p->relatedpeer) 05862 p->relatedpeer = sip_unref_peer(p->relatedpeer,"unsetting a dialog relatedpeer field in sip_destroy"); 05863 05864 if (p->registry) { 05865 if (p->registry->call == p) 05866 p->registry->call = dialog_unref(p->registry->call, "nulling out the registry's call dialog field in unlink_all"); 05867 p->registry = registry_unref(p->registry, "delete p->registry"); 05868 } 05869 05870 if (p->mwi) { 05871 p->mwi->call = NULL; 05872 } 05873 05874 if (dumphistory) 05875 sip_dump_history(p); 05876 05877 if (p->options) 05878 ast_free(p->options); 05879 05880 if (p->notify) { 05881 ast_variables_destroy(p->notify->headers); 05882 ast_free(p->notify->content); 05883 ast_free(p->notify); 05884 } 05885 if (p->rtp) { 05886 ast_rtp_instance_destroy(p->rtp); 05887 } 05888 if (p->vrtp) { 05889 ast_rtp_instance_destroy(p->vrtp); 05890 } 05891 if (p->trtp) { 05892 ast_rtp_instance_destroy(p->trtp); 05893 } 05894 if (p->udptl) 05895 ast_udptl_destroy(p->udptl); 05896 if (p->refer) 05897 ast_free(p->refer); 05898 if (p->route) { 05899 free_old_route(p->route); 05900 p->route = NULL; 05901 } 05902 deinit_req(&p->initreq); 05903 05904 /* Clear history */ 05905 if (p->history) { 05906 struct sip_history *hist; 05907 while ( (hist = AST_LIST_REMOVE_HEAD(p->history, list)) ) { 05908 ast_free(hist); 05909 p->history_entries--; 05910 } 05911 ast_free(p->history); 05912 p->history = NULL; 05913 } 05914 05915 while ((req = AST_LIST_REMOVE_HEAD(&p->request_queue, next))) { 05916 ast_free(req); 05917 } 05918 05919 if (p->chanvars) { 05920 ast_variables_destroy(p->chanvars); 05921 p->chanvars = NULL; 05922 } 05923 05924 destroy_msg_headers(p); 05925 05926 if (p->srtp) { 05927 sip_srtp_destroy(p->srtp); 05928 p->srtp = NULL; 05929 } 05930 05931 if (p->vsrtp) { 05932 sip_srtp_destroy(p->vsrtp); 05933 p->vsrtp = NULL; 05934 } 05935 05936 if (p->tsrtp) { 05937 sip_srtp_destroy(p->tsrtp); 05938 p->tsrtp = NULL; 05939 } 05940 05941 if (p->directmediaha) { 05942 ast_free_ha(p->directmediaha); 05943 p->directmediaha = NULL; 05944 } 05945 05946 ast_string_field_free_memory(p); 05947 05948 ast_cc_config_params_destroy(p->cc_params); 05949 05950 if (p->epa_entry) { 05951 ao2_ref(p->epa_entry, -1); 05952 p->epa_entry = NULL; 05953 } 05954 05955 if (p->socket.tcptls_session) { 05956 ao2_ref(p->socket.tcptls_session, -1); 05957 p->socket.tcptls_session = NULL; 05958 } 05959 05960 if (p->peerauth) { 05961 ao2_t_ref(p->peerauth, -1, "Removing active peer authentication"); 05962 p->peerauth = NULL; 05963 } 05964 05965 p->caps = ast_format_cap_destroy(p->caps); 05966 p->jointcaps = ast_format_cap_destroy(p->jointcaps); 05967 p->peercaps = ast_format_cap_destroy(p->peercaps); 05968 p->redircaps = ast_format_cap_destroy(p->redircaps); 05969 p->prefcaps = ast_format_cap_destroy(p->prefcaps); 05970 }
| static int __sip_do_register | ( | struct sip_registry * | r | ) | [static] |
Register with SIP proxy.
Definition at line 13521 of file chan_sip.c.
References transmit_register().
Referenced by sip_reregister().
13522 { 13523 int res; 13524 13525 res = transmit_register(r, SIP_REGISTER, NULL, NULL); 13526 return res; 13527 }
| void __sip_pretend_ack | ( | struct sip_pvt * | p | ) |
Pretend to ack all packets called with p locked.
Definition at line 4060 of file chan_sip.c.
References __sip_ack(), ast_log(), find_sip_method(), LOG_WARNING, sip_methods, and cfsip_methods::text.
Referenced by __sip_autodestruct(), handle_request_bye(), handle_request_cancel(), and sip_reg_timeout().
04061 { 04062 struct sip_pkt *cur = NULL; 04063 04064 while (p->packets) { 04065 int method; 04066 if (cur == p->packets) { 04067 ast_log(LOG_WARNING, "Have a packet that doesn't want to give up! %s\n", sip_methods[cur->method].text); 04068 return; 04069 } 04070 cur = p->packets; 04071 method = (cur->method) ? cur->method : find_sip_method(cur->data->str); 04072 __sip_ack(p, cur->seqno, cur->is_resp, method); 04073 } 04074 }
| static enum sip_result __sip_reliable_xmit | ( | struct sip_pvt * | p, | |
| uint32_t | seqno, | |||
| int | resp, | |||
| struct ast_str * | data, | |||
| int | fatal, | |||
| int | sipmethod | |||
| ) | [static] |
Definition at line 3766 of file chan_sip.c.
References __sip_xmit(), append_history, ast_calloc, ast_debug, ast_free, ast_log(), AST_PTHREADT_NULL, AST_SCHED_DEL, AST_SCHED_REPLACE_VARIABLE, ast_str_buffer(), ast_str_create(), ast_str_set(), ast_str_strlen(), ast_tvnow(), DEFAULT_RETRANS, LOG_ERROR, and retrans_pkt().
Referenced by send_request(), and send_response().
03767 { 03768 struct sip_pkt *pkt = NULL; 03769 int siptimer_a = DEFAULT_RETRANS; 03770 int xmitres = 0; 03771 int respid; 03772 03773 if (sipmethod == SIP_INVITE) { 03774 /* Note this is a pending invite */ 03775 p->pendinginvite = seqno; 03776 } 03777 03778 /* If the transport is something reliable (TCP or TLS) then don't really send this reliably */ 03779 /* I removed the code from retrans_pkt that does the same thing so it doesn't get loaded into the scheduler */ 03780 /*! \todo According to the RFC some packets need to be retransmitted even if its TCP, so this needs to get revisited */ 03781 if (!(p->socket.type & SIP_TRANSPORT_UDP)) { 03782 xmitres = __sip_xmit(p, data); /* Send packet */ 03783 if (xmitres == XMIT_ERROR) { /* Serious network trouble, no need to try again */ 03784 append_history(p, "XmitErr", "%s", fatal ? "(Critical)" : "(Non-critical)"); 03785 return AST_FAILURE; 03786 } else { 03787 return AST_SUCCESS; 03788 } 03789 } 03790 03791 if (!(pkt = ast_calloc(1, sizeof(*pkt)))) { 03792 return AST_FAILURE; 03793 } 03794 /* copy data, add a terminator and save length */ 03795 if (!(pkt->data = ast_str_create(ast_str_strlen(data)))) { 03796 ast_free(pkt); 03797 return AST_FAILURE; 03798 } 03799 ast_str_set(&pkt->data, 0, "%s%s", data->str, "\0"); 03800 /* copy other parameters from the caller */ 03801 pkt->method = sipmethod; 03802 pkt->seqno = seqno; 03803 pkt->is_resp = resp; 03804 pkt->is_fatal = fatal; 03805 pkt->owner = dialog_ref(p, "__sip_reliable_xmit: setting pkt->owner"); 03806 pkt->next = p->packets; 03807 p->packets = pkt; /* Add it to the queue */ 03808 if (resp) { 03809 /* Parse out the response code */ 03810 if (sscanf(ast_str_buffer(pkt->data), "SIP/2.0 %30u", &respid) == 1) { 03811 pkt->response_code = respid; 03812 } 03813 } 03814 pkt->timer_t1 = p->timer_t1; /* Set SIP timer T1 */ 03815 pkt->retransid = -1; 03816 if (pkt->timer_t1) { 03817 siptimer_a = pkt->timer_t1; 03818 } 03819 03820 pkt->time_sent = ast_tvnow(); /* time packet was sent */ 03821 pkt->retrans_stop_time = 64 * (pkt->timer_t1 ? pkt->timer_t1 : DEFAULT_TIMER_T1); /* time in ms after pkt->time_sent to stop retransmission */ 03822 03823 /* Schedule retransmission */ 03824 AST_SCHED_REPLACE_VARIABLE(pkt->retransid, sched, siptimer_a, retrans_pkt, pkt, 1); 03825 if (sipdebug) { 03826 ast_debug(4, "*** SIP TIMER: Initializing retransmit timer on packet: Id #%d\n", pkt->retransid); 03827 } 03828 03829 xmitres = __sip_xmit(pkt->owner, pkt->data); /* Send packet */ 03830 03831 if (xmitres == XMIT_ERROR) { /* Serious network trouble, no need to try again */ 03832 append_history(pkt->owner, "XmitErr", "%s", pkt->is_fatal ? "(Critical)" : "(Non-critical)"); 03833 ast_log(LOG_ERROR, "Serious Network Trouble; __sip_xmit returns error for pkt data\n"); 03834 AST_SCHED_DEL(sched, pkt->retransid); 03835 p->packets = pkt->next; 03836 pkt->owner = dialog_unref(pkt->owner,"pkt is being freed, its dialog ref is dead now"); 03837 ast_free(pkt->data); 03838 ast_free(pkt); 03839 return AST_FAILURE; 03840 } else { 03841 /* This is odd, but since the retrans timer starts at 500ms and the do_monitor thread 03842 * only wakes up every 1000ms by default, we have to poke the thread here to make 03843 * sure it successfully detects this must be retransmitted in less time than 03844 * it usually sleeps for. Otherwise it might not retransmit this packet for 1000ms. */ 03845 if (monitor_thread != AST_PTHREADT_NULL) { 03846 pthread_kill(monitor_thread, SIGURG); 03847 } 03848 return AST_SUCCESS; 03849 } 03850 }
| int __sip_semi_ack | ( | struct sip_pvt * | p, | |
| uint32_t | seqno, | |||
| int | resp, | |||
| int | sipmethod | |||
| ) |
Acks receipt of packet, keep it around (used for provisional responses).
Definition at line 4077 of file chan_sip.c.
References ast_debug, AST_SCHED_DEL, FALSE, method_match(), sip_methods, cfsip_methods::text, and TRUE.
Referenced by handle_response(), and sip_hangup().
04078 { 04079 struct sip_pkt *cur; 04080 int res = FALSE; 04081 04082 for (cur = p->packets; cur; cur = cur->next) { 04083 if (cur->seqno == seqno && cur->is_resp == resp && 04084 (cur->is_resp || method_match(sipmethod, cur->data->str))) { 04085 /* this is our baby */ 04086 if (cur->retransid > -1) { 04087 if (sipdebug) 04088 ast_debug(4, "*** SIP TIMER: Cancelling retransmission #%d - %s (got response)\n", cur->retransid, sip_methods[sipmethod].text); 04089 } 04090 AST_SCHED_DEL(sched, cur->retransid); 04091 res = TRUE; 04092 break; 04093 } 04094 } 04095 ast_debug(1, "(Provisional) Stopping retransmission (but retaining packet) on '%s' %s %u: %s\n", p->callid, resp ? "Response" : "Request", seqno, res == -1 ? "Not Found" : "Found"); 04096 return res; 04097 }
| static int __sip_subscribe_mwi_do | ( | struct sip_subscription_mwi * | mwi | ) | [static] |
Actually setup an MWI subscription or resubscribe.
Definition at line 12855 of file chan_sip.c.
References ast_dnsmgr_lookup_cb(), ast_set_flag, ast_sip_ouraddrfor(), ast_sockaddr_port, ast_sockaddr_set_port, ast_string_field_set, ast_strlen_zero(), ASTOBJ_REF, ASTOBJ_UNREF, bindaddr, build_contact(), build_via(), change_callid_pvt(), create_addr(), dialog_unlink_all(), get_address_family_filter(), get_srv_protocol(), get_srv_service(), MAXHOSTNAMELEN, obproxy_get(), on_dns_update_mwi(), ref_proxy(), set_socket_transport(), sip_alloc(), sip_cfg, sip_subscribe_mwi_destroy(), and transmit_invite().
Referenced by sip_subscribe_mwi_do().
12856 { 12857 /* If we have no DNS manager let's do a lookup */ 12858 if (!mwi->dnsmgr) { 12859 char transport[MAXHOSTNAMELEN]; 12860 snprintf(transport, sizeof(transport), "_%s._%s", get_srv_service(mwi->transport), get_srv_protocol(mwi->transport)); 12861 12862 mwi->us.ss.ss_family = get_address_family_filter(&bindaddr); /* Filter address family */ 12863 ASTOBJ_REF(mwi); /* Add a ref for storing the mwi on the dnsmgr for updates */ 12864 ast_dnsmgr_lookup_cb(mwi->hostname, &mwi->us, &mwi->dnsmgr, sip_cfg.srvlookup ? transport : NULL, on_dns_update_mwi, mwi); 12865 if (!mwi->dnsmgr) { 12866 ASTOBJ_UNREF(mwi, sip_subscribe_mwi_destroy); /* dnsmgr disabled, remove reference */ 12867 } 12868 } 12869 12870 /* If we already have a subscription up simply send a resubscription */ 12871 if (mwi->call) { 12872 transmit_invite(mwi->call, SIP_SUBSCRIBE, 0, 0, NULL); 12873 return 0; 12874 } 12875 12876 /* Create a dialog that we will use for the subscription */ 12877 if (!(mwi->call = sip_alloc(NULL, NULL, 0, SIP_SUBSCRIBE, NULL))) { 12878 return -1; 12879 } 12880 12881 ref_proxy(mwi->call, obproxy_get(mwi->call, NULL)); 12882 12883 if (!ast_sockaddr_port(&mwi->us) && mwi->portno) { 12884 ast_sockaddr_set_port(&mwi->us, mwi->portno); 12885 } 12886 12887 /* Setup the destination of our subscription */ 12888 if (create_addr(mwi->call, mwi->hostname, &mwi->us, 0, NULL)) { 12889 dialog_unlink_all(mwi->call); 12890 mwi->call = dialog_unref(mwi->call, "unref dialog after unlink_all"); 12891 return 0; 12892 } 12893 12894 mwi->call->expiry = mwi_expiry; 12895 12896 if (!mwi->dnsmgr && mwi->portno) { 12897 ast_sockaddr_set_port(&mwi->call->sa, mwi->portno); 12898 ast_sockaddr_set_port(&mwi->call->recv, mwi->portno); 12899 } else { 12900 mwi->portno = ast_sockaddr_port(&mwi->call->sa); 12901 } 12902 12903 /* Set various other information */ 12904 if (!ast_strlen_zero(mwi->authuser)) { 12905 ast_string_field_set(mwi->call, peername, mwi->authuser); 12906 ast_string_field_set(mwi->call, authname, mwi->authuser); 12907 ast_string_field_set(mwi->call, fromuser, mwi->authuser); 12908 } else { 12909 ast_string_field_set(mwi->call, peername, mwi->username); 12910 ast_string_field_set(mwi->call, authname, mwi->username); 12911 ast_string_field_set(mwi->call, fromuser, mwi->username); 12912 } 12913 ast_string_field_set(mwi->call, username, mwi->username); 12914 if (!ast_strlen_zero(mwi->secret)) { 12915 ast_string_field_set(mwi->call, peersecret, mwi->secret); 12916 } 12917 set_socket_transport(&mwi->call->socket, mwi->transport); 12918 mwi->call->socket.port = htons(mwi->portno); 12919 ast_sip_ouraddrfor(&mwi->call->sa, &mwi->call->ourip, mwi->call); 12920 build_contact(mwi->call); 12921 build_via(mwi->call); 12922 12923 /* Change the dialog callid. */ 12924 change_callid_pvt(mwi->call, NULL); 12925 12926 ast_set_flag(&mwi->call->flags[0], SIP_OUTGOING); 12927 12928 /* Associate the call with us */ 12929 mwi->call->mwi = ASTOBJ_REF(mwi); 12930 12931 mwi->call->subscribed = MWI_NOTIFICATION; 12932 12933 /* Actually send the packet */ 12934 transmit_invite(mwi->call, SIP_SUBSCRIBE, 0, 2, NULL); 12935 12936 return 0; 12937 }
| static int __sip_xmit | ( | struct sip_pvt * | p, | |
| struct ast_str * | data | |||
| ) | [static] |
Definition at line 3364 of file chan_sip.c.
References ast_debug, ast_log(), ast_sendto(), ast_sockaddr_stringify(), ast_str_strlen(), errno, get_transport_pvt(), LOG_WARNING, sip_prepare_socket(), sip_real_dst(), and sip_tcptls_write().
Referenced by __sip_reliable_xmit(), retrans_pkt(), send_request(), and send_response().
03365 { 03366 int res = 0; 03367 const struct ast_sockaddr *dst = sip_real_dst(p); 03368 03369 ast_debug(2, "Trying to put '%.11s' onto %s socket destined for %s\n", data->str, get_transport_pvt(p), ast_sockaddr_stringify(dst)); 03370 03371 if (sip_prepare_socket(p) < 0) { 03372 return XMIT_ERROR; 03373 } 03374 03375 if (p->socket.type == SIP_TRANSPORT_UDP) { 03376 res = ast_sendto(p->socket.fd, data->str, ast_str_strlen(data), 0, dst); 03377 } else if (p->socket.tcptls_session) { 03378 res = sip_tcptls_write(p->socket.tcptls_session, data->str, ast_str_strlen(data)); 03379 } else { 03380 ast_debug(2, "Socket type is TCP but no tcptls_session is present to write to\n"); 03381 return XMIT_ERROR; 03382 } 03383 03384 if (res == -1) { 03385 switch (errno) { 03386 case EBADF: /* Bad file descriptor - seems like this is generated when the host exist, but doesn't accept the UDP packet */ 03387 case EHOSTUNREACH: /* Host can't be reached */ 03388 case ENETDOWN: /* Interface down */ 03389 case ENETUNREACH: /* Network failure */ 03390 case ECONNREFUSED: /* ICMP port unreachable */ 03391 res = XMIT_ERROR; /* Don't bother with trying to transmit again */ 03392 } 03393 } 03394 if (res != ast_str_strlen(data)) { 03395 ast_log(LOG_WARNING, "sip_xmit of %p (len %zu) to %s returned %d: %s\n", data, ast_str_strlen(data), ast_sockaddr_stringify(dst), res, strerror(errno)); 03396 } 03397 03398 return res; 03399 }
| static int __transmit_response | ( | struct sip_pvt * | p, | |
| const char * | msg, | |||
| const struct sip_request * | req, | |||
| enum xmittype | reliable | |||
| ) | [static] |
Base transmit response function.
Definition at line 10732 of file chan_sip.c.
References add_cc_call_info_to_response(), add_diversion_header(), add_header(), add_rpid(), ast_cause2str(), ast_clear_flag, ast_log(), ast_test_flag, hangup_sip2cause(), LOG_WARNING, respprep(), send_response(), and sip_get_header().
Referenced by transmit_response(), transmit_response_reliable(), and transmit_response_using_temp().
10733 { 10734 struct sip_request resp; 10735 uint32_t seqno = 0; 10736 10737 if (reliable && (sscanf(sip_get_header(req, "CSeq"), "%30u ", &seqno) != 1)) { 10738 ast_log(LOG_WARNING, "Unable to determine sequence number from '%s'\n", sip_get_header(req, "CSeq")); 10739 return -1; 10740 } 10741 respprep(&resp, p, msg, req); 10742 10743 if (ast_test_flag(&p->flags[0], SIP_SENDRPID) 10744 && ast_test_flag(&p->flags[1], SIP_PAGE2_CONNECTLINEUPDATE_PEND) 10745 && (!strncmp(msg, "180", 3) || !strncmp(msg, "183", 3))) { 10746 ast_clear_flag(&p->flags[1], SIP_PAGE2_CONNECTLINEUPDATE_PEND); 10747 add_rpid(&resp, p); 10748 } 10749 if (ast_test_flag(&p->flags[0], SIP_OFFER_CC)) { 10750 add_cc_call_info_to_response(p, &resp); 10751 } 10752 10753 /* If we are sending a 302 Redirect we can add a diversion header if the redirect information is set */ 10754 if (!strncmp(msg, "302", 3)) { 10755 add_diversion_header(&resp, p); 10756 } 10757 10758 /* If we are cancelling an incoming invite for some reason, add information 10759 about the reason why we are doing this in clear text */ 10760 if (p->method == SIP_INVITE && msg[0] != '1') { 10761 char buf[20]; 10762 10763 if (ast_test_flag(&p->flags[1], SIP_PAGE2_Q850_REASON)) { 10764 int hangupcause = 0; 10765 10766 if (p->owner && p->owner->hangupcause) { 10767 hangupcause = p->owner->hangupcause; 10768 } else if (p->hangupcause) { 10769 hangupcause = p->hangupcause; 10770 } else { 10771 int respcode; 10772 if (sscanf(msg, "%30d ", &respcode)) 10773 hangupcause = hangup_sip2cause(respcode); 10774 } 10775 10776 if (hangupcause) { 10777 sprintf(buf, "Q.850;cause=%i", hangupcause & 0x7f); 10778 add_header(&resp, "Reason", buf); 10779 } 10780 } 10781 10782 if (p->owner && p->owner->hangupcause) { 10783 add_header(&resp, "X-Asterisk-HangupCause", ast_cause2str(p->owner->hangupcause)); 10784 snprintf(buf, sizeof(buf), "%d", p->owner->hangupcause); 10785 add_header(&resp, "X-Asterisk-HangupCauseCode", buf); 10786 } 10787 } 10788 return send_response(p, &resp, reliable, seqno); 10789 }
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 31726 of file chan_sip.c.
| static char * _sip_qualify_peer | ( | int | type, | |
| int | fd, | |||
| struct mansession * | s, | |||
| const struct message * | m, | |||
| int | argc, | |||
| const char * | argv[] | |||
| ) | [static] |
Send qualify message to peer from cli or manager. Mostly for debugging.
Definition at line 18009 of file chan_sip.c.
References ast_cli(), astman_send_error(), CLI_SHOWUSAGE, CLI_SUCCESS, FALSE, sip_find_peer(), sip_poke_peer(), sip_unref_peer(), and TRUE.
Referenced by manager_sip_qualify_peer(), and sip_qualify_peer().
18010 { 18011 struct sip_peer *peer; 18012 int load_realtime; 18013 18014 if (argc < 4) 18015 return CLI_SHOWUSAGE; 18016 18017 load_realtime = (argc == 5 && !strcmp(argv[4], "load")) ? TRUE : FALSE; 18018 if ((peer = sip_find_peer(argv[3], NULL, load_realtime, FINDPEERS, FALSE, 0))) { 18019 sip_poke_peer(peer, 1); 18020 sip_unref_peer(peer, "qualify: done with peer"); 18021 } else if (type == 0) { 18022 ast_cli(fd, "Peer '%s' not found\n", argv[3]); 18023 } else { 18024 astman_send_error(s, m, "Peer not found"); 18025 } 18026 return CLI_SUCCESS; 18027 }
| static char * _sip_show_peer | ( | int | type, | |
| int | fd, | |||
| struct mansession * | s, | |||
| const struct message * | m, | |||
| int | argc, | |||
| const char * | argv[] | |||
| ) | [static] |
Show one peer in detail (main function).
Definition at line 18094 of file chan_sip.c.
References allowoverlap2str(), ao2_lock, ao2_t_ref, ao2_unlock, ARRAY_LEN, ast_callerid_merge(), ast_cdr_flags2str(), ast_check_realtime(), ast_cli(), AST_CLI_YESNO, ast_codec_pref_index(), AST_CODEC_PREF_SIZE, ast_describe_caller_presentation(), ast_getformatname(), ast_getformatname_multiple(), AST_LIST_TRAVERSE, ast_print_group(), ast_sched_when(), ast_sockaddr_port, ast_sockaddr_stringify(), ast_sockaddr_stringify_addr(), ast_str_alloca, ast_strlen_zero(), ast_test_flag, astman_append(), astman_get_header(), astman_send_error(), CLI_SHOWUSAGE, CLI_SUCCESS, comedia_string(), dtmfmode2str(), FALSE, faxec2str(), force_rport_string(), get_transport_list(), insecure2str(), ast_variable::name, ast_variable::next, peer_mailboxes_to_str(), peer_status(), print_codec_to_cli(), print_group(), S_OR, sip_cfg, sip_find_peer(), sip_get_transport(), sip_unref_peer(), status, stmode2str(), strefresher2str(), text, transfermode2str(), TRUE, and ast_variable::value.
Referenced by manager_sip_show_peer(), and sip_show_peer().
18095 { 18096 char status[30] = ""; 18097 char cbuf[256]; 18098 struct sip_peer *peer; 18099 char codec_buf[512]; 18100 struct ast_codec_pref *pref; 18101 struct ast_variable *v; 18102 int x = 0, load_realtime; 18103 struct ast_format codec; 18104 int realtimepeers; 18105 18106 realtimepeers = ast_check_realtime("sippeers"); 18107 18108 if (argc < 4) 18109 return CLI_SHOWUSAGE; 18110 18111 load_realtime = (argc == 5 && !strcmp(argv[4], "load")) ? TRUE : FALSE; 18112 peer = sip_find_peer(argv[3], NULL, load_realtime, FINDPEERS, FALSE, 0); 18113 18114 if (s) { /* Manager */ 18115 if (peer) { 18116 const char *id = astman_get_header(m, "ActionID"); 18117 18118 astman_append(s, "Response: Success\r\n"); 18119 if (!ast_strlen_zero(id)) 18120 astman_append(s, "ActionID: %s\r\n", id); 18121 } else { 18122 snprintf (cbuf, sizeof(cbuf), "Peer %s not found.", argv[3]); 18123 astman_send_error(s, m, cbuf); 18124 return CLI_SUCCESS; 18125 } 18126 } 18127 if (peer && type==0 ) { /* Normal listing */ 18128 struct ast_str *mailbox_str = ast_str_alloca(512); 18129 struct sip_auth_container *credentials; 18130 18131 ao2_lock(peer); 18132 credentials = peer->auth; 18133 if (credentials) { 18134 ao2_t_ref(credentials, +1, "Ref peer auth for show"); 18135 } 18136 ao2_unlock(peer); 18137 18138 ast_cli(fd, "\n\n"); 18139 ast_cli(fd, " * Name : %s\n", peer->name); 18140 ast_cli(fd, " Description : %s\n", peer->description); 18141 if (realtimepeers) { /* Realtime is enabled */ 18142 ast_cli(fd, " Realtime peer: %s\n", peer->is_realtime ? "Yes, cached" : "No"); 18143 } 18144 ast_cli(fd, " Secret : %s\n", ast_strlen_zero(peer->secret)?"<Not set>":"<Set>"); 18145 ast_cli(fd, " MD5Secret : %s\n", ast_strlen_zero(peer->md5secret)?"<Not set>":"<Set>"); 18146 ast_cli(fd, " Remote Secret: %s\n", ast_strlen_zero(peer->remotesecret)?"<Not set>":"<Set>"); 18147 if (credentials) { 18148 struct sip_auth *auth; 18149 18150 AST_LIST_TRAVERSE(&credentials->list, auth, node) { 18151 ast_cli(fd, " Realm-auth : Realm %-15.15s User %-10.20s %s\n", 18152 auth->realm, 18153 auth->username, 18154 !ast_strlen_zero(auth->secret) 18155 ? "<Secret set>" 18156 : (!ast_strlen_zero(auth->md5secret) 18157 ? "<MD5secret set>" : "<Not set>")); 18158 } 18159 ao2_t_ref(credentials, -1, "Unref peer auth for show"); 18160 } 18161 ast_cli(fd, " Context : %s\n", peer->context); 18162 ast_cli(fd, " Record On feature : %s\n", peer->record_on_feature); 18163 ast_cli(fd, " Record Off feature : %s\n", peer->record_off_feature); 18164 ast_cli(fd, " Subscr.Cont. : %s\n", S_OR(peer->subscribecontext, "<Not set>") ); 18165 ast_cli(fd, " Language : %s\n", peer->language); 18166 ast_cli(fd, " Tonezone : %s\n", peer->zone[0] != '\0' ? peer->zone : "<Not set>"); 18167 if (!ast_strlen_zero(peer->accountcode)) 18168 ast_cli(fd, " Accountcode : %s\n", peer->accountcode); 18169 ast_cli(fd, " AMA flags : %s\n", ast_cdr_flags2str(peer->amaflags)); 18170 ast_cli(fd, " Transfer mode: %s\n", transfermode2str(peer->allowtransfer)); 18171 ast_cli(fd, " CallingPres : %s\n", ast_describe_caller_presentation(peer->callingpres)); 18172 if (!ast_strlen_zero(peer->fromuser)) 18173 ast_cli(fd, " FromUser : %s\n", peer->fromuser); 18174 if (!ast_strlen_zero(peer->fromdomain)) 18175 ast_cli(fd, " FromDomain : %s Port %d\n", peer->fromdomain, (peer->fromdomainport) ? peer->fromdomainport : STANDARD_SIP_PORT); 18176 ast_cli(fd, " Callgroup : "); 18177 print_group(fd, peer->callgroup, 0); 18178 ast_cli(fd, " Pickupgroup : "); 18179 print_group(fd, peer->pickupgroup, 0); 18180 peer_mailboxes_to_str(&mailbox_str, peer); 18181 ast_cli(fd, " MOH Suggest : %s\n", peer->mohsuggest); 18182 ast_cli(fd, " Mailbox : %s\n", mailbox_str->str); 18183 ast_cli(fd, " VM Extension : %s\n", peer->vmexten); 18184 ast_cli(fd, " Call limit : %d\n", peer->call_limit); 18185 ast_cli(fd, " Max forwards : %d\n", peer->maxforwards); 18186 if (peer->busy_level) 18187 ast_cli(fd, " Busy level : %d\n", peer->busy_level); 18188 ast_cli(fd, " Dynamic : %s\n", AST_CLI_YESNO(peer->host_dynamic)); 18189 ast_cli(fd, " Callerid : %s\n", ast_callerid_merge(cbuf, sizeof(cbuf), peer->cid_name, peer->cid_num, "<unspecified>")); 18190 ast_cli(fd, " MaxCallBR : %d kbps\n", peer->maxcallbitrate); 18191 ast_cli(fd, " Expire : %ld\n", ast_sched_when(sched, peer->expire)); 18192 ast_cli(fd, " Insecure : %s\n", insecure2str(ast_test_flag(&peer->flags[0], SIP_INSECURE))); 18193 ast_cli(fd, " Force rport : %s\n", force_rport_string(peer->flags)); 18194 ast_cli(fd, " Symmetric RTP: %s\n", comedia_string(peer->flags)); 18195 ast_cli(fd, " ACL : %s\n", AST_CLI_YESNO(peer->ha != NULL)); 18196 ast_cli(fd, " DirectMedACL : %s\n", AST_CLI_YESNO(peer->directmediaha != NULL)); 18197 ast_cli(fd, " T.38 support : %s\n", AST_CLI_YESNO(ast_test_flag(&peer->flags[1], SIP_PAGE2_T38SUPPORT))); 18198 ast_cli(fd, " T.38 EC mode : %s\n", faxec2str(ast_test_flag(&peer->flags[1], SIP_PAGE2_T38SUPPORT))); 18199 ast_cli(fd, " T.38 MaxDtgrm: %d\n", peer->t38_maxdatagram); 18200 ast_cli(fd, " DirectMedia : %s\n", AST_CLI_YESNO(ast_test_flag(&peer->flags[0], SIP_DIRECT_MEDIA))); 18201 ast_cli(fd, " PromiscRedir : %s\n", AST_CLI_YESNO(ast_test_flag(&peer->flags[0], SIP_PROMISCREDIR))); 18202 ast_cli(fd, " User=Phone : %s\n", AST_CLI_YESNO(ast_test_flag(&peer->flags[0], SIP_USEREQPHONE))); 18203 ast_cli(fd, " Video Support: %s\n", AST_CLI_YESNO(ast_test_flag(&peer->flags[1], SIP_PAGE2_VIDEOSUPPORT) || ast_test_flag(&peer->flags[1], SIP_PAGE2_VIDEOSUPPORT_ALWAYS))); 18204 ast_cli(fd, " Text Support : %s\n", AST_CLI_YESNO(ast_test_flag(&peer->flags[1], SIP_PAGE2_TEXTSUPPORT))); 18205 ast_cli(fd, " Ign SDP ver : %s\n", AST_CLI_YESNO(ast_test_flag(&peer->flags[1], SIP_PAGE2_IGNORESDPVERSION))); 18206 ast_cli(fd, " Trust RPID : %s\n", AST_CLI_YESNO(ast_test_flag(&peer->flags[0], SIP_TRUSTRPID))); 18207 ast_cli(fd, " Send RPID : %s\n", AST_CLI_YESNO(ast_test_flag(&peer->flags[0], SIP_SENDRPID))); 18208 ast_cli(fd, " Subscriptions: %s\n", AST_CLI_YESNO(ast_test_flag(&peer->flags[1], SIP_PAGE2_ALLOWSUBSCRIBE))); 18209 ast_cli(fd, " Overlap dial : %s\n", allowoverlap2str(ast_test_flag(&peer->flags[1], SIP_PAGE2_ALLOWOVERLAP))); 18210 if (peer->outboundproxy) 18211 ast_cli(fd, " Outb. proxy : %s %s\n", ast_strlen_zero(peer->outboundproxy->name) ? "<not set>" : peer->outboundproxy->name, 18212 peer->outboundproxy->force ? "(forced)" : ""); 18213 18214 /* - is enumerated */ 18215 ast_cli(fd, " DTMFmode : %s\n", dtmfmode2str(ast_test_flag(&peer->flags[0], SIP_DTMF))); 18216 ast_cli(fd, " Timer T1 : %d\n", peer->timer_t1); 18217 ast_cli(fd, " Timer B : %d\n", peer->timer_b); 18218 ast_cli(fd, " ToHost : %s\n", peer->tohost); 18219 ast_cli(fd, " Addr->IP : %s\n", ast_sockaddr_stringify(&peer->addr)); 18220 ast_cli(fd, " Defaddr->IP : %s\n", ast_sockaddr_stringify(&peer->defaddr)); 18221 ast_cli(fd, " Prim.Transp. : %s\n", sip_get_transport(peer->socket.type)); 18222 ast_cli(fd, " Allowed.Trsp : %s\n", get_transport_list(peer->transports)); 18223 if (!ast_strlen_zero(sip_cfg.regcontext)) 18224 ast_cli(fd, " Reg. exten : %s\n", peer->regexten); 18225 ast_cli(fd, " Def. Username: %s\n", peer->username); 18226 ast_cli(fd, " SIP Options : "); 18227 if (peer->sipoptions) { 18228 int lastoption = -1; 18229 for (x = 0 ; x < ARRAY_LEN(sip_options); x++) { 18230 if (sip_options[x].id != lastoption) { 18231 if (peer->sipoptions & sip_options[x].id) 18232 ast_cli(fd, "%s ", sip_options[x].text); 18233 lastoption = x; 18234 } 18235 } 18236 } else 18237 ast_cli(fd, "(none)"); 18238 18239 ast_cli(fd, "\n"); 18240 ast_cli(fd, " Codecs : "); 18241 ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, peer->caps); 18242 ast_cli(fd, "%s\n", codec_buf); 18243 ast_cli(fd, " Codec Order : ("); 18244 print_codec_to_cli(fd, &peer->prefs); 18245 ast_cli(fd, ")\n"); 18246 18247 ast_cli(fd, " Auto-Framing : %s \n", AST_CLI_YESNO(peer->autoframing)); 18248 ast_cli(fd, " Status : "); 18249 peer_status(peer, status, sizeof(status)); 18250 ast_cli(fd, "%s\n", status); 18251 ast_cli(fd, " Useragent : %s\n", peer->useragent); 18252 ast_cli(fd, " Reg. Contact : %s\n", peer->fullcontact); 18253 ast_cli(fd, " Qualify Freq : %d ms\n", peer->qualifyfreq); 18254 if (peer->chanvars) { 18255 ast_cli(fd, " Variables :\n"); 18256 for (v = peer->chanvars ; v ; v = v->next) 18257 ast_cli(fd, " %s = %s\n", v->name, v->value); 18258 } 18259 18260 ast_cli(fd, " Sess-Timers : %s\n", stmode2str(peer->stimer.st_mode_oper)); 18261 ast_cli(fd, " Sess-Refresh : %s\n", strefresher2str(peer->stimer.st_ref)); 18262 ast_cli(fd, " Sess-Expires : %d secs\n", peer->stimer.st_max_se); 18263 ast_cli(fd, " Min-Sess : %d secs\n", peer->stimer.st_min_se); 18264 ast_cli(fd, " RTP Engine : %s\n", peer->engine); 18265 ast_cli(fd, " Parkinglot : %s\n", peer->parkinglot); 18266 ast_cli(fd, " Use Reason : %s\n", AST_CLI_YESNO(ast_test_flag(&peer->flags[1], SIP_PAGE2_Q850_REASON))); 18267 ast_cli(fd, " Encryption : %s\n", AST_CLI_YESNO(ast_test_flag(&peer->flags[1], SIP_PAGE2_USE_SRTP))); 18268 ast_cli(fd, "\n"); 18269 peer = sip_unref_peer(peer, "sip_show_peer: sip_unref_peer: done with peer ptr"); 18270 } else if (peer && type == 1) { /* manager listing */ 18271 char buffer[256]; 18272 struct ast_str *mailbox_str = ast_str_alloca(512); 18273 astman_append(s, "Channeltype: SIP\r\n"); 18274 astman_append(s, "ObjectName: %s\r\n", peer->name); 18275 astman_append(s, "ChanObjectType: peer\r\n"); 18276 astman_append(s, "SecretExist: %s\r\n", ast_strlen_zero(peer->secret)?"N":"Y"); 18277 astman_append(s, "RemoteSecretExist: %s\r\n", ast_strlen_zero(peer->remotesecret)?"N":"Y"); 18278 astman_append(s, "MD5SecretExist: %s\r\n", ast_strlen_zero(peer->md5secret)?"N":"Y"); 18279 astman_append(s, "Context: %s\r\n", peer->context); 18280 astman_append(s, "Language: %s\r\n", peer->language); 18281 astman_append(s, "ToneZone: %s\r\n", peer->zone[0] != '\0' ? peer->zone : "<Not set>"); 18282 if (!ast_strlen_zero(peer->accountcode)) 18283 astman_append(s, "Accountcode: %s\r\n", peer->accountcode); 18284 astman_append(s, "AMAflags: %s\r\n", ast_cdr_flags2str(peer->amaflags)); 18285 astman_append(s, "CID-CallingPres: %s\r\n", ast_describe_caller_presentation(peer->callingpres)); 18286 if (!ast_strlen_zero(peer->fromuser)) 18287 astman_append(s, "SIP-FromUser: %s\r\n", peer->fromuser); 18288 if (!ast_strlen_zero(peer->fromdomain)) 18289 astman_append(s, "SIP-FromDomain: %s\r\nSip-FromDomain-Port: %d\r\n", peer->fromdomain, (peer->fromdomainport) ? peer->fromdomainport : STANDARD_SIP_PORT); 18290 astman_append(s, "Callgroup: "); 18291 astman_append(s, "%s\r\n", ast_print_group(buffer, sizeof(buffer), peer->callgroup)); 18292 astman_append(s, "Pickupgroup: "); 18293 astman_append(s, "%s\r\n", ast_print_group(buffer, sizeof(buffer), peer->pickupgroup)); 18294 astman_append(s, "MOHSuggest: %s\r\n", peer->mohsuggest); 18295 peer_mailboxes_to_str(&mailbox_str, peer); 18296 astman_append(s, "VoiceMailbox: %s\r\n", mailbox_str->str); 18297 astman_append(s, "TransferMode: %s\r\n", transfermode2str(peer->allowtransfer)); 18298 astman_append(s, "Maxforwards: %d\r\n", peer->maxforwards); 18299 astman_append(s, "Call-limit: %d\r\n", peer->call_limit); 18300 astman_append(s, "Busy-level: %d\r\n", peer->busy_level); 18301 astman_append(s, "MaxCallBR: %d kbps\r\n", peer->maxcallbitrate); 18302 astman_append(s, "Dynamic: %s\r\n", peer->host_dynamic?"Y":"N"); 18303 astman_append(s, "Callerid: %s\r\n", ast_callerid_merge(cbuf, sizeof(cbuf), peer->cid_name, peer->cid_num, "")); 18304 astman_append(s, "RegExpire: %ld seconds\r\n", ast_sched_when(sched, peer->expire)); 18305 astman_append(s, "SIP-AuthInsecure: %s\r\n", insecure2str(ast_test_flag(&peer->flags[0], SIP_INSECURE))); 18306 astman_append(s, "SIP-Forcerport: %s\r\n", ast_test_flag(&peer->flags[2], SIP_PAGE3_NAT_AUTO_RPORT) ? 18307 (ast_test_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT) ? "A" : "a") : 18308 (ast_test_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT) ? "Y" : "N")); 18309 astman_append(s, "SIP-Comedia: %s\r\n", ast_test_flag(&peer->flags[2], SIP_PAGE3_NAT_AUTO_COMEDIA) ? 18310 (ast_test_flag(&peer->flags[1], SIP_PAGE2_SYMMETRICRTP) ? "A" : "a") : 18311 (ast_test_flag(&peer->flags[1], SIP_PAGE2_SYMMETRICRTP) ? "Y" : "N")); 18312 astman_append(s, "ACL: %s\r\n", (peer->ha?"Y":"N")); 18313 astman_append(s, "SIP-CanReinvite: %s\r\n", (ast_test_flag(&peer->flags[0], SIP_DIRECT_MEDIA)?"Y":"N")); 18314 astman_append(s, "SIP-DirectMedia: %s\r\n", (ast_test_flag(&peer->flags[0], SIP_DIRECT_MEDIA)?"Y":"N")); 18315 astman_append(s, "SIP-PromiscRedir: %s\r\n", (ast_test_flag(&peer->flags[0], SIP_PROMISCREDIR)?"Y":"N")); 18316 astman_append(s, "SIP-UserPhone: %s\r\n", (ast_test_flag(&peer->flags[0], SIP_USEREQPHONE)?"Y":"N")); 18317 astman_append(s, "SIP-VideoSupport: %s\r\n", (ast_test_flag(&peer->flags[1], SIP_PAGE2_VIDEOSUPPORT)?"Y":"N")); 18318 astman_append(s, "SIP-TextSupport: %s\r\n", (ast_test_flag(&peer->flags[1], SIP_PAGE2_TEXTSUPPORT)?"Y":"N")); 18319 astman_append(s, "SIP-T.38Support: %s\r\n", (ast_test_flag(&peer->flags[1], SIP_PAGE2_T38SUPPORT)?"Y":"N")); 18320 astman_append(s, "SIP-T.38EC: %s\r\n", faxec2str(ast_test_flag(&peer->flags[1], SIP_PAGE2_T38SUPPORT))); 18321 astman_append(s, "SIP-T.38MaxDtgrm: %d\r\n", peer->t38_maxdatagram); 18322 astman_append(s, "SIP-Sess-Timers: %s\r\n", stmode2str(peer->stimer.st_mode_oper)); 18323 astman_append(s, "SIP-Sess-Refresh: %s\r\n", strefresher2str(peer->stimer.st_ref)); 18324 astman_append(s, "SIP-Sess-Expires: %d\r\n", peer->stimer.st_max_se); 18325 astman_append(s, "SIP-Sess-Min: %d\r\n", peer->stimer.st_min_se); 18326 astman_append(s, "SIP-RTP-Engine: %s\r\n", peer->engine); 18327 astman_append(s, "SIP-Encryption: %s\r\n", ast_test_flag(&peer->flags[1], SIP_PAGE2_USE_SRTP) ? "Y" : "N"); 18328 18329 /* - is enumerated */ 18330 astman_append(s, "SIP-DTMFmode: %s\r\n", dtmfmode2str(ast_test_flag(&peer->flags[0], SIP_DTMF))); 18331 astman_append(s, "ToHost: %s\r\n", peer->tohost); 18332 astman_append(s, "Address-IP: %s\r\nAddress-Port: %d\r\n", ast_sockaddr_stringify_addr(&peer->addr), ast_sockaddr_port(&peer->addr)); 18333 astman_append(s, "Default-addr-IP: %s\r\nDefault-addr-port: %d\r\n", ast_sockaddr_stringify_addr(&peer->defaddr), ast_sockaddr_port(&peer->defaddr)); 18334 astman_append(s, "Default-Username: %s\r\n", peer->username); 18335 if (!ast_strlen_zero(sip_cfg.regcontext)) 18336 astman_append(s, "RegExtension: %s\r\n", peer->regexten); 18337 astman_append(s, "Codecs: "); 18338 ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, peer->caps); 18339 astman_append(s, "%s\r\n", codec_buf); 18340 astman_append(s, "CodecOrder: "); 18341 pref = &peer->prefs; 18342 for(x = 0; x < AST_CODEC_PREF_SIZE ; x++) { 18343 if (!(ast_codec_pref_index(pref, x, &codec))) { 18344 break; 18345 } 18346 astman_append(s, "%s", ast_getformatname(&codec)); 18347 if ((x < (AST_CODEC_PREF_SIZE - 1)) && ast_codec_pref_index(pref, x+1, &codec)) 18348 astman_append(s, ","); 18349 } 18350 18351 astman_append(s, "\r\n"); 18352 astman_append(s, "Status: "); 18353 peer_status(peer, status, sizeof(status)); 18354 astman_append(s, "%s\r\n", status); 18355 astman_append(s, "SIP-Useragent: %s\r\n", peer->useragent); 18356 astman_append(s, "Reg-Contact: %s\r\n", peer->fullcontact); 18357 astman_append(s, "QualifyFreq: %d ms\r\n", peer->qualifyfreq); 18358 astman_append(s, "Parkinglot: %s\r\n", peer->parkinglot); 18359 if (peer->chanvars) { 18360 for (v = peer->chanvars ; v ; v = v->next) { 18361 astman_append(s, "ChanVariable: %s=%s\r\n", v->name, v->value); 18362 } 18363 } 18364 astman_append(s, "SIP-Use-Reason-Header: %s\r\n", (ast_test_flag(&peer->flags[1], SIP_PAGE2_Q850_REASON)) ? "Y" : "N"); 18365 astman_append(s, "Description: %s\r\n", peer->description); 18366 18367 peer = sip_unref_peer(peer, "sip_show_peer: sip_unref_peer: done with peer"); 18368 18369 } else { 18370 ast_cli(fd, "Peer %s not found.\n", argv[3]); 18371 ast_cli(fd, "\n"); 18372 } 18373 18374 return CLI_SUCCESS; 18375 }
| static char * _sip_show_peers | ( | int | fd, | |
| int * | total, | |||
| struct mansession * | s, | |||
| const struct message * | m, | |||
| int | argc, | |||
| const char * | argv[] | |||
| ) | [static] |
Execute sip show peers command.
Definition at line 17355 of file chan_sip.c.
References ao2_container_count(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_lock, ao2_t_iterator_next, ao2_unlock, ast_calloc, ast_check_realtime(), ast_cli(), ast_copy_string(), ast_free, ast_sockaddr_isnull(), ast_sockaddr_port, ast_sockaddr_stringify_addr(), ast_sockaddr_stringify_port(), ast_strdupa, ast_strlen_zero(), ast_test_flag, astman_append(), astman_get_header(), CLI_SHOWUSAGE, CLI_SUCCESS, FALSE, FORMAT2, id, name, peer_status(), peercomparefunc(), sip_unref_peer(), status, and TRUE.
Referenced by manager_sip_show_peers(), and sip_show_peers().
17356 { 17357 regex_t regexbuf; 17358 int havepattern = FALSE; 17359 struct sip_peer *peer; 17360 struct ao2_iterator i; 17361 17362 /* the last argument is left-aligned, so we don't need a size anyways */ 17363 #define FORMAT2 "%-25.25s %-39.39s %-3.3s %-10.10s %-3.3s %-8s %-11s %-32.32s %s\n" 17364 17365 char name[256]; 17366 int total_peers = 0; 17367 int peers_mon_online = 0; 17368 int peers_mon_offline = 0; 17369 int peers_unmon_offline = 0; 17370 int peers_unmon_online = 0; 17371 const char *id; 17372 char idtext[256] = ""; 17373 int realtimepeers; 17374 int objcount = ao2_container_count(peers); 17375 struct sip_peer **peerarray; 17376 int k; 17377 17378 realtimepeers = ast_check_realtime("sippeers"); 17379 peerarray = ast_calloc(sizeof(struct sip_peer *), objcount); 17380 17381 if (s) { /* Manager - get ActionID */ 17382 id = astman_get_header(m, "ActionID"); 17383 if (!ast_strlen_zero(id)) 17384 snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id); 17385 } 17386 17387 switch (argc) { 17388 case 5: 17389 if (!strcasecmp(argv[3], "like")) { 17390 if (regcomp(®exbuf, argv[4], REG_EXTENDED | REG_NOSUB)) 17391 return CLI_SHOWUSAGE; 17392 havepattern = TRUE; 17393 } else 17394 return CLI_SHOWUSAGE; 17395 case 3: 17396 break; 17397 default: 17398 return CLI_SHOWUSAGE; 17399 } 17400 17401 if (!s) /* Normal list */ 17402 ast_cli(fd, FORMAT2, "Name/username", "Host", "Dyn", "Forcerport", "ACL", "Port", "Status", "Description", (realtimepeers ? "Realtime" : "")); 17403 17404 i = ao2_iterator_init(peers, 0); 17405 while ((peer = ao2_t_iterator_next(&i, "iterate thru peers table"))) { 17406 ao2_lock(peer); 17407 17408 if (!(peer->type & SIP_TYPE_PEER)) { 17409 ao2_unlock(peer); 17410 sip_unref_peer(peer, "unref peer because it's actually a user"); 17411 continue; 17412 } 17413 17414 if (havepattern && regexec(®exbuf, peer->name, 0, NULL, 0)) { 17415 objcount--; 17416 ao2_unlock(peer); 17417 sip_unref_peer(peer, "toss iterator peer ptr before continue"); 17418 continue; 17419 } 17420 17421 peerarray[total_peers++] = peer; 17422 ao2_unlock(peer); 17423 } 17424 ao2_iterator_destroy(&i); 17425 17426 qsort(peerarray, total_peers, sizeof(struct sip_peer *), peercomparefunc); 17427 17428 for(k=0; k < total_peers; k++) { 17429 char status[20] = ""; 17430 char srch[2000]; 17431 char pstatus; 17432 17433 /* 17434 * tmp_port and tmp_host store copies of ast_sockaddr_stringify strings since the 17435 * string pointers for that function aren't valid between subsequent calls to 17436 * ast_sockaddr_stringify functions 17437 */ 17438 char *tmp_port; 17439 char *tmp_host; 17440 17441 peer = peerarray[k]; 17442 17443 tmp_port = ast_sockaddr_isnull(&peer->addr) ? 17444 "0" : ast_strdupa(ast_sockaddr_stringify_port(&peer->addr)); 17445 17446 tmp_host = ast_sockaddr_isnull(&peer->addr) ? 17447 "(Unspecified)" : ast_strdupa(ast_sockaddr_stringify_addr(&peer->addr)); 17448 17449 ao2_lock(peer); 17450 if (havepattern && regexec(®exbuf, peer->name, 0, NULL, 0)) { 17451 ao2_unlock(peer); 17452 peer = peerarray[k] = sip_unref_peer(peer, "toss iterator peer ptr before continue"); 17453 continue; 17454 } 17455 17456 if (!ast_strlen_zero(peer->username) && !s) 17457 snprintf(name, sizeof(name), "%s/%s", peer->name, peer->username); 17458 else 17459 ast_copy_string(name, peer->name, sizeof(name)); 17460 17461 pstatus = peer_status(peer, status, sizeof(status)); 17462 if (pstatus == 1) 17463 peers_mon_online++; 17464 else if (pstatus == 0) 17465 peers_mon_offline++; 17466 else { 17467 if (ast_sockaddr_isnull(&peer->addr) || 17468 !ast_sockaddr_port(&peer->addr)) { 17469 peers_unmon_offline++; 17470 } else { 17471 peers_unmon_online++; 17472 } 17473 } 17474 17475 snprintf(srch, sizeof(srch), FORMAT2, name, 17476 tmp_host, 17477 peer->host_dynamic ? " D " : " ", /* Dynamic or not? */ 17478 ast_test_flag(&peer->flags[2], SIP_PAGE3_NAT_AUTO_RPORT) ? 17479 ast_test_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT) ? " A " : " a " : 17480 ast_test_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT) ? " N " : " ", /* NAT=yes? */ 17481 peer->ha ? " A " : " ", /* permit/deny */ 17482 tmp_port, status, 17483 peer->description ? peer->description : "", 17484 realtimepeers ? (peer->is_realtime ? "Cached RT":"") : ""); 17485 17486 if (!s) {/* Normal CLI list */ 17487 ast_cli(fd, FORMAT2, name, 17488 tmp_host, 17489 peer->host_dynamic ? " D " : " ", /* Dynamic or not? */ 17490 ast_test_flag(&peer->flags[2], SIP_PAGE3_NAT_AUTO_RPORT) ? 17491 ast_test_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT) ? " A " : " a " : 17492 ast_test_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT) ? " N " : " ", /* NAT=yes? */ 17493 peer->ha ? " A " : " ", /* permit/deny */ 17494 tmp_port, status, 17495 peer->description ? peer->description : "", 17496 realtimepeers ? (peer->is_realtime ? "Cached RT":"") : ""); 17497 } else { /* Manager format */ 17498 /* The names here need to be the same as other channels */ 17499 astman_append(s, 17500 "Event: PeerEntry\r\n%s" 17501 "Channeltype: SIP\r\n" 17502 "ObjectName: %s\r\n" 17503 "ChanObjectType: peer\r\n" /* "peer" or "user" */ 17504 "IPaddress: %s\r\n" 17505 "IPport: %s\r\n" 17506 "Dynamic: %s\r\n" 17507 "AutoForcerport: %s\r\n" 17508 "Forcerport: %s\r\n" 17509 "AutoComedia: %s\r\n" 17510 "Comedia: %s\r\n" 17511 "VideoSupport: %s\r\n" 17512 "TextSupport: %s\r\n" 17513 "ACL: %s\r\n" 17514 "Status: %s\r\n" 17515 "RealtimeDevice: %s\r\n" 17516 "Description: %s\r\n\r\n", 17517 idtext, 17518 peer->name, 17519 ast_sockaddr_isnull(&peer->addr) ? "-none-" : tmp_host, 17520 ast_sockaddr_isnull(&peer->addr) ? "0" : tmp_port, 17521 peer->host_dynamic ? "yes" : "no", /* Dynamic or not? */ 17522 ast_test_flag(&peer->flags[2], SIP_PAGE3_NAT_AUTO_RPORT) ? "yes" : "no", 17523 ast_test_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT) ? "yes" : "no", /* NAT=yes? */ 17524 ast_test_flag(&peer->flags[2], SIP_PAGE3_NAT_AUTO_COMEDIA) ? "yes" : "no", 17525 ast_test_flag(&peer->flags[1], SIP_PAGE2_SYMMETRICRTP) ? "yes" : "no", 17526 ast_test_flag(&peer->flags[1], SIP_PAGE2_VIDEOSUPPORT) ? "yes" : "no", /* VIDEOSUPPORT=yes? */ 17527 ast_test_flag(&peer->flags[1], SIP_PAGE2_TEXTSUPPORT) ? "yes" : "no", /* TEXTSUPPORT=yes? */ 17528 peer->ha ? "yes" : "no", /* permit/deny */ 17529 status, 17530 realtimepeers ? (peer->is_realtime ? "yes":"no") : "no", 17531 peer->description); 17532 } 17533 ao2_unlock(peer); 17534 peer = peerarray[k] = sip_unref_peer(peer, "toss iterator peer ptr"); 17535 } 17536 17537 if (!s) 17538 ast_cli(fd, "%d sip peers [Monitored: %d online, %d offline Unmonitored: %d online, %d offline]\n", 17539 total_peers, peers_mon_online, peers_mon_offline, peers_unmon_online, peers_unmon_offline); 17540 17541 if (havepattern) 17542 regfree(®exbuf); 17543 17544 if (total) 17545 *total = total_peers; 17546 17547 ast_free(peerarray); 17548 17549 return CLI_SUCCESS; 17550 #undef FORMAT2 17551 }
| static void * _sip_tcp_helper_thread | ( | struct sip_pvt * | pvt, | |
| struct ast_tcptls_session_instance * | tcptls_session | |||
| ) | [static] |
SIP TCP thread management function This function reads from the socket, parses the packet into a request.
Definition at line 2522 of file chan_sip.c.
References ao2_lock, ao2_ref, ao2_t_find, ao2_t_ref, ao2_t_unlink, ao2_unlock, ast_atomic_fetchadd_int(), ast_debug, AST_LIST_REMOVE_HEAD, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_poll, ast_str_append(), ast_str_buffer(), ast_str_create(), ast_str_reset(), ast_str_strlen(), ast_tcptls_client_start(), ast_tcptls_close_session_file(), ast_tcptls_server_write(), ast_wait_for_input(), cleanup(), ast_tcptls_session_instance::client, copy_request(), deinit_req(), errno, ast_tcptls_session_instance::f, ast_tcptls_session_instance::fd, handle_request_do(), ast_tcptls_session_instance::lock, LOG_ERROR, LOG_WARNING, MIN, OBJ_POINTER, ast_tcptls_session_instance::parent, parse_request(), ast_tcptls_session_instance::remote_address, set_socket_transport(), sip_check_authtimeout(), sip_get_header(), sip_threadinfo_create(), and ast_tcptls_session_instance::ssl.
Referenced by sip_tcp_worker_fn().
02523 { 02524 int res, cl, timeout = -1, authenticated = 0, flags, after_poll = 0, need_poll = 1; 02525 time_t start; 02526 struct sip_request req = { 0, } , reqcpy = { 0, }; 02527 struct sip_threadinfo *me = NULL; 02528 char buf[1024] = ""; 02529 struct pollfd fds[2] = { { 0 }, { 0 }, }; 02530 struct ast_tcptls_session_args *ca = NULL; 02531 02532 /* If this is a server session, then the connection has already been 02533 * setup. Check if the authlimit has been reached and if not create the 02534 * threadinfo object so we can access this thread for writing. 02535 * 02536 * if this is a client connection more work must be done. 02537 * 1. We own the parent session args for a client connection. This pointer needs 02538 * to be held on to so we can decrement it's ref count on thread destruction. 02539 * 2. The threadinfo object was created before this thread was launched, however 02540 * it must be found within the threadt table. 02541 * 3. Last, the tcptls_session must be started. 02542 */ 02543 if (!tcptls_session->client) { 02544 if (ast_atomic_fetchadd_int(&unauth_sessions, +1) >= authlimit) { 02545 /* unauth_sessions is decremented in the cleanup code */ 02546 goto cleanup; 02547 } 02548 02549 if ((flags = fcntl(tcptls_session->fd, F_GETFL)) == -1) { 02550 ast_log(LOG_ERROR, "error setting socket to non blocking mode, fcntl() failed: %s\n", strerror(errno)); 02551 goto cleanup; 02552 } 02553 02554 flags |= O_NONBLOCK; 02555 if (fcntl(tcptls_session->fd, F_SETFL, flags) == -1) { 02556 ast_log(LOG_ERROR, "error setting socket to non blocking mode, fcntl() failed: %s\n", strerror(errno)); 02557 goto cleanup; 02558 } 02559 02560 if (!(me = sip_threadinfo_create(tcptls_session, tcptls_session->ssl ? SIP_TRANSPORT_TLS : SIP_TRANSPORT_TCP))) { 02561 goto cleanup; 02562 } 02563 ao2_t_ref(me, +1, "Adding threadinfo ref for tcp_helper_thread"); 02564 } else { 02565 struct sip_threadinfo tmp = { 02566 .tcptls_session = tcptls_session, 02567 }; 02568 02569 if ((!(ca = tcptls_session->parent)) || 02570 (!(me = ao2_t_find(threadt, &tmp, OBJ_POINTER, "ao2_find, getting sip_threadinfo in tcp helper thread"))) || 02571 (!(tcptls_session = ast_tcptls_client_start(tcptls_session)))) { 02572 goto cleanup; 02573 } 02574 } 02575 02576 flags = 1; 02577 if (setsockopt(tcptls_session->fd, SOL_SOCKET, SO_KEEPALIVE, &flags, sizeof(flags))) { 02578 ast_log(LOG_ERROR, "error enabling TCP keep-alives on sip socket: %s\n", strerror(errno)); 02579 goto cleanup; 02580 } 02581 02582 me->threadid = pthread_self(); 02583 ast_debug(2, "Starting thread for %s server\n", tcptls_session->ssl ? "SSL" : "TCP"); 02584 02585 /* set up pollfd to watch for reads on both the socket and the alert_pipe */ 02586 fds[0].fd = tcptls_session->fd; 02587 fds[1].fd = me->alert_pipe[0]; 02588 fds[0].events = fds[1].events = POLLIN | POLLPRI; 02589 02590 if (!(req.data = ast_str_create(SIP_MIN_PACKET))) { 02591 goto cleanup; 02592 } 02593 if (!(reqcpy.data = ast_str_create(SIP_MIN_PACKET))) { 02594 goto cleanup; 02595 } 02596 02597 if(time(&start) == -1) { 02598 ast_log(LOG_ERROR, "error executing time(): %s\n", strerror(errno)); 02599 goto cleanup; 02600 } 02601 02602 for (;;) { 02603 struct ast_str *str_save; 02604 02605 if (!tcptls_session->client && req.authenticated && !authenticated) { 02606 authenticated = 1; 02607 ast_atomic_fetchadd_int(&unauth_sessions, -1); 02608 } 02609 02610 /* calculate the timeout for unauthenticated server sessions */ 02611 if (!tcptls_session->client && !authenticated ) { 02612 if ((timeout = sip_check_authtimeout(start)) < 0) { 02613 goto cleanup; 02614 } 02615 02616 if (timeout == 0) { 02617 ast_debug(2, "SIP %s server timed out\n", tcptls_session->ssl ? "SSL": "TCP"); 02618 goto cleanup; 02619 } 02620 } else { 02621 timeout = -1; 02622 } 02623 02624 res = ast_poll(fds, 2, timeout); /* polls for both socket and alert_pipe */ 02625 if (res < 0) { 02626 ast_debug(2, "SIP %s server :: ast_wait_for_input returned %d\n", tcptls_session->ssl ? "SSL": "TCP", res); 02627 goto cleanup; 02628 } else if (res == 0) { 02629 /* timeout */ 02630 ast_debug(2, "SIP %s server timed out\n", tcptls_session->ssl ? "SSL": "TCP"); 02631 goto cleanup; 02632 } 02633 02634 /* handle the socket event, check for both reads from the socket fd, 02635 * and writes from alert_pipe fd */ 02636 if (fds[0].revents) { /* there is data on the socket to be read */ 02637 after_poll = 1; 02638 02639 fds[0].revents = 0; 02640 02641 /* clear request structure */ 02642 str_save = req.data; 02643 memset(&req, 0, sizeof(req)); 02644 req.data = str_save; 02645 ast_str_reset(req.data); 02646 02647 str_save = reqcpy.data; 02648 memset(&reqcpy, 0, sizeof(reqcpy)); 02649 reqcpy.data = str_save; 02650 ast_str_reset(reqcpy.data); 02651 02652 memset(buf, 0, sizeof(buf)); 02653 02654 if (tcptls_session->ssl) { 02655 set_socket_transport(&req.socket, SIP_TRANSPORT_TLS); 02656 req.socket.port = htons(ourport_tls); 02657 } else { 02658 set_socket_transport(&req.socket, SIP_TRANSPORT_TCP); 02659 req.socket.port = htons(ourport_tcp); 02660 } 02661 req.socket.fd = tcptls_session->fd; 02662 02663 /* Read in headers one line at a time */ 02664 while (ast_str_strlen(req.data) < 4 || strncmp(REQ_OFFSET_TO_STR(&req, data->used - 4), "\r\n\r\n", 4)) { 02665 if (!tcptls_session->client && !authenticated ) { 02666 if ((timeout = sip_check_authtimeout(start)) < 0) { 02667 goto cleanup; 02668 } 02669 02670 if (timeout == 0) { 02671 ast_debug(2, "SIP %s server timed out\n", tcptls_session->ssl ? "SSL": "TCP"); 02672 goto cleanup; 02673 } 02674 } else { 02675 timeout = -1; 02676 } 02677 02678 /* special polling behavior is required for TLS 02679 * sockets because of the buffering done in the 02680 * TLS layer */ 02681 if (!tcptls_session->ssl || need_poll) { 02682 need_poll = 0; 02683 after_poll = 1; 02684 res = ast_wait_for_input(tcptls_session->fd, timeout); 02685 if (res < 0) { 02686 ast_debug(2, "SIP TCP server :: ast_wait_for_input returned %d\n", res); 02687 goto cleanup; 02688 } else if (res == 0) { 02689 /* timeout */ 02690 ast_debug(2, "SIP TCP server timed out\n"); 02691 goto cleanup; 02692 } 02693 } 02694 02695 ast_mutex_lock(&tcptls_session->lock); 02696 if (!fgets(buf, sizeof(buf), tcptls_session->f)) { 02697 ast_mutex_unlock(&tcptls_session->lock); 02698 if (after_poll) { 02699 goto cleanup; 02700 } else { 02701 need_poll = 1; 02702 continue; 02703 } 02704 } 02705 ast_mutex_unlock(&tcptls_session->lock); 02706 after_poll = 0; 02707 if (me->stop) { 02708 goto cleanup; 02709 } 02710 ast_str_append(&req.data, 0, "%s", buf); 02711 } 02712 copy_request(&reqcpy, &req); 02713 parse_request(&reqcpy); 02714 /* In order to know how much to read, we need the content-length header */ 02715 if (sscanf(sip_get_header(&reqcpy, "Content-Length"), "%30d", &cl)) { 02716 while (cl > 0) { 02717 size_t bytes_read; 02718 if (!tcptls_session->client && !authenticated ) { 02719 if ((timeout = sip_check_authtimeout(start)) < 0) { 02720 goto cleanup; 02721 } 02722 02723 if (timeout == 0) { 02724 ast_debug(2, "SIP %s server timed out\n", tcptls_session->ssl ? "SSL": "TCP"); 02725 goto cleanup; 02726 } 02727 } else { 02728 timeout = -1; 02729 } 02730 02731 if (!tcptls_session->ssl || need_poll) { 02732 need_poll = 0; 02733 after_poll = 1; 02734 res = ast_wait_for_input(tcptls_session->fd, timeout); 02735 if (res < 0) { 02736 ast_debug(2, "SIP TCP server :: ast_wait_for_input returned %d\n", res); 02737 goto cleanup; 02738 } else if (res == 0) { 02739 /* timeout */ 02740 ast_debug(2, "SIP TCP server timed out\n"); 02741 goto cleanup; 02742 } 02743 } 02744 02745 ast_mutex_lock(&tcptls_session->lock); 02746 if (!(bytes_read = fread(buf, 1, MIN(sizeof(buf) - 1, cl), tcptls_session->f))) { 02747 ast_mutex_unlock(&tcptls_session->lock); 02748 if (after_poll) { 02749 goto cleanup; 02750 } else { 02751 need_poll = 1; 02752 continue; 02753 } 02754 } 02755 buf[bytes_read] = '\0'; 02756 ast_mutex_unlock(&tcptls_session->lock); 02757 after_poll = 0; 02758 if (me->stop) { 02759 goto cleanup; 02760 } 02761 cl -= strlen(buf); 02762 ast_str_append(&req.data, 0, "%s", buf); 02763 } 02764 } 02765 /*! \todo XXX If there's no Content-Length or if the content-length and what 02766 we receive is not the same - we should generate an error */ 02767 02768 req.socket.tcptls_session = tcptls_session; 02769 handle_request_do(&req, &tcptls_session->remote_address); 02770 } 02771 02772 if (fds[1].revents) { /* alert_pipe indicates there is data in the send queue to be sent */ 02773 enum sip_tcptls_alert alert; 02774 struct tcptls_packet *packet; 02775 02776 fds[1].revents = 0; 02777 02778 if (read(me->alert_pipe[0], &alert, sizeof(alert)) == -1) { 02779 ast_log(LOG_ERROR, "read() failed: %s\n", strerror(errno)); 02780 continue; 02781 } 02782 02783 switch (alert) { 02784 case TCPTLS_ALERT_STOP: 02785 goto cleanup; 02786 case TCPTLS_ALERT_DATA: 02787 ao2_lock(me); 02788 if (!(packet = AST_LIST_REMOVE_HEAD(&me->packet_q, entry))) { 02789 ast_log(LOG_WARNING, "TCPTLS thread alert_pipe indicated packet should be sent, but frame_q is empty"); 02790 } 02791 ao2_unlock(me); 02792 02793 if (packet) { 02794 if (ast_tcptls_server_write(tcptls_session, ast_str_buffer(packet->data), packet->len) == -1) { 02795 ast_log(LOG_WARNING, "Failure to write to tcp/tls socket\n"); 02796 } 02797 ao2_t_ref(packet, -1, "tcptls packet sent, this is no longer needed"); 02798 } 02799 break; 02800 default: 02801 ast_log(LOG_ERROR, "Unknown tcptls thread alert '%d'\n", alert); 02802 } 02803 } 02804 } 02805 02806 ast_debug(2, "Shutting down thread for %s server\n", tcptls_session->ssl ? "SSL" : "TCP"); 02807 02808 cleanup: 02809 if (tcptls_session && !tcptls_session->client && !authenticated) { 02810 ast_atomic_fetchadd_int(&unauth_sessions, -1); 02811 } 02812 02813 if (me) { 02814 ao2_t_unlink(threadt, me, "Removing tcptls helper thread, thread is closing"); 02815 ao2_t_ref(me, -1, "Removing tcp_helper_threads threadinfo ref"); 02816 } 02817 deinit_req(&reqcpy); 02818 deinit_req(&req); 02819 02820 /* if client, we own the parent session arguments and must decrement ref */ 02821 if (ca) { 02822 ao2_t_ref(ca, -1, "closing tcptls thread, getting rid of client tcptls_session arguments"); 02823 } 02824 02825 if (tcptls_session) { 02826 ast_mutex_lock(&tcptls_session->lock); 02827 ast_tcptls_close_session_file(tcptls_session); 02828 tcptls_session->parent = NULL; 02829 ast_mutex_unlock(&tcptls_session->lock); 02830 02831 ao2_ref(tcptls_session, -1); 02832 tcptls_session = NULL; 02833 } 02834 return NULL; 02835 }
| static void add_blank | ( | struct sip_request * | req | ) | [static] |
add a blank line if no body
Definition at line 4108 of file chan_sip.c.
References ast_str_append().
Referenced by send_request(), and send_response().
04109 { 04110 if (!req->lines) { 04111 /* Add extra empty return. add_header() reserves 4 bytes so cannot be truncated */ 04112 ast_str_append(&req->data, 0, "\r\n"); 04113 } 04114 }
| static void add_cc_call_info_to_response | ( | struct sip_pvt * | p, | |
| struct sip_request * | resp | |||
| ) | [static] |
Definition at line 12125 of file chan_sip.c.
References add_header(), ao2_ref, ast_copy_string(), ast_log(), ast_str_alloca, ast_str_buffer(), ast_str_set(), ast_strlen_zero(), find_sip_cc_agent_by_original_callid(), generate_uri(), LOG_WARNING, and ast_cc_agent::private_data.
Referenced by __transmit_response(), and transmit_response_with_sdp().
12126 { 12127 char uri[SIPBUFSIZE]; 12128 struct ast_str *header = ast_str_alloca(SIPBUFSIZE); 12129 struct ast_cc_agent *agent = find_sip_cc_agent_by_original_callid(p); 12130 struct sip_cc_agent_pvt *agent_pvt; 12131 12132 if (!agent) { 12133 /* Um, what? How could the SIP_OFFER_CC flag be set but there not be an 12134 * agent? Oh well, we'll just warn and return without adding the header. 12135 */ 12136 ast_log(LOG_WARNING, "Can't find SIP CC agent for call '%s' even though OFFER_CC flag was set?\n", p->callid); 12137 return; 12138 } 12139 12140 agent_pvt = agent->private_data; 12141 12142 if (!ast_strlen_zero(agent_pvt->subscribe_uri)) { 12143 ast_copy_string(uri, agent_pvt->subscribe_uri, sizeof(uri)); 12144 } else { 12145 generate_uri(p, uri, sizeof(uri)); 12146 ast_copy_string(agent_pvt->subscribe_uri, uri, sizeof(agent_pvt->subscribe_uri)); 12147 } 12148 /* XXX Hardcode "NR" as the m reason for now. This should perhaps be changed 12149 * to be more accurate. This parameter has no bearing on the actual operation 12150 * of the feature; it's just there for informational purposes. 12151 */ 12152 ast_str_set(&header, 0, "<%s>;purpose=call-completion;m=%s", uri, "NR"); 12153 add_header(resp, "Call-Info", ast_str_buffer(header)); 12154 ao2_ref(agent, -1); 12155 }
| static void add_codec_to_sdp | ( | const struct sip_pvt * | p, | |
| struct ast_format * | codec, | |||
| struct ast_str ** | m_buf, | |||
| struct ast_str ** | a_buf, | |||
| int | debug, | |||
| int * | min_packet_size | |||
| ) | [static] |
Add codec offer to SDP offer/answer body in INVITE or 200 OK.
Definition at line 11313 of file chan_sip.c.
References ast_codec_pref_getsize(), AST_FORMAT_CELT, AST_FORMAT_G719, AST_FORMAT_G723_1, AST_FORMAT_G729A, ast_format_get_value(), AST_FORMAT_ILBC, AST_FORMAT_SILK, AST_FORMAT_SIREN14, AST_FORMAT_SIREN7, ast_getformatname(), ast_rtp_codecs_payload_code(), ast_rtp_instance_get_codecs(), ast_rtp_lookup_mime_subtype2(), ast_rtp_lookup_sample_rate2(), AST_RTP_OPT_G726_NONSTANDARD, ast_str_append(), ast_test_flag, ast_verbose, CELT_ATTR_KEY_FRAME_SIZE, ast_format_list::cur_ms, ast_format::id, ast_rtp_codecs::pref, SILK_ATTR_KEY_DTX, SILK_ATTR_KEY_FEC, and SILK_ATTR_KEY_MAX_BITRATE.
Referenced by add_sdp().
11319 { 11320 int rtp_code; 11321 struct ast_format_list fmt; 11322 int val = 0; 11323 11324 if (debug) 11325 ast_verbose("Adding codec %d (%s) to SDP\n", format->id, ast_getformatname(format)); 11326 if ((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->rtp), 1, format, 0)) == -1) 11327 return; 11328 11329 if (p->rtp) { 11330 struct ast_codec_pref *pref = &ast_rtp_instance_get_codecs(p->rtp)->pref; 11331 fmt = ast_codec_pref_getsize(pref, format); 11332 } else /* I don't see how you couldn't have p->rtp, but good to check for and error out if not there like earlier code */ 11333 return; 11334 ast_str_append(m_buf, 0, " %d", rtp_code); 11335 ast_str_append(a_buf, 0, "a=rtpmap:%d %s/%d\r\n", 11336 rtp_code, 11337 ast_rtp_lookup_mime_subtype2(1, format, 0, ast_test_flag(&p->flags[0], SIP_G726_NONSTANDARD) ? AST_RTP_OPT_G726_NONSTANDARD : 0), 11338 ast_rtp_lookup_sample_rate2(1, format, 0)); 11339 11340 switch ((int) format->id) { 11341 case AST_FORMAT_G729A: 11342 /* Indicate that we don't support VAD (G.729 annex B) */ 11343 ast_str_append(a_buf, 0, "a=fmtp:%d annexb=no\r\n", rtp_code); 11344 break; 11345 case AST_FORMAT_G723_1: 11346 /* Indicate that we don't support VAD (G.723.1 annex A) */ 11347 ast_str_append(a_buf, 0, "a=fmtp:%d annexa=no\r\n", rtp_code); 11348 break; 11349 case AST_FORMAT_ILBC: 11350 /* Add information about us using only 20/30 ms packetization */ 11351 ast_str_append(a_buf, 0, "a=fmtp:%d mode=%d\r\n", rtp_code, fmt.cur_ms); 11352 break; 11353 case AST_FORMAT_SIREN7: 11354 /* Indicate that we only expect 32Kbps */ 11355 ast_str_append(a_buf, 0, "a=fmtp:%d bitrate=32000\r\n", rtp_code); 11356 break; 11357 case AST_FORMAT_SIREN14: 11358 /* Indicate that we only expect 48Kbps */ 11359 ast_str_append(a_buf, 0, "a=fmtp:%d bitrate=48000\r\n", rtp_code); 11360 break; 11361 case AST_FORMAT_G719: 11362 /* Indicate that we only expect 64Kbps */ 11363 ast_str_append(a_buf, 0, "a=fmtp:%d bitrate=64000\r\n", rtp_code); 11364 break; 11365 case AST_FORMAT_CELT: 11366 if (!ast_format_get_value(format, CELT_ATTR_KEY_FRAME_SIZE, &val) && val > 0) { 11367 ast_str_append(a_buf, 0, "a=fmtp:%d framesize=%u\r\n", rtp_code, val); 11368 } 11369 break; 11370 case AST_FORMAT_SILK: 11371 if (!ast_format_get_value(format, SILK_ATTR_KEY_MAX_BITRATE, &val) && val > 5000 && val < 40000) { 11372 ast_str_append(a_buf, 0, "a=fmtp:%d maxaveragebitrate=%u\r\n", rtp_code, val); 11373 } 11374 if (!ast_format_get_value(format, SILK_ATTR_KEY_DTX, &val)) { 11375 ast_str_append(a_buf, 0, "a=fmtp:%d usedtx=%u\r\n", rtp_code, val ? 1 : 0); 11376 } 11377 if (!ast_format_get_value(format, SILK_ATTR_KEY_FEC, &val)) { 11378 ast_str_append(a_buf, 0, "a=fmtp:%d useinbandfec=%u\r\n", rtp_code, val ? 1 : 0); 11379 } 11380 break; 11381 } 11382 11383 if (fmt.cur_ms && (fmt.cur_ms < *min_packet_size)) 11384 *min_packet_size = fmt.cur_ms; 11385 11386 /* Our first codec packetization processed cannot be zero */ 11387 if ((*min_packet_size)==0 && fmt.cur_ms) 11388 *min_packet_size = fmt.cur_ms; 11389 }
| static int add_content | ( | struct sip_request * | req, | |
| const char * | line | |||
| ) | [static] |
Add content (not header) to SIP message.
Definition at line 10185 of file chan_sip.c.
References ast_log(), ast_str_append(), and LOG_WARNING.
Referenced by add_digit(), add_sdp(), add_text(), add_vidupdate(), transmit_cc_notify(), transmit_invite(), transmit_notify_with_mwi(), transmit_notify_with_sipfrag(), and transmit_state_notify().
10186 { 10187 if (req->lines) { 10188 ast_log(LOG_WARNING, "Can't add more content when the content has been finalized\n"); 10189 return -1; 10190 } 10191 10192 ast_str_append(&req->content, 0, "%s", line); 10193 return 0; 10194 }
| static int add_digit | ( | struct sip_request * | req, | |
| char | digit, | |||
| unsigned int | duration, | |||
| int | mode | |||
| ) | [static] |
Add DTMF INFO tone to sip message Mode = 0 for application/dtmf-relay (Cisco) 1 for application/dtmf.
Definition at line 11171 of file chan_sip.c.
References add_content(), and add_header().
Referenced by transmit_info_with_digit().
11172 { 11173 char tmp[256]; 11174 int event; 11175 if (mode) { 11176 /* Application/dtmf short version used by some implementations */ 11177 if ('0' <= digit && digit <= '9') { 11178 event = digit - '0'; 11179 } else if (digit == '*') { 11180 event = 10; 11181 } else if (digit == '#') { 11182 event = 11; 11183 } else if ('A' <= digit && digit <= 'D') { 11184 event = 12 + digit - 'A'; 11185 } else if ('a' <= digit && digit <= 'd') { 11186 event = 12 + digit - 'a'; 11187 } else { 11188 /* Unknown digit */ 11189 event = 0; 11190 } 11191 snprintf(tmp, sizeof(tmp), "%d\r\n", event); 11192 add_header(req, "Content-Type", "application/dtmf"); 11193 add_content(req, tmp); 11194 } else { 11195 /* Application/dtmf-relay as documented by Cisco */ 11196 snprintf(tmp, sizeof(tmp), "Signal=%c\r\nDuration=%u\r\n", digit, duration); 11197 add_header(req, "Content-Type", "application/dtmf-relay"); 11198 add_content(req, tmp); 11199 } 11200 return 0; 11201 }
| static void add_diversion_header | ( | struct sip_request * | req, | |
| struct sip_pvt * | pvt | |||
| ) | [static] |
Add "Diversion" header to outgoing message.
We need to add a Diversion header if the owner channel of this dialog has redirecting information associated with it.
| req | The request/response to which we will add the header | |
| pvt | The sip_pvt which represents the call-leg |
Definition at line 12528 of file chan_sip.c.
References add_header(), ast_sockaddr_stringify_host_remote(), ast_strlen_zero(), and sip_reason_code_to_str().
Referenced by __transmit_response(), transmit_invite(), and update_redirecting().
12529 { 12530 const char *diverting_number; 12531 const char *diverting_name; 12532 const char *reason; 12533 char header_text[256]; 12534 12535 if (!pvt->owner) { 12536 return; 12537 } 12538 12539 diverting_number = pvt->owner->redirecting.from.number.str; 12540 if (!pvt->owner->redirecting.from.number.valid 12541 || ast_strlen_zero(diverting_number)) { 12542 return; 12543 } 12544 12545 reason = sip_reason_code_to_str(pvt->owner->redirecting.reason); 12546 12547 /* We at least have a number to place in the Diversion header, which is enough */ 12548 diverting_name = pvt->owner->redirecting.from.name.str; 12549 if (!pvt->owner->redirecting.from.name.valid 12550 || ast_strlen_zero(diverting_name)) { 12551 snprintf(header_text, sizeof(header_text), "<sip:%s@%s>;reason=%s", diverting_number, 12552 ast_sockaddr_stringify_host_remote(&pvt->ourip), reason); 12553 } else { 12554 snprintf(header_text, sizeof(header_text), "\"%s\" <sip:%s@%s>;reason=%s", 12555 diverting_name, diverting_number, 12556 ast_sockaddr_stringify_host_remote(&pvt->ourip), reason); 12557 } 12558 12559 add_header(req, "Diversion", header_text); 12560 }
| static int add_header | ( | struct sip_request * | req, | |
| const char * | var, | |||
| const char * | value | |||
| ) | [static] |
Add header to SIP message.
Definition at line 10127 of file chan_sip.c.
References ast_log(), ast_str_append(), ast_str_strlen(), find_alias(), LOG_WARNING, and sip_cfg.
10128 { 10129 if (req->headers == SIP_MAX_HEADERS) { 10130 ast_log(LOG_WARNING, "Out of SIP header space\n"); 10131 return -1; 10132 } 10133 10134 if (req->lines) { 10135 ast_log(LOG_WARNING, "Can't add more headers when lines have been added\n"); 10136 return -1; 10137 } 10138 10139 if (sip_cfg.compactheaders) { 10140 var = find_alias(var, var); 10141 } 10142 10143 ast_str_append(&req->data, 0, "%s: %s\r\n", var, value); 10144 req->header[req->headers] = ast_str_strlen(req->data); 10145 10146 req->headers++; 10147 10148 return 0; 10149 }
| static int add_header_max_forwards | ( | struct sip_pvt * | dialog, | |
| struct sip_request * | req | |||
| ) | [static] |
Add 'Max-Forwards' header to SIP message.
Definition at line 10155 of file chan_sip.c.
References add_header().
Referenced by initreqprep(), reqprep(), and transmit_register().
10156 { 10157 char clen[10]; 10158 10159 snprintf(clen, sizeof(clen), "%d", dialog->maxforwards); 10160 10161 return add_header(req, "Max-Forwards", clen); 10162 }
| static void add_msg_header | ( | struct sip_pvt * | pvt, | |
| const char * | hdr_name, | |||
| const char * | hdr_value | |||
| ) | [static] |
Definition at line 11117 of file chan_sip.c.
References ast_calloc, and AST_LIST_INSERT_TAIL.
Referenced by sip_msg_send().
11118 { 11119 size_t hdr_len_name; 11120 size_t hdr_len_value; 11121 struct sip_msg_hdr *node; 11122 char *pos; 11123 11124 hdr_len_name = strlen(hdr_name) + 1; 11125 hdr_len_value = strlen(hdr_value) + 1; 11126 11127 node = ast_calloc(1, sizeof(*node) + hdr_len_name + hdr_len_value); 11128 if (!node) { 11129 return; 11130 } 11131 pos = node->stuff; 11132 node->name = pos; 11133 strcpy(pos, hdr_name); 11134 pos += hdr_len_name; 11135 node->value = pos; 11136 strcpy(pos, hdr_value); 11137 11138 AST_LIST_INSERT_TAIL(&pvt->msg_headers, node, next); 11139 }
| static void add_noncodec_to_sdp | ( | const struct sip_pvt * | p, | |
| int | format, | |||
| struct ast_str ** | m_buf, | |||
| struct ast_str ** | a_buf, | |||
| int | debug | |||
| ) | [static] |
Add RFC 2833 DTMF offer to SDP.
Definition at line 11471 of file chan_sip.c.
References ast_rtp_codecs_payload_code(), AST_RTP_DTMF, ast_rtp_instance_get_codecs(), ast_rtp_lookup_mime_subtype2(), ast_rtp_lookup_sample_rate2(), ast_str_append(), and ast_verbose.
Referenced by add_sdp().
11474 { 11475 int rtp_code; 11476 11477 if (debug) 11478 ast_verbose("Adding non-codec 0x%x (%s) to SDP\n", format, ast_rtp_lookup_mime_subtype2(0, NULL, format, 0)); 11479 if ((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->rtp), 0, NULL, format)) == -1) 11480 return; 11481 11482 ast_str_append(m_buf, 0, " %d", rtp_code); 11483 ast_str_append(a_buf, 0, "a=rtpmap:%d %s/%d\r\n", rtp_code, 11484 ast_rtp_lookup_mime_subtype2(0, NULL, format, 0), 11485 ast_rtp_lookup_sample_rate2(0, NULL, format)); 11486 if (format == AST_RTP_DTMF) /* Indicate we support DTMF and FLASH... */ 11487 ast_str_append(a_buf, 0, "a=fmtp:%d 0-16\r\n", rtp_code); 11488 }
| static void add_peer_mailboxes | ( | struct sip_peer * | peer, | |
| const char * | value | |||
| ) | [static] |
Definition at line 28192 of file chan_sip.c.
References ast_calloc, AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_strdupa, ast_strip(), ast_strlen_zero(), context, mailbox, mbox(), S_OR, and strsep().
Referenced by build_peer().
28193 { 28194 char *next, *mbox, *context; 28195 28196 next = ast_strdupa(value); 28197 28198 while ((mbox = context = strsep(&next, ","))) { 28199 struct sip_mailbox *mailbox; 28200 int duplicate = 0; 28201 /* remove leading/trailing whitespace from mailbox string */ 28202 mbox = ast_strip(mbox); 28203 strsep(&context, "@"); 28204 28205 if (ast_strlen_zero(mbox)) { 28206 continue; 28207 } 28208 28209 /* Check whether the mailbox is already in the list */ 28210 AST_LIST_TRAVERSE(&peer->mailboxes, mailbox, entry) { 28211 if (!strcmp(mailbox->mailbox, mbox) && !strcmp(S_OR(mailbox->context, ""), S_OR(context, ""))) { 28212 duplicate = 1; 28213 break; 28214 } 28215 } 28216 if (duplicate) { 28217 continue; 28218 } 28219 28220 if (!(mailbox = ast_calloc(1, sizeof(*mailbox) + strlen(mbox) + strlen(S_OR(context, ""))))) { 28221 continue; 28222 } 28223 28224 if (!ast_strlen_zero(context)) { 28225 mailbox->context = mailbox->mailbox + strlen(mbox) + 1; 28226 strcpy(mailbox->context, context); /* SAFE */ 28227 } 28228 strcpy(mailbox->mailbox, mbox); /* SAFE */ 28229 28230 AST_LIST_INSERT_TAIL(&peer->mailboxes, mailbox, entry); 28231 } 28232 }
| static void add_peer_mwi_subs | ( | struct sip_peer * | peer | ) | [static] |
Definition at line 25437 of file chan_sip.c.
References AST_EVENT_IE_CONTEXT, AST_EVENT_IE_END, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_MWI, ast_event_subscribe(), ast_event_unsubscribe(), AST_LIST_TRAVERSE, mailbox, mwi_event_cb(), and S_OR.
Referenced by build_peer(), and handle_request_subscribe().
25438 { 25439 struct sip_mailbox *mailbox; 25440 25441 AST_LIST_TRAVERSE(&peer->mailboxes, mailbox, entry) { 25442 if (mailbox->event_sub) { 25443 ast_event_unsubscribe(mailbox->event_sub); 25444 } 25445 25446 mailbox->event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "SIP mbox event", peer, 25447 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox->mailbox, 25448 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, S_OR(mailbox->context, "default"), 25449 AST_EVENT_IE_END); 25450 } 25451 }
| static void add_realm_authentication | ( | struct sip_auth_container ** | credentials, | |
| const char * | configuration, | |||
| int | lineno | |||
| ) | [static] |
Definition at line 27986 of file chan_sip.c.
References ao2_t_alloc, ast_calloc, ast_copy_string(), ast_debug, AST_LIST_INSERT_TAIL, ast_log(), ast_strdupa, ast_strlen_zero(), ast_verb, destroy_realm_authentication(), LOG_WARNING, and secret.
Referenced by build_peer(), and reload_config().
27987 { 27988 char *authcopy; 27989 char *username=NULL, *realm=NULL, *secret=NULL, *md5secret=NULL; 27990 struct sip_auth *auth; 27991 27992 if (ast_strlen_zero(configuration)) { 27993 /* Nothing to add */ 27994 return; 27995 } 27996 27997 ast_debug(1, "Auth config :: %s\n", configuration); 27998 27999 authcopy = ast_strdupa(configuration); 28000 username = authcopy; 28001 28002 /* split user[:secret] and relm */ 28003 realm = strrchr(username, '@'); 28004 if (realm) 28005 *realm++ = '\0'; 28006 if (ast_strlen_zero(username) || ast_strlen_zero(realm)) { 28007 ast_log(LOG_WARNING, "Format for authentication entry is user[:secret]@realm at line %d\n", lineno); 28008 return; 28009 } 28010 28011 /* parse username at ':' for secret, or '#" for md5secret */ 28012 if ((secret = strchr(username, ':'))) { 28013 *secret++ = '\0'; 28014 } else if ((md5secret = strchr(username, '#'))) { 28015 *md5secret++ = '\0'; 28016 } 28017 28018 /* Create the continer if needed. */ 28019 if (!*credentials) { 28020 *credentials = ao2_t_alloc(sizeof(**credentials), destroy_realm_authentication, 28021 "Create realm auth container."); 28022 if (!*credentials) { 28023 /* Failed to create the credentials container. */ 28024 return; 28025 } 28026 } 28027 28028 /* Create the authentication credential entry. */ 28029 auth = ast_calloc(1, sizeof(*auth)); 28030 if (!auth) { 28031 return; 28032 } 28033 ast_copy_string(auth->realm, realm, sizeof(auth->realm)); 28034 ast_copy_string(auth->username, username, sizeof(auth->username)); 28035 if (secret) 28036 ast_copy_string(auth->secret, secret, sizeof(auth->secret)); 28037 if (md5secret) 28038 ast_copy_string(auth->md5secret, md5secret, sizeof(auth->md5secret)); 28039 28040 /* Add credential to container list. */ 28041 AST_LIST_INSERT_TAIL(&(*credentials)->list, auth, node); 28042 28043 ast_verb(3, "Added authentication for realm %s\n", realm); 28044 }
| static void add_route | ( | struct sip_request * | req, | |
| struct sip_route * | route | |||
| ) | [static] |
Add route header into request per learned route.
Definition at line 10296 of file chan_sip.c.
References add_header(), and ast_copy_string().
Referenced by initreqprep(), and reqprep().
10297 { 10298 char r[SIPBUFSIZE*2], *p; 10299 int n, rem = sizeof(r); 10300 10301 if (!route) 10302 return; 10303 10304 p = r; 10305 for (;route ; route = route->next) { 10306 n = strlen(route->hop); 10307 if (rem < n+3) /* we need room for ",<route>" */ 10308 break; 10309 if (p != r) { /* add a separator after fist route */ 10310 *p++ = ','; 10311 --rem; 10312 } 10313 *p++ = '<'; 10314 ast_copy_string(p, route->hop, rem); /* cannot fail */ 10315 p += n; 10316 *p++ = '>'; 10317 rem -= (n+2); 10318 } 10319 *p = '\0'; 10320 add_header(req, "Route", r); 10321 }
| static int add_rpid | ( | struct sip_request * | req, | |
| struct sip_pvt * | p | |||
| ) | [static] |
Add Remote-Party-ID header to SIP message.
Definition at line 11207 of file chan_sip.c.
References add_header(), ast_party_id_presentation(), AST_PRES_ALLOWED, AST_PRES_ALLOWED_NETWORK_NUMBER, AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN, AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED, AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, AST_PRES_NUMBER_NOT_AVAILABLE, AST_PRES_PROHIB_NETWORK_NUMBER, AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN, AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED, AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN, AST_PRES_RESTRICTION, ast_sockaddr_stringify_host_remote(), ast_str_alloca, ast_str_append(), ast_str_buffer(), ast_str_set(), ast_strlen_zero(), ast_test_flag, ast_uri_encode(), ast_uri_sip_user, and S_OR.
Referenced by __transmit_response(), transmit_invite(), transmit_reinvite_with_sdp(), transmit_response_with_sdp(), and update_connectedline().
11208 { 11209 struct ast_str *tmp = ast_str_alloca(256); 11210 char tmp2[256]; 11211 char *lid_num = NULL; 11212 char *lid_name = NULL; 11213 int lid_pres; 11214 const char *fromdomain; 11215 const char *privacy = NULL; 11216 const char *screen = NULL; 11217 const char *anonymous_string = "\"Anonymous\" <sip:anonymous@anonymous.invalid>"; 11218 11219 if (!ast_test_flag(&p->flags[0], SIP_SENDRPID)) { 11220 return 0; 11221 } 11222 11223 if (p->owner && p->owner->connected.id.number.valid 11224 && p->owner->connected.id.number.str) { 11225 lid_num = p->owner->connected.id.number.str; 11226 } 11227 if (p->owner && p->owner->connected.id.name.valid 11228 && p->owner->connected.id.name.str) { 11229 lid_name = p->owner->connected.id.name.str; 11230 } 11231 lid_pres = (p->owner) ? ast_party_id_presentation(&p->owner->connected.id) : AST_PRES_NUMBER_NOT_AVAILABLE; 11232 11233 if (ast_strlen_zero(lid_num)) 11234 return 0; 11235 if (ast_strlen_zero(lid_name)) 11236 lid_name = lid_num; 11237 fromdomain = S_OR(p->fromdomain, ast_sockaddr_stringify_host_remote(&p->ourip)); 11238 11239 lid_num = ast_uri_encode(lid_num, tmp2, sizeof(tmp2), ast_uri_sip_user); 11240 11241 if (ast_test_flag(&p->flags[0], SIP_SENDRPID_PAI)) { 11242 if ((lid_pres & AST_PRES_RESTRICTION) != AST_PRES_ALLOWED) { 11243 ast_str_set(&tmp, -1, "%s", anonymous_string); 11244 } else { 11245 ast_str_set(&tmp, -1, "\"%s\" <sip:%s@%s>", lid_name, lid_num, fromdomain); 11246 } 11247 add_header(req, "P-Asserted-Identity", ast_str_buffer(tmp)); 11248 } else { 11249 ast_str_set(&tmp, -1, "\"%s\" <sip:%s@%s>;party=%s", lid_name, lid_num, fromdomain, ast_test_flag(&p->flags[0], SIP_OUTGOING) ? "calling" : "called"); 11250 11251 switch (lid_pres) { 11252 case AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED: 11253 case AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN: 11254 privacy = "off"; 11255 screen = "no"; 11256 break; 11257 case AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN: 11258 case AST_PRES_ALLOWED_NETWORK_NUMBER: 11259 privacy = "off"; 11260 screen = "yes"; 11261 break; 11262 case AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED: 11263 case AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN: 11264 privacy = "full"; 11265 screen = "no"; 11266 break; 11267 case AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN: 11268 case AST_PRES_PROHIB_NETWORK_NUMBER: 11269 privacy = "full"; 11270 screen = "yes"; 11271 break; 11272 case AST_PRES_NUMBER_NOT_AVAILABLE: 11273 break; 11274 default: 11275 if ((lid_pres & AST_PRES_RESTRICTION) != AST_PRES_ALLOWED) { 11276 privacy = "full"; 11277 } 11278 else 11279 privacy = "off"; 11280 screen = "no"; 11281 break; 11282 } 11283 11284 if (!ast_strlen_zero(privacy) && !ast_strlen_zero(screen)) { 11285 ast_str_append(&tmp, -1, ";privacy=%s;screen=%s", privacy, screen); 11286 } 11287 11288 add_header(req, "Remote-Party-ID", ast_str_buffer(tmp)); 11289 } 11290 return 0; 11291 }
| static enum sip_result add_sdp | ( | struct sip_request * | resp, | |
| struct sip_pvt * | p, | |||
| int | oldsdp, | |||
| int | add_audio, | |||
| int | add_t38 | |||
| ) | [static] |
Add Session Description Protocol message.
If oldsdp is TRUE, then the SDP version number is not incremented. This mechanism is used in Session-Timers where RE-INVITEs are used for refreshing SIP sessions without modifying the media session in any way.
Definition at line 11620 of file chan_sip.c.
References add_codec_to_sdp(), add_content(), add_header(), add_noncodec_to_sdp(), add_tcodec_to_sdp(), add_vcodec_to_sdp(), ao2_lock, ao2_t_link, ao2_t_unlink, ao2_unlock, ast_codec_pref_index(), AST_CODEC_PREF_SIZE, ast_debug, ast_format_cap_add(), ast_format_cap_alloc_nolock(), ast_format_cap_copy(), ast_format_cap_destroy(), ast_format_cap_has_joint(), ast_format_cap_has_type(), ast_format_cap_is_empty(), ast_format_cap_iscompatible(), ast_format_cap_iter_end(), ast_format_cap_iter_next(), ast_format_cap_iter_start(), ast_format_cap_joint_copy(), AST_FORMAT_GET_TYPE, AST_FORMAT_TYPE_AUDIO, AST_FORMAT_TYPE_TEXT, AST_FORMAT_TYPE_VIDEO, ast_getformatname_multiple(), ast_internal_timing_enabled(), ast_log(), ast_random(), AST_RTP_MAX, ast_sockaddr_cmp(), ast_sockaddr_copy(), ast_sockaddr_is_ipv4_mapped(), ast_sockaddr_is_ipv6(), ast_sockaddr_isnull(), ast_sockaddr_port, ast_sockaddr_set_port, ast_sockaddr_stringify(), ast_sockaddr_stringify_addr(), ast_sockaddr_stringify_addr_remote(), ast_sockaddr_stringify_port(), ast_str_alloca, ast_str_append(), ast_strlen_zero(), AST_T38_RATE_MANAGEMENT_LOCAL_TCF, AST_T38_RATE_MANAGEMENT_TRANSFERRED_TCF, ast_test_flag, ast_udptl_get_error_correction_scheme(), ast_udptl_get_local_max_datagram(), ast_udptl_get_us(), ast_verbose, debug, FALSE, get_crypto_attrib(), get_our_media_address(), ast_format::id, LOG_WARNING, sip_debug_test_pvt(), t38_get_rate(), TRUE, UDPTL_ERROR_CORRECTION_FEC, UDPTL_ERROR_CORRECTION_NONE, UDPTL_ERROR_CORRECTION_REDUNDANCY, and version.
11621 { 11622 struct ast_format_cap *alreadysent = ast_format_cap_alloc_nolock(); 11623 struct ast_format_cap *tmpcap = ast_format_cap_alloc_nolock(); 11624 int res = AST_SUCCESS; 11625 int doing_directmedia = FALSE; 11626 struct ast_sockaddr addr = { {0,} }; 11627 struct ast_sockaddr vaddr = { {0,} }; 11628 struct ast_sockaddr taddr = { {0,} }; 11629 struct ast_sockaddr udptladdr = { {0,} }; 11630 struct ast_sockaddr dest = { {0,} }; 11631 struct ast_sockaddr vdest = { {0,} }; 11632 struct ast_sockaddr tdest = { {0,} }; 11633 struct ast_sockaddr udptldest = { {0,} }; 11634 11635 /* SDP fields */ 11636 char *version = "v=0\r\n"; /* Protocol version */ 11637 char subject[256]; /* Subject of the session */ 11638 char owner[256]; /* Session owner/creator */ 11639 char connection[256]; /* Connection data */ 11640 char *session_time = "t=0 0\r\n"; /* Time the session is active */ 11641 char bandwidth[256] = ""; /* Max bitrate */ 11642 char *hold = ""; 11643 struct ast_str *m_audio = ast_str_alloca(256); /* Media declaration line for audio */ 11644 struct ast_str *m_video = ast_str_alloca(256); /* Media declaration line for video */ 11645 struct ast_str *m_text = ast_str_alloca(256); /* Media declaration line for text */ 11646 struct ast_str *m_modem = ast_str_alloca(256); /* Media declaration line for modem */ 11647 struct ast_str *a_audio = ast_str_alloca(1024); /* Attributes for audio */ 11648 struct ast_str *a_video = ast_str_alloca(1024); /* Attributes for video */ 11649 struct ast_str *a_text = ast_str_alloca(1024); /* Attributes for text */ 11650 struct ast_str *a_modem = ast_str_alloca(1024); /* Attributes for modem */ 11651 const char *a_crypto = NULL; 11652 const char *v_a_crypto = NULL; 11653 const char *t_a_crypto = NULL; 11654 11655 int x; 11656 struct ast_format tmp_fmt; 11657 int needaudio = FALSE; 11658 int needvideo = FALSE; 11659 int needtext = FALSE; 11660 int debug = sip_debug_test_pvt(p); 11661 int min_audio_packet_size = 0; 11662 int min_video_packet_size = 0; 11663 int min_text_packet_size = 0; 11664 11665 char codecbuf[SIPBUFSIZE]; 11666 char buf[SIPBUFSIZE]; 11667 char dummy_answer[256]; 11668 11669 /* Set the SDP session name */ 11670 snprintf(subject, sizeof(subject), "s=%s\r\n", ast_strlen_zero(global_sdpsession) ? "-" : global_sdpsession); 11671 11672 if (!alreadysent || !tmpcap) { 11673 res = AST_FAILURE; 11674 goto add_sdp_cleanup; 11675 } 11676 if (!p->rtp) { 11677 ast_log(LOG_WARNING, "No way to add SDP without an RTP structure\n"); 11678 res = AST_FAILURE; 11679 goto add_sdp_cleanup; 11680 11681 } 11682 /* XXX We should not change properties in the SIP dialog until 11683 we have acceptance of the offer if this is a re-invite */ 11684 11685 /* Set RTP Session ID and version */ 11686 if (!p->sessionid) { 11687 p->sessionid = (int)ast_random(); 11688 p->sessionversion = p->sessionid; 11689 } else { 11690 if (oldsdp == FALSE) 11691 p->sessionversion++; 11692 } 11693 11694 if (add_audio) { 11695 doing_directmedia = (!ast_sockaddr_isnull(&p->redirip) && !(ast_format_cap_is_empty(p->redircaps))) ? TRUE : FALSE; 11696 /* Check if we need video in this call */ 11697 if ((ast_format_cap_has_type(p->jointcaps, AST_FORMAT_TYPE_VIDEO)) && !p->novideo) { 11698 ast_format_cap_joint_copy(p->jointcaps, p->redircaps, tmpcap); 11699 if (doing_directmedia && !ast_format_cap_has_type(tmpcap, AST_FORMAT_TYPE_VIDEO)) { 11700 ast_debug(2, "This call needs video offers, but caller probably did not offer it!\n"); 11701 } else if (p->vrtp) { 11702 needvideo = TRUE; 11703 ast_debug(2, "This call needs video offers!\n"); 11704 } else { 11705 ast_debug(2, "This call needs video offers, but there's no video support enabled!\n"); 11706 } 11707 } 11708 /* Check if we need text in this call */ 11709 if ((ast_format_cap_has_type(p->jointcaps, AST_FORMAT_TYPE_TEXT)) && !p->notext) { 11710 if (sipdebug_text) 11711 ast_verbose("We think we can do text\n"); 11712 if (p->trtp) { 11713 if (sipdebug_text) { 11714 ast_verbose("And we have a text rtp object\n"); 11715 } 11716 needtext = TRUE; 11717 ast_debug(2, "This call needs text offers! \n"); 11718 } else { 11719 ast_debug(2, "This call needs text offers, but there's no text support enabled ! \n"); 11720 } 11721 } 11722 } 11723 11724 get_our_media_address(p, needvideo, needtext, &addr, &vaddr, &taddr, &dest, &vdest, &tdest); 11725 11726 snprintf(owner, sizeof(owner), "o=%s %d %d IN %s %s\r\n", 11727 ast_strlen_zero(global_sdpowner) ? "-" : global_sdpowner, 11728 p->sessionid, p->sessionversion, 11729 (ast_sockaddr_is_ipv6(&dest) && !ast_sockaddr_is_ipv4_mapped(&dest)) ? 11730 "IP6" : "IP4", 11731 ast_sockaddr_stringify_addr_remote(&dest)); 11732 11733 snprintf(connection, sizeof(connection), "c=IN %s %s\r\n", 11734 (ast_sockaddr_is_ipv6(&dest) && !ast_sockaddr_is_ipv4_mapped(&dest)) ? 11735 "IP6" : "IP4", 11736 ast_sockaddr_stringify_addr_remote(&dest)); 11737 11738 if (add_audio) { 11739 if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD) == SIP_PAGE2_CALL_ONHOLD_ONEDIR) { 11740 hold = "a=recvonly\r\n"; 11741 doing_directmedia = FALSE; 11742 } else if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD) == SIP_PAGE2_CALL_ONHOLD_INACTIVE) { 11743 hold = "a=inactive\r\n"; 11744 doing_directmedia = FALSE; 11745 } else { 11746 hold = "a=sendrecv\r\n"; 11747 } 11748 11749 ast_format_cap_copy(tmpcap, p->jointcaps); 11750 11751 /* XXX note, Video and Text are negated - 'true' means 'no' */ 11752 ast_debug(1, "** Our capability: %s Video flag: %s Text flag: %s\n", ast_getformatname_multiple(codecbuf, sizeof(codecbuf), tmpcap), 11753 p->novideo ? "True" : "False", p->notext ? "True" : "False"); 11754 ast_debug(1, "** Our prefcodec: %s \n", ast_getformatname_multiple(codecbuf, sizeof(codecbuf), p->prefcaps)); 11755 11756 if (doing_directmedia) { 11757 ast_format_cap_joint_copy(p->jointcaps, p->redircaps, tmpcap); 11758 ast_debug(1, "** Our native-bridge filtered capablity: %s\n", ast_getformatname_multiple(codecbuf, sizeof(codecbuf), tmpcap)); 11759 } 11760 11761 /* Check if we need audio */ 11762 if (ast_format_cap_has_type(tmpcap, AST_FORMAT_TYPE_AUDIO)) 11763 needaudio = TRUE; 11764 11765 if (debug) { 11766 ast_verbose("Audio is at %s\n", ast_sockaddr_stringify_port(&addr)); 11767 } 11768 11769 /* Ok, we need video. Let's add what we need for video and set codecs. 11770 Video is handled differently than audio since we can not transcode. */ 11771 if (needvideo) { 11772 get_crypto_attrib(p, p->vsrtp, &v_a_crypto); 11773 ast_str_append(&m_video, 0, "m=video %d RTP/%s", ast_sockaddr_port(&vdest), 11774 v_a_crypto ? "SAVP" : "AVP"); 11775 11776 /* Build max bitrate string */ 11777 if (p->maxcallbitrate) 11778 snprintf(bandwidth, sizeof(bandwidth), "b=CT:%d\r\n", p->maxcallbitrate); 11779 if (debug) { 11780 ast_verbose("Video is at %s\n", ast_sockaddr_stringify(&vdest)); 11781 } 11782 } 11783 11784 /* Ok, we need text. Let's add what we need for text and set codecs. 11785 Text is handled differently than audio since we can not transcode. */ 11786 if (needtext) { 11787 if (sipdebug_text) 11788 ast_verbose("Lets set up the text sdp\n"); 11789 get_crypto_attrib(p, p->tsrtp, &t_a_crypto); 11790 ast_str_append(&m_text, 0, "m=text %d RTP/%s", ast_sockaddr_port(&tdest), 11791 t_a_crypto ? "SAVP" : "AVP"); 11792 if (debug) { /* XXX should I use tdest below ? */ 11793 ast_verbose("Text is at %s\n", ast_sockaddr_stringify(&taddr)); 11794 } 11795 } 11796 11797 /* Start building generic SDP headers */ 11798 11799 /* We break with the "recommendation" and send our IP, in order that our 11800 peer doesn't have to ast_gethostbyname() us */ 11801 11802 get_crypto_attrib(p, p->srtp, &a_crypto); 11803 ast_str_append(&m_audio, 0, "m=audio %d RTP/%s", ast_sockaddr_port(&dest), 11804 a_crypto ? "SAVP" : "AVP"); 11805 11806 /* Now, start adding audio codecs. These are added in this order: 11807 - First what was requested by the calling channel 11808 - Then preferences in order from sip.conf device config for this peer/user 11809 - Then other codecs in capabilities, including video 11810 */ 11811 11812 /* Prefer the audio codec we were requested to use, first, no matter what 11813 Note that p->prefcodec can include video codecs, so mask them out 11814 */ 11815 if (ast_format_cap_has_joint(tmpcap, p->prefcaps)) { 11816 ast_format_cap_iter_start(p->prefcaps); 11817 while (!(ast_format_cap_iter_next(p->prefcaps, &tmp_fmt))) { 11818 if (AST_FORMAT_GET_TYPE(tmp_fmt.id) != AST_FORMAT_TYPE_AUDIO) { 11819 continue; 11820 } 11821 add_codec_to_sdp(p, &tmp_fmt, &m_audio, &a_audio, debug, &min_audio_packet_size); 11822 ast_format_cap_add(alreadysent, &tmp_fmt); 11823 } 11824 ast_format_cap_iter_end(p->prefcaps); 11825 } 11826 11827 /* Start by sending our preferred audio/video codecs */ 11828 for (x = 0; x < AST_CODEC_PREF_SIZE; x++) { 11829 if (!(ast_codec_pref_index(&p->prefs, x, &tmp_fmt))) 11830 break; 11831 11832 if (!(ast_format_cap_iscompatible(tmpcap, &tmp_fmt))) 11833 continue; 11834 11835 if (ast_format_cap_iscompatible(alreadysent, &tmp_fmt)) 11836 continue; 11837 11838 if (AST_FORMAT_GET_TYPE(tmp_fmt.id) == AST_FORMAT_TYPE_AUDIO) { 11839 add_codec_to_sdp(p, &tmp_fmt, &m_audio, &a_audio, debug, &min_audio_packet_size); 11840 } else if (needvideo && (AST_FORMAT_GET_TYPE(tmp_fmt.id) == AST_FORMAT_TYPE_VIDEO)) { 11841 add_vcodec_to_sdp(p, &tmp_fmt, &m_video, &a_video, debug, &min_video_packet_size); 11842 } else if (needtext && (AST_FORMAT_GET_TYPE(tmp_fmt.id) == AST_FORMAT_TYPE_TEXT)) { 11843 add_tcodec_to_sdp(p, &tmp_fmt, &m_text, &a_text, debug, &min_text_packet_size); 11844 } 11845 11846 ast_format_cap_add(alreadysent, &tmp_fmt); 11847 } 11848 11849 /* Now send any other common audio and video codecs, and non-codec formats: */ 11850 ast_format_cap_iter_start(tmpcap); 11851 while (!(ast_format_cap_iter_next(tmpcap, &tmp_fmt))) { 11852 if (ast_format_cap_iscompatible(alreadysent, &tmp_fmt)) 11853 continue; 11854 11855 if (AST_FORMAT_GET_TYPE(tmp_fmt.id) == AST_FORMAT_TYPE_AUDIO) { 11856 add_codec_to_sdp(p, &tmp_fmt, &m_audio, &a_audio, debug, &min_audio_packet_size); 11857 } else if (needvideo && (AST_FORMAT_GET_TYPE(tmp_fmt.id) == AST_FORMAT_TYPE_VIDEO)) { 11858 add_vcodec_to_sdp(p, &tmp_fmt, &m_video, &a_video, debug, &min_video_packet_size); 11859 } else if (needtext && (AST_FORMAT_GET_TYPE(tmp_fmt.id) == AST_FORMAT_TYPE_TEXT)) { 11860 add_tcodec_to_sdp(p, &tmp_fmt, &m_text, &a_text, debug, &min_text_packet_size); 11861 } 11862 } 11863 ast_format_cap_iter_end(tmpcap); 11864 11865 /* Now add DTMF RFC2833 telephony-event as a codec */ 11866 for (x = 1LL; x <= AST_RTP_MAX; x <<= 1) { 11867 if (!(p->jointnoncodeccapability & x)) 11868 continue; 11869 11870 add_noncodec_to_sdp(p, x, &m_audio, &a_audio, debug); 11871 } 11872 11873 ast_debug(3, "-- Done with adding codecs to SDP\n"); 11874 11875 if (!p->owner || !ast_internal_timing_enabled(p->owner)) 11876 ast_str_append(&a_audio, 0, "a=silenceSupp:off - - - -\r\n"); 11877 11878 if (min_audio_packet_size) 11879 ast_str_append(&a_audio, 0, "a=ptime:%d\r\n", min_audio_packet_size); 11880 11881 /* XXX don't think you can have ptime for video */ 11882 if (min_video_packet_size) 11883 ast_str_append(&a_video, 0, "a=ptime:%d\r\n", min_video_packet_size); 11884 11885 /* XXX don't think you can have ptime for text */ 11886 if (min_text_packet_size) 11887 ast_str_append(&a_text, 0, "a=ptime:%d\r\n", min_text_packet_size); 11888 11889 if (m_audio->len - m_audio->used < 2 || m_video->len - m_video->used < 2 || 11890 m_text->len - m_text->used < 2 || a_text->len - a_text->used < 2 || 11891 a_audio->len - a_audio->used < 2 || a_video->len - a_video->used < 2) 11892 ast_log(LOG_WARNING, "SIP SDP may be truncated due to undersized buffer!!\n"); 11893 } 11894 11895 if (add_t38) { 11896 /* Our T.38 end is */ 11897 ast_udptl_get_us(p->udptl, &udptladdr); 11898 11899 /* Determine T.38 UDPTL destination */ 11900 if (!ast_sockaddr_isnull(&p->udptlredirip)) { 11901 ast_sockaddr_copy(&udptldest, &p->udptlredirip); 11902 } else { 11903 ast_sockaddr_copy(&udptldest, &p->ourip); 11904 ast_sockaddr_set_port(&udptldest, ast_sockaddr_port(&udptladdr)); 11905 } 11906 11907 if (debug) { 11908 ast_debug(1, "T.38 UDPTL is at %s port %d\n", ast_sockaddr_stringify_addr(&p->ourip), ast_sockaddr_port(&udptladdr)); 11909 } 11910 11911 /* We break with the "recommendation" and send our IP, in order that our 11912 peer doesn't have to ast_gethostbyname() us */ 11913 11914 ast_str_append(&m_modem, 0, "m=image %d udptl t38\r\n", ast_sockaddr_port(&udptldest)); 11915 11916 if (!ast_sockaddr_cmp(&udptldest, &dest)) { 11917 ast_str_append(&m_modem, 0, "c=IN %s %s\r\n", 11918 (ast_sockaddr_is_ipv6(&dest) && !ast_sockaddr_is_ipv4_mapped(&dest)) ? 11919 "IP6" : "IP4", ast_sockaddr_stringify_addr_remote(&udptldest)); 11920 } 11921 11922 ast_str_append(&a_modem, 0, "a=T38FaxVersion:%d\r\n", p->t38.our_parms.version); 11923 ast_str_append(&a_modem, 0, "a=T38MaxBitRate:%d\r\n", t38_get_rate(p->t38.our_parms.rate)); 11924 if (p->t38.our_parms.fill_bit_removal) { 11925 ast_str_append(&a_modem, 0, "a=T38FaxFillBitRemoval\r\n"); 11926 } 11927 if (p->t38.our_parms.transcoding_mmr) { 11928 ast_str_append(&a_modem, 0, "a=T38FaxTranscodingMMR\r\n"); 11929 } 11930 if (p->t38.our_parms.transcoding_jbig) { 11931 ast_str_append(&a_modem, 0, "a=T38FaxTranscodingJBIG\r\n"); 11932 } 11933 switch (p->t38.our_parms.rate_management) { 11934 case AST_T38_RATE_MANAGEMENT_TRANSFERRED_TCF: 11935 ast_str_append(&a_modem, 0, "a=T38FaxRateManagement:transferredTCF\r\n"); 11936 break; 11937 case AST_T38_RATE_MANAGEMENT_LOCAL_TCF: 11938 ast_str_append(&a_modem, 0, "a=T38FaxRateManagement:localTCF\r\n"); 11939 break; 11940 } 11941 ast_str_append(&a_modem, 0, "a=T38FaxMaxDatagram:%u\r\n", ast_udptl_get_local_max_datagram(p->udptl)); 11942 switch (ast_udptl_get_error_correction_scheme(p->udptl)) { 11943 case UDPTL_ERROR_CORRECTION_NONE: 11944 break; 11945 case UDPTL_ERROR_CORRECTION_FEC: 11946 ast_str_append(&a_modem, 0, "a=T38FaxUdpEC:t38UDPFEC\r\n"); 11947 break; 11948 case UDPTL_ERROR_CORRECTION_REDUNDANCY: 11949 ast_str_append(&a_modem, 0, "a=T38FaxUdpEC:t38UDPRedundancy\r\n"); 11950 break; 11951 } 11952 } 11953 11954 if (needaudio) 11955 ast_str_append(&m_audio, 0, "\r\n"); 11956 if (needvideo) 11957 ast_str_append(&m_video, 0, "\r\n"); 11958 if (needtext) 11959 ast_str_append(&m_text, 0, "\r\n"); 11960 11961 add_header(resp, "Content-Type", "application/sdp"); 11962 add_content(resp, version); 11963 add_content(resp, owner); 11964 add_content(resp, subject); 11965 add_content(resp, connection); 11966 /* only if video response is appropriate */ 11967 if (needvideo) { 11968 add_content(resp, bandwidth); 11969 } 11970 add_content(resp, session_time); 11971 /* if this is a response to an invite, order our offers properly */ 11972 if (p->offered_media[SDP_AUDIO].order_offered || 11973 p->offered_media[SDP_VIDEO].order_offered || 11974 p->offered_media[SDP_TEXT].order_offered || 11975 p->offered_media[SDP_IMAGE].order_offered) { 11976 int i; 11977 /* we have up to 3 streams as limited by process_sdp */ 11978 for (i = 1; i <= 3; i++) { 11979 if (p->offered_media[SDP_AUDIO].order_offered == i) { 11980 if (needaudio) { 11981 add_content(resp, m_audio->str); 11982 add_content(resp, a_audio->str); 11983 add_content(resp, hold); 11984 if (a_crypto) { 11985 add_content(resp, a_crypto); 11986 } 11987 } else { 11988 snprintf(dummy_answer, sizeof(dummy_answer), "m=audio 0 RTP/AVP %s\r\n", p->offered_media[SDP_AUDIO].codecs); 11989 add_content(resp, dummy_answer); 11990 } 11991 } else if (p->offered_media[SDP_VIDEO].order_offered == i) { 11992 if (needvideo) { /* only if video response is appropriate */ 11993 add_content(resp, m_video->str); 11994 add_content(resp, a_video->str); 11995 add_content(resp, hold); /* Repeat hold for the video stream */ 11996 if (v_a_crypto) { 11997 add_content(resp, v_a_crypto); 11998 } 11999 } else { 12000 snprintf(dummy_answer, sizeof(dummy_answer), "m=video 0 RTP/AVP %s\r\n", p->offered_media[SDP_VIDEO].codecs); 12001 add_content(resp, dummy_answer); 12002 } 12003 } else if (p->offered_media[SDP_TEXT].order_offered == i) { 12004 if (needtext) { /* only if text response is appropriate */ 12005 add_content(resp, m_text->str); 12006 add_content(resp, a_text->str); 12007 add_content(resp, hold); /* Repeat hold for the text stream */ 12008 if (t_a_crypto) { 12009 add_content(resp, t_a_crypto); 12010 } 12011 } else { 12012 snprintf(dummy_answer, sizeof(dummy_answer), "m=text 0 RTP/AVP %s\r\n", p->offered_media[SDP_TEXT].codecs); 12013 add_content(resp, dummy_answer); 12014 } 12015 } else if (p->offered_media[SDP_IMAGE].order_offered == i) { 12016 if (add_t38) { 12017 add_content(resp, m_modem->str); 12018 add_content(resp, a_modem->str); 12019 } else { 12020 add_content(resp, "m=image 0 udptl t38\r\n"); 12021 } 12022 } 12023 } 12024 } else { 12025 /* generate new SDP from scratch, no offers */ 12026 if (needaudio) { 12027 add_content(resp, m_audio->str); 12028 add_content(resp, a_audio->str); 12029 add_content(resp, hold); 12030 if (a_crypto) { 12031 add_content(resp, a_crypto); 12032 } 12033 } 12034 if (needvideo) { /* only if video response is appropriate */ 12035 add_content(resp, m_video->str); 12036 add_content(resp, a_video->str); 12037 add_content(resp, hold); /* Repeat hold for the video stream */ 12038 if (v_a_crypto) { 12039 add_content(resp, v_a_crypto); 12040 } 12041 } 12042 if (needtext) { /* only if text response is appropriate */ 12043 add_content(resp, m_text->str); 12044 add_content(resp, a_text->str); 12045 add_content(resp, hold); /* Repeat hold for the text stream */ 12046 if (t_a_crypto) { 12047 add_content(resp, t_a_crypto); 12048 } 12049 } 12050 if (add_t38) { 12051 add_content(resp, m_modem->str); 12052 add_content(resp, a_modem->str); 12053 } 12054 } 12055 12056 /* Update lastrtprx when we send our SDP */ 12057 p->lastrtprx = p->lastrtptx = time(NULL); /* XXX why both ? */ 12058 12059 /* 12060 * We unlink this dialog and link again into the 12061 * dialogs_rtpcheck container so its not in there twice. 12062 */ 12063 ao2_lock(dialogs_rtpcheck); 12064 ao2_t_unlink(dialogs_rtpcheck, p, "unlink pvt into dialogs_rtpcheck container"); 12065 ao2_t_link(dialogs_rtpcheck, p, "link pvt into dialogs_rtpcheck container"); 12066 ao2_unlock(dialogs_rtpcheck); 12067 12068 ast_debug(3, "Done building SDP. Settling with this capability: %s\n", ast_getformatname_multiple(buf, SIPBUFSIZE, tmpcap)); 12069 12070 add_sdp_cleanup: 12071 alreadysent = ast_format_cap_destroy(alreadysent); 12072 tmpcap = ast_format_cap_destroy(tmpcap); 12073 12074 return res; 12075 }
| static int add_sip_domain | ( | const char * | domain, | |
| const enum domain_mode | mode, | |||
| const char * | context | |||
| ) | [static] |
Add SIP domain to list of domains we are responsible for.
Definition at line 27895 of file chan_sip.c.
References ast_calloc, ast_copy_string(), ast_debug, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_strlen_zero(), and LOG_WARNING.
Referenced by reload_config().
27896 { 27897 struct domain *d; 27898 27899 if (ast_strlen_zero(domain)) { 27900 ast_log(LOG_WARNING, "Zero length domain.\n"); 27901 return 1; 27902 } 27903 27904 if (!(d = ast_calloc(1, sizeof(*d)))) 27905 return 0; 27906 27907 ast_copy_string(d->domain, domain, sizeof(d->domain)); 27908 27909 if (!ast_strlen_zero(context)) 27910 ast_copy_string(d->context, context, sizeof(d->context)); 27911 27912 d->mode = mode; 27913 27914 AST_LIST_LOCK(&domain_list); 27915 AST_LIST_INSERT_TAIL(&domain_list, d, list); 27916 AST_LIST_UNLOCK(&domain_list); 27917 27918 if (sipdebug) 27919 ast_debug(1, "Added local SIP domain '%s'\n", domain); 27920 27921 return 1; 27922 }
| static int add_supported_header | ( | struct sip_pvt * | pvt, | |
| struct sip_request * | req | |||
| ) | [static] |
Add "Supported" header to sip message. Since some options may be disabled in the config, the sip_pvt must be inspected to determine what is supported for this dialog.
Definition at line 10115 of file chan_sip.c.
References add_header(), and st_get_mode().
Referenced by respprep(), transmit_invite(), transmit_notify_with_sipfrag(), transmit_refer(), transmit_reinvite_with_sdp(), and update_connectedline().
10116 { 10117 int res; 10118 if (st_get_mode(pvt, 0) != SESSION_TIMER_MODE_REFUSE) { 10119 res = add_header(req, "Supported", "replaces, timer"); 10120 } else { 10121 res = add_header(req, "Supported", "replaces"); 10122 } 10123 return res; 10124 }
| static void add_tcodec_to_sdp | ( | const struct sip_pvt * | p, | |
| struct ast_format * | format, | |||
| struct ast_str ** | m_buf, | |||
| struct ast_str ** | a_buf, | |||
| int | debug, | |||
| int * | min_packet_size | |||
| ) | [static] |
Add text codec offer to SDP offer/answer body in INVITE or 200 OK.
Definition at line 11416 of file chan_sip.c.
References ast_format_set(), AST_FORMAT_T140, AST_FORMAT_T140RED, ast_getformatname(), ast_rtp_codecs_payload_code(), ast_rtp_instance_get_codecs(), ast_rtp_lookup_mime_subtype2(), ast_rtp_lookup_sample_rate2(), ast_str_append(), ast_verbose, and ast_format::id.
Referenced by add_sdp().
11419 { 11420 int rtp_code; 11421 11422 if (!p->trtp) 11423 return; 11424 11425 if (debug) 11426 ast_verbose("Adding text codec %d (%s) to SDP\n", format->id, ast_getformatname(format)); 11427 11428 if ((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->trtp), 1, format, 0)) == -1) 11429 return; 11430 11431 ast_str_append(m_buf, 0, " %d", rtp_code); 11432 ast_str_append(a_buf, 0, "a=rtpmap:%d %s/%d\r\n", rtp_code, 11433 ast_rtp_lookup_mime_subtype2(1, format, 0, 0), 11434 ast_rtp_lookup_sample_rate2(1, format, 0)); 11435 /* Add fmtp code here */ 11436 11437 if (format->id == AST_FORMAT_T140RED) { 11438 struct ast_format tmp_fmt; 11439 int t140code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->trtp), 1, ast_format_set(&tmp_fmt, AST_FORMAT_T140, 0), 0); 11440 ast_str_append(a_buf, 0, "a=fmtp:%d %d/%d/%d\r\n", rtp_code, 11441 t140code, 11442 t140code, 11443 t140code); 11444 11445 } 11446 }
| static int add_text | ( | struct sip_request * | req, | |
| struct sip_pvt * | p | |||
| ) | [static] |
Add text body to SIP message.
Definition at line 11142 of file chan_sip.c.
References add_content(), add_header(), AST_LIST_TRAVERSE, and ast_strlen_zero().
Referenced by transmit_message(), and transmit_request_with_auth().
11143 { 11144 const char *content_type = NULL; 11145 struct sip_msg_hdr *node; 11146 11147 /* Add any additional MESSAGE headers. */ 11148 AST_LIST_TRAVERSE(&p->msg_headers, node, next) { 11149 if (!strcasecmp(node->name, "Content-Type")) { 11150 /* Save content type */ 11151 content_type = node->value; 11152 } else { 11153 add_header(req, node->name, node->value); 11154 } 11155 } 11156 if (ast_strlen_zero(content_type)) { 11157 /* "Content-Type" not set - use default value */ 11158 content_type = "text/plain;charset=UTF-8"; 11159 } 11160 add_header(req, "Content-Type", content_type); 11161 11162 /* XXX Convert \n's to \r\n's XXX */ 11163 add_content(req, p->msg_body); 11164 return 0; 11165 }
| static struct ast_variable* add_var | ( | const char * | buf, | |
| struct ast_variable * | list | |||
| ) | [static, read] |
implement the setvar config line
Definition at line 28075 of file chan_sip.c.
References ast_strdupa, ast_variable_new(), and ast_variable::next.
28076 { 28077 struct ast_variable *tmpvar = NULL; 28078 char *varname = ast_strdupa(buf), *varval = NULL; 28079 28080 if ((varval = strchr(varname, '='))) { 28081 *varval++ = '\0'; 28082 if ((tmpvar = ast_variable_new(varname, varval, ""))) { 28083 tmpvar->next = list; 28084 list = tmpvar; 28085 } 28086 } 28087 return list; 28088 }
| static void add_vcodec_to_sdp | ( | const struct sip_pvt * | p, | |
| struct ast_format * | format, | |||
| struct ast_str ** | m_buf, | |||
| struct ast_str ** | a_buf, | |||
| int | debug, | |||
| int * | min_packet_size | |||
| ) | [static] |
Add video codec offer to SDP offer/answer body in INVITE or 200 OK.
Definition at line 11393 of file chan_sip.c.
References ast_getformatname(), ast_rtp_codecs_payload_code(), ast_rtp_instance_get_codecs(), ast_rtp_lookup_mime_subtype2(), ast_rtp_lookup_sample_rate2(), ast_str_append(), ast_verbose, and ast_format::id.
Referenced by add_sdp().
11396 { 11397 int rtp_code; 11398 11399 if (!p->vrtp) 11400 return; 11401 11402 if (debug) 11403 ast_verbose("Adding video codec %d (%s) to SDP\n", format->id, ast_getformatname(format)); 11404 11405 if ((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->vrtp), 1, format, 0)) == -1) 11406 return; 11407 11408 ast_str_append(m_buf, 0, " %d", rtp_code); 11409 ast_str_append(a_buf, 0, "a=rtpmap:%d %s/%d\r\n", rtp_code, 11410 ast_rtp_lookup_mime_subtype2(1, format, 0, 0), 11411 ast_rtp_lookup_sample_rate2(1, format, 0)); 11412 /* Add fmtp code here */ 11413 }
| static int add_vidupdate | ( | struct sip_request * | req | ) | [static] |
add XML encoded media control with update
Definition at line 11295 of file chan_sip.c.
References add_content(), and add_header().
Referenced by transmit_info_with_vidupdate().
11296 { 11297 const char *xml_is_a_huge_waste_of_space = 11298 "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\r\n" 11299 " <media_control>\r\n" 11300 " <vc_primitive>\r\n" 11301 " <to_encoder>\r\n" 11302 " <picture_fast_update>\r\n" 11303 " </picture_fast_update>\r\n" 11304 " </to_encoder>\r\n" 11305 " </vc_primitive>\r\n" 11306 " </media_control>\r\n"; 11307 add_header(req, "Content-Type", "application/media_control+xml"); 11308 add_content(req, xml_is_a_huge_waste_of_space); 11309 return 0; 11310 }
| static const char * allowoverlap2str | ( | int | mode | ) | [static] |
Convert AllowOverlap setting to printable string.
Definition at line 17655 of file chan_sip.c.
References map_x_s().
Referenced by _sip_show_peer(), and sip_show_settings().
17656 { 17657 return map_x_s(allowoverlapstr, mode, "<error>"); 17658 }
| static void append_date | ( | struct sip_request * | req | ) | [static] |
Append date to SIP message.
Definition at line 10914 of file chan_sip.c.
References add_header().
10915 { 10916 char tmpdat[256]; 10917 struct tm tm; 10918 time_t t = time(NULL); 10919 10920 gmtime_r(&t, &tm); 10921 strftime(tmpdat, sizeof(tmpdat), "%a, %d %b %Y %T GMT", &tm); 10922 add_header(req, "Date", tmpdat); 10923 }
| static void append_history_full | ( | struct sip_pvt * | p, | |
| const char * | fmt, | |||
| ... | ||||
| ) | [static] |
Append to SIP dialog history with arg list.
Definition at line 3555 of file chan_sip.c.
References append_history_va().
03556 { 03557 va_list ap; 03558 03559 if (!p) { 03560 return; 03561 } 03562 03563 if (!p->do_history && !recordhistory && !dumphistory) { 03564 return; 03565 } 03566 03567 va_start(ap, fmt); 03568 append_history_va(p, fmt, ap); 03569 va_end(ap); 03570 03571 return; 03572 }
| static void append_history_va | ( | struct sip_pvt * | p, | |
| const char * | fmt, | |||
| va_list | ap | |||
| ) | [static] |
Append to SIP dialog history with arg list.
Definition at line 3527 of file chan_sip.c.
References ast_calloc, ast_free, AST_LIST_INSERT_TAIL, AST_LIST_REMOVE_HEAD, and strsep().
Referenced by append_history_full().
03528 { 03529 char buf[80], *c = buf; /* max history length */ 03530 struct sip_history *hist; 03531 int l; 03532 03533 vsnprintf(buf, sizeof(buf), fmt, ap); 03534 strsep(&c, "\r\n"); /* Trim up everything after \r or \n */ 03535 l = strlen(buf) + 1; 03536 if (!(hist = ast_calloc(1, sizeof(*hist) + l))) { 03537 return; 03538 } 03539 if (!p->history && !(p->history = ast_calloc(1, sizeof(*p->history)))) { 03540 ast_free(hist); 03541 return; 03542 } 03543 memcpy(hist->event, buf, l); 03544 if (p->history_entries == MAX_HISTORY_ENTRIES) { 03545 struct sip_history *oldest; 03546 oldest = AST_LIST_REMOVE_HEAD(p->history, list); 03547 p->history_entries--; 03548 ast_free(oldest); 03549 } 03550 AST_LIST_INSERT_TAIL(p->history, hist, list); 03551 p->history_entries++; 03552 }
| static int apply_directmedia_ha | ( | struct sip_pvt * | p, | |
| const char * | op | |||
| ) | [static] |
Definition at line 30109 of file chan_sip.c.
References ast_apply_ha(), ast_debug, ast_rtp_instance_get_local_address(), ast_rtp_instance_get_remote_address(), AST_SENSE_ALLOW, AST_SENSE_DENY, ast_sockaddr_stringify(), and ast_strdupa.
Referenced by sip_get_rtp_peer(), sip_get_trtp_peer(), sip_get_udptl_peer(), and sip_get_vrtp_peer().
30110 { 30111 struct ast_sockaddr us = { { 0, }, }, them = { { 0, }, }; 30112 int res = AST_SENSE_ALLOW; 30113 30114 ast_rtp_instance_get_remote_address(p->rtp, &them); 30115 ast_rtp_instance_get_local_address(p->rtp, &us); 30116 30117 if ((res = ast_apply_ha(p->directmediaha, &them)) == AST_SENSE_DENY) { 30118 const char *us_addr = ast_strdupa(ast_sockaddr_stringify(&us)); 30119 const char *them_addr = ast_strdupa(ast_sockaddr_stringify(&them)); 30120 30121 ast_debug(3, "Reinvite %s to %s denied by directmedia ACL on %s\n", 30122 op, them_addr, us_addr); 30123 } 30124 30125 return res; 30126 }
| AST_DATA_STRUCTURE | ( | sip_peer | , | |
| DATA_EXPORT_SIP_PEER | ||||
| ) |
| static void ast_quiet_chan | ( | struct ast_channel * | chan | ) | [static] |
Turn off generator data XXX Does this function belong in the SIP channel?
Definition at line 22382 of file chan_sip.c.
References ast_channel::_state, ast_deactivate_generator(), AST_FLAG_MOH, ast_moh_stop(), AST_STATE_UP, ast_test_flag, and ast_channel::generatordata.
Referenced by attempt_transfer(), and handle_invite_replaces().
22383 { 22384 if (chan && chan->_state == AST_STATE_UP) { 22385 if (ast_test_flag(chan, AST_FLAG_MOH)) 22386 ast_moh_stop(chan); 22387 else if (chan->generatordata) 22388 ast_deactivate_generator(chan); 22389 } 22390 }
| static void ast_sip_ouraddrfor | ( | const struct ast_sockaddr * | them, | |
| struct ast_sockaddr * | us, | |||
| struct sip_pvt * | p | |||
| ) | [static] |
NAT fix - decide which IP address to use for Asterisk server?
Using the localaddr structure built up with localnet statements in sip.conf apply it to their address to see if we need to substitute our externaddr or can get away with our internal bindaddr 'us' is always overwritten.
Definition at line 3421 of file chan_sip.c.
References ast_apply_ha(), ast_debug, ast_log(), ast_ouraddrfor(), AST_SENSE_ALLOW, ast_sockaddr_copy(), ast_sockaddr_is_any(), ast_sockaddr_is_ipv6(), ast_sockaddr_isnull(), ast_sockaddr_port, ast_sockaddr_resolve_first(), ast_sockaddr_set_port, ast_sockaddr_stringify(), bindaddr, externaddr, internip, ast_tcptls_session_args::local_address, LOG_NOTICE, LOG_WARNING, sip_cfg, and sip_get_transport().
Referenced by __sip_subscribe_mwi_do(), sip_alloc(), sip_cc_monitor_request_cc(), sip_msg_send(), sip_poke_peer(), sip_request_call(), sip_send_mwi_to_peer(), transmit_publish(), transmit_register(), and transmit_response_using_temp().
03422 { 03423 struct ast_sockaddr theirs; 03424 03425 /* Set want_remap to non-zero if we want to remap 'us' to an externally 03426 * reachable IP address and port. This is done if: 03427 * 1. we have a localaddr list (containing 'internal' addresses marked 03428 * as 'deny', so ast_apply_ha() will return AST_SENSE_DENY on them, 03429 * and AST_SENSE_ALLOW on 'external' ones); 03430 * 2. externaddr is set, so we know what to use as the 03431 * externally visible address; 03432 * 3. the remote address, 'them', is external; 03433 * 4. the address returned by ast_ouraddrfor() is 'internal' (AST_SENSE_DENY 03434 * when passed to ast_apply_ha() so it does need to be remapped. 03435 * This fourth condition is checked later. 03436 */ 03437 int want_remap = 0; 03438 03439 ast_sockaddr_copy(us, &internip); /* starting guess for the internal address */ 03440 /* now ask the system what would it use to talk to 'them' */ 03441 ast_ouraddrfor(them, us); 03442 ast_sockaddr_copy(&theirs, them); 03443 03444 if (ast_sockaddr_is_ipv6(&theirs)) { 03445 if (localaddr && !ast_sockaddr_isnull(&externaddr)) { 03446 ast_log(LOG_WARNING, "Address remapping activated in sip.conf " 03447 "but we're using IPv6, which doesn't need it. Please " 03448 "remove \"localnet\" and/or \"externaddr\" settings.\n"); 03449 } 03450 } else { 03451 want_remap = localaddr && 03452 !ast_sockaddr_isnull(&externaddr) && 03453 ast_apply_ha(localaddr, &theirs) == AST_SENSE_ALLOW ; 03454 } 03455 03456 if (want_remap && 03457 (!sip_cfg.matchexternaddrlocally || !ast_apply_ha(localaddr, us)) ) { 03458 /* if we used externhost, see if it is time to refresh the info */ 03459 if (externexpire && time(NULL) >= externexpire) { 03460 if (ast_sockaddr_resolve_first(&externaddr, externhost, 0)) { 03461 ast_log(LOG_NOTICE, "Warning: Re-lookup of '%s' failed!\n", externhost); 03462 } 03463 externexpire = time(NULL) + externrefresh; 03464 } 03465 if (!ast_sockaddr_isnull(&externaddr)) { 03466 ast_sockaddr_copy(us, &externaddr); 03467 switch (p->socket.type) { 03468 case SIP_TRANSPORT_TCP: 03469 if (!externtcpport && ast_sockaddr_port(&externaddr)) { 03470 /* for consistency, default to the externaddr port */ 03471 externtcpport = ast_sockaddr_port(&externaddr); 03472 } 03473 ast_sockaddr_set_port(us, externtcpport); 03474 break; 03475 case SIP_TRANSPORT_TLS: 03476 ast_sockaddr_set_port(us, externtlsport); 03477 break; 03478 case SIP_TRANSPORT_UDP: 03479 if (!ast_sockaddr_port(&externaddr)) { 03480 ast_sockaddr_set_port(us, ast_sockaddr_port(&bindaddr)); 03481 } 03482 break; 03483 default: 03484 break; 03485 } 03486 } 03487 ast_debug(1, "Target address %s is not local, substituting externaddr\n", 03488 ast_sockaddr_stringify(them)); 03489 } else if (p) { 03490 /* no remapping, but we bind to a specific address, so use it. */ 03491 switch (p->socket.type) { 03492 case SIP_TRANSPORT_TCP: 03493 if (!ast_sockaddr_is_any(&sip_tcp_desc.local_address)) { 03494 ast_sockaddr_copy(us, 03495 &sip_tcp_desc.local_address); 03496 } else { 03497 ast_sockaddr_set_port(us, 03498 ast_sockaddr_port(&sip_tcp_desc.local_address)); 03499 } 03500 break; 03501 case SIP_TRANSPORT_TLS: 03502 if (!ast_sockaddr_is_any(&sip_tls_desc.local_address)) { 03503 ast_sockaddr_copy(us, 03504 &sip_tls_desc.local_address); 03505 } else { 03506 ast_sockaddr_set_port(us, 03507 ast_sockaddr_port(&sip_tls_desc.local_address)); 03508 } 03509 break; 03510 case SIP_TRANSPORT_UDP: 03511 /* fall through on purpose */ 03512 default: 03513 if (!ast_sockaddr_is_any(&bindaddr)) { 03514 ast_sockaddr_copy(us, &bindaddr); 03515 } 03516 if (!ast_sockaddr_port(us)) { 03517 ast_sockaddr_set_port(us, ast_sockaddr_port(&bindaddr)); 03518 } 03519 } 03520 } else if (!ast_sockaddr_is_any(&bindaddr)) { 03521 ast_sockaddr_copy(us, &bindaddr); 03522 } 03523 ast_debug(3, "Setting SIP_TRANSPORT_%s with address %s\n", sip_get_transport(p->socket.type), ast_sockaddr_stringify(us)); 03524 }
| static int ast_sockaddr_resolve_first | ( | struct ast_sockaddr * | addr, | |
| const char * | name, | |||
| int | flag | |||
| ) | [static] |
Return the first entry from ast_sockaddr_resolve filtered by family of binddaddr.
Using this function probably means you have a faulty design.
Definition at line 30813 of file chan_sip.c.
References ast_sockaddr_resolve_first_af(), bindaddr, and get_address_family_filter().
Referenced by __set_address_from_contact(), ast_sip_ouraddrfor(), check_via(), create_addr(), parse_register_contact(), process_via(), reload_config(), set_destination(), sip_do_debug_ip(), and sip_request_call().
30815 { 30816 return ast_sockaddr_resolve_first_af(addr, name, flag, get_address_family_filter(&bindaddr)); 30817 }
| static int ast_sockaddr_resolve_first_af | ( | struct ast_sockaddr * | addr, | |
| const char * | name, | |||
| int | flag, | |||
| int | family | |||
| ) | [static] |
Return the first entry from ast_sockaddr_resolve filtered by address family.
Using this function probably means you have a faulty design.
Definition at line 30789 of file chan_sip.c.
References ast_debug, ast_free, ast_sockaddr_copy(), and ast_sockaddr_resolve().
Referenced by ast_sockaddr_resolve_first(), get_ip_and_port_from_sdp(), and process_sdp_c().
30791 { 30792 struct ast_sockaddr *addrs; 30793 int addrs_cnt; 30794 30795 addrs_cnt = ast_sockaddr_resolve(&addrs, name, flag, family); 30796 if (addrs_cnt <= 0) { 30797 return 1; 30798 } 30799 if (addrs_cnt > 1) { 30800 ast_debug(1, "Multiple addresses, using the first one only\n"); 30801 } 30802 30803 ast_sockaddr_copy(addr, &addrs[0]); 30804 30805 ast_free(addrs); 30806 return 0; 30807 }
| static int attempt_transfer | ( | struct sip_dual * | transferer, | |
| struct sip_dual * | target | |||
| ) | [static] |
Attempt transfer of SIP call This fix for attended transfers on a local PBX.
Definition at line 22394 of file chan_sip.c.
References ast_channel_masquerade(), ast_channel_name(), ast_debug, ast_log(), ast_quiet_chan(), AST_SOFTHANGUP_DEV, ast_softhangup_nolock(), ast_state2str(), LOG_NOTICE, and LOG_WARNING.
22395 { 22396 int res = 0; 22397 struct ast_channel *peera = NULL, 22398 *peerb = NULL, 22399 *peerc = NULL, 22400 *peerd = NULL; 22401 22402 22403 /* We will try to connect the transferee with the target and hangup 22404 all channels to the transferer */ 22405 ast_debug(4, "Sip transfer:--------------------\n"); 22406 if (transferer->chan1) 22407 ast_debug(4, "-- Transferer to PBX channel: %s State %s\n", ast_channel_name(transferer->chan1), ast_state2str(transferer->chan1->_state)); 22408 else 22409 ast_debug(4, "-- No transferer first channel - odd??? \n"); 22410 if (target->chan1) 22411 ast_debug(4, "-- Transferer to PBX second channel (target): %s State %s\n", ast_channel_name(target->chan1), ast_state2str(target->chan1->_state)); 22412 else 22413 ast_debug(4, "-- No target first channel ---\n"); 22414 if (transferer->chan2) 22415 ast_debug(4, "-- Bridged call to transferee: %s State %s\n", ast_channel_name(transferer->chan2), ast_state2str(transferer->chan2->_state)); 22416 else 22417 ast_debug(4, "-- No bridged call to transferee\n"); 22418 if (target->chan2) 22419 ast_debug(4, "-- Bridged call to transfer target: %s State %s\n", target->chan2 ? ast_channel_name(target->chan2) : "<none>", target->chan2 ? ast_state2str(target->chan2->_state) : "(none)"); 22420 else 22421 ast_debug(4, "-- No target second channel ---\n"); 22422 ast_debug(4, "-- END Sip transfer:--------------------\n"); 22423 if (transferer->chan2) { /* We have a bridge on the transferer's channel */ 22424 peera = transferer->chan1; /* Transferer - PBX -> transferee channel * the one we hangup */ 22425 peerb = target->chan1; /* Transferer - PBX -> target channel - This will get lost in masq */ 22426 peerc = transferer->chan2; /* Asterisk to Transferee */ 22427 peerd = target->chan2; /* Asterisk to Target */ 22428 ast_debug(3, "SIP transfer: Four channels to handle\n"); 22429 } else if (target->chan2) { /* Transferer has no bridge (IVR), but transferee */ 22430 peera = target->chan1; /* Transferer to PBX -> target channel */ 22431 peerb = transferer->chan1; /* Transferer to IVR*/ 22432 peerc = target->chan2; /* Asterisk to Target */ 22433 peerd = transferer->chan2; /* Nothing */ 22434 ast_debug(3, "SIP transfer: Three channels to handle\n"); 22435 } 22436 22437 if (peera && peerb && peerc && (peerb != peerc)) { 22438 ast_quiet_chan(peera); /* Stop generators */ 22439 ast_quiet_chan(peerb); 22440 ast_quiet_chan(peerc); 22441 if (peerd) 22442 ast_quiet_chan(peerd); 22443 22444 ast_debug(4, "SIP transfer: trying to masquerade %s into %s\n", ast_channel_name(peerc), ast_channel_name(peerb)); 22445 if (ast_channel_masquerade(peerb, peerc)) { 22446 ast_log(LOG_WARNING, "Failed to masquerade %s into %s\n", ast_channel_name(peerb), ast_channel_name(peerc)); 22447 res = -1; 22448 } else 22449 ast_debug(4, "SIP transfer: Succeeded to masquerade channels.\n"); 22450 return res; 22451 } else { 22452 ast_log(LOG_NOTICE, "SIP Transfer attempted with no appropriate bridged calls to transfer\n"); 22453 if (transferer->chan1) 22454 ast_softhangup_nolock(transferer->chan1, AST_SOFTHANGUP_DEV); 22455 if (target->chan1) 22456 ast_softhangup_nolock(target->chan1, AST_SOFTHANGUP_DEV); 22457 return -1; 22458 } 22459 return 0; 22460 }
| static int auto_congest | ( | const void * | arg | ) | [static] |
Scheduled congestion on a call. Only called by the scheduler, must return the reference when done.
Definition at line 5593 of file chan_sip.c.
References append_history, ast_channel_trylock, ast_channel_unlock, AST_CONTROL_CONGESTION, ast_queue_control(), sip_pvt_lock, sip_pvt_unlock, and sip_scheddestroy().
05594 { 05595 struct sip_pvt *p = (struct sip_pvt *)arg; 05596 05597 sip_pvt_lock(p); 05598 p->initid = -1; /* event gone, will not be rescheduled */ 05599 if (p->owner) { 05600 /* XXX fails on possible deadlock */ 05601 if (!ast_channel_trylock(p->owner)) { 05602 append_history(p, "Cong", "Auto-congesting (timer)"); 05603 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 05604 ast_channel_unlock(p->owner); 05605 } 05606 05607 /* Give the channel a chance to act before we proceed with destruction */ 05608 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 05609 } 05610 sip_pvt_unlock(p); 05611 dialog_unref(p, "unreffing arg passed into auto_congest callback (p->initid)"); 05612 return 0; 05613 }
| static const char* autocreatepeer2str | ( | enum autocreatepeer_mode | r | ) | [static] |
Definition at line 17113 of file chan_sip.c.
References map_x_s().
Referenced by sip_show_settings().
17114 { 17115 return map_x_s(autopeermodes, r, "Unknown"); 17116 }
| static int block_msg_header | ( | const char * | header_name | ) | [static] |
Definition at line 24789 of file chan_sip.c.
References ARRAY_LEN.
Referenced by sip_msg_send().
24790 { 24791 int idx; 24792 24793 /* 24794 * Don't block Content-Type or Max-Forwards headers because the 24795 * user can override them. 24796 */ 24797 static const char *hdr[] = { 24798 "To", 24799 "From", 24800 "Via", 24801 "Route", 24802 "Contact", 24803 "Call-ID", 24804 "CSeq", 24805 "Allow", 24806 "Content-Length", 24807 }; 24808 24809 for (idx = 0; idx < ARRAY_LEN(hdr); ++idx) { 24810 if (!strcasecmp(header_name, hdr[idx])) { 24811 /* Block addition of this header. */ 24812 return 1; 24813 } 24814 } 24815 return 0; 24816 }
| static void build_callid_pvt | ( | struct sip_pvt * | pvt | ) | [static] |
Build SIP Call-ID value for a non-REGISTER transaction.
Definition at line 7690 of file chan_sip.c.
References ast_sockaddr_stringify_remote(), ast_string_field_build, generate_random_string(), and S_OR.
Referenced by change_callid_pvt(), and sip_alloc().
07691 { 07692 char buf[33]; 07693 const char *host = S_OR(pvt->fromdomain, ast_sockaddr_stringify_remote(&pvt->ourip)); 07694 07695 ast_string_field_build(pvt, callid, "%s@%s", generate_random_string(buf, sizeof(buf)), host); 07696 }
| static void build_callid_registry | ( | struct sip_registry * | reg, | |
| const struct ast_sockaddr * | ourip, | |||
| const char * | fromdomain | |||
| ) | [static] |
Build SIP Call-ID value for a REGISTER transaction.
Definition at line 7748 of file chan_sip.c.
References ast_sockaddr_stringify_host_remote(), ast_string_field_build, generate_random_string(), and S_OR.
Referenced by transmit_register().
07749 { 07750 char buf[33]; 07751 07752 const char *host = S_OR(fromdomain, ast_sockaddr_stringify_host_remote(ourip)); 07753 07754 ast_string_field_build(reg, callid, "%s@%s", generate_random_string(buf, sizeof(buf)), host); 07755 }
| static void build_contact | ( | struct sip_pvt * | p | ) | [static] |
Build contact header - the contact header we send out.
Definition at line 12319 of file chan_sip.c.
References ast_sockaddr_stringify_remote(), ast_string_field_build, ast_strlen_zero(), ast_uri_encode(), ast_uri_sip_user, and sip_get_transport().
Referenced by __sip_subscribe_mwi_do(), check_user_full(), handle_request_invite(), handle_request_options(), handle_request_subscribe(), initreqprep(), register_verify(), and transmit_register().
12320 { 12321 char tmp[SIPBUFSIZE]; 12322 char *user = ast_uri_encode(p->exten, tmp, sizeof(tmp), ast_uri_sip_user); 12323 12324 if (p->socket.type == SIP_TRANSPORT_UDP) { 12325 ast_string_field_build(p, our_contact, "<sip:%s%s%s>", user, 12326 ast_strlen_zero(user) ? "" : "@", ast_sockaddr_stringify_remote(&p->ourip)); 12327 } else { 12328 ast_string_field_build(p, our_contact, "<sip:%s%s%s;transport=%s>", user, 12329 ast_strlen_zero(user) ? "" : "@", ast_sockaddr_stringify_remote(&p->ourip), 12330 sip_get_transport(p->socket.type)); 12331 } 12332 }
| static struct sip_peer * build_peer | ( | const char * | name, | |
| struct ast_variable * | v, | |||
| struct ast_variable * | alt, | |||
| int | realtime, | |||
| int | devstate_only | |||
| ) | [static, read] |
Build peer from configuration (file or realtime static/dynamic).
< The first transport listed should be default outbound
Definition at line 28235 of file chan_sip.c.
References __set_address_from_contact(), accountcode, add_peer_mailboxes(), add_peer_mwi_subs(), add_realm_authentication(), add_var(), ao2_alloc, ao2_lock, ao2_t_alloc, ao2_t_find, ao2_t_ref, ao2_t_unlink, ao2_unlock, asprintf, ast_append_ha(), ast_atomic_fetchadd_int(), ast_callerid_split(), AST_CC_AGENT_NATIVE, AST_CC_AGENT_NEVER, ast_cc_config_params_init, ast_cc_is_config_param(), ast_cc_set_param(), ast_cdr_amaflags2int(), ast_copy_flags, ast_copy_string(), ast_debug, ast_dnsmgr_lookup_cb(), ast_dnsmgr_refresh(), ast_format_cap_alloc_nolock(), ast_free, ast_free_ha(), ast_get_cc_agent_policy(), ast_get_group(), ast_get_indication_zone(), ast_get_ip(), ast_get_time_t(), AST_LIST_EMPTY, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_log(), ast_parse_allow_disallow(), ast_parse_caller_presentation(), AST_SCHED_DEL_UNREF, ast_set2_flag, ast_set_cc_agent_policy(), ast_set_flag, ast_skip_blanks(), ast_sockaddr_isnull(), ast_sockaddr_parse(), ast_sockaddr_port, ast_sockaddr_set_port, ast_sockaddr_setnull(), ast_sockaddr_stringify_addr(), ast_str_alloca, ast_str_append(), ast_str_buffer(), ast_str_reset(), ast_str_set(), ast_str_strlen(), ast_strdupa, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_tone_zone_unref(), ast_true(), ast_variables_destroy(), bindaddr, cid_name, cid_num, context, DEFAULT_MAXMS, destroy_association(), destroy_mailbox(), ast_tls_config::enabled, errno, FALSE, ast_flags::flags, format, get_address_family_filter(), get_srv_protocol(), get_srv_service(), handle_common_options(), handle_t38_options(), language, ast_variable::lineno, LOG_ERROR, LOG_NOTICE, LOG_WARNING, mailbox, mark_parsed_methods(), MAXHOSTNAMELEN, mohinterpret, mohsuggest, ast_variable::name, ast_variable::next, OBJ_POINTER, OBJ_UNLINK, on_dns_update_peer(), parkinglot, PARSE_PORT_FORBID, port_str2int(), proxy_update(), reg_source_db(), secret, set_peer_defaults(), set_socket_transport(), sip_cfg, sip_destroy_peer_fn(), sip_parse_host(), sip_poke_peer(), sip_ref_peer(), sip_register(), sip_send_mwi_to_peer(), sip_unref_peer(), srvlookup, str2stmode(), str2strefresher(), strsep(), TRUE, and ast_variable::value.
28236 { 28237 struct sip_peer *peer = NULL; 28238 struct ast_ha *oldha = NULL; 28239 struct ast_ha *olddirectmediaha = NULL; 28240 int found = 0; 28241 int firstpass = 1; 28242 uint16_t port = 0; 28243 int format = 0; /* Ama flags */ 28244 int timerb_set = 0, timert1_set = 0; 28245 time_t regseconds = 0; 28246 struct ast_flags peerflags[3] = {{(0)}}; 28247 struct ast_flags mask[3] = {{(0)}}; 28248 struct sip_peer tmp_peer; 28249 const char *srvlookup = NULL; 28250 static int deprecation_warning = 1; 28251 int alt_fullcontact = alt ? 1 : 0, headercount = 0; 28252 struct ast_str *fullcontact = ast_str_alloca(512); 28253 28254 if (!realtime || ast_test_flag(&global_flags[1], SIP_PAGE2_RTCACHEFRIENDS)) { 28255 /* Note we do NOT use sip_find_peer here, to avoid realtime recursion */ 28256 /* We also use a case-sensitive comparison (unlike sip_find_peer) so 28257 that case changes made to the peer name will be properly handled 28258 during reload 28259 */ 28260 ast_copy_string(tmp_peer.name, name, sizeof(tmp_peer.name)); 28261 peer = ao2_t_find(peers, &tmp_peer, OBJ_POINTER | OBJ_UNLINK, "find and unlink peer from peers table"); 28262 } 28263 28264 if (peer) { 28265 /* Already in the list, remove it and it will be added back (or FREE'd) */ 28266 found++; 28267 /* we've unlinked the peer from the peers container but not unlinked from the peers_by_ip container yet 28268 this leads to a wrong refcounter and the peer object is never destroyed */ 28269 if (!ast_sockaddr_isnull(&peer->addr)) { 28270 ao2_t_unlink(peers_by_ip, peer, "ao2_unlink peer from peers_by_ip table"); 28271 } 28272 if (!(peer->the_mark)) 28273 firstpass = 0; 28274 } else { 28275 if (!(peer = ao2_t_alloc(sizeof(*peer), sip_destroy_peer_fn, "allocate a peer struct"))) { 28276 return NULL; 28277 } 28278 if (!(peer->caps = ast_format_cap_alloc_nolock())) { 28279 ao2_t_ref(peer, -1, "failed to allocate format capabilities, drop peer"); 28280 return NULL; 28281 } 28282 if (ast_string_field_init(peer, 512)) { 28283 ao2_t_ref(peer, -1, "failed to string_field_init, drop peer"); 28284 return NULL; 28285 } 28286 28287 if (!(peer->cc_params = ast_cc_config_params_init())) { 28288 ao2_t_ref(peer, -1, "failed to allocate cc_params for peer"); 28289 return NULL; 28290 } 28291 28292 if (realtime && !ast_test_flag(&global_flags[1], SIP_PAGE2_RTCACHEFRIENDS)) { 28293 ast_atomic_fetchadd_int(&rpeerobjs, 1); 28294 ast_debug(3, "-REALTIME- peer built. Name: %s. Peer objects: %d\n", name, rpeerobjs); 28295 } else 28296 ast_atomic_fetchadd_int(&speerobjs, 1); 28297 } 28298 28299 /* Note that our peer HAS had its reference count increased */ 28300 if (firstpass) { 28301 oldha = peer->ha; 28302 peer->ha = NULL; 28303 olddirectmediaha = peer->directmediaha; 28304 peer->directmediaha = NULL; 28305 set_peer_defaults(peer); /* Set peer defaults */ 28306 peer->type = 0; 28307 } 28308 28309 /* in case the case of the peer name has changed, update the name */ 28310 ast_copy_string(peer->name, name, sizeof(peer->name)); 28311 28312 /* If we have channel variables, remove them (reload) */ 28313 if (peer->chanvars) { 28314 ast_variables_destroy(peer->chanvars); 28315 peer->chanvars = NULL; 28316 /* XXX should unregister ? */ 28317 } 28318 28319 if (found) 28320 peer->portinuri = 0; 28321 28322 /* If we have realm authentication information, remove them (reload) */ 28323 ao2_lock(peer); 28324 if (peer->auth) { 28325 ao2_t_ref(peer->auth, -1, "Removing old peer authentication"); 28326 peer->auth = NULL; 28327 } 28328 ao2_unlock(peer); 28329 28330 /* clear the transport information. We will detect if a default value is required after parsing the config */ 28331 peer->default_outbound_transport = 0; 28332 peer->transports = 0; 28333 28334 if (!devstate_only) { 28335 struct sip_mailbox *mailbox; 28336 AST_LIST_TRAVERSE(&peer->mailboxes, mailbox, entry) { 28337 mailbox->delme = 1; 28338 } 28339 } 28340 28341 for (; v || ((v = alt) && !(alt=NULL)); v = v->next) { 28342 if (!devstate_only) { 28343 if (handle_common_options(&peerflags[0], &mask[0], v)) { 28344 continue; 28345 } 28346 if (handle_t38_options(&peerflags[0], &mask[0], v, &peer->t38_maxdatagram)) { 28347 continue; 28348 } 28349 if (!strcasecmp(v->name, "transport") && !ast_strlen_zero(v->value)) { 28350 char *val = ast_strdupa(v->value); 28351 char *trans; 28352 28353 while ((trans = strsep(&val, ","))) { 28354 trans = ast_skip_blanks(trans); 28355 28356 if (!strncasecmp(trans, "udp", 3)) { 28357 peer->transports |= SIP_TRANSPORT_UDP; 28358 } else if (sip_cfg.tcp_enabled && !strncasecmp(trans, "tcp", 3)) { 28359 peer->transports |= SIP_TRANSPORT_TCP; 28360 } else if (default_tls_cfg.enabled && !strncasecmp(trans, "tls", 3)) { 28361 peer->transports |= SIP_TRANSPORT_TLS; 28362 } else if (!strncasecmp(trans, "tcp", 3) || !strncasecmp(trans, "tls", 3)) { 28363 ast_log(LOG_WARNING, "'%.3s' is not a valid transport type when %.3senabled=no. If no other is specified, the defaults from general will be used.\n", trans, trans); 28364 } else { 28365 ast_log(LOG_NOTICE, "'%s' is not a valid transport type. if no other is specified, the defaults from general will be used.\n", trans); 28366 } 28367 28368 if (!peer->default_outbound_transport) { /*!< The first transport listed should be default outbound */ 28369 peer->default_outbound_transport = peer->transports; 28370 } 28371 } 28372 } else if (realtime && !strcasecmp(v->name, "regseconds")) { 28373 ast_get_time_t(v->value, ®seconds, 0, NULL); 28374 } else if (realtime && !strcasecmp(v->name, "name")) { 28375 ast_copy_string(peer->name, v->value, sizeof(peer->name)); 28376 } else if (realtime && !strcasecmp(v->name, "useragent")) { 28377 ast_string_field_set(peer, useragent, v->value); 28378 } else if (!strcasecmp(v->name, "type")) { 28379 if (!strcasecmp(v->value, "peer")) { 28380 peer->type |= SIP_TYPE_PEER; 28381 } else if (!strcasecmp(v->value, "user")) { 28382 peer->type |= SIP_TYPE_USER; 28383 } else if (!strcasecmp(v->value, "friend")) { 28384 peer->type = SIP_TYPE_USER | SIP_TYPE_PEER; 28385 } 28386 } else if (!strcasecmp(v->name, "remotesecret")) { 28387 ast_string_field_set(peer, remotesecret, v->value); 28388 } else if (!strcasecmp(v->name, "secret")) { 28389 ast_string_field_set(peer, secret, v->value); 28390 } else if (!strcasecmp(v->name, "description")) { 28391 ast_string_field_set(peer, description, v->value); 28392 } else if (!strcasecmp(v->name, "md5secret")) { 28393 ast_string_field_set(peer, md5secret, v->value); 28394 } else if (!strcasecmp(v->name, "auth")) { 28395 add_realm_authentication(&peer->auth, v->value, v->lineno); 28396 } else if (!strcasecmp(v->name, "callerid")) { 28397 char cid_name[80] = { '\0' }, cid_num[80] = { '\0' }; 28398 28399 ast_callerid_split(v->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num)); 28400 ast_string_field_set(peer, cid_name, cid_name); 28401 ast_string_field_set(peer, cid_num, cid_num); 28402 } else if (!strcasecmp(v->name, "mwi_from")) { 28403 ast_string_field_set(peer, mwi_from, v->value); 28404 } else if (!strcasecmp(v->name, "fullname")) { 28405 ast_string_field_set(peer, cid_name, v->value); 28406 } else if (!strcasecmp(v->name, "trunkname")) { 28407 /* This is actually for a trunk, so we don't want to override callerid */ 28408 ast_string_field_set(peer, cid_name, ""); 28409 } else if (!strcasecmp(v->name, "cid_number")) { 28410 ast_string_field_set(peer, cid_num, v->value); 28411 } else if (!strcasecmp(v->name, "cid_tag")) { 28412 ast_string_field_set(peer, cid_tag, v->value); 28413 } else if (!strcasecmp(v->name, "context")) { 28414 ast_string_field_set(peer, context, v->value); 28415 ast_set_flag(&peer->flags[1], SIP_PAGE2_HAVEPEERCONTEXT); 28416 } else if (!strcasecmp(v->name, "recordonfeature")) { 28417 ast_string_field_set(peer, record_on_feature, v->value); 28418 } else if (!strcasecmp(v->name, "recordofffeature")) { 28419 ast_string_field_set(peer, record_off_feature, v->value); 28420 } else if (!strcasecmp(v->name, "outofcall_message_context")) { 28421 ast_string_field_set(peer, messagecontext, v->value); 28422 } else if (!strcasecmp(v->name, "subscribecontext")) { 28423 ast_string_field_set(peer, subscribecontext, v->value); 28424 } else if (!strcasecmp(v->name, "fromdomain")) { 28425 char *fromdomainport; 28426 ast_string_field_set(peer, fromdomain, v->value); 28427 if ((fromdomainport = strchr(peer->fromdomain, ':'))) { 28428 *fromdomainport++ = '\0'; 28429 if (!(peer->fromdomainport = port_str2int(fromdomainport, 0))) { 28430 ast_log(LOG_NOTICE, "'%s' is not a valid port number for fromdomain.\n",fromdomainport); 28431 } 28432 } else { 28433 peer->fromdomainport = STANDARD_SIP_PORT; 28434 } 28435 } else if (!strcasecmp(v->name, "usereqphone")) { 28436 ast_set2_flag(&peer->flags[0], ast_true(v->value), SIP_USEREQPHONE); 28437 } else if (!strcasecmp(v->name, "fromuser")) { 28438 ast_string_field_set(peer, fromuser, v->value); 28439 } else if (!strcasecmp(v->name, "outboundproxy")) { 28440 char *tok, *proxyname; 28441 28442 if (ast_strlen_zero(v->value)) { 28443 ast_log(LOG_WARNING, "no value given for outbound proxy on line %d of sip.conf.", v->lineno); 28444 continue; 28445 } 28446 28447 peer->outboundproxy = 28448 ao2_alloc(sizeof(*peer->outboundproxy), NULL); 28449 28450 tok = ast_skip_blanks(strtok(ast_strdupa(v->value), ",")); 28451 28452 sip_parse_host(tok, v->lineno, &proxyname, 28453 &peer->outboundproxy->port, 28454 &peer->outboundproxy->transport); 28455 28456 tok = ast_skip_blanks(strtok(ast_strdupa(v->value), ",")); 28457 28458 if ((tok = strtok(NULL, ","))) { 28459 peer->outboundproxy->force = !strncasecmp(ast_skip_blanks(tok), "force", 5); 28460 } else { 28461 peer->outboundproxy->force = FALSE; 28462 } 28463 28464 if (ast_strlen_zero(proxyname)) { 28465 ast_log(LOG_WARNING, "you must specify a name for the outboundproxy on line %d of sip.conf.", v->lineno); 28466 sip_cfg.outboundproxy.name[0] = '\0'; 28467 continue; 28468 } 28469 28470 ast_copy_string(peer->outboundproxy->name, proxyname, sizeof(peer->outboundproxy->name)); 28471 28472 proxy_update(peer->outboundproxy); 28473 } else if (!strcasecmp(v->name, "host")) { 28474 if (!strcasecmp(v->value, "dynamic")) { 28475 /* They'll register with us */ 28476 if (!found || !peer->host_dynamic) { 28477 /* Initialize stuff if this is a new peer, or if it used to 28478 * not be dynamic before the reload. */ 28479 ast_sockaddr_setnull(&peer->addr); 28480 } 28481 peer->host_dynamic = TRUE; 28482 } else { 28483 /* Non-dynamic. Make sure we become that way if we're not */ 28484 AST_SCHED_DEL_UNREF(sched, peer->expire, 28485 sip_unref_peer(peer, "removing register expire ref")); 28486 peer->host_dynamic = FALSE; 28487 srvlookup = v->value; 28488 } 28489 } else if (!strcasecmp(v->name, "defaultip")) { 28490 if (!ast_strlen_zero(v->value) && ast_get_ip(&peer->defaddr, v->value)) { 28491 sip_unref_peer(peer, "sip_unref_peer: from build_peer defaultip"); 28492 return NULL; 28493 } 28494 } else if (!strcasecmp(v->name, "permit") || !strcasecmp(v->name, "deny")) { 28495 int ha_error = 0; 28496 if (!ast_strlen_zero(v->value)) { 28497 peer->ha = ast_append_ha(v->name, v->value, peer->ha, &ha_error); 28498 } 28499 if (ha_error) { 28500 ast_log(LOG_ERROR, "Bad ACL entry in configuration line %d : %s\n", v->lineno, v->value); 28501 } 28502 } else if (!strcasecmp(v->name, "contactpermit") || !strcasecmp(v->name, "contactdeny")) { 28503 int ha_error = 0; 28504 if (!ast_strlen_zero(v->value)) { 28505 peer->contactha = ast_append_ha(v->name + 7, v->value, peer->contactha, &ha_error); 28506 } 28507 if (ha_error) { 28508 ast_log(LOG_ERROR, "Bad ACL entry in configuration line %d : %s\n", v->lineno, v->value); 28509 } 28510 } else if (!strcasecmp(v->name, "directmediapermit") || !strcasecmp(v->name, "directmediadeny")) { 28511 int ha_error = 0; 28512 peer->directmediaha = ast_append_ha(v->name + 11, v->value, peer->directmediaha, &ha_error); 28513 if (ha_error) { 28514 ast_log(LOG_ERROR, "Bad directmedia ACL entry in configuration line %d : %s\n", v->lineno, v->value); 28515 } 28516 } else if (!strcasecmp(v->name, "port")) { 28517 peer->portinuri = 1; 28518 if (!(port = port_str2int(v->value, 0))) { 28519 if (realtime) { 28520 /* If stored as integer, could be 0 for some DBs (notably MySQL) */ 28521 peer->portinuri = 0; 28522 } else { 28523 ast_log(LOG_WARNING, "Invalid peer port configuration at line %d : %s\n", v->lineno, v->value); 28524 } 28525 } 28526 } else if (!strcasecmp(v->name, "callingpres")) { 28527 peer->callingpres = ast_parse_caller_presentation(v->value); 28528 if (peer->callingpres == -1) { 28529 peer->callingpres = atoi(v->value); 28530 } 28531 } else if (!strcasecmp(v->name, "username") || !strcmp(v->name, "defaultuser")) { /* "username" is deprecated */ 28532 ast_string_field_set(peer, username, v->value); 28533 if (!strcasecmp(v->name, "username")) { 28534 if (deprecation_warning) { 28535 ast_log(LOG_NOTICE, "The 'username' field for sip peers has been deprecated in favor of the term 'defaultuser'\n"); 28536 deprecation_warning = 0; 28537 } 28538 peer->deprecated_username = 1; 28539 } 28540 } else if (!strcasecmp(v->name, "tonezone")) { 28541 struct ast_tone_zone *new_zone; 28542 if (!(new_zone = ast_get_indication_zone(v->value))) { 28543 ast_log(LOG_ERROR, "Unknown country code '%s' for tonezone in device [%s] at line %d. Check indications.conf for available country codes.\n", v->value, peer->name, v->lineno); 28544 } else { 28545 ast_tone_zone_unref(new_zone); 28546 ast_string_field_set(peer, zone, v->value); 28547 } 28548 } else if (!strcasecmp(v->name, "language")) { 28549 ast_string_field_set(peer, language, v->value); 28550 } else if (!strcasecmp(v->name, "regexten")) { 28551 ast_string_field_set(peer, regexten, v->value); 28552 } else if (!strcasecmp(v->name, "callbackextension")) { 28553 ast_string_field_set(peer, callback, v->value); 28554 } else if (!strcasecmp(v->name, "amaflags")) { 28555 format = ast_cdr_amaflags2int(v->value); 28556 if (format < 0) { 28557 ast_log(LOG_WARNING, "Invalid AMA Flags for peer: %s at line %d\n", v->value, v->lineno); 28558 } else { 28559 peer->amaflags = format; 28560 } 28561 } else if (!strcasecmp(v->name, "maxforwards")) { 28562 if (sscanf(v->value, "%30d", &peer->maxforwards) != 1 28563 || peer->maxforwards < 1 || 255 < peer->maxforwards) { 28564 ast_log(LOG_WARNING, "'%s' is not a valid maxforwards value at line %d. Using default.\n", v->value, v->lineno); 28565 peer->maxforwards = sip_cfg.default_max_forwards; 28566 } 28567 } else if (!strcasecmp(v->name, "accountcode")) { 28568 ast_string_field_set(peer, accountcode, v->value); 28569 } else if (!strcasecmp(v->name, "mohinterpret")) { 28570 ast_string_field_set(peer, mohinterpret, v->value); 28571 } else if (!strcasecmp(v->name, "mohsuggest")) { 28572 ast_string_field_set(peer, mohsuggest, v->value); 28573 } else if (!strcasecmp(v->name, "parkinglot")) { 28574 ast_string_field_set(peer, parkinglot, v->value); 28575 } else if (!strcasecmp(v->name, "rtp_engine")) { 28576 ast_string_field_set(peer, engine, v->value); 28577 } else if (!strcasecmp(v->name, "mailbox")) { 28578 add_peer_mailboxes(peer, v->value); 28579 } else if (!strcasecmp(v->name, "hasvoicemail")) { 28580 /* People expect that if 'hasvoicemail' is set, that the mailbox will 28581 * be also set, even if not explicitly specified. */ 28582 if (ast_true(v->value) && AST_LIST_EMPTY(&peer->mailboxes)) { 28583 add_peer_mailboxes(peer, name); 28584 } 28585 } else if (!strcasecmp(v->name, "subscribemwi")) { 28586 ast_set2_flag(&peer->flags[1], ast_true(v->value), SIP_PAGE2_SUBSCRIBEMWIONLY); 28587 } else if (!strcasecmp(v->name, "vmexten")) { 28588 ast_string_field_set(peer, vmexten, v->value); 28589 } else if (!strcasecmp(v->name, "callgroup")) { 28590 peer->callgroup = ast_get_group(v->value); 28591 } else if (!strcasecmp(v->name, "allowtransfer")) { 28592 peer->allowtransfer = ast_true(v->value) ? TRANSFER_OPENFORALL : TRANSFER_CLOSED; 28593 } else if (!strcasecmp(v->name, "pickupgroup")) { 28594 peer->pickupgroup = ast_get_group(v->value); 28595 } else if (!strcasecmp(v->name, "allow")) { 28596 int error = ast_parse_allow_disallow(&peer->prefs, peer->caps, v->value, TRUE); 28597 if (error) { 28598 ast_log(LOG_WARNING, "Codec configuration errors found in line %d : %s = %s\n", v->lineno, v->name, v->value); 28599 } 28600 } else if (!strcasecmp(v->name, "disallow")) { 28601 int error = ast_parse_allow_disallow(&peer->prefs, peer->caps, v->value, FALSE); 28602 if (error) { 28603 ast_log(LOG_WARNING, "Codec configuration errors found in line %d : %s = %s\n", v->lineno, v->name, v->value); 28604 } 28605 } else if (!strcasecmp(v->name, "preferred_codec_only")) { 28606 ast_set2_flag(&peer->flags[1], ast_true(v->value), SIP_PAGE2_PREFERRED_CODEC); 28607 } else if (!strcasecmp(v->name, "autoframing")) { 28608 peer->autoframing = ast_true(v->value); 28609 } else if (!strcasecmp(v->name, "rtptimeout")) { 28610 if ((sscanf(v->value, "%30d", &peer->rtptimeout) != 1) || (peer->rtptimeout < 0)) { 28611 ast_log(LOG_WARNING, "'%s' is not a valid RTP hold time at line %d. Using default.\n", v->value, v->lineno); 28612 peer->rtptimeout = global_rtptimeout; 28613 } 28614 } else if (!strcasecmp(v->name, "rtpholdtimeout")) { 28615 if ((sscanf(v->value, "%30d", &peer->rtpholdtimeout) != 1) || (peer->rtpholdtimeout < 0)) { 28616 ast_log(LOG_WARNING, "'%s' is not a valid RTP hold time at line %d. Using default.\n", v->value, v->lineno); 28617 peer->rtpholdtimeout = global_rtpholdtimeout; 28618 } 28619 } else if (!strcasecmp(v->name, "rtpkeepalive")) { 28620 if ((sscanf(v->value, "%30d", &peer->rtpkeepalive) != 1) || (peer->rtpkeepalive < 0)) { 28621 ast_log(LOG_WARNING, "'%s' is not a valid RTP keepalive time at line %d. Using default.\n", v->value, v->lineno); 28622 peer->rtpkeepalive = global_rtpkeepalive; 28623 } 28624 } else if (!strcasecmp(v->name, "timert1")) { 28625 if ((sscanf(v->value, "%30d", &peer->timer_t1) != 1) || (peer->timer_t1 < 200) || (peer->timer_t1 < global_t1min)) { 28626 ast_log(LOG_WARNING, "'%s' is not a valid T1 time at line %d. Using default.\n", v->value, v->lineno); 28627 peer->timer_t1 = global_t1min; 28628 } 28629 timert1_set = 1; 28630 } else if (!strcasecmp(v->name, "timerb")) { 28631 if ((sscanf(v->value, "%30d", &peer->timer_b) != 1) || (peer->timer_b < 200)) { 28632 ast_log(LOG_WARNING, "'%s' is not a valid Timer B time at line %d. Using default.\n", v->value, v->lineno); 28633 peer->timer_b = global_timer_b; 28634 } 28635 timerb_set = 1; 28636 } else if (!strcasecmp(v->name, "setvar")) { 28637 peer->chanvars = add_var(v->value, peer->chanvars); 28638 } else if (!strcasecmp(v->name, "header")) { 28639 char tmp[4096]; 28640 snprintf(tmp, sizeof(tmp), "__SIPADDHEADERpre%2d=%s", ++headercount, v->value); 28641 peer->chanvars = add_var(tmp, peer->chanvars); 28642 } else if (!strcasecmp(v->name, "qualifyfreq")) { 28643 int i; 28644 if (sscanf(v->value, "%30d", &i) == 1) { 28645 peer->qualifyfreq = i * 1000; 28646 } else { 28647 ast_log(LOG_WARNING, "Invalid qualifyfreq number '%s' at line %d of %s\n", v->value, v->lineno, config); 28648 peer->qualifyfreq = global_qualifyfreq; 28649 } 28650 } else if (!strcasecmp(v->name, "maxcallbitrate")) { 28651 peer->maxcallbitrate = atoi(v->value); 28652 if (peer->maxcallbitrate < 0) { 28653 peer->maxcallbitrate = default_maxcallbitrate; 28654 } 28655 } else if (!strcasecmp(v->name, "session-timers")) { 28656 int i = (int) str2stmode(v->value); 28657 if (i < 0) { 28658 ast_log(LOG_WARNING, "Invalid session-timers '%s' at line %d of %s\n", v->value, v->lineno, config); 28659 peer->stimer.st_mode_oper = global_st_mode; 28660 } else { 28661 peer->stimer.st_mode_oper = i; 28662 } 28663 } else if (!strcasecmp(v->name, "session-expires")) { 28664 if (sscanf(v->value, "%30d", &peer->stimer.st_max_se) != 1) { 28665 ast_log(LOG_WARNING, "Invalid session-expires '%s' at line %d of %s\n", v->value, v->lineno, config); 28666 peer->stimer.st_max_se = global_max_se; 28667 } 28668 } else if (!strcasecmp(v->name, "session-minse")) { 28669 if (sscanf(v->value, "%30d", &peer->stimer.st_min_se) != 1) { 28670 ast_log(LOG_WARNING, "Invalid session-minse '%s' at line %d of %s\n", v->value, v->lineno, config); 28671 peer->stimer.st_min_se = global_min_se; 28672 } 28673 if (peer->stimer.st_min_se < 90) { 28674 ast_log(LOG_WARNING, "session-minse '%s' at line %d of %s is not allowed to be < 90 secs\n", v->value, v->lineno, config); 28675 peer->stimer.st_min_se = global_min_se; 28676 } 28677 } else if (!strcasecmp(v->name, "session-refresher")) { 28678 int i = (int) str2strefresher(v->value); 28679 if (i < 0) { 28680 ast_log(LOG_WARNING, "Invalid session-refresher '%s' at line %d of %s\n", v->value, v->lineno, config); 28681 peer->stimer.st_ref = global_st_refresher; 28682 } else { 28683 peer->stimer.st_ref = i; 28684 } 28685 } else if (!strcasecmp(v->name, "disallowed_methods")) { 28686 char *disallow = ast_strdupa(v->value); 28687 mark_parsed_methods(&peer->disallowed_methods, disallow); 28688 } else if (!strcasecmp(v->name, "unsolicited_mailbox")) { 28689 ast_string_field_set(peer, unsolicited_mailbox, v->value); 28690 } else if (!strcasecmp(v->name, "use_q850_reason")) { 28691 ast_set2_flag(&peer->flags[1], ast_true(v->value), SIP_PAGE2_Q850_REASON); 28692 } else if (!strcasecmp(v->name, "encryption")) { 28693 ast_set2_flag(&peer->flags[1], ast_true(v->value), SIP_PAGE2_USE_SRTP); 28694 } else if (!strcasecmp(v->name, "encryption_taglen")) { 28695 ast_set2_flag(&peer->flags[2], !strcasecmp(v->value, "32"), SIP_PAGE3_SRTP_TAG_32); 28696 } else if (!strcasecmp(v->name, "snom_aoc_enabled")) { 28697 ast_set2_flag(&peer->flags[2], ast_true(v->value), SIP_PAGE3_SNOM_AOC); 28698 } 28699 } 28700 28701 /* These apply to devstate lookups */ 28702 if (realtime && !strcasecmp(v->name, "lastms")) { 28703 sscanf(v->value, "%30d", &peer->lastms); 28704 } else if (realtime && !strcasecmp(v->name, "ipaddr") && !ast_strlen_zero(v->value) ) { 28705 ast_sockaddr_parse(&peer->addr, v->value, PARSE_PORT_FORBID); 28706 } else if (realtime && !strcasecmp(v->name, "fullcontact")) { 28707 if (alt_fullcontact && !alt) { 28708 /* Reset, because the alternate also has a fullcontact and we 28709 * do NOT want the field value to be doubled. It might be 28710 * tempting to skip this, but the first table might not have 28711 * fullcontact and since we're here, we know that the alternate 28712 * absolutely does. */ 28713 alt_fullcontact = 0; 28714 ast_str_reset(fullcontact); 28715 } 28716 /* Reconstruct field, because realtime separates our value at the ';' */ 28717 if (fullcontact->used > 0) { 28718 ast_str_append(&fullcontact, 0, ";%s", v->value); 28719 } else { 28720 ast_str_set(&fullcontact, 0, "%s", v->value); 28721 } 28722 } else if (!strcasecmp(v->name, "qualify")) { 28723 if (!strcasecmp(v->value, "no")) { 28724 peer->maxms = 0; 28725 } else if (!strcasecmp(v->value, "yes")) { 28726 peer->maxms = default_qualify ? default_qualify : DEFAULT_MAXMS; 28727 } else if (sscanf(v->value, "%30d", &peer->maxms) != 1) { 28728 ast_log(LOG_WARNING, "Qualification of peer '%s' should be 'yes', 'no', or a number of milliseconds at line %d of sip.conf\n", peer->name, v->lineno); 28729 peer->maxms = 0; 28730 } 28731 if (realtime && !ast_test_flag(&global_flags[1], SIP_PAGE2_RTCACHEFRIENDS) && peer->maxms > 0) { 28732 /* This would otherwise cause a network storm, where the 28733 * qualify response refreshes the peer from the database, 28734 * which in turn causes another qualify to be sent, ad 28735 * infinitum. */ 28736 ast_log(LOG_WARNING, "Qualify is incompatible with dynamic uncached realtime. Please either turn rtcachefriends on or turn qualify off on peer '%s'\n", peer->name); 28737 peer->maxms = 0; 28738 } 28739 } else if (!strcasecmp(v->name, "callcounter")) { 28740 peer->call_limit = ast_true(v->value) ? INT_MAX : 0; 28741 } else if (!strcasecmp(v->name, "call-limit")) { 28742 peer->call_limit = atoi(v->value); 28743 if (peer->call_limit < 0) { 28744 peer->call_limit = 0; 28745 } 28746 } else if (!strcasecmp(v->name, "busylevel")) { 28747 peer->busy_level = atoi(v->value); 28748 if (peer->busy_level < 0) { 28749 peer->busy_level = 0; 28750 } 28751 } else if (ast_cc_is_config_param(v->name)) { 28752 ast_cc_set_param(peer->cc_params, v->name, v->value); 28753 } 28754 } 28755 28756 if (!devstate_only) { 28757 struct sip_mailbox *mailbox; 28758 AST_LIST_TRAVERSE_SAFE_BEGIN(&peer->mailboxes, mailbox, entry) { 28759 if (mailbox->delme) { 28760 AST_LIST_REMOVE_CURRENT(entry); 28761 destroy_mailbox(mailbox); 28762 } 28763 } 28764 AST_LIST_TRAVERSE_SAFE_END; 28765 } 28766 28767 if (!can_parse_xml && (ast_get_cc_agent_policy(peer->cc_params) == AST_CC_AGENT_NATIVE)) { 28768 ast_log(LOG_WARNING, "Peer %s has a cc_agent_policy of 'native' but required libxml2 dependency is not installed. Changing policy to 'never'\n", peer->name); 28769 ast_set_cc_agent_policy(peer->cc_params, AST_CC_AGENT_NEVER); 28770 } 28771 28772 /* Note that Timer B is dependent upon T1 and MUST NOT be lower 28773 * than T1 * 64, according to RFC 3261, Section 17.1.1.2 */ 28774 if (peer->timer_b < peer->timer_t1 * 64) { 28775 if (timerb_set && timert1_set) { 28776 ast_log(LOG_WARNING, "Timer B has been set lower than recommended for peer %s (%d < 64 * Timer-T1=%d)\n", peer->name, peer->timer_b, peer->timer_t1); 28777 } else if (timerb_set) { 28778 if ((peer->timer_t1 = peer->timer_b / 64) < global_t1min) { 28779 ast_log(LOG_WARNING, "Timer B has been set lower than recommended (%d < 64 * timert1=%d). (RFC 3261, 17.1.1.2)\n", peer->timer_b, peer->timer_t1); 28780 peer->timer_t1 = global_t1min; 28781 peer->timer_b = peer->timer_t1 * 64; 28782 } 28783 peer->timer_t1 = peer->timer_b / 64; 28784 } else { 28785 peer->timer_b = peer->timer_t1 * 64; 28786 } 28787 } 28788 28789 if (!peer->default_outbound_transport) { 28790 /* Set default set of transports */ 28791 peer->transports = default_transports; 28792 /* Set default primary transport */ 28793 peer->default_outbound_transport = default_primary_transport; 28794 } 28795 28796 /* The default transport type set during build_peer should only replace the socket.type when... 28797 * 1. Registration is not present and the socket.type and default transport types are different. 28798 * 2. The socket.type is not an acceptable transport type after rebuilding peer. 28799 * 3. The socket.type is not set yet. */ 28800 if (((peer->socket.type != peer->default_outbound_transport) && (peer->expire == -1)) || 28801 !(peer->socket.type & peer->transports) || !(peer->socket.type)) { 28802 28803 set_socket_transport(&peer->socket, peer->default_outbound_transport); 28804 } 28805 28806 if (ast_str_strlen(fullcontact)) { 28807 ast_string_field_set(peer, fullcontact, ast_str_buffer(fullcontact)); 28808 peer->rt_fromcontact = TRUE; 28809 /* We have a hostname in the fullcontact, but if we don't have an 28810 * address listed on the entry (or if it's 'dynamic'), then we need to 28811 * parse the entry to obtain the IP address, so a dynamic host can be 28812 * contacted immediately after reload (as opposed to waiting for it to 28813 * register once again). But if we have an address for this peer and NAT was 28814 * specified, use that address instead. */ 28815 /* XXX May need to revisit the final argument; does the realtime DB store whether 28816 * the original contact was over TLS or not? XXX */ 28817 if (!ast_test_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT) || ast_sockaddr_isnull(&peer->addr)) { 28818 __set_address_from_contact(fullcontact->str, &peer->addr, 0); 28819 } 28820 } 28821 28822 if (srvlookup && peer->dnsmgr == NULL) { 28823 char transport[MAXHOSTNAMELEN]; 28824 char _srvlookup[MAXHOSTNAMELEN]; 28825 char *params; 28826 28827 ast_copy_string(_srvlookup, srvlookup, sizeof(_srvlookup)); 28828 if ((params = strchr(_srvlookup, ';'))) { 28829 *params++ = '\0'; 28830 } 28831 28832 snprintf(transport, sizeof(transport), "_%s._%s", get_srv_service(peer->socket.type), get_srv_protocol(peer->socket.type)); 28833 28834 peer->addr.ss.ss_family = get_address_family_filter(&bindaddr); /* Filter address family */ 28835 if (ast_dnsmgr_lookup_cb(_srvlookup, &peer->addr, &peer->dnsmgr, sip_cfg.srvlookup && !peer->portinuri ? transport : NULL, 28836 on_dns_update_peer, sip_ref_peer(peer, "Store peer on dnsmgr"))) { 28837 ast_log(LOG_ERROR, "srvlookup failed for host: %s, on peer %s, removing peer\n", _srvlookup, peer->name); 28838 sip_unref_peer(peer, "dnsmgr lookup failed, getting rid of peer dnsmgr ref"); 28839 sip_unref_peer(peer, "getting rid of a peer pointer"); 28840 return NULL; 28841 } 28842 if (!peer->dnsmgr) { 28843 /* dnsmgr refresh disabeld, release reference */ 28844 sip_unref_peer(peer, "dnsmgr disabled, unref peer"); 28845 } 28846 28847 ast_string_field_set(peer, tohost, srvlookup); 28848 28849 if (global_dynamic_exclude_static) { 28850 int ha_error = 0; 28851 sip_cfg.contact_ha = ast_append_ha("deny", ast_sockaddr_stringify_addr(&peer->addr), 28852 sip_cfg.contact_ha, &ha_error); 28853 if (ha_error) { 28854 ast_log(LOG_ERROR, "Bad or unresolved host/IP entry in configuration for peer %s, cannot add to contact ACL\n", peer->name); 28855 } 28856 } 28857 } else if (peer->dnsmgr && !peer->host_dynamic) { 28858 /* force a refresh here on reload if dnsmgr already exists and host is set. */ 28859 ast_dnsmgr_refresh(peer->dnsmgr); 28860 } 28861 28862 if (port && !realtime && peer->host_dynamic) { 28863 ast_sockaddr_set_port(&peer->defaddr, port); 28864 } else if (port) { 28865 ast_sockaddr_set_port(&peer->addr, port); 28866 } 28867 28868 if (ast_sockaddr_port(&peer->addr) == 0) { 28869 ast_sockaddr_set_port(&peer->addr, 28870 (peer->socket.type & SIP_TRANSPORT_TLS) ? 28871 STANDARD_TLS_PORT : STANDARD_SIP_PORT); 28872 } 28873 if (ast_sockaddr_port(&peer->defaddr) == 0) { 28874 ast_sockaddr_set_port(&peer->defaddr, 28875 (peer->socket.type & SIP_TRANSPORT_TLS) ? 28876 STANDARD_TLS_PORT : STANDARD_SIP_PORT); 28877 } 28878 if (!peer->socket.port) { 28879 peer->socket.port = htons(((peer->socket.type & SIP_TRANSPORT_TLS) ? STANDARD_TLS_PORT : STANDARD_SIP_PORT)); 28880 } 28881 28882 if (!sip_cfg.ignore_regexpire && peer->host_dynamic && realtime) { 28883 time_t nowtime = time(NULL); 28884 28885 if ((nowtime - regseconds) > 0) { 28886 destroy_association(peer); 28887 memset(&peer->addr, 0, sizeof(peer->addr)); 28888 peer->lastms = -1; 28889 ast_debug(1, "Bah, we're expired (%d/%d/%d)!\n", (int)(nowtime - regseconds), (int)regseconds, (int)nowtime); 28890 } 28891 } 28892 28893 /* Startup regular pokes */ 28894 if (!devstate_only && realtime && peer->lastms > 0) { 28895 sip_ref_peer(peer, "schedule qualify"); 28896 sip_poke_peer(peer, 0); 28897 } 28898 28899 ast_copy_flags(&peer->flags[0], &peerflags[0], mask[0].flags); 28900 ast_copy_flags(&peer->flags[1], &peerflags[1], mask[1].flags); 28901 ast_copy_flags(&peer->flags[2], &peerflags[2], mask[2].flags); 28902 if (ast_test_flag(&peer->flags[1], SIP_PAGE2_ALLOWSUBSCRIBE)) { 28903 sip_cfg.allowsubscribe = TRUE; /* No global ban any more */ 28904 } 28905 /* If read-only RT backend, then refresh from local DB cache */ 28906 if (peer->host_dynamic && (!peer->is_realtime || !sip_cfg.peer_rtupdate)) { 28907 reg_source_db(peer); 28908 } 28909 28910 /* If they didn't request that MWI is sent *only* on subscribe, go ahead and 28911 * subscribe to it now. */ 28912 if (!devstate_only && !ast_test_flag(&peer->flags[1], SIP_PAGE2_SUBSCRIBEMWIONLY) && 28913 !AST_LIST_EMPTY(&peer->mailboxes)) { 28914 add_peer_mwi_subs(peer); 28915 /* Send MWI from the event cache only. This is so we can send initial 28916 * MWI if app_voicemail got loaded before chan_sip. If it is the other 28917 * way, then we will get events when app_voicemail gets loaded. */ 28918 sip_send_mwi_to_peer(peer, 1); 28919 } 28920 28921 peer->the_mark = 0; 28922 28923 ast_free_ha(oldha); 28924 ast_free_ha(olddirectmediaha); 28925 if (!ast_strlen_zero(peer->callback)) { /* build string from peer info */ 28926 char *reg_string; 28927 if (asprintf(®_string, "%s?%s:%s@%s/%s", peer->name, peer->username, !ast_strlen_zero(peer->remotesecret) ? peer->remotesecret : peer->secret, peer->tohost, peer->callback) < 0) { 28928 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno)); 28929 } else if (reg_string) { 28930 sip_register(reg_string, 0); /* XXX TODO: count in registry_count */ 28931 ast_free(reg_string); 28932 } 28933 } 28934 return peer; 28935 }
| static int build_reply_digest | ( | struct sip_pvt * | p, | |
| int | method, | |||
| char * | digest, | |||
| int | digest_len | |||
| ) | [static] |
Build reply digest.
Definition at line 19983 of file chan_sip.c.
References ao2_lock, ao2_t_ref, ao2_unlock, append_history, ast_copy_string(), ast_debug, ast_md5_hash(), ast_mutex_lock, ast_mutex_unlock, ast_random(), ast_sockaddr_stringify_host_remote(), ast_strlen_zero(), authl_lock, find_realm_authentication(), secret, sip_methods, and text.
Referenced by reply_digest(), transmit_register(), and transmit_request_with_auth().
19984 { 19985 char a1[256]; 19986 char a2[256]; 19987 char a1_hash[256]; 19988 char a2_hash[256]; 19989 char resp[256]; 19990 char resp_hash[256]; 19991 char uri[256]; 19992 char opaque[256] = ""; 19993 char cnonce[80]; 19994 const char *username; 19995 const char *secret; 19996 const char *md5secret; 19997 struct sip_auth *auth; /* Realm authentication credential */ 19998 struct sip_auth_container *credentials; 19999 20000 if (!ast_strlen_zero(p->domain)) 20001 snprintf(uri, sizeof(uri), "%s:%s", p->socket.type == SIP_TRANSPORT_TLS ? "sips" : "sip", p->domain); 20002 else if (!ast_strlen_zero(p->uri)) 20003 ast_copy_string(uri, p->uri, sizeof(uri)); 20004 else 20005 snprintf(uri, sizeof(uri), "%s:%s@%s", p->socket.type == SIP_TRANSPORT_TLS ? "sips" : "sip", p->username, ast_sockaddr_stringify_host_remote(&p->sa)); 20006 20007 snprintf(cnonce, sizeof(cnonce), "%08lx", ast_random()); 20008 20009 /* Check if we have peer credentials */ 20010 ao2_lock(p); 20011 credentials = p->peerauth; 20012 if (credentials) { 20013 ao2_t_ref(credentials, +1, "Ref peer auth for digest"); 20014 } 20015 ao2_unlock(p); 20016 auth = find_realm_authentication(credentials, p->realm); 20017 if (!auth) { 20018 /* If not, check global credentials */ 20019 if (credentials) { 20020 ao2_t_ref(credentials, -1, "Unref peer auth for digest"); 20021 } 20022 ast_mutex_lock(&authl_lock); 20023 credentials = authl; 20024 if (credentials) { 20025 ao2_t_ref(credentials, +1, "Ref global auth for digest"); 20026 } 20027 ast_mutex_unlock(&authl_lock); 20028 auth = find_realm_authentication(credentials, p->realm); 20029 } 20030 20031 if (auth) { 20032 ast_debug(3, "use realm [%s] from peer [%s][%s]\n", auth->username, p->peername, p->username); 20033 username = auth->username; 20034 secret = auth->secret; 20035 md5secret = auth->md5secret; 20036 if (sipdebug) 20037 ast_debug(1, "Using realm %s authentication for call %s\n", p->realm, p->callid); 20038 } else { 20039 /* No authentication, use peer or register= config */ 20040 username = p->authname; 20041 secret = p->relatedpeer 20042 && !ast_strlen_zero(p->relatedpeer->remotesecret) 20043 ? p->relatedpeer->remotesecret : p->peersecret; 20044 md5secret = p->peermd5secret; 20045 } 20046 if (ast_strlen_zero(username)) { 20047 /* We have no authentication */ 20048 if (credentials) { 20049 ao2_t_ref(credentials, -1, "Unref auth for digest"); 20050 } 20051 return -1; 20052 } 20053 20054 /* Calculate SIP digest response */ 20055 snprintf(a1, sizeof(a1), "%s:%s:%s", username, p->realm, secret); 20056 snprintf(a2, sizeof(a2), "%s:%s", sip_methods[method].text, uri); 20057 if (!ast_strlen_zero(md5secret)) 20058 ast_copy_string(a1_hash, md5secret, sizeof(a1_hash)); 20059 else 20060 ast_md5_hash(a1_hash, a1); 20061 ast_md5_hash(a2_hash, a2); 20062 20063 p->noncecount++; 20064 if (!ast_strlen_zero(p->qop)) 20065 snprintf(resp, sizeof(resp), "%s:%s:%08x:%s:%s:%s", a1_hash, p->nonce, p->noncecount, cnonce, "auth", a2_hash); 20066 else 20067 snprintf(resp, sizeof(resp), "%s:%s:%s", a1_hash, p->nonce, a2_hash); 20068 ast_md5_hash(resp_hash, resp); 20069 20070 /* only include the opaque string if it's set */ 20071 if (!ast_strlen_zero(p->opaque)) { 20072 snprintf(opaque, sizeof(opaque), ", opaque=\"%s\"", p->opaque); 20073 } 20074 20075 /* XXX We hard code our qop to "auth" for now. XXX */ 20076 if (!ast_strlen_zero(p->qop)) 20077 snprintf(digest, digest_len, "Digest username=\"%s\", realm=\"%s\", algorithm=MD5, uri=\"%s\", nonce=\"%s\", response=\"%s\"%s, qop=auth, cnonce=\"%s\", nc=%08x", username, p->realm, uri, p->nonce, resp_hash, opaque, cnonce, p->noncecount); 20078 else 20079 snprintf(digest, digest_len, "Digest username=\"%s\", realm=\"%s\", algorithm=MD5, uri=\"%s\", nonce=\"%s\", response=\"%s\"%s", username, p->realm, uri, p->nonce, resp_hash, opaque); 20080 20081 append_history(p, "AuthResp", "Auth response sent for %s in realm %s - nc %d", username, p->realm, p->noncecount); 20082 20083 if (credentials) { 20084 ao2_t_ref(credentials, -1, "Unref auth for digest"); 20085 } 20086 return 0; 20087 }
| static void build_route | ( | struct sip_pvt * | p, | |
| struct sip_request * | req, | |||
| int | backwards | |||
| ) | [static] |
Build route list from Record-Route header.
Definition at line 14636 of file chan_sip.c.
References __get_header(), ast_copy_string(), ast_debug, ast_malloc, ast_strdupa, ast_strlen_zero(), free_old_route(), get_in_brackets(), len(), list_route(), sip_debug_test_pvt(), sip_get_header(), and strsep().
Referenced by build_profile(), build_user_routes(), forked_invite_init(), handle_request_invite(), handle_request_subscribe(), and handle_response_invite().
14637 { 14638 struct sip_route *thishop, *head, *tail; 14639 int start = 0; 14640 int len; 14641 const char *rr, *c; 14642 14643 /* Once a persistent route is set, don't fool with it */ 14644 if (p->route && p->route_persistent) { 14645 ast_debug(1, "build_route: Retaining previous route: <%s>\n", p->route->hop); 14646 return; 14647 } 14648 14649 if (p->route) { 14650 free_old_route(p->route); 14651 p->route = NULL; 14652 } 14653 14654 /* We only want to create the route set the first time this is called */ 14655 p->route_persistent = 1; 14656 14657 /* Build a tailq, then assign it to p->route when done. 14658 * If backwards, we add entries from the head so they end up 14659 * in reverse order. However, we do need to maintain a correct 14660 * tail pointer because the contact is always at the end. 14661 */ 14662 head = NULL; 14663 tail = head; 14664 /* 1st we pass through all the hops in any Record-Route headers */ 14665 for (;;) { 14666 /* Each Record-Route header */ 14667 char rr_copy[256]; 14668 char *rr_copy_ptr; 14669 char *rr_iter; 14670 rr = __get_header(req, "Record-Route", &start); 14671 if (*rr == '\0') { 14672 break; 14673 } 14674 ast_copy_string(rr_copy, rr, sizeof(rr_copy)); 14675 rr_copy_ptr = rr_copy; 14676 while ((rr_iter = strsep(&rr_copy_ptr, ","))) { /* Each route entry */ 14677 char *uri = get_in_brackets(rr_iter); 14678 len = strlen(uri) + 1; 14679 /* Make a struct route */ 14680 if ((thishop = ast_malloc(sizeof(*thishop) + len))) { 14681 /* ast_calloc is not needed because all fields are initialized in this block */ 14682 ast_copy_string(thishop->hop, uri, len); 14683 ast_debug(2, "build_route: Record-Route hop: <%s>\n", thishop->hop); 14684 /* Link in */ 14685 if (backwards) { 14686 /* Link in at head so they end up in reverse order */ 14687 thishop->next = head; 14688 head = thishop; 14689 /* If this was the first then it'll be the tail */ 14690 if (!tail) { 14691 tail = thishop; 14692 } 14693 } else { 14694 thishop->next = NULL; 14695 /* Link in at the end */ 14696 if (tail) { 14697 tail->next = thishop; 14698 } else { 14699 head = thishop; 14700 } 14701 tail = thishop; 14702 } 14703 } 14704 } 14705 } 14706 14707 /* Only append the contact if we are dealing with a strict router */ 14708 if (!head || (!ast_strlen_zero(head->hop) && strstr(head->hop, ";lr") == NULL) ) { 14709 /* 2nd append the Contact: if there is one */ 14710 /* Can be multiple Contact headers, comma separated values - we just take the first */ 14711 char *contact = ast_strdupa(sip_get_header(req, "Contact")); 14712 if (!ast_strlen_zero(contact)) { 14713 ast_debug(2, "build_route: Contact hop: %s\n", contact); 14714 /* Look for <: delimited address */ 14715 c = get_in_brackets(contact); 14716 len = strlen(c) + 1; 14717 if ((thishop = ast_malloc(sizeof(*thishop) + len))) { 14718 /* ast_calloc is not needed because all fields are initialized in this block */ 14719 ast_copy_string(thishop->hop, c, len); 14720 thishop->next = NULL; 14721 /* Goes at the end */ 14722 if (tail) { 14723 tail->next = thishop; 14724 } else { 14725 head = thishop; 14726 } 14727 } 14728 } 14729 } 14730 14731 /* Store as new route */ 14732 p->route = head; 14733 14734 /* For debugging dump what we ended up with */ 14735 if (sip_debug_test_pvt(p)) { 14736 list_route(p->route); 14737 } 14738 }
| static void build_via | ( | struct sip_pvt * | p | ) | [static] |
Build a Via header for a request.
Definition at line 3402 of file chan_sip.c.
References ast_sockaddr_stringify_remote(), ast_test_flag, and get_transport_pvt().
Referenced by __sip_subscribe_mwi_do(), reqprep(), sip_alloc(), sip_poke_peer(), sip_request_call(), sip_send_mwi_to_peer(), transmit_invite(), transmit_register(), and transmit_response_using_temp().
03403 { 03404 /* Work around buggy UNIDEN UIP200 firmware */ 03405 const char *rport = (ast_test_flag(&p->flags[0], SIP_NAT_FORCE_RPORT) || ast_test_flag(&p->flags[0], SIP_NAT_RPORT_PRESENT)) ? ";rport" : ""; 03406 03407 /* z9hG4bK is a magic cookie. See RFC 3261 section 8.1.1.7 */ 03408 snprintf(p->via, sizeof(p->via), "SIP/2.0/%s %s;branch=z9hG4bK%08x%s", 03409 get_transport_pvt(p), 03410 ast_sockaddr_stringify_remote(&p->ourip), 03411 (int) p->branch, rport); 03412 }
| static int cb_extensionstate | ( | const char * | context, | |
| const char * | exten, | |||
| enum ast_extension_states | state, | |||
| void * | data | |||
| ) | [static] |
Callback for the devicestate notification (SUBSCRIBE) support subsystem.
Definition at line 15013 of file chan_sip.c.
References append_history, AST_EXTENSION_DEACTIVATED, AST_EXTENSION_REMOVED, ast_extension_state2str(), ast_set_flag, ast_test_flag, ast_verb, FALSE, NONE, sip_pvt_lock, sip_pvt_unlock, sip_scheddestroy(), and transmit_state_notify().
Referenced by dialog_unlink_all(), handle_request_subscribe(), and handle_response_notify().
15014 { 15015 struct sip_pvt *p = data; 15016 15017 sip_pvt_lock(p); 15018 15019 switch(state) { 15020 case AST_EXTENSION_DEACTIVATED: /* Retry after a while */ 15021 case AST_EXTENSION_REMOVED: /* Extension is gone */ 15022 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); /* Delete subscription in 32 secs */ 15023 ast_verb(2, "Extension state: Watcher for hint %s %s. Notify User %s\n", exten, state == AST_EXTENSION_DEACTIVATED ? "deactivated" : "removed", p->username); 15024 p->subscribed = NONE; 15025 append_history(p, "Subscribestatus", "%s", state == AST_EXTENSION_REMOVED ? "HintRemoved" : "Deactivated"); 15026 break; 15027 default: /* Tell user */ 15028 p->laststate = state; 15029 break; 15030 } 15031 if (p->subscribed != NONE) { /* Only send state NOTIFY if we know the format */ 15032 if (!p->pendinginvite) { 15033 transmit_state_notify(p, state, 1, FALSE); 15034 } else { 15035 /* We already have a NOTIFY sent that is not answered. Queue the state up. 15036 if many state changes happen meanwhile, we will only send a notification of the last one */ 15037 ast_set_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE); 15038 } 15039 } 15040 ast_verb(2, "Extension Changed %s[%s] new state %s for Notify User %s %s\n", exten, context, ast_extension_state2str(state), p->username, 15041 ast_test_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE) ? "(queued)" : ""); 15042 15043 sip_pvt_unlock(p); 15044 15045 return 0; 15046 }
| static void cb_extensionstate_destroy | ( | int | id, | |
| void * | data | |||
| ) | [static] |
Definition at line 15003 of file chan_sip.c.
Referenced by handle_request_subscribe().
15004 { 15005 struct sip_pvt *p = data; 15006 15007 dialog_unref(p, "the extensionstate containing this dialog ptr was destroyed"); 15008 }
| static void cc_epa_destructor | ( | void * | data | ) | [static] |
Definition at line 896 of file chan_sip.c.
References ast_free.
00897 { 00898 struct sip_epa_entry *epa_entry = data; 00899 struct cc_epa_entry *cc_entry = epa_entry->instance_data; 00900 ast_free(cc_entry); 00901 }
| static void cc_handle_publish_error | ( | struct sip_pvt * | pvt, | |
| const int | resp, | |||
| struct sip_request * | req, | |||
| struct sip_epa_entry * | epa_entry | |||
| ) | [static] |
Definition at line 20598 of file chan_sip.c.
References ao2_callback, ao2_ref, ast_cc_monitor_failed(), ast_log(), ast_strlen_zero(), FALSE, find_sip_monitor_instance_by_suspension_entry(), LOG_WARNING, sip_get_header(), and transmit_invite().
20599 { 20600 struct cc_epa_entry *cc_entry = epa_entry->instance_data; 20601 struct sip_monitor_instance *monitor_instance = ao2_callback(sip_monitor_instances, 0, 20602 find_sip_monitor_instance_by_suspension_entry, epa_entry); 20603 const char *min_expires; 20604 20605 if (!monitor_instance) { 20606 ast_log(LOG_WARNING, "Can't find monitor_instance corresponding to epa_entry %p.\n", epa_entry); 20607 return; 20608 } 20609 20610 if (resp != 423) { 20611 ast_cc_monitor_failed(cc_entry->core_id, monitor_instance->device_name, 20612 "Received error response to our PUBLISH"); 20613 ao2_ref(monitor_instance, -1); 20614 return; 20615 } 20616 20617 /* Allrighty, the other end doesn't like our Expires value. They think it's 20618 * too small, so let's see if they've provided a more sensible value. If they 20619 * haven't, then we'll just double our Expires value and see if they like that 20620 * instead. 20621 * 20622 * XXX Ideally this logic could be placed into its own function so that SUBSCRIBE, 20623 * PUBLISH, and REGISTER could all benefit from the same shared code. 20624 */ 20625 min_expires = sip_get_header(req, "Min-Expires"); 20626 if (ast_strlen_zero(min_expires)) { 20627 pvt->expiry *= 2; 20628 if (pvt->expiry < 0) { 20629 /* You dork! You overflowed! */ 20630 ast_cc_monitor_failed(cc_entry->core_id, monitor_instance->device_name, 20631 "PUBLISH expiry overflowed"); 20632 ao2_ref(monitor_instance, -1); 20633 return; 20634 } 20635 } else if (sscanf(min_expires, "%30d", &pvt->expiry) != 1) { 20636 ast_cc_monitor_failed(cc_entry->core_id, monitor_instance->device_name, 20637 "Min-Expires has non-numeric value"); 20638 ao2_ref(monitor_instance, -1); 20639 return; 20640 } 20641 /* At this point, we have most certainly changed pvt->expiry, so try transmitting 20642 * again 20643 */ 20644 transmit_invite(pvt, SIP_PUBLISH, FALSE, 0, NULL); 20645 ao2_ref(monitor_instance, -1); 20646 }
| static void change_callid_pvt | ( | struct sip_pvt * | pvt, | |
| const char * | callid | |||
| ) | [static] |
Definition at line 7721 of file chan_sip.c.
References ao2_lock, ao2_t_link, ao2_unlock, ast_string_field_set, build_callid_pvt(), and CONTAINER_UNLINK.
Referenced by __sip_subscribe_mwi_do(), create_addr_from_peer(), sip_poke_peer(), sip_request_call(), and sip_send_mwi_to_peer().
07722 { 07723 int in_dialog_container; 07724 int in_rtp_container; 07725 07726 ao2_lock(dialogs); 07727 ao2_lock(dialogs_rtpcheck); 07728 in_dialog_container = CONTAINER_UNLINK(dialogs, pvt, 07729 "About to change the callid -- remove the old name"); 07730 in_rtp_container = CONTAINER_UNLINK(dialogs_rtpcheck, pvt, 07731 "About to change the callid -- remove the old name"); 07732 if (callid) { 07733 ast_string_field_set(pvt, callid, callid); 07734 } else { 07735 build_callid_pvt(pvt); 07736 } 07737 if (in_dialog_container) { 07738 ao2_t_link(dialogs, pvt, "New dialog callid -- inserted back into table"); 07739 } 07740 if (in_rtp_container) { 07741 ao2_t_link(dialogs_rtpcheck, pvt, "New dialog callid -- inserted back into table"); 07742 } 07743 ao2_unlock(dialogs_rtpcheck); 07744 ao2_unlock(dialogs); 07745 }
| static void change_hold_state | ( | struct sip_pvt * | dialog, | |
| struct sip_request * | req, | |||
| int | holdstate, | |||
| int | sendonly | |||
| ) | [static] |
Change hold state for a call.
Definition at line 8906 of file chan_sip.c.
References append_history, ast_channel_name(), ast_channel_uniqueid(), ast_clear_flag, ast_set_flag, ast_test_flag, EVENT_FLAG_CALL, manager_event, sip_cfg, and sip_peer_hold().
Referenced by handle_request_invite(), and process_sdp().
08907 { 08908 if (sip_cfg.notifyhold && (!holdstate || !ast_test_flag(&dialog->flags[1], SIP_PAGE2_CALL_ONHOLD))) 08909 sip_peer_hold(dialog, holdstate); 08910 if (sip_cfg.callevents) 08911 manager_event(EVENT_FLAG_CALL, "Hold", 08912 "Status: %s\r\n" 08913 "Channel: %s\r\n" 08914 "Uniqueid: %s\r\n", 08915 holdstate ? "On" : "Off", 08916 ast_channel_name(dialog->owner), 08917 ast_channel_uniqueid(dialog->owner)); 08918 append_history(dialog, holdstate ? "Hold" : "Unhold", "%s", req->data->str); 08919 if (!holdstate) { /* Put off remote hold */ 08920 ast_clear_flag(&dialog->flags[1], SIP_PAGE2_CALL_ONHOLD); /* Clear both flags */ 08921 return; 08922 } 08923 /* No address for RTP, we're on hold */ 08924 08925 if (sendonly == 1) /* One directional hold (sendonly/recvonly) */ 08926 ast_set_flag(&dialog->flags[1], SIP_PAGE2_CALL_ONHOLD_ONEDIR); 08927 else if (sendonly == 2) /* Inactive stream */ 08928 ast_set_flag(&dialog->flags[1], SIP_PAGE2_CALL_ONHOLD_INACTIVE); 08929 else 08930 ast_set_flag(&dialog->flags[1], SIP_PAGE2_CALL_ONHOLD_ACTIVE); 08931 return; 08932 }
| static void change_redirecting_information | ( | struct sip_pvt * | p, | |
| struct sip_request * | req, | |||
| struct ast_party_redirecting * | redirecting, | |||
| struct ast_set_party_redirecting * | update_redirecting, | |||
| int | set_call_forward | |||
| ) | [static] |
update redirecting information for a channel based on headers
Definition at line 20335 of file chan_sip.c.
References ast_debug, ast_free, AST_REDIRECTING_REASON_UNCONDITIONAL, ast_strdup, ast_strlen_zero(), ast_party_redirecting::from, ast_set_party_redirecting::from, get_name_and_number(), get_rdnis(), ast_party_id::name, ast_set_party_id::name, ast_party_id::number, ast_set_party_id::number, parse_moved_contact(), ast_party_redirecting::reason, sip_get_header(), ast_party_name::str, ast_party_number::str, ast_party_id::tag, ast_set_party_redirecting::to, ast_party_redirecting::to, ast_party_name::valid, and ast_party_number::valid.
Referenced by handle_request_invite(), handle_response(), and handle_response_invite().
20338 { 20339 char *redirecting_from_name = NULL; 20340 char *redirecting_from_number = NULL; 20341 char *redirecting_to_name = NULL; 20342 char *redirecting_to_number = NULL; 20343 int reason = AST_REDIRECTING_REASON_UNCONDITIONAL; 20344 int is_response = req->method == SIP_RESPONSE; 20345 int res = 0; 20346 20347 res = get_rdnis(p, req, &redirecting_from_name, &redirecting_from_number, &reason); 20348 if (res == -1) { 20349 if (is_response) { 20350 get_name_and_number(sip_get_header(req, "TO"), &redirecting_from_name, &redirecting_from_number); 20351 } else { 20352 return; 20353 } 20354 } 20355 20356 /* At this point, all redirecting "from" info should be filled in appropriately 20357 * on to the "to" info 20358 */ 20359 20360 if (is_response) { 20361 parse_moved_contact(p, req, &redirecting_to_name, &redirecting_to_number, set_call_forward); 20362 } else { 20363 get_name_and_number(sip_get_header(req, "TO"), &redirecting_to_name, &redirecting_to_number); 20364 } 20365 20366 if (!ast_strlen_zero(redirecting_from_number)) { 20367 ast_debug(3, "Got redirecting from number %s\n", redirecting_from_number); 20368 update_redirecting->from.number = 1; 20369 redirecting->from.number.valid = 1; 20370 ast_free(redirecting->from.number.str); 20371 redirecting->from.number.str = redirecting_from_number; 20372 } 20373 if (!ast_strlen_zero(redirecting_from_name)) { 20374 ast_debug(3, "Got redirecting from name %s\n", redirecting_from_name); 20375 update_redirecting->from.name = 1; 20376 redirecting->from.name.valid = 1; 20377 ast_free(redirecting->from.name.str); 20378 redirecting->from.name.str = redirecting_from_name; 20379 } 20380 if (!ast_strlen_zero(p->cid_tag)) { 20381 ast_free(redirecting->from.tag); 20382 redirecting->from.tag = ast_strdup(p->cid_tag); 20383 ast_free(redirecting->to.tag); 20384 redirecting->to.tag = ast_strdup(p->cid_tag); 20385 } 20386 if (!ast_strlen_zero(redirecting_to_number)) { 20387 ast_debug(3, "Got redirecting to number %s\n", redirecting_to_number); 20388 update_redirecting->to.number = 1; 20389 redirecting->to.number.valid = 1; 20390 ast_free(redirecting->to.number.str); 20391 redirecting->to.number.str = redirecting_to_number; 20392 } 20393 if (!ast_strlen_zero(redirecting_to_name)) { 20394 ast_debug(3, "Got redirecting to name %s\n", redirecting_from_number); 20395 update_redirecting->to.name = 1; 20396 redirecting->to.name.valid = 1; 20397 ast_free(redirecting->to.name.str); 20398 redirecting->to.name.str = redirecting_to_name; 20399 } 20400 redirecting->reason = reason; 20401 }
| static void change_t38_state | ( | struct sip_pvt * | p, | |
| int | state | |||
| ) | [static] |
Change the T38 state on a SIP dialog.
Definition at line 5193 of file chan_sip.c.
References ast_channel_name(), AST_CONTROL_T38_PARAMETERS, ast_debug, ast_queue_control_data(), AST_T38_NEGOTIATED, AST_T38_REFUSED, AST_T38_REQUEST_NEGOTIATE, AST_T38_TERMINATED, ast_udptl_get_far_max_ifp(), ast_udptl_set_tag(), ast_control_t38_parameters::max_ifp, and ast_control_t38_parameters::request_response.
Referenced by handle_response_invite(), interpret_t38_parameters(), process_sdp(), and sip_t38_abort().
05194 { 05195 int old = p->t38.state; 05196 struct ast_channel *chan = p->owner; 05197 struct ast_control_t38_parameters parameters = { .request_response = 0 }; 05198 05199 /* Don't bother changing if we are already in the state wanted */ 05200 if (old == state) 05201 return; 05202 05203 p->t38.state = state; 05204 ast_debug(2, "T38 state changed to %d on channel %s\n", p->t38.state, chan ? ast_channel_name(chan) : "<none>"); 05205 05206 /* If no channel was provided we can't send off a control frame */ 05207 if (!chan) 05208 return; 05209 05210 /* Given the state requested and old state determine what control frame we want to queue up */ 05211 switch (state) { 05212 case T38_PEER_REINVITE: 05213 parameters = p->t38.their_parms; 05214 parameters.max_ifp = ast_udptl_get_far_max_ifp(p->udptl); 05215 parameters.request_response = AST_T38_REQUEST_NEGOTIATE; 05216 ast_udptl_set_tag(p->udptl, "%s", ast_channel_name(chan)); 05217 break; 05218 case T38_ENABLED: 05219 parameters = p->t38.their_parms; 05220 parameters.max_ifp = ast_udptl_get_far_max_ifp(p->udptl); 05221 parameters.request_response = AST_T38_NEGOTIATED; 05222 ast_udptl_set_tag(p->udptl, "%s", ast_channel_name(chan)); 05223 break; 05224 case T38_REJECTED: 05225 case T38_DISABLED: 05226 if (old == T38_ENABLED) { 05227 parameters.request_response = AST_T38_TERMINATED; 05228 } else if (old == T38_LOCAL_REINVITE) { 05229 parameters.request_response = AST_T38_REFUSED; 05230 } 05231 break; 05232 case T38_LOCAL_REINVITE: 05233 /* wait until we get a peer response before responding to local reinvite */ 05234 break; 05235 } 05236 05237 /* Woot we got a message, create a control frame and send it on! */ 05238 if (parameters.request_response) 05239 ast_queue_control_data(chan, AST_CONTROL_T38_PARAMETERS, ¶meters, sizeof(parameters)); 05240 }
| static enum check_auth_result check_auth | ( | struct sip_pvt * | p, | |
| struct sip_request * | req, | |||
| const char * | username, | |||
| const char * | secret, | |||
| const char * | md5secret, | |||
| int | sipmethod, | |||
| const char * | uri, | |||
| enum xmittype | reliable, | |||
| int | ignore | |||
| ) | [static] |
Check user authorization from peer definition Some actions, like REGISTER and INVITEs from peers require authentication (if peer have secret set).
XXX
XXX
Definition at line 14787 of file chan_sip.c.
References append_history, ast_copy_string(), AST_DYNSTR_BUILD_FAILED, ast_log(), ast_md5_hash(), ast_str_set(), ast_str_thread_get(), ast_strlen_zero(), FALSE, LOG_NOTICE, LOG_WARNING, S_OR, set_nonce_randdata(), sip_auth_headers(), sip_digest_parser(), sip_get_header(), sip_methods, sip_scheddestroy(), text, transmit_response_with_auth(), and TRUE.
Referenced by check_peer_ok(), and register_verify().
14790 { 14791 const char *response; 14792 char *reqheader, *respheader; 14793 const char *authtoken; 14794 char a1_hash[256]; 14795 char resp_hash[256]=""; 14796 char *c; 14797 int wrongnonce = FALSE; 14798 int good_response; 14799 const char *usednonce = p->randdata; 14800 struct ast_str *buf; 14801 int res; 14802 14803 /* table of recognised keywords, and their value in the digest */ 14804 struct digestkeys keys[] = { 14805 [K_RESP] = { "response=", "" }, 14806 [K_URI] = { "uri=", "" }, 14807 [K_USER] = { "username=", "" }, 14808 [K_NONCE] = { "nonce=", "" }, 14809 [K_LAST] = { NULL, NULL} 14810 }; 14811 14812 /* Always OK if no secret */ 14813 if (ast_strlen_zero(secret) && ast_strlen_zero(md5secret)) { 14814 return AUTH_SUCCESSFUL; 14815 } 14816 14817 /* Always auth with WWW-auth since we're NOT a proxy */ 14818 /* Using proxy-auth in a B2BUA may block proxy authorization in the same transaction */ 14819 response = "401 Unauthorized"; 14820 14821 /* 14822 * Note the apparent swap of arguments below, compared to other 14823 * usages of sip_auth_headers(). 14824 */ 14825 sip_auth_headers(WWW_AUTH, &respheader, &reqheader); 14826 14827 authtoken = sip_get_header(req, reqheader); 14828 if (ignore && !ast_strlen_zero(p->randdata) && ast_strlen_zero(authtoken)) { 14829 /* This is a retransmitted invite/register/etc, don't reconstruct authentication 14830 information */ 14831 if (!reliable) { 14832 /* Resend message if this was NOT a reliable delivery. Otherwise the 14833 retransmission should get it */ 14834 transmit_response_with_auth(p, response, req, p->randdata, reliable, respheader, 0); 14835 /* Schedule auto destroy in 32 seconds (according to RFC 3261) */ 14836 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 14837 } 14838 return AUTH_CHALLENGE_SENT; 14839 } else if (ast_strlen_zero(p->randdata) || ast_strlen_zero(authtoken)) { 14840 /* We have no auth, so issue challenge and request authentication */ 14841 set_nonce_randdata(p, 1); /* Create nonce for challenge */ 14842 transmit_response_with_auth(p, response, req, p->randdata, reliable, respheader, 0); 14843 /* Schedule auto destroy in 32 seconds */ 14844 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 14845 return AUTH_CHALLENGE_SENT; 14846 } 14847 14848 /* --- We have auth, so check it */ 14849 14850 /* Whoever came up with the authentication section of SIP can suck my %&#$&* for not putting 14851 an example in the spec of just what it is you're doing a hash on. */ 14852 14853 if (!(buf = ast_str_thread_get(&check_auth_buf, CHECK_AUTH_BUF_INITLEN))) { 14854 return AUTH_SECRET_FAILED; /*! XXX \todo need a better return code here */ 14855 } 14856 14857 /* Make a copy of the response and parse it */ 14858 res = ast_str_set(&buf, 0, "%s", authtoken); 14859 14860 if (res == AST_DYNSTR_BUILD_FAILED) { 14861 return AUTH_SECRET_FAILED; /*! XXX \todo need a better return code here */ 14862 } 14863 14864 c = buf->str; 14865 14866 sip_digest_parser(c, keys); 14867 14868 /* Verify that digest username matches the username we auth as */ 14869 if (strcmp(username, keys[K_USER].s)) { 14870 ast_log(LOG_WARNING, "username mismatch, have <%s>, digest has <%s>\n", 14871 username, keys[K_USER].s); 14872 /* Oops, we're trying something here */ 14873 return AUTH_USERNAME_MISMATCH; 14874 } 14875 14876 /* Verify nonce from request matches our nonce, and the nonce has not already been responded to. 14877 * If this check fails, send 401 with new nonce */ 14878 if (strcasecmp(p->randdata, keys[K_NONCE].s) || p->stalenonce) { /* XXX it was 'n'casecmp ? */ 14879 wrongnonce = TRUE; 14880 usednonce = keys[K_NONCE].s; 14881 } else { 14882 p->stalenonce = 1; /* now, since the nonce has a response, mark it as stale so it can't be sent or responded to again */ 14883 } 14884 14885 if (!ast_strlen_zero(md5secret)) { 14886 ast_copy_string(a1_hash, md5secret, sizeof(a1_hash)); 14887 } else { 14888 char a1[256]; 14889 14890 snprintf(a1, sizeof(a1), "%s:%s:%s", username, p->realm, secret); 14891 ast_md5_hash(a1_hash, a1); 14892 } 14893 14894 /* compute the expected response to compare with what we received */ 14895 { 14896 char a2[256]; 14897 char a2_hash[256]; 14898 char resp[256]; 14899 14900 snprintf(a2, sizeof(a2), "%s:%s", sip_methods[sipmethod].text, 14901 S_OR(keys[K_URI].s, uri)); 14902 ast_md5_hash(a2_hash, a2); 14903 snprintf(resp, sizeof(resp), "%s:%s:%s", a1_hash, usednonce, a2_hash); 14904 ast_md5_hash(resp_hash, resp); 14905 } 14906 14907 good_response = keys[K_RESP].s && 14908 !strncasecmp(keys[K_RESP].s, resp_hash, strlen(resp_hash)); 14909 if (wrongnonce) { 14910 if (good_response) { 14911 if (sipdebug) 14912 ast_log(LOG_NOTICE, "Correct auth, but based on stale nonce received from '%s'\n", sip_get_header(req, "From")); 14913 /* We got working auth token, based on stale nonce . */ 14914 set_nonce_randdata(p, 0); 14915 transmit_response_with_auth(p, response, req, p->randdata, reliable, respheader, TRUE); 14916 } else { 14917 /* Everything was wrong, so give the device one more try with a new challenge */ 14918 if (!req->ignore) { 14919 if (sipdebug) { 14920 ast_log(LOG_NOTICE, "Bad authentication received from '%s'\n", sip_get_header(req, "To")); 14921 } 14922 set_nonce_randdata(p, 1); 14923 } else { 14924 if (sipdebug) { 14925 ast_log(LOG_NOTICE, "Duplicate authentication received from '%s'\n", sip_get_header(req, "To")); 14926 } 14927 } 14928 transmit_response_with_auth(p, response, req, p->randdata, reliable, respheader, FALSE); 14929 } 14930 14931 /* Schedule auto destroy in 32 seconds */ 14932 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 14933 return AUTH_CHALLENGE_SENT; 14934 } 14935 if (good_response) { 14936 append_history(p, "AuthOK", "Auth challenge successful for %s", username); 14937 return AUTH_SUCCESSFUL; 14938 } 14939 14940 /* Ok, we have a bad username/secret pair */ 14941 /* Tell the UAS not to re-send this authentication data, because 14942 it will continue to fail 14943 */ 14944 14945 return AUTH_SECRET_FAILED; 14946 }
| static enum check_auth_result check_peer_ok | ( | struct sip_pvt * | p, | |
| char * | of, | |||
| struct sip_request * | req, | |||
| int | sipmethod, | |||
| struct ast_sockaddr * | addr, | |||
| struct sip_peer ** | authpeer, | |||
| enum xmittype | reliable, | |||
| char * | calleridname, | |||
| char * | uri2 | |||
| ) | [static] |
Validate device authentication.
Definition at line 16404 of file chan_sip.c.
References accountcode, ao2_t_ref, ast_apply_ha(), ast_cc_copy_config_params(), ast_copy_flags, ast_copy_string(), ast_debug, ast_format_cap_copy(), ast_format_cap_destroy(), ast_format_cap_is_empty(), ast_format_cap_joint(), ast_is_shrinkable_phonenumber(), ast_rtp_codecs_packetization_set(), AST_RTP_DTMF, ast_rtp_instance_get_codecs(), ast_set_flag, ast_shrink_phone_number(), ast_sockaddr_stringify(), ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_variables_destroy(), ast_verbose, check_auth(), cid_name, cid_num, context, copy_vars(), debug, dialog_initialize_rtp(), do_setnat(), dummy(), FALSE, get_rpid(), language, mohinterpret, mohsuggest, parkinglot, parse_uri(), set_pvt_allowed_methods(), set_t38_capabilities(), sip_debug_test_addr(), sip_find_peer(), sip_find_peer_by_ip_and_exten(), sip_unref_peer(), and TRUE.
Referenced by check_user_full().
16408 { 16409 enum check_auth_result res; 16410 int debug = sip_debug_test_addr(addr); 16411 struct sip_peer *peer; 16412 16413 if (sipmethod == SIP_SUBSCRIBE) { 16414 /* For subscribes, match on device name only; for other methods, 16415 * match on IP address-port of the incoming request. 16416 */ 16417 peer = sip_find_peer(of, NULL, TRUE, FINDALLDEVICES, FALSE, 0); 16418 } else { 16419 /* First find devices based on username (avoid all type=peer's) */ 16420 peer = sip_find_peer(of, NULL, TRUE, FINDUSERS, FALSE, 0); 16421 16422 /* Then find devices based on IP */ 16423 if (!peer) { 16424 char *uri_tmp, *callback = NULL, *dummy; 16425 uri_tmp = ast_strdupa(uri2); 16426 parse_uri(uri_tmp, "sip:,sips:", &callback, &dummy, &dummy, &dummy); 16427 if (!ast_strlen_zero(callback) && (peer = sip_find_peer_by_ip_and_exten(&p->recv, callback, p->socket.type))) { 16428 ; /* found, fall through */ 16429 } else { 16430 peer = sip_find_peer(NULL, &p->recv, TRUE, FINDPEERS, FALSE, p->socket.type); 16431 } 16432 } 16433 } 16434 16435 if (!peer) { 16436 if (debug) { 16437 ast_verbose("No matching peer for '%s' from '%s'\n", 16438 of, ast_sockaddr_stringify(&p->recv)); 16439 } 16440 return AUTH_DONT_KNOW; 16441 } 16442 16443 if (!ast_apply_ha(peer->ha, addr)) { 16444 ast_debug(2, "Found peer '%s' for '%s', but fails host access\n", peer->name, of); 16445 sip_unref_peer(peer, "sip_unref_peer: check_peer_ok: from sip_find_peer call, early return of AUTH_ACL_FAILED"); 16446 return AUTH_ACL_FAILED; 16447 } 16448 if (debug) 16449 ast_verbose("Found peer '%s' for '%s' from %s\n", 16450 peer->name, of, ast_sockaddr_stringify(&p->recv)); 16451 16452 /* XXX what about p->prefs = peer->prefs; ? */ 16453 /* Set Frame packetization */ 16454 if (p->rtp) { 16455 ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(p->rtp), p->rtp, &peer->prefs); 16456 p->autoframing = peer->autoframing; 16457 } 16458 16459 /* Take the peer */ 16460 ast_copy_flags(&p->flags[0], &peer->flags[0], SIP_FLAGS_TO_COPY); 16461 ast_copy_flags(&p->flags[1], &peer->flags[1], SIP_PAGE2_FLAGS_TO_COPY); 16462 ast_copy_flags(&p->flags[2], &peer->flags[2], SIP_PAGE3_FLAGS_TO_COPY); 16463 16464 if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT) && p->udptl) { 16465 p->t38_maxdatagram = peer->t38_maxdatagram; 16466 set_t38_capabilities(p); 16467 } 16468 16469 /* Copy SIP extensions profile to peer */ 16470 /* XXX is this correct before a successful auth ? */ 16471 if (p->sipoptions) 16472 peer->sipoptions = p->sipoptions; 16473 16474 do_setnat(p); 16475 16476 ast_string_field_set(p, peersecret, peer->secret); 16477 ast_string_field_set(p, peermd5secret, peer->md5secret); 16478 ast_string_field_set(p, subscribecontext, peer->subscribecontext); 16479 ast_string_field_set(p, mohinterpret, peer->mohinterpret); 16480 ast_string_field_set(p, mohsuggest, peer->mohsuggest); 16481 if (!ast_strlen_zero(peer->parkinglot)) { 16482 ast_string_field_set(p, parkinglot, peer->parkinglot); 16483 } 16484 ast_string_field_set(p, engine, peer->engine); 16485 p->disallowed_methods = peer->disallowed_methods; 16486 set_pvt_allowed_methods(p, req); 16487 ast_cc_copy_config_params(p->cc_params, peer->cc_params); 16488 if (peer->callingpres) /* Peer calling pres setting will override RPID */ 16489 p->callingpres = peer->callingpres; 16490 if (peer->maxms && peer->lastms) 16491 p->timer_t1 = peer->lastms < global_t1min ? global_t1min : peer->lastms; 16492 else 16493 p->timer_t1 = peer->timer_t1; 16494 16495 /* Set timer B to control transaction timeouts */ 16496 if (peer->timer_b) 16497 p->timer_b = peer->timer_b; 16498 else 16499 p->timer_b = 64 * p->timer_t1; 16500 16501 if (ast_test_flag(&peer->flags[0], SIP_INSECURE_INVITE)) { 16502 /* Pretend there is no required authentication */ 16503 ast_string_field_set(p, peersecret, NULL); 16504 ast_string_field_set(p, peermd5secret, NULL); 16505 } 16506 if (!(res = check_auth(p, req, peer->name, p->peersecret, p->peermd5secret, sipmethod, uri2, reliable, req->ignore))) { 16507 ast_copy_flags(&p->flags[0], &peer->flags[0], SIP_FLAGS_TO_COPY); 16508 ast_copy_flags(&p->flags[1], &peer->flags[1], SIP_PAGE2_FLAGS_TO_COPY); 16509 ast_copy_flags(&p->flags[2], &peer->flags[2], SIP_PAGE3_FLAGS_TO_COPY); 16510 /* If we have a call limit, set flag */ 16511 if (peer->call_limit) 16512 ast_set_flag(&p->flags[0], SIP_CALL_LIMIT); 16513 ast_string_field_set(p, peername, peer->name); 16514 ast_string_field_set(p, authname, peer->name); 16515 16516 if (sipmethod == SIP_INVITE) { 16517 /* destroy old channel vars and copy in new ones. */ 16518 ast_variables_destroy(p->chanvars); 16519 p->chanvars = copy_vars(peer->chanvars); 16520 } 16521 16522 if (authpeer) { 16523 ao2_t_ref(peer, 1, "copy pointer into (*authpeer)"); 16524 (*authpeer) = peer; /* Add a ref to the object here, to keep it in memory a bit longer if it is realtime */ 16525 } 16526 16527 if (!ast_strlen_zero(peer->username)) { 16528 ast_string_field_set(p, username, peer->username); 16529 /* Use the default username for authentication on outbound calls */ 16530 /* XXX this takes the name from the caller... can we override ? */ 16531 ast_string_field_set(p, authname, peer->username); 16532 } 16533 if (!get_rpid(p, req)) { 16534 if (!ast_strlen_zero(peer->cid_num)) { 16535 char *tmp = ast_strdupa(peer->cid_num); 16536 if (global_shrinkcallerid && ast_is_shrinkable_phonenumber(tmp)) 16537 ast_shrink_phone_number(tmp); 16538 ast_string_field_set(p, cid_num, tmp); 16539 } 16540 if (!ast_strlen_zero(peer->cid_name)) 16541 ast_string_field_set(p, cid_name, peer->cid_name); 16542 if (!ast_strlen_zero(peer->cid_tag)) 16543 ast_string_field_set(p, cid_tag, peer->cid_tag); 16544 if (peer->callingpres) 16545 p->callingpres = peer->callingpres; 16546 } 16547 ast_string_field_set(p, fullcontact, peer->fullcontact); 16548 if (!ast_strlen_zero(peer->context)) { 16549 ast_string_field_set(p, context, peer->context); 16550 } 16551 if (!ast_strlen_zero(peer->messagecontext)) { 16552 ast_string_field_set(p, messagecontext, peer->messagecontext); 16553 } 16554 if (!ast_strlen_zero(peer->mwi_from)) { 16555 ast_string_field_set(p, mwi_from, peer->mwi_from); 16556 } 16557 ast_string_field_set(p, peersecret, peer->secret); 16558 ast_string_field_set(p, peermd5secret, peer->md5secret); 16559 ast_string_field_set(p, language, peer->language); 16560 ast_string_field_set(p, accountcode, peer->accountcode); 16561 p->amaflags = peer->amaflags; 16562 p->callgroup = peer->callgroup; 16563 p->pickupgroup = peer->pickupgroup; 16564 ast_format_cap_copy(p->caps, peer->caps); 16565 ast_format_cap_copy(p->jointcaps, peer->caps); 16566 p->prefs = peer->prefs; 16567 ast_copy_string(p->zone, peer->zone, sizeof(p->zone)); 16568 if (peer->maxforwards > 0) { 16569 p->maxforwards = peer->maxforwards; 16570 } 16571 if (!(ast_format_cap_is_empty(p->peercaps))) { 16572 struct ast_format_cap *tmp = ast_format_cap_joint(p->jointcaps, p->peercaps); 16573 struct ast_format_cap *tmp2; 16574 if (tmp) { 16575 tmp2 = p->jointcaps; 16576 p->jointcaps = tmp; 16577 ast_format_cap_destroy(tmp2); 16578 } 16579 } 16580 p->maxcallbitrate = peer->maxcallbitrate; 16581 if ((ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833) || 16582 (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO)) 16583 p->noncodeccapability |= AST_RTP_DTMF; 16584 else 16585 p->noncodeccapability &= ~AST_RTP_DTMF; 16586 p->jointnoncodeccapability = p->noncodeccapability; 16587 p->rtptimeout = peer->rtptimeout; 16588 p->rtpholdtimeout = peer->rtpholdtimeout; 16589 p->rtpkeepalive = peer->rtpkeepalive; 16590 if (!dialog_initialize_rtp(p)) { 16591 if (p->rtp) { 16592 ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(p->rtp), p->rtp, &peer->prefs); 16593 p->autoframing = peer->autoframing; 16594 } 16595 } else { 16596 res = AUTH_RTP_FAILED; 16597 } 16598 } 16599 sip_unref_peer(peer, "check_peer_ok: sip_unref_peer: tossing temp ptr to peer from sip_find_peer"); 16600 return res; 16601 }
| static void check_pendings | ( | struct sip_pvt * | p | ) | [static] |
Check pending actions on SIP call.
Definition at line 20521 of file chan_sip.c.
References ast_clear_flag, ast_debug, AST_SOFTHANGUP_DEV, ast_softhangup_nolock(), ast_test_flag, FALSE, sip_scheddestroy(), transmit_reinvite_with_sdp(), transmit_request(), transmit_request_with_auth(), and TRUE.
Referenced by handle_incoming(), handle_response_invite(), and sip_reinvite_retry().
20522 { 20523 if (ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) { 20524 /* if we can't BYE, then this is really a pending CANCEL */ 20525 if (p->invitestate == INV_PROCEEDING || p->invitestate == INV_EARLY_MEDIA) { 20526 p->invitestate = INV_CANCELLED; 20527 transmit_request(p, SIP_CANCEL, p->lastinvite, XMIT_RELIABLE, FALSE); 20528 /* Actually don't destroy us yet, wait for the 487 on our original 20529 INVITE, but do set an autodestruct just in case we never get it. */ 20530 } else { 20531 /* We have a pending outbound invite, don't send something 20532 new in-transaction */ 20533 if (p->pendinginvite) 20534 return; 20535 20536 if (p->owner) { 20537 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_DEV); 20538 } 20539 /* Perhaps there is an SD change INVITE outstanding */ 20540 transmit_request_with_auth(p, SIP_BYE, 0, XMIT_RELIABLE, TRUE); 20541 } 20542 ast_clear_flag(&p->flags[0], SIP_PENDINGBYE); 20543 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 20544 } else if (ast_test_flag(&p->flags[0], SIP_NEEDREINVITE)) { 20545 /* if we can't REINVITE, hold it for later */ 20546 if (p->pendinginvite || p->invitestate == INV_CALLING || p->invitestate == INV_PROCEEDING || p->invitestate == INV_EARLY_MEDIA || p->waitid > 0) { 20547 ast_debug(2, "NOT Sending pending reinvite (yet) on '%s'\n", p->callid); 20548 } else { 20549 ast_debug(2, "Sending pending reinvite on '%s'\n", p->callid); 20550 /* Didn't get to reinvite yet, so do it now */ 20551 transmit_reinvite_with_sdp(p, (p->t38.state == T38_LOCAL_REINVITE ? TRUE : FALSE), FALSE); 20552 ast_clear_flag(&p->flags[0], SIP_NEEDREINVITE); 20553 } 20554 } 20555 }
| static int check_rtp_timeout | ( | struct sip_pvt * | dialog, | |
| time_t | t | |||
| ) | [static] |
helper function for the monitoring thread -- seems to be called with the assumption that the dialog is locked
Definition at line 26710 of file chan_sip.c.
References ast_channel_name(), ast_channel_trylock, ast_channel_uniqueid(), ast_channel_unlock, ast_log(), ast_rtp_instance_get_hold_timeout(), ast_rtp_instance_get_keepalive(), ast_rtp_instance_get_timeout(), ast_rtp_instance_sendcng(), ast_rtp_instance_set_hold_timeout(), ast_rtp_instance_set_timeout(), ast_sockaddr_isnull(), AST_SOFTHANGUP_DEV, ast_softhangup_nolock(), AST_STATE_UP, ast_test_flag, CMP_MATCH, EVENT_FLAG_CALL, keepalive, LOG_NOTICE, and manager_event.
Referenced by dialog_checkrtp_cb().
26711 { 26712 int timeout; 26713 int hold_timeout; 26714 int keepalive; 26715 26716 if (!dialog->rtp) { 26717 /* 26718 * We have no RTP. Since we don't do much with video RTP for 26719 * now, stop checking this dialog. 26720 */ 26721 return CMP_MATCH; 26722 } 26723 26724 /* If we have no active owner, no need to check timers */ 26725 if (!dialog->owner) { 26726 return CMP_MATCH; 26727 } 26728 26729 /* If the call is redirected outside Asterisk, no need to check timers */ 26730 if (!ast_sockaddr_isnull(&dialog->redirip)) { 26731 return CMP_MATCH; 26732 } 26733 26734 /* If the call is involved in a T38 fax session do not check RTP timeout */ 26735 if (dialog->t38.state == T38_ENABLED) { 26736 return CMP_MATCH; 26737 } 26738 /* If the call is not in UP state return for later check. */ 26739 if (dialog->owner->_state != AST_STATE_UP) { 26740 return 0; 26741 } 26742 26743 /* Store these values locally to avoid multiple function calls */ 26744 timeout = ast_rtp_instance_get_timeout(dialog->rtp); 26745 hold_timeout = ast_rtp_instance_get_hold_timeout(dialog->rtp); 26746 keepalive = ast_rtp_instance_get_keepalive(dialog->rtp); 26747 26748 /* If we have no timers set, return now */ 26749 if (!keepalive && !timeout && !hold_timeout) { 26750 return CMP_MATCH; 26751 } 26752 26753 /* Check AUDIO RTP keepalives */ 26754 if (dialog->lastrtptx && keepalive && (t > dialog->lastrtptx + keepalive)) { 26755 /* Need to send an empty RTP packet */ 26756 dialog->lastrtptx = time(NULL); 26757 ast_rtp_instance_sendcng(dialog->rtp, 0); 26758 } 26759 26760 /*! \todo Check video RTP keepalives 26761 26762 Do we need to move the lastrtptx to the RTP structure to have one for audio and one 26763 for video? It really does belong to the RTP structure. 26764 */ 26765 26766 /* Check AUDIO RTP timers */ 26767 if (dialog->lastrtprx && (timeout || hold_timeout) && (t > dialog->lastrtprx + timeout)) { 26768 if (!ast_test_flag(&dialog->flags[1], SIP_PAGE2_CALL_ONHOLD) || (hold_timeout && (t > dialog->lastrtprx + hold_timeout))) { 26769 /* Needs a hangup */ 26770 if (timeout) { 26771 if (!dialog->owner || ast_channel_trylock(dialog->owner)) { 26772 /* 26773 * Don't block, just try again later. 26774 * If there was no owner, the call is dead already. 26775 */ 26776 return 0; 26777 } 26778 ast_log(LOG_NOTICE, "Disconnecting call '%s' for lack of RTP activity in %ld seconds\n", 26779 ast_channel_name(dialog->owner), (long) (t - dialog->lastrtprx)); 26780 manager_event(EVENT_FLAG_CALL, "SessionTimeout", "Source: RTPTimeout\r\n" 26781 "Channel: %s\r\nUniqueid: %s\r\n", ast_channel_name(dialog->owner), ast_channel_uniqueid(dialog->owner)); 26782 /* Issue a softhangup */ 26783 ast_softhangup_nolock(dialog->owner, AST_SOFTHANGUP_DEV); 26784 ast_channel_unlock(dialog->owner); 26785 /* forget the timeouts for this call, since a hangup 26786 has already been requested and we don't want to 26787 repeatedly request hangups 26788 */ 26789 ast_rtp_instance_set_timeout(dialog->rtp, 0); 26790 ast_rtp_instance_set_hold_timeout(dialog->rtp, 0); 26791 if (dialog->vrtp) { 26792 ast_rtp_instance_set_timeout(dialog->vrtp, 0); 26793 ast_rtp_instance_set_hold_timeout(dialog->vrtp, 0); 26794 } 26795 /* finally unlink the dialog from dialogs_rtpcheck. */ 26796 return CMP_MATCH; 26797 } 26798 } 26799 } 26800 return 0; 26801 }
| static int check_sip_domain | ( | const char * | domain, | |
| char * | context, | |||
| size_t | len | |||
| ) | [static] |
check_sip_domain: Check if domain part of uri is local to our server
Definition at line 27925 of file chan_sip.c.
References ast_copy_string(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and ast_strlen_zero().
Referenced by func_check_sipdomain(), get_destination(), get_realm(), handle_request_refer(), and register_verify().
27926 { 27927 struct domain *d; 27928 int result = 0; 27929 27930 AST_LIST_LOCK(&domain_list); 27931 AST_LIST_TRAVERSE(&domain_list, d, list) { 27932 if (strcasecmp(d->domain, domain)) { 27933 continue; 27934 } 27935 27936 if (len && !ast_strlen_zero(d->context)) 27937 ast_copy_string(context, d->context, len); 27938 27939 result = 1; 27940 break; 27941 } 27942 AST_LIST_UNLOCK(&domain_list); 27943 27944 return result; 27945 }
| static int check_user | ( | struct sip_pvt * | p, | |
| struct sip_request * | req, | |||
| int | sipmethod, | |||
| const char * | uri, | |||
| enum xmittype | reliable, | |||
| struct ast_sockaddr * | addr | |||
| ) | [static] |
Find user If we get a match, this will add a reference pointer to the user object in ASTOBJ, that needs to be unreferenced.
Definition at line 16740 of file chan_sip.c.
References check_user_full().
Referenced by handle_request_options(), handle_request_publish(), and receive_message().
16741 { 16742 return check_user_full(p, req, sipmethod, uri, reliable, addr, NULL); 16743 }
| static enum check_auth_result check_user_full | ( | struct sip_pvt * | p, | |
| struct sip_request * | req, | |||
| int | sipmethod, | |||
| const char * | uri, | |||
| enum xmittype | reliable, | |||
| struct ast_sockaddr * | addr, | |||
| struct sip_peer ** | authpeer | |||
| ) | [static] |
Check if matching user or peer is defined Match user on From: user name and peer on IP/port This is used on first invite (not re-invites) and subscribe requests.
Definition at line 16609 of file chan_sip.c.
References ast_copy_string(), ast_is_shrinkable_phonenumber(), ast_log(), ast_set_flag, ast_shrink_phone_number(), ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, build_contact(), check_peer_ok(), cid_name, cid_num, dialog_initialize_rtp(), exten, extract_host_from_hostport(), get_calleridname(), get_in_brackets(), get_rpid(), LOG_ERROR, LOG_NOTICE, name, parse_uri_legacy_check(), sip_cfg, sip_get_header(), SIP_PEDANTIC_DECODE, strsep(), and terminate_uri().
Referenced by check_user(), handle_request_invite(), and handle_request_subscribe().
16612 { 16613 char from[256] = "", *of, *name, *unused_password, *domain; 16614 enum check_auth_result res = AUTH_DONT_KNOW; 16615 char calleridname[50]; 16616 char *uri2 = ast_strdupa(uri); 16617 16618 terminate_uri(uri2); /* trim extra stuff */ 16619 16620 ast_copy_string(from, sip_get_header(req, "From"), sizeof(from)); 16621 /* XXX here tries to map the username for invite things */ 16622 16623 /* strip the display-name portion off the beginning of the FROM header. */ 16624 if (!(of = (char *) get_calleridname(from, calleridname, sizeof(calleridname)))) { 16625 ast_log(LOG_ERROR, "FROM header can not be parsed \n"); 16626 return res; 16627 } 16628 16629 if (calleridname[0]) { 16630 ast_string_field_set(p, cid_name, calleridname); 16631 } 16632 16633 if (ast_strlen_zero(p->exten)) { 16634 char *t = uri2; 16635 if (!strncasecmp(t, "sip:", 4)) 16636 t+= 4; 16637 else if (!strncasecmp(t, "sips:", 5)) 16638 t += 5; 16639 ast_string_field_set(p, exten, t); 16640 t = strchr(p->exten, '@'); 16641 if (t) 16642 *t = '\0'; 16643 16644 if (ast_strlen_zero(p->our_contact)) 16645 build_contact(p); 16646 } 16647 16648 of = get_in_brackets(of); 16649 16650 /* save the URI part of the From header */ 16651 ast_string_field_set(p, from, of); 16652 16653 if (parse_uri_legacy_check(of, "sip:,sips:", &name, &unused_password, &domain, NULL)) { 16654 ast_log(LOG_NOTICE, "From address missing 'sip:', using it anyway\n"); 16655 } 16656 16657 SIP_PEDANTIC_DECODE(name); 16658 SIP_PEDANTIC_DECODE(domain); 16659 16660 extract_host_from_hostport(&domain); 16661 16662 if (ast_strlen_zero(domain)) { 16663 /* <sip:name@[EMPTY]>, never good */ 16664 ast_log(LOG_ERROR, "Empty domain name in FROM header\n"); 16665 return res; 16666 } 16667 16668 if (ast_strlen_zero(name)) { 16669 /* <sip:[EMPTY][@]hostport>. Asterisk 1.4 and 1.6 have always 16670 * treated that as a username, so we continue the tradition: 16671 * uri is now <sip:host@hostport>. */ 16672 name = domain; 16673 } else { 16674 /* Non-empty name, try to get caller id from it */ 16675 char *tmp = ast_strdupa(name); 16676 /* We need to be able to handle from-headers looking like 16677 <sip:8164444422;phone-context=+1@1.2.3.4:5060;user=phone;tag=SDadkoa01-gK0c3bdb43> 16678 */ 16679 tmp = strsep(&tmp, ";"); 16680 if (global_shrinkcallerid && ast_is_shrinkable_phonenumber(tmp)) { 16681 ast_shrink_phone_number(tmp); 16682 } 16683 ast_string_field_set(p, cid_num, tmp); 16684 } 16685 16686 if (global_match_auth_username) { 16687 /* 16688 * XXX This is experimental code to grab the search key from the 16689 * Auth header's username instead of the 'From' name, if available. 16690 * Do not enable this block unless you understand the side effects (if any!) 16691 * Note, the search for "username" should be done in a more robust way. 16692 * Note2, at the moment we check both fields, though maybe we should 16693 * pick one or another depending on the request ? XXX 16694 */ 16695 const char *hdr = sip_get_header(req, "Authorization"); 16696 if (ast_strlen_zero(hdr)) { 16697 hdr = sip_get_header(req, "Proxy-Authorization"); 16698 } 16699 16700 if (!ast_strlen_zero(hdr) && (hdr = strstr(hdr, "username=\""))) { 16701 ast_copy_string(from, hdr + strlen("username=\""), sizeof(from)); 16702 name = from; 16703 name = strsep(&name, "\""); 16704 } 16705 } 16706 16707 res = check_peer_ok(p, name, req, sipmethod, addr, 16708 authpeer, reliable, calleridname, uri2); 16709 if (res != AUTH_DONT_KNOW) { 16710 return res; 16711 } 16712 16713 /* Finally, apply the guest policy */ 16714 if (sip_cfg.allowguest) { 16715 get_rpid(p, req); 16716 p->rtptimeout = global_rtptimeout; 16717 p->rtpholdtimeout = global_rtpholdtimeout; 16718 p->rtpkeepalive = global_rtpkeepalive; 16719 if (!dialog_initialize_rtp(p)) { 16720 res = AUTH_SUCCESSFUL; 16721 } else { 16722 res = AUTH_RTP_FAILED; 16723 } 16724 } else if (sip_cfg.alwaysauthreject) { 16725 res = AUTH_FAKE_AUTH; /* reject with fake authorization request */ 16726 } else { 16727 res = AUTH_SECRET_FAILED; /* we don't want any guests, authentication will fail */ 16728 } 16729 16730 if (ast_test_flag(&p->flags[1], SIP_PAGE2_RPORT_PRESENT)) { 16731 ast_set_flag(&p->flags[0], SIP_NAT_RPORT_PRESENT); 16732 } 16733 16734 return res; 16735 }
| static void check_via | ( | struct sip_pvt * | p, | |
| struct sip_request * | req | |||
| ) | [static] |
check Via: header for hostname, port and rport request/answer
Definition at line 16319 of file chan_sip.c.
References ast_clear_flag, ast_copy_string(), ast_debug, ast_log(), ast_set_flag, ast_skip_blanks(), ast_sockaddr_cmp(), ast_sockaddr_port, ast_sockaddr_resolve_first(), ast_sockaddr_set_port, ast_sockaddr_stringify(), ast_strdupa, ast_test_flag, ast_verbose, LOG_WARNING, sip_debug_test_pvt(), sip_get_header(), sip_nat_mode(), and sip_real_dst().
Referenced by handle_request_bye(), handle_request_cancel(), handle_request_invite(), handle_request_register(), and handle_request_subscribe().
16320 { 16321 char via[512]; 16322 char *c, *maddr; 16323 struct ast_sockaddr tmp = { { 0, } }; 16324 uint16_t port; 16325 16326 ast_copy_string(via, sip_get_header(req, "Via"), sizeof(via)); 16327 16328 /* Work on the leftmost value of the topmost Via header */ 16329 c = strchr(via, ','); 16330 if (c) 16331 *c = '\0'; 16332 16333 /* Check for rport */ 16334 c = strstr(via, ";rport"); 16335 if (c && (c[6] != '=')) { /* rport query, not answer */ 16336 ast_set_flag(&p->flags[1], SIP_PAGE2_RPORT_PRESENT); 16337 ast_set_flag(&p->flags[0], SIP_NAT_RPORT_PRESENT); 16338 } 16339 16340 /* Check for maddr */ 16341 maddr = strstr(via, "maddr="); 16342 if (maddr) { 16343 maddr += 6; 16344 c = maddr + strspn(maddr, "abcdefghijklmnopqrstuvwxyz" 16345 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-.:[]"); 16346 *c = '\0'; 16347 } 16348 16349 c = strchr(via, ';'); 16350 if (c) 16351 *c = '\0'; 16352 16353 c = strchr(via, ' '); 16354 if (c) { 16355 *c = '\0'; 16356 c = ast_skip_blanks(c+1); 16357 if (strcasecmp(via, "SIP/2.0/UDP") && strcasecmp(via, "SIP/2.0/TCP") && strcasecmp(via, "SIP/2.0/TLS")) { 16358 ast_log(LOG_WARNING, "Don't know how to respond via '%s'\n", via); 16359 return; 16360 } 16361 16362 if (maddr && ast_sockaddr_resolve_first(&p->sa, maddr, 0)) { 16363 p->sa = p->recv; 16364 } 16365 16366 ast_sockaddr_resolve_first(&tmp, c, 0); 16367 port = ast_sockaddr_port(&tmp); 16368 ast_sockaddr_set_port(&p->sa, 16369 port != 0 ? port : STANDARD_SIP_PORT); 16370 16371 /* Check and see if the requesting UA is likely to be behind a NAT. If they are, set the 16372 * natdetected flag so that later, peers with nat=auto_* can use the value. Also 16373 * set the flags so that Asterisk responds identically whether or not a peer exists 16374 * so as not to leak peer name information. */ 16375 if (ast_sockaddr_cmp(&tmp, &p->recv)) { 16376 char *tmp_str = ast_strdupa(ast_sockaddr_stringify(&tmp)); 16377 ast_debug(3, "NAT detected for %s / %s\n", tmp_str, ast_sockaddr_stringify(&p->recv)); 16378 p->natdetected = 1; 16379 if (ast_test_flag(&p->flags[2], SIP_PAGE3_NAT_AUTO_RPORT)) { 16380 ast_set_flag(&p->flags[0], SIP_NAT_FORCE_RPORT); 16381 } 16382 if (ast_test_flag(&p->flags[2], SIP_PAGE3_NAT_AUTO_COMEDIA)) { 16383 ast_set_flag(&p->flags[1], SIP_PAGE2_SYMMETRICRTP); 16384 } 16385 } else { 16386 p->natdetected = 0; 16387 if (ast_test_flag(&p->flags[2], SIP_PAGE3_NAT_AUTO_RPORT)) { 16388 ast_clear_flag(&p->flags[0], SIP_NAT_FORCE_RPORT); 16389 } 16390 if (ast_test_flag(&p->flags[2], SIP_PAGE3_NAT_AUTO_COMEDIA)) { 16391 ast_clear_flag(&p->flags[1], SIP_PAGE2_SYMMETRICRTP); 16392 } 16393 } 16394 16395 if (sip_debug_test_pvt(p)) { 16396 ast_verbose("Sending to %s (%s)\n", 16397 ast_sockaddr_stringify(sip_real_dst(p)), 16398 sip_nat_mode(p)); 16399 } 16400 } 16401 }
| static attribute_unused void check_via_response | ( | struct sip_pvt * | p, | |
| struct sip_request * | req | |||
| ) | [static] |
check received= and rport= in a SIP response. If we get a response with received= and/or rport= in the Via: line, use them as 'p->ourip' (see RFC 3581 for rport, and RFC 3261 for received). Using these two fields SIP can produce the correct address and port in the SIP headers without the need for STUN. The address part is also reused for the media sessions. Note that ast_sip_ouraddrfor() still rewrites p->ourip if you specify externaddr/seternaddr/.
Definition at line 16289 of file chan_sip.c.
References ast_copy_string(), ast_parse_arg(), ast_sockaddr_set_port, PARSE_ADDR, sip_get_header(), and strsep().
16290 { 16291 char via[256]; 16292 char *cur, *opts; 16293 16294 ast_copy_string(via, sip_get_header(req, "Via"), sizeof(via)); 16295 16296 /* Work on the leftmost value of the topmost Via header */ 16297 opts = strchr(via, ','); 16298 if (opts) 16299 *opts = '\0'; 16300 16301 /* parse all relevant options */ 16302 opts = strchr(via, ';'); 16303 if (!opts) 16304 return; /* no options to parse */ 16305 *opts++ = '\0'; 16306 while ( (cur = strsep(&opts, ";")) ) { 16307 if (!strncmp(cur, "rport=", 6)) { 16308 int port = strtol(cur+6, NULL, 10); 16309 /* XXX add error checking */ 16310 ast_sockaddr_set_port(&p->ourip, port); 16311 } else if (!strncmp(cur, "received=", 9)) { 16312 if (ast_parse_arg(cur + 9, PARSE_ADDR, &p->ourip)) 16313 ; /* XXX add error checking */ 16314 } 16315 } 16316 }
| static void cleanup_all_regs | ( | void | ) | [static] |
Definition at line 28974 of file chan_sip.c.
References ast_debug, ast_dnsmgr_release(), AST_SCHED_DEL_UNREF, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_UNLOCK, ASTOBJ_WRLOCK, dialog_unlink_all(), registry_unref(), and regl.
Referenced by reload_config(), and unload_module().
28975 { 28976 /* First, destroy all outstanding registry calls */ 28977 /* This is needed, since otherwise active registry entries will not be destroyed */ 28978 ASTOBJ_CONTAINER_TRAVERSE(®l, 1, do { /* regl is locked */ 28979 ASTOBJ_WRLOCK(iterator); /* now regl is locked, and the object is also locked */ 28980 if (iterator->call) { 28981 ast_debug(3, "Destroying active SIP dialog for registry %s@%s\n", iterator->username, iterator->hostname); 28982 /* This will also remove references to the registry */ 28983 dialog_unlink_all(iterator->call); 28984 iterator->call = dialog_unref(iterator->call, "remove iterator->call from registry traversal"); 28985 } 28986 if (iterator->expire > -1) { 28987 AST_SCHED_DEL_UNREF(sched, iterator->expire, registry_unref(iterator, "reg ptr unref from reload config")); 28988 } 28989 if (iterator->timeout > -1) { 28990 AST_SCHED_DEL_UNREF(sched, iterator->timeout, registry_unref(iterator, "reg ptr unref from reload config")); 28991 } 28992 if (iterator->dnsmgr) { 28993 ast_dnsmgr_release(iterator->dnsmgr); 28994 iterator->dnsmgr = NULL; 28995 registry_unref(iterator, "reg ptr unref from dnsmgr"); 28996 } 28997 ASTOBJ_UNLOCK(iterator); 28998 } while(0)); 28999 }
| static void cleanup_stale_contexts | ( | char * | new, | |
| char * | old | |||
| ) | [static] |
Destroy disused contexts between reloads Only used in reload_config so the code for regcontext doesn't get ugly.
Definition at line 17663 of file chan_sip.c.
References ast_context_destroy(), ast_context_find(), ast_copy_string(), AST_MAX_CONTEXT, and strsep().
Referenced by config_parse_variables(), and reload_config().
17664 { 17665 char *oldcontext, *newcontext, *stalecontext, *stringp, newlist[AST_MAX_CONTEXT]; 17666 17667 while ((oldcontext = strsep(&old, "&"))) { 17668 stalecontext = '\0'; 17669 ast_copy_string(newlist, new, sizeof(newlist)); 17670 stringp = newlist; 17671 while ((newcontext = strsep(&stringp, "&"))) { 17672 if (!strcmp(newcontext, oldcontext)) { 17673 /* This is not the context you're looking for */ 17674 stalecontext = '\0'; 17675 break; 17676 } else if (strcmp(newcontext, oldcontext)) { 17677 stalecontext = oldcontext; 17678 } 17679 17680 } 17681 if (stalecontext) 17682 ast_context_destroy(ast_context_find(stalecontext), "SIP"); 17683 } 17684 }
| static void clear_peer_mailboxes | ( | struct sip_peer * | peer | ) | [static] |
Destroy all peer-related mailbox subscriptions
Definition at line 4629 of file chan_sip.c.
References AST_LIST_REMOVE_HEAD, destroy_mailbox(), and mailbox.
Referenced by set_peer_defaults(), and sip_destroy_peer().
04630 { 04631 struct sip_mailbox *mailbox; 04632 04633 while ((mailbox = AST_LIST_REMOVE_HEAD(&peer->mailboxes, entry))) 04634 destroy_mailbox(mailbox); 04635 }
| static void clear_sip_domains | ( | void | ) | [static] |
Clear our domain list (at reload).
Definition at line 27948 of file chan_sip.c.
References ast_free, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, and AST_LIST_UNLOCK.
Referenced by reload_config(), and unload_module().
27949 { 27950 struct domain *d; 27951 27952 AST_LIST_LOCK(&domain_list); 27953 while ((d = AST_LIST_REMOVE_HEAD(&domain_list, list))) 27954 ast_free(d); 27955 AST_LIST_UNLOCK(&domain_list); 27956 }
| static char * complete_sip_peer | ( | const char * | word, | |
| int | state, | |||
| int | flags2 | |||
| ) | [static] |
Do completion on peer name.
Definition at line 19139 of file chan_sip.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_t_iterator_next, ast_strdup, ast_test_flag, and sip_unref_peer().
Referenced by complete_sip_show_peer(), complete_sipnotify(), sip_do_debug(), and sip_prune_realtime().
19140 { 19141 char *result = NULL; 19142 int wordlen = strlen(word); 19143 int which = 0; 19144 struct ao2_iterator i = ao2_iterator_init(peers, 0); 19145 struct sip_peer *peer; 19146 19147 while ((peer = ao2_t_iterator_next(&i, "iterate thru peers table"))) { 19148 /* locking of the object is not required because only the name and flags are being compared */ 19149 if (!strncasecmp(word, peer->name, wordlen) && 19150 (!flags2 || ast_test_flag(&peer->flags[1], flags2)) && 19151 ++which > state) 19152 result = ast_strdup(peer->name); 19153 sip_unref_peer(peer, "toss iterator peer ptr before break"); 19154 if (result) { 19155 break; 19156 } 19157 } 19158 ao2_iterator_destroy(&i); 19159 return result; 19160 }
| static char * complete_sip_registered_peer | ( | const char * | word, | |
| int | state, | |||
| int | flags2 | |||
| ) | [static] |
Do completion on registered peer name.
Definition at line 19163 of file chan_sip.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_t_iterator_next, ast_strdup, ast_test_flag, and sip_unref_peer().
Referenced by complete_sip_unregister().
19164 { 19165 char *result = NULL; 19166 int wordlen = strlen(word); 19167 int which = 0; 19168 struct ao2_iterator i; 19169 struct sip_peer *peer; 19170 19171 i = ao2_iterator_init(peers, 0); 19172 while ((peer = ao2_t_iterator_next(&i, "iterate thru peers table"))) { 19173 if (!strncasecmp(word, peer->name, wordlen) && 19174 (!flags2 || ast_test_flag(&peer->flags[1], flags2)) && 19175 ++which > state && peer->expire > 0) 19176 result = ast_strdup(peer->name); 19177 if (result) { 19178 sip_unref_peer(peer, "toss iterator peer ptr before break"); 19179 break; 19180 } 19181 sip_unref_peer(peer, "toss iterator peer ptr"); 19182 } 19183 ao2_iterator_destroy(&i); 19184 return result; 19185 }
| static char * complete_sip_show_history | ( | const char * | line, | |
| const char * | word, | |||
| int | pos, | |||
| int | state | |||
| ) | [static] |
Support routine for 'sip show history' CLI.
Definition at line 19188 of file chan_sip.c.
References complete_sipch().
Referenced by sip_show_history().
19189 { 19190 if (pos == 3) 19191 return complete_sipch(line, word, pos, state); 19192 19193 return NULL; 19194 }
| static char * complete_sip_show_peer | ( | const char * | line, | |
| const char * | word, | |||
| int | pos, | |||
| int | state | |||
| ) | [static] |
Support routine for 'sip show peer' CLI.
Definition at line 19197 of file chan_sip.c.
References complete_sip_peer().
Referenced by sip_qualify_peer(), and sip_show_peer().
19198 { 19199 if (pos == 3) { 19200 return complete_sip_peer(word, state, 0); 19201 } 19202 19203 return NULL; 19204 }
| static char* complete_sip_show_user | ( | const char * | line, | |
| const char * | word, | |||
| int | pos, | |||
| int | state | |||
| ) | [static] |
Support routine for 'sip show user' CLI.
Definition at line 18408 of file chan_sip.c.
References complete_sip_user().
Referenced by sip_show_user().
18409 { 18410 if (pos == 3) 18411 return complete_sip_user(word, state); 18412 18413 return NULL; 18414 }
| static char * complete_sip_unregister | ( | const char * | line, | |
| const char * | word, | |||
| int | pos, | |||
| int | state | |||
| ) | [static] |
Support routine for 'sip unregister' CLI.
Definition at line 19207 of file chan_sip.c.
References complete_sip_registered_peer().
Referenced by sip_unregister().
19208 { 19209 if (pos == 2) 19210 return complete_sip_registered_peer(word, state, 0); 19211 19212 return NULL; 19213 }
| static char* complete_sip_user | ( | const char * | word, | |
| int | state | |||
| ) | [static] |
Do completion on user name.
Definition at line 18378 of file chan_sip.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_lock, ao2_t_iterator_next, ao2_unlock, ast_strdup, and sip_unref_peer().
Referenced by complete_sip_show_user().
18379 { 18380 char *result = NULL; 18381 int wordlen = strlen(word); 18382 int which = 0; 18383 struct ao2_iterator user_iter; 18384 struct sip_peer *user; 18385 18386 user_iter = ao2_iterator_init(peers, 0); 18387 while ((user = ao2_t_iterator_next(&user_iter, "iterate thru peers table"))) { 18388 ao2_lock(user); 18389 if (!(user->type & SIP_TYPE_USER)) { 18390 ao2_unlock(user); 18391 sip_unref_peer(user, "complete sip user"); 18392 continue; 18393 } 18394 /* locking of the object is not required because only the name and flags are being compared */ 18395 if (!strncasecmp(word, user->name, wordlen) && ++which > state) { 18396 result = ast_strdup(user->name); 18397 } 18398 ao2_unlock(user); 18399 sip_unref_peer(user, "complete sip user"); 18400 if (result) { 18401 break; 18402 } 18403 } 18404 ao2_iterator_destroy(&user_iter); 18405 return result; 18406 }
| static char* complete_sipch | ( | const char * | line, | |
| const char * | word, | |||
| int | pos, | |||
| int | state | |||
| ) | [static] |
Support routine for 'sip show channel' and 'sip show history' CLI This is in charge of generating all strings that match a prefix in the given position. As many functions of this kind, each invokation has O(state) time complexity so be careful in using it.
Definition at line 19109 of file chan_sip.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_t_iterator_next, ast_strdup, sip_pvt_lock, and sip_pvt_unlock.
Referenced by complete_sip_show_history(), and sip_show_channel().
19110 { 19111 int which=0; 19112 struct sip_pvt *cur; 19113 char *c = NULL; 19114 int wordlen = strlen(word); 19115 struct ao2_iterator i; 19116 19117 if (pos != 3) { 19118 return NULL; 19119 } 19120 19121 i = ao2_iterator_init(dialogs, 0); 19122 while ((cur = ao2_t_iterator_next(&i, "iterate thru dialogs"))) { 19123 sip_pvt_lock(cur); 19124 if (!strncasecmp(word, cur->callid, wordlen) && ++which > state) { 19125 c = ast_strdup(cur->callid); 19126 sip_pvt_unlock(cur); 19127 dialog_unref(cur, "drop ref in iterator loop break"); 19128 break; 19129 } 19130 sip_pvt_unlock(cur); 19131 dialog_unref(cur, "drop ref in iterator loop"); 19132 } 19133 ao2_iterator_destroy(&i); 19134 return c; 19135 }
| static char * complete_sipnotify | ( | const char * | line, | |
| const char * | word, | |||
| int | pos, | |||
| int | state | |||
| ) | [static] |
Support routine for 'sip notify' CLI.
Definition at line 19216 of file chan_sip.c.
References ast_category_browse(), ast_strdup, and complete_sip_peer().
Referenced by sip_cli_notify().
19217 { 19218 char *c = NULL; 19219 19220 if (pos == 2) { 19221 int which = 0; 19222 char *cat = NULL; 19223 int wordlen = strlen(word); 19224 19225 /* do completion for notify type */ 19226 19227 if (!notify_types) 19228 return NULL; 19229 19230 while ( (cat = ast_category_browse(notify_types, cat)) ) { 19231 if (!strncasecmp(word, cat, wordlen) && ++which > state) { 19232 c = ast_strdup(cat); 19233 break; 19234 } 19235 } 19236 return c; 19237 } 19238 19239 if (pos > 2) 19240 return complete_sip_peer(word, state, 0); 19241 19242 return NULL; 19243 }
| static int construct_pidf_body | ( | enum sip_cc_publish_state | state, | |
| char * | pidf_body, | |||
| size_t | size, | |||
| const char * | presentity | |||
| ) | [static] |
Definition at line 1965 of file chan_sip.c.
References ast_copy_string(), ast_str_alloca, ast_str_append(), ast_str_buffer(), and generate_random_string().
Referenced by handle_cc_notify(), sip_cc_monitor_suspend(), and sip_cc_monitor_unsuspend().
01966 { 01967 struct ast_str *body = ast_str_alloca(size); 01968 char tuple_id[32]; 01969 01970 generate_random_string(tuple_id, sizeof(tuple_id)); 01971 01972 /* We'll make this a bare-bones pidf body. In state_notify_build_xml, the PIDF 01973 * body gets a lot more extra junk that isn't necessary, so we'll leave it out here. 01974 */ 01975 ast_str_append(&body, 0, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); 01976 /* XXX The entity attribute is currently set to the peer name associated with the 01977 * dialog. This is because we currently only call this function for call-completion 01978 * PUBLISH bodies. In such cases, the entity is completely disregarded. For other 01979 * event packages, it may be crucial to have a proper URI as the presentity so this 01980 * should be revisited as support is expanded. 01981 */ 01982 ast_str_append(&body, 0, "<presence xmlns=\"urn:ietf:params:xml:ns:pidf\" entity=\"%s\">\n", presentity); 01983 ast_str_append(&body, 0, "<tuple id=\"%s\">\n", tuple_id); 01984 ast_str_append(&body, 0, "<status><basic>%s</basic></status>\n", state == CC_OPEN ? "open" : "closed"); 01985 ast_str_append(&body, 0, "</tuple>\n"); 01986 ast_str_append(&body, 0, "</presence>\n"); 01987 ast_copy_string(pidf_body, ast_str_buffer(body), size); 01988 return 0; 01989 }
| static int copy_all_header | ( | struct sip_request * | req, | |
| const struct sip_request * | orig, | |||
| const char * | field | |||
| ) | [static] |
Copy all headers from one request to another.
Definition at line 10208 of file chan_sip.c.
References __get_header(), add_header(), and ast_strlen_zero().
Referenced by respprep().
10209 { 10210 int start = 0; 10211 int copied = 0; 10212 for (;;) { 10213 const char *tmp = __get_header(orig, field, &start); 10214 10215 if (ast_strlen_zero(tmp)) 10216 break; 10217 /* Add what we're responding to */ 10218 add_header(req, field, tmp); 10219 copied++; 10220 } 10221 return copied ? 0 : -1; 10222 }
| static int copy_header | ( | struct sip_request * | req, | |
| const struct sip_request * | orig, | |||
| const char * | field | |||
| ) | [static] |
Copy one header field from one request to another.
Definition at line 10197 of file chan_sip.c.
References add_header(), ast_log(), ast_strlen_zero(), LOG_NOTICE, and sip_get_header().
Referenced by reqprep(), and respprep().
10198 { 10199 const char *tmp = sip_get_header(orig, field); 10200 10201 if (!ast_strlen_zero(tmp)) /* Add what we're responding to */ 10202 return add_header(req, field, tmp); 10203 ast_log(LOG_NOTICE, "No field '%s' present to copy\n", field); 10204 return -1; 10205 }
| static void copy_request | ( | struct sip_request * | dst, | |
| const struct sip_request * | src | |||
| ) | [static] |
copy SIP request (mostly used to save request for responses)
Definition at line 12098 of file chan_sip.c.
References ast_str_copy_string(), ast_str_create(), and ast_str_strlen().
Referenced by _sip_tcp_helper_thread(), forked_invite_init(), handle_request_bye(), handle_request_invite(), handle_request_options(), handle_request_register(), handle_request_subscribe(), initialize_initreq(), parse_copy(), receive_message(), and sip_park().
12099 { 12100 /* XXX this function can encounter memory allocation errors, perhaps it 12101 * should return a value */ 12102 12103 struct ast_str *duplicate = dst->data; 12104 struct ast_str *duplicate_content = dst->content; 12105 12106 /* copy the entire request then restore the original data and content 12107 * members from the dst request */ 12108 memcpy(dst, src, sizeof(*dst)); 12109 dst->data = duplicate; 12110 dst->content = duplicate_content; 12111 12112 /* copy the data into the dst request */ 12113 if (!dst->data && !(dst->data = ast_str_create(ast_str_strlen(src->data) + 1))) 12114 return; 12115 ast_str_copy_string(&dst->data, src->data); 12116 12117 /* copy the content into the dst request (if it exists) */ 12118 if (src->content) { 12119 if (!dst->content && !(dst->content = ast_str_create(ast_str_strlen(src->content) + 1))) 12120 return; 12121 ast_str_copy_string(&dst->content, src->content); 12122 } 12123 }
| static void copy_socket_data | ( | struct sip_socket * | to_sock, | |
| const struct sip_socket * | from_sock | |||
| ) | [static] |
Definition at line 5256 of file chan_sip.c.
References ao2_ref.
Referenced by create_addr_from_peer(), handle_request_do(), parse_register_contact(), sip_poke_peer(), and transmit_response_using_temp().
05257 { 05258 if (to_sock->tcptls_session) { 05259 ao2_ref(to_sock->tcptls_session, -1); 05260 to_sock->tcptls_session = NULL; 05261 } 05262 05263 if (from_sock->tcptls_session) { 05264 ao2_ref(from_sock->tcptls_session, +1); 05265 } 05266 05267 *to_sock = *from_sock; 05268 }
| static struct ast_variable * copy_vars | ( | struct ast_variable * | src | ) | [static, read] |
duplicate a list of channel variables,
Definition at line 2348 of file chan_sip.c.
References ast_variable_new(), and ast_variable::next.
02349 { 02350 struct ast_variable *res = NULL, *tmp, *v = NULL; 02351 02352 for (v = src ; v ; v = v->next) { 02353 if ((tmp = ast_variable_new(v->name, v->value, v->file))) { 02354 tmp->next = res; 02355 res = tmp; 02356 } 02357 } 02358 return res; 02359 }
| static int copy_via_headers | ( | struct sip_pvt * | p, | |
| struct sip_request * | req, | |||
| const struct sip_request * | orig, | |||
| const char * | field | |||
| ) | [static] |
Copy SIP VIA Headers from the request to the response.
We always add ;received=<ip address> to the topmost via header.
Definition at line 10232 of file chan_sip.c.
References __get_header(), add_header(), ast_copy_string(), ast_log(), ast_sockaddr_port, ast_sockaddr_stringify_addr_remote(), ast_strlen_zero(), ast_test_flag, and LOG_NOTICE.
Referenced by respprep().
10233 { 10234 int copied = 0; 10235 int start = 0; 10236 10237 for (;;) { 10238 char new[512]; 10239 const char *oh = __get_header(orig, field, &start); 10240 10241 if (ast_strlen_zero(oh)) 10242 break; 10243 10244 if (!copied) { /* Only check for empty rport in topmost via header */ 10245 char leftmost[512], *others, *rport; 10246 10247 /* Only work on leftmost value */ 10248 ast_copy_string(leftmost, oh, sizeof(leftmost)); 10249 others = strchr(leftmost, ','); 10250 if (others) 10251 *others++ = '\0'; 10252 10253 /* Find ;rport; (empty request) */ 10254 rport = strstr(leftmost, ";rport"); 10255 if (rport && *(rport+6) == '=') 10256 rport = NULL; /* We already have a parameter to rport */ 10257 10258 if (((ast_test_flag(&p->flags[0], SIP_NAT_FORCE_RPORT)) || (rport && ast_test_flag(&p->flags[0], SIP_NAT_RPORT_PRESENT)))) { 10259 /* We need to add received port - rport */ 10260 char *end; 10261 10262 rport = strstr(leftmost, ";rport"); 10263 10264 if (rport) { 10265 end = strchr(rport + 1, ';'); 10266 if (end) 10267 memmove(rport, end, strlen(end) + 1); 10268 else 10269 *rport = '\0'; 10270 } 10271 10272 /* Add rport to first VIA header if requested */ 10273 snprintf(new, sizeof(new), "%s;received=%s;rport=%d%s%s", 10274 leftmost, ast_sockaddr_stringify_addr_remote(&p->recv), 10275 ast_sockaddr_port(&p->recv), 10276 others ? "," : "", others ? others : ""); 10277 } else { 10278 /* We should *always* add a received to the topmost via */ 10279 snprintf(new, sizeof(new), "%s;received=%s%s%s", 10280 leftmost, ast_sockaddr_stringify_addr_remote(&p->recv), 10281 others ? "," : "", others ? others : ""); 10282 } 10283 oh = new; /* the header to copy */ 10284 } /* else add the following via headers untouched */ 10285 add_header(req, field, oh); 10286 copied++; 10287 } 10288 if (!copied) { 10289 ast_log(LOG_NOTICE, "No header field '%s' present to copy\n", field); 10290 return -1; 10291 } 10292 return 0; 10293 }
| static int create_addr | ( | struct sip_pvt * | dialog, | |
| const char * | opeer, | |||
| struct ast_sockaddr * | addr, | |||
| int | newdialog, | |||
| struct ast_sockaddr * | remote_address | |||
| ) | [static] |
create address structure from device name Or, if peer not found, find it in the global DNS returns TRUE (-1) on failure, FALSE on success
Definition at line 5485 of file chan_sip.c.
References AST_APP_ARG, ast_check_digits(), AST_DECLARE_APP_ARGS, ast_get_srv(), ast_log(), AST_NONSTANDARD_RAW_ARGS, ast_sockaddr_copy(), ast_sockaddr_isnull(), ast_sockaddr_port, ast_sockaddr_resolve_first(), ast_sockaddr_set_port, ast_strdupa, ast_string_field_set, bindaddr, create_addr_from_peer(), default_sip_port(), dialog_initialize_rtp(), FALSE, get_srv_protocol(), get_srv_service(), LOG_WARNING, MAXHOSTNAMELEN, obproxy_get(), ref_proxy(), service, set_socket_transport(), sip_cfg, sip_find_peer(), sip_ref_peer(), sip_unref_peer(), and TRUE.
05486 { 05487 struct sip_peer *peer; 05488 char *peername, *peername2, *hostn; 05489 char host[MAXHOSTNAMELEN]; 05490 char service[MAXHOSTNAMELEN]; 05491 int srv_ret = 0; 05492 int tportno; 05493 05494 AST_DECLARE_APP_ARGS(hostport, 05495 AST_APP_ARG(host); 05496 AST_APP_ARG(port); 05497 ); 05498 05499 peername = ast_strdupa(opeer); 05500 peername2 = ast_strdupa(opeer); 05501 AST_NONSTANDARD_RAW_ARGS(hostport, peername2, ':'); 05502 05503 if (hostport.port) 05504 dialog->portinuri = 1; 05505 05506 dialog->timer_t1 = global_t1; /* Default SIP retransmission timer T1 (RFC 3261) */ 05507 dialog->timer_b = global_timer_b; /* Default SIP transaction timer B (RFC 3261) */ 05508 peer = sip_find_peer(peername, NULL, TRUE, FINDPEERS, FALSE, 0); 05509 05510 if (peer) { 05511 int res; 05512 if (newdialog) { 05513 set_socket_transport(&dialog->socket, 0); 05514 } 05515 res = create_addr_from_peer(dialog, peer); 05516 if (!ast_sockaddr_isnull(remote_address)) { 05517 ast_sockaddr_copy(&dialog->sa, remote_address); 05518 } 05519 dialog->relatedpeer = sip_ref_peer(peer, "create_addr: setting dialog's relatedpeer pointer"); 05520 sip_unref_peer(peer, "create_addr: unref peer from sip_find_peer hashtab lookup"); 05521 return res; 05522 } else if (ast_check_digits(peername)) { 05523 /* Although an IPv4 hostname *could* be represented as a 32-bit integer, it is uncommon and 05524 * it makes dialing SIP/${EXTEN} for a peer that isn't defined resolve to an IP that is 05525 * almost certainly not intended. It is much better to just reject purely numeric hostnames */ 05526 ast_log(LOG_WARNING, "Purely numeric hostname (%s), and not a peer--rejecting!\n", peername); 05527 return -1; 05528 } else { 05529 dialog->rtptimeout = global_rtptimeout; 05530 dialog->rtpholdtimeout = global_rtpholdtimeout; 05531 dialog->rtpkeepalive = global_rtpkeepalive; 05532 if (dialog_initialize_rtp(dialog)) { 05533 return -1; 05534 } 05535 } 05536 05537 ast_string_field_set(dialog, tohost, hostport.host); 05538 dialog->allowed_methods &= ~sip_cfg.disallowed_methods; 05539 05540 /* Get the outbound proxy information */ 05541 ref_proxy(dialog, obproxy_get(dialog, NULL)); 05542 05543 if (addr) { 05544 /* This address should be updated using dnsmgr */ 05545 ast_sockaddr_copy(&dialog->sa, addr); 05546 } else { 05547 05548 /* Let's see if we can find the host in DNS. First try DNS SRV records, 05549 then hostname lookup */ 05550 /*! \todo Fix this function. When we ask for SRV, we should check all transports 05551 In the future, we should first check NAPTR to find out transport preference 05552 */ 05553 hostn = peername; 05554 /* Section 4.2 of RFC 3263 specifies that if a port number is specified, then 05555 * an A record lookup should be used instead of SRV. 05556 */ 05557 if (!hostport.port && sip_cfg.srvlookup) { 05558 snprintf(service, sizeof(service), "_%s._%s.%s", 05559 get_srv_service(dialog->socket.type), 05560 get_srv_protocol(dialog->socket.type), peername); 05561 if ((srv_ret = ast_get_srv(NULL, host, sizeof(host), &tportno, 05562 service)) > 0) { 05563 hostn = host; 05564 } 05565 } 05566 05567 if (ast_sockaddr_resolve_first(&dialog->sa, hostn, 0)) { 05568 ast_log(LOG_WARNING, "No such host: %s\n", peername); 05569 return -1; 05570 } 05571 05572 if (srv_ret > 0) { 05573 ast_sockaddr_set_port(&dialog->sa, tportno); 05574 } 05575 } 05576 05577 if (!dialog->socket.type) 05578 set_socket_transport(&dialog->socket, SIP_TRANSPORT_UDP); 05579 if (!dialog->socket.port) { 05580 dialog->socket.port = htons(ast_sockaddr_port(&bindaddr)); 05581 } 05582 05583 if (!ast_sockaddr_port(&dialog->sa)) { 05584 ast_sockaddr_set_port(&dialog->sa, default_sip_port(dialog->socket.type)); 05585 } 05586 ast_sockaddr_copy(&dialog->recv, &dialog->sa); 05587 return 0; 05588 }
| static int create_addr_from_peer | ( | struct sip_pvt * | dialog, | |
| struct sip_peer * | peer | |||
| ) | [static] |
Create address structure from peer reference. This function copies data from peer to the dialog, so we don't have to look up the peer again from memory or database during the life time of the dialog.
Definition at line 5330 of file chan_sip.c.
References accountcode, ao2_lock, ao2_t_ref, ao2_unlock, ast_cc_copy_config_params(), ast_copy_flags, ast_copy_string(), ast_duplicate_ha_list(), ast_format_cap_copy(), ast_rtp_codecs_packetization_set(), AST_RTP_DTMF, ast_rtp_instance_get_codecs(), ast_rtp_instance_set_prop(), AST_RTP_PROPERTY_DTMF, AST_RTP_PROPERTY_DTMF_COMPENSATE, ast_set_flag, ast_sockaddr_isnull(), ast_sockaddr_stringify_host_remote(), ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, change_callid_pvt(), check_request_transport, cid_name, cid_num, context, copy_socket_data(), copy_vars(), dialog_initialize_rtp(), language, mohinterpret, mohsuggest, obproxy_get(), parkinglot, and ref_proxy().
Referenced by create_addr(), and sip_send_mwi_to_peer().
05331 { 05332 struct sip_auth_container *credentials; 05333 05334 /* this checks that the dialog is contacting the peer on a valid 05335 * transport type based on the peers transport configuration, 05336 * otherwise, this function bails out */ 05337 if (dialog->socket.type && check_request_transport(peer, dialog)) 05338 return -1; 05339 copy_socket_data(&dialog->socket, &peer->socket); 05340 05341 if (!(ast_sockaddr_isnull(&peer->addr) && ast_sockaddr_isnull(&peer->defaddr)) && 05342 (!peer->maxms || ((peer->lastms >= 0) && (peer->lastms <= peer->maxms)))) { 05343 dialog->sa = ast_sockaddr_isnull(&peer->addr) ? peer->defaddr : peer->addr; 05344 dialog->recv = dialog->sa; 05345 } else 05346 return -1; 05347 05348 /* XXX TODO: get flags directly from peer only as they are needed using dialog->relatedpeer */ 05349 ast_copy_flags(&dialog->flags[0], &peer->flags[0], SIP_FLAGS_TO_COPY); 05350 ast_copy_flags(&dialog->flags[1], &peer->flags[1], SIP_PAGE2_FLAGS_TO_COPY); 05351 ast_copy_flags(&dialog->flags[2], &peer->flags[2], SIP_PAGE3_FLAGS_TO_COPY); 05352 ast_format_cap_copy(dialog->caps, peer->caps); 05353 dialog->prefs = peer->prefs; 05354 dialog->amaflags = peer->amaflags; 05355 05356 ast_string_field_set(dialog, engine, peer->engine); 05357 05358 dialog->rtptimeout = peer->rtptimeout; 05359 dialog->rtpholdtimeout = peer->rtpholdtimeout; 05360 dialog->rtpkeepalive = peer->rtpkeepalive; 05361 if (dialog_initialize_rtp(dialog)) { 05362 return -1; 05363 } 05364 05365 if (dialog->rtp) { /* Audio */ 05366 ast_rtp_instance_set_prop(dialog->rtp, AST_RTP_PROPERTY_DTMF, ast_test_flag(&dialog->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833); 05367 ast_rtp_instance_set_prop(dialog->rtp, AST_RTP_PROPERTY_DTMF_COMPENSATE, ast_test_flag(&dialog->flags[1], SIP_PAGE2_RFC2833_COMPENSATE)); 05368 /* Set Frame packetization */ 05369 ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(dialog->rtp), dialog->rtp, &dialog->prefs); 05370 dialog->autoframing = peer->autoframing; 05371 } 05372 05373 /* XXX TODO: get fields directly from peer only as they are needed using dialog->relatedpeer */ 05374 ast_string_field_set(dialog, peername, peer->name); 05375 ast_string_field_set(dialog, authname, peer->username); 05376 ast_string_field_set(dialog, username, peer->username); 05377 ast_string_field_set(dialog, peersecret, peer->secret); 05378 ast_string_field_set(dialog, peermd5secret, peer->md5secret); 05379 ast_string_field_set(dialog, mohsuggest, peer->mohsuggest); 05380 ast_string_field_set(dialog, mohinterpret, peer->mohinterpret); 05381 ast_string_field_set(dialog, tohost, peer->tohost); 05382 ast_string_field_set(dialog, fullcontact, peer->fullcontact); 05383 ast_string_field_set(dialog, accountcode, peer->accountcode); 05384 ast_string_field_set(dialog, context, peer->context); 05385 ast_string_field_set(dialog, cid_num, peer->cid_num); 05386 ast_string_field_set(dialog, cid_name, peer->cid_name); 05387 ast_string_field_set(dialog, cid_tag, peer->cid_tag); 05388 ast_string_field_set(dialog, mwi_from, peer->mwi_from); 05389 if (!ast_strlen_zero(peer->parkinglot)) { 05390 ast_string_field_set(dialog, parkinglot, peer->parkinglot); 05391 } 05392 ast_string_field_set(dialog, engine, peer->engine); 05393 ref_proxy(dialog, obproxy_get(dialog, peer)); 05394 dialog->callgroup = peer->callgroup; 05395 dialog->pickupgroup = peer->pickupgroup; 05396 ast_copy_string(dialog->zone, peer->zone, sizeof(dialog->zone)); 05397 dialog->allowtransfer = peer->allowtransfer; 05398 dialog->jointnoncodeccapability = dialog->noncodeccapability; 05399 05400 /* Update dialog authorization credentials */ 05401 ao2_lock(peer); 05402 credentials = peer->auth; 05403 if (credentials) { 05404 ao2_t_ref(credentials, +1, "Ref peer auth for dialog"); 05405 } 05406 ao2_unlock(peer); 05407 ao2_lock(dialog); 05408 if (dialog->peerauth) { 05409 ao2_t_ref(dialog->peerauth, -1, "Unref old dialog peer auth"); 05410 } 05411 dialog->peerauth = credentials; 05412 ao2_unlock(dialog); 05413 05414 dialog->maxcallbitrate = peer->maxcallbitrate; 05415 dialog->disallowed_methods = peer->disallowed_methods; 05416 ast_cc_copy_config_params(dialog->cc_params, peer->cc_params); 05417 if (ast_strlen_zero(dialog->tohost)) 05418 ast_string_field_set(dialog, tohost, ast_sockaddr_stringify_host_remote(&dialog->sa)); 05419 if (!ast_strlen_zero(peer->fromdomain)) { 05420 ast_string_field_set(dialog, fromdomain, peer->fromdomain); 05421 if (!dialog->initreq.headers) { 05422 char *new_callid; 05423 char *tmpcall = ast_strdupa(dialog->callid); 05424 /* this sure looks to me like we are going to change the callid on this dialog!! */ 05425 new_callid = strchr(tmpcall, '@'); 05426 if (new_callid) { 05427 int callid_size; 05428 05429 *new_callid = '\0'; 05430 05431 /* Change the dialog callid. */ 05432 callid_size = strlen(tmpcall) + strlen(peer->fromdomain) + 2; 05433 new_callid = alloca(callid_size); 05434 snprintf(new_callid, callid_size, "%s@%s", tmpcall, peer->fromdomain); 05435 change_callid_pvt(dialog, new_callid); 05436 } 05437 } 05438 } 05439 if (!ast_strlen_zero(peer->fromuser)) 05440 ast_string_field_set(dialog, fromuser, peer->fromuser); 05441 if (!ast_strlen_zero(peer->language)) 05442 ast_string_field_set(dialog, language, peer->language); 05443 /* Set timer T1 to RTT for this peer (if known by qualify=) */ 05444 /* Minimum is settable or default to 100 ms */ 05445 /* If there is a maxms and lastms from a qualify use that over a manual T1 05446 value. Otherwise, use the peer's T1 value. */ 05447 if (peer->maxms && peer->lastms) 05448 dialog->timer_t1 = peer->lastms < global_t1min ? global_t1min : peer->lastms; 05449 else 05450 dialog->timer_t1 = peer->timer_t1; 05451 05452 /* Set timer B to control transaction timeouts, the peer setting is the default and overrides 05453 the known timer */ 05454 if (peer->timer_b) 05455 dialog->timer_b = peer->timer_b; 05456 else 05457 dialog->timer_b = 64 * dialog->timer_t1; 05458 05459 if ((ast_test_flag(&dialog->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833) || 05460 (ast_test_flag(&dialog->flags[0], SIP_DTMF) == SIP_DTMF_AUTO)) 05461 dialog->noncodeccapability |= AST_RTP_DTMF; 05462 else 05463 dialog->noncodeccapability &= ~AST_RTP_DTMF; 05464 dialog->directmediaha = ast_duplicate_ha_list(peer->directmediaha); 05465 if (peer->call_limit) 05466 ast_set_flag(&dialog->flags[0], SIP_CALL_LIMIT); 05467 if (!dialog->portinuri) 05468 dialog->portinuri = peer->portinuri; 05469 dialog->chanvars = copy_vars(peer->chanvars); 05470 if (peer->fromdomainport) 05471 dialog->fromdomainport = peer->fromdomainport; 05472 05473 return 0; 05474 }
| static struct sip_epa_entry* create_epa_entry | ( | const char *const | event_package, | |
| const char *const | destination | |||
| ) | [static, read] |
Definition at line 924 of file chan_sip.c.
References ao2_t_alloc, ast_copy_string(), and find_static_data().
Referenced by sip_cc_monitor_suspend().
00925 { 00926 struct sip_epa_entry *epa_entry; 00927 const struct epa_static_data *static_data; 00928 00929 if (!(static_data = find_static_data(event_package))) { 00930 return NULL; 00931 } 00932 00933 if (!(epa_entry = ao2_t_alloc(sizeof(*epa_entry), static_data->destructor, "Allocate new EPA entry"))) { 00934 return NULL; 00935 } 00936 00937 epa_entry->static_data = static_data; 00938 ast_copy_string(epa_entry->destination, destination, sizeof(epa_entry->destination)); 00939 return epa_entry; 00940 }
| static struct sip_esc_entry* create_esc_entry | ( | struct event_state_compositor * | esc, | |
| struct sip_request * | req, | |||
| const int | expires | |||
| ) | [static, read] |
Definition at line 1050 of file chan_sip.c.
References ao2_alloc, ao2_ref, ast_sched_add(), create_new_sip_etag(), esc_entry_destructor(), event_state_compositor::name, and publish_expire().
Referenced by handle_sip_publish_initial().
01051 { 01052 struct sip_esc_entry *esc_entry; 01053 int expires_ms; 01054 01055 if (!(esc_entry = ao2_alloc(sizeof(*esc_entry), esc_entry_destructor))) { 01056 return NULL; 01057 } 01058 01059 esc_entry->event = esc->name; 01060 01061 expires_ms = expires * 1000; 01062 /* Bump refcount for scheduler */ 01063 ao2_ref(esc_entry, +1); 01064 esc_entry->sched_id = ast_sched_add(sched, expires_ms, publish_expire, esc_entry); 01065 01066 /* Note: This links the esc_entry into the ESC properly */ 01067 create_new_sip_etag(esc_entry, 0); 01068 01069 return esc_entry; 01070 }
| static void create_new_sip_etag | ( | struct sip_esc_entry * | esc_entry, | |
| int | is_linked | |||
| ) | [static] |
Definition at line 1037 of file chan_sip.c.
References ao2_link, ao2_unlink, ast_assert, ast_atomic_fetchadd_int(), event_state_compositor::compositor, and get_esc().
Referenced by create_esc_entry(), and transmit_response_with_sip_etag().
01038 { 01039 int new_etag = ast_atomic_fetchadd_int(&esc_etag_counter, +1); 01040 struct event_state_compositor *esc = get_esc(esc_entry->event); 01041 01042 ast_assert(esc != NULL); 01043 if (is_linked) { 01044 ao2_unlink(esc->compositor, esc_entry); 01045 } 01046 snprintf(esc_entry->entity_tag, sizeof(esc_entry->entity_tag), "%d", new_etag); 01047 ao2_link(esc->compositor, esc_entry); 01048 }
| static int default_sip_port | ( | enum sip_transport | type | ) | [inline, static] |
The default sip port for the given transport.
Definition at line 5477 of file chan_sip.c.
Referenced by create_addr(), on_dns_update_peer(), and parse_register_contact().
05478 { 05479 return type == SIP_TRANSPORT_TLS ? STANDARD_TLS_PORT : STANDARD_SIP_PORT; 05480 }
| static void deinit_req | ( | struct sip_request * | req | ) | [static] |
Deinitialize SIP response/request.
Definition at line 10449 of file chan_sip.c.
References ast_free.
Referenced by __sip_destroy(), _sip_tcp_helper_thread(), send_request(), send_response(), sip_park(), sip_park_thread(), and sipsock_read().
10450 { 10451 if (req->data) { 10452 ast_free(req->data); 10453 req->data = NULL; 10454 } 10455 if (req->content) { 10456 ast_free(req->content); 10457 req->content = NULL; 10458 } 10459 }
| static void destroy_association | ( | struct sip_peer * | peer | ) | [static] |
Remove registration data from realtime database or AST/DB when registration expires.
Definition at line 14129 of file chan_sip.c.
References ast_check_realtime(), ast_db_del(), ast_update_realtime(), SENTINEL, and sip_cfg.
Referenced by build_peer(), and expire_register().
14130 { 14131 int realtimeregs = ast_check_realtime("sipregs"); 14132 char *tablename = (realtimeregs) ? "sipregs" : "sippeers"; 14133 14134 if (!sip_cfg.ignore_regexpire) { 14135 if (peer->rt_fromcontact && sip_cfg.peer_rtupdate) { 14136 ast_update_realtime(tablename, "name", peer->name, "fullcontact", "", "ipaddr", "", "port", "", "regseconds", "0", "regserver", "", "useragent", "", "lastms", "0", SENTINEL); 14137 } else { 14138 ast_db_del("SIP/Registry", peer->name); 14139 ast_db_del("SIP/PeerMethods", peer->name); 14140 } 14141 } 14142 }
| static void destroy_escs | ( | void | ) | [static] |
Definition at line 1084 of file chan_sip.c.
References ao2_ref, ARRAY_LEN, and event_state_compositors.
Referenced by unload_module().
01085 { 01086 int i; 01087 for (i = 0; i < ARRAY_LEN(event_state_compositors); i++) { 01088 ao2_ref(event_state_compositors[i].compositor, -1); 01089 } 01090 }
| static void destroy_mailbox | ( | struct sip_mailbox * | mailbox | ) | [static] |
Destroy mailbox subscriptions
Definition at line 4621 of file chan_sip.c.
References ast_event_unsubscribe(), and ast_free.
Referenced by build_peer(), and clear_peer_mailboxes().
04622 { 04623 if (mailbox->event_sub) 04624 ast_event_unsubscribe(mailbox->event_sub); 04625 ast_free(mailbox); 04626 }
| static void destroy_msg_headers | ( | struct sip_pvt * | pvt | ) | [static] |
Definition at line 11098 of file chan_sip.c.
References ast_free, and AST_LIST_REMOVE_HEAD.
Referenced by __sip_destroy(), sip_park_thread(), and sip_sendtext().
11099 { 11100 struct sip_msg_hdr *doomed; 11101 11102 while ((doomed = AST_LIST_REMOVE_HEAD(&pvt->msg_headers, next))) { 11103 ast_free(doomed); 11104 } 11105 }
| static void destroy_realm_authentication | ( | void * | obj | ) | [static] |
Definition at line 27966 of file chan_sip.c.
References ast_free, and AST_LIST_REMOVE_HEAD.
Referenced by add_realm_authentication().
27967 { 27968 struct sip_auth_container *credentials = obj; 27969 struct sip_auth *auth; 27970 27971 while ((auth = AST_LIST_REMOVE_HEAD(&credentials->list, node))) { 27972 ast_free(auth); 27973 } 27974 }
| static int determine_firstline_parts | ( | struct sip_request * | req | ) | [static] |
Parse first line of incoming SIP request.
Definition at line 12195 of file chan_sip.c.
References ast_debug, ast_skip_blanks(), ast_skip_nonblanks(), and ast_trim_blanks().
Referenced by parse_request().
12196 { 12197 char *e = ast_skip_blanks(req->data->str); /* there shouldn't be any */ 12198 char *local_rlPart1; 12199 12200 if (!*e) 12201 return -1; 12202 req->rlPart1 = e - req->data->str; /* method or protocol */ 12203 local_rlPart1 = e; 12204 e = ast_skip_nonblanks(e); 12205 if (*e) 12206 *e++ = '\0'; 12207 /* Get URI or status code */ 12208 e = ast_skip_blanks(e); 12209 if ( !*e ) 12210 return -1; 12211 ast_trim_blanks(e); 12212 12213 if (!strcasecmp(local_rlPart1, "SIP/2.0") ) { /* We have a response */ 12214 if (strlen(e) < 3) /* status code is 3 digits */ 12215 return -1; 12216 req->rlPart2 = e - req->data->str; 12217 } else { /* We have a request */ 12218 if ( *e == '<' ) { /* XXX the spec says it must not be in <> ! */ 12219 ast_debug(3, "Oops. Bogus uri in <> %s\n", e); 12220 e++; 12221 if (!*e) 12222 return -1; 12223 } 12224 req->rlPart2 = e - req->data->str; /* URI */ 12225 e = ast_skip_nonblanks(e); 12226 if (*e) 12227 *e++ = '\0'; 12228 e = ast_skip_blanks(e); 12229 if (strcasecmp(e, "SIP/2.0") ) { 12230 ast_debug(3, "Skipping packet - Bad request protocol %s\n", e); 12231 return -1; 12232 } 12233 } 12234 return 1; 12235 }
| static enum sip_publish_type determine_sip_publish_type | ( | struct sip_request * | req, | |
| const char *const | event, | |||
| const char *const | etag, | |||
| const char *const | expires, | |||
| int * | expires_int | |||
| ) | [static] |
Definition at line 24925 of file chan_sip.c.
References ast_assert, and ast_strlen_zero().
Referenced by handle_request_publish().
24926 { 24927 int etag_present = !ast_strlen_zero(etag); 24928 int body_present = req->lines > 0; 24929 24930 ast_assert(expires_int != NULL); 24931 24932 if (ast_strlen_zero(expires)) { 24933 /* Section 6, item 4, second bullet point of RFC 3903 says to 24934 * use a locally-configured default expiration if none is provided 24935 * in the request 24936 */ 24937 *expires_int = DEFAULT_PUBLISH_EXPIRES; 24938 } else if (sscanf(expires, "%30d", expires_int) != 1) { 24939 return SIP_PUBLISH_UNKNOWN; 24940 } 24941 24942 if (*expires_int == 0) { 24943 return SIP_PUBLISH_REMOVE; 24944 } else if (!etag_present && body_present) { 24945 return SIP_PUBLISH_INITIAL; 24946 } else if (etag_present && !body_present) { 24947 return SIP_PUBLISH_REFRESH; 24948 } else if (etag_present && body_present) { 24949 return SIP_PUBLISH_MODIFY; 24950 } 24951 24952 return SIP_PUBLISH_UNKNOWN; 24953 }
| static int dialog_checkrtp_cb | ( | void * | dialogobj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Check RTP Timeout on dialogs.
This is used with ao2_callback to check rtptimeout rtponholdtimeout and send rtpkeepalive packets.
Definition at line 17694 of file chan_sip.c.
References check_rtp_timeout(), CMP_MATCH, sip_pvt_trylock, and sip_pvt_unlock.
Referenced by do_monitor().
17695 { 17696 struct sip_pvt *dialog = dialogobj; 17697 time_t *t = arg; 17698 int match_status; 17699 17700 if (sip_pvt_trylock(dialog)) { 17701 return 0; 17702 } 17703 17704 if (dialog->rtp || dialog->vrtp) { 17705 match_status = check_rtp_timeout(dialog, *t); 17706 } else { 17707 /* Dialog has no active RTP or VRTP. unlink it from dialogs_rtpcheck. */ 17708 match_status = CMP_MATCH; 17709 } 17710 sip_pvt_unlock(dialog); 17711 17712 return match_status; 17713 }
| static int dialog_cmp_cb | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 30955 of file chan_sip.c.
References CMP_MATCH, and CMP_STOP.
Referenced by load_module().
30956 { 30957 struct sip_pvt *pvt = obj, *pvt2 = arg; 30958 30959 return !strcasecmp(pvt->callid, pvt2->callid) ? CMP_MATCH | CMP_STOP : 0; 30960 }
| static int dialog_dump_func | ( | void * | userobj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 17564 of file chan_sip.c.
References ao2_t_ref, ast_cli(), and ast_cli_args::fd.
Referenced by sip_show_objects().
17565 { 17566 struct sip_pvt *pvt = userobj; 17567 int refc = ao2_t_ref(userobj, 0, ""); 17568 struct ast_cli_args *a = (struct ast_cli_args *) arg; 17569 17570 ast_cli(a->fd, "name: %s\ntype: dialog\nobjflags: %d\nrefcount: %d\n\n", 17571 pvt->callid, 0, refc); 17572 return 0; 17573 }
| static int dialog_find_multiple | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 30945 of file chan_sip.c.
References CMP_MATCH.
Referenced by find_call().
30946 { 30947 struct sip_pvt *pvt = obj, *pvt2 = arg; 30948 30949 return !strcasecmp(pvt->callid, pvt2->callid) ? CMP_MATCH : 0; 30950 }
| static int dialog_hash_cb | ( | const void * | obj, | |
| const int | flags | |||
| ) | [static] |
Definition at line 30935 of file chan_sip.c.
References ast_str_case_hash().
Referenced by load_module().
30936 { 30937 const struct sip_pvt *pvt = obj; 30938 30939 return ast_str_case_hash(pvt->callid); 30940 }
| static int dialog_initialize_rtp | ( | struct sip_pvt * | dialog | ) | [static] |
Initialize RTP portion of a dialog.
Definition at line 5273 of file chan_sip.c.
References ast_format_cap_has_type(), AST_FORMAT_TYPE_VIDEO, ast_rtp_instance_new(), ast_rtp_instance_set_hold_timeout(), ast_rtp_instance_set_keepalive(), ast_rtp_instance_set_prop(), ast_rtp_instance_set_qos(), ast_rtp_instance_set_timeout(), AST_RTP_PROPERTY_DTMF, AST_RTP_PROPERTY_DTMF_COMPENSATE, AST_RTP_PROPERTY_RTCP, ast_sockaddr_copy(), ast_test_flag, bindaddr, do_setnat(), cfsip_methods::need_rtp, and sip_methods.
Referenced by check_peer_ok(), check_user_full(), create_addr(), and create_addr_from_peer().
05274 { 05275 struct ast_sockaddr bindaddr_tmp; 05276 05277 if (!sip_methods[dialog->method].need_rtp) { 05278 return 0; 05279 } 05280 05281 ast_sockaddr_copy(&bindaddr_tmp, &bindaddr); 05282 if (!(dialog->rtp = ast_rtp_instance_new(dialog->engine, sched, &bindaddr_tmp, NULL))) { 05283 return -1; 05284 } 05285 05286 if (ast_test_flag(&dialog->flags[1], SIP_PAGE2_VIDEOSUPPORT_ALWAYS) || 05287 (ast_test_flag(&dialog->flags[1], SIP_PAGE2_VIDEOSUPPORT) && (ast_format_cap_has_type(dialog->caps, AST_FORMAT_TYPE_VIDEO)))) { 05288 if (!(dialog->vrtp = ast_rtp_instance_new(dialog->engine, sched, &bindaddr_tmp, NULL))) { 05289 return -1; 05290 } 05291 ast_rtp_instance_set_timeout(dialog->vrtp, dialog->rtptimeout); 05292 ast_rtp_instance_set_hold_timeout(dialog->vrtp, dialog->rtpholdtimeout); 05293 ast_rtp_instance_set_keepalive(dialog->vrtp, dialog->rtpkeepalive); 05294 05295 ast_rtp_instance_set_prop(dialog->vrtp, AST_RTP_PROPERTY_RTCP, 1); 05296 } 05297 05298 if (ast_test_flag(&dialog->flags[1], SIP_PAGE2_TEXTSUPPORT)) { 05299 if (!(dialog->trtp = ast_rtp_instance_new(dialog->engine, sched, &bindaddr_tmp, NULL))) { 05300 return -1; 05301 } 05302 /* Do not timeout text as its not constant*/ 05303 ast_rtp_instance_set_keepalive(dialog->trtp, dialog->rtpkeepalive); 05304 05305 ast_rtp_instance_set_prop(dialog->trtp, AST_RTP_PROPERTY_RTCP, 1); 05306 } 05307 05308 ast_rtp_instance_set_timeout(dialog->rtp, dialog->rtptimeout); 05309 ast_rtp_instance_set_hold_timeout(dialog->rtp, dialog->rtpholdtimeout); 05310 ast_rtp_instance_set_keepalive(dialog->rtp, dialog->rtpkeepalive); 05311 05312 ast_rtp_instance_set_prop(dialog->rtp, AST_RTP_PROPERTY_RTCP, 1); 05313 ast_rtp_instance_set_prop(dialog->rtp, AST_RTP_PROPERTY_DTMF, ast_test_flag(&dialog->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833); 05314 ast_rtp_instance_set_prop(dialog->rtp, AST_RTP_PROPERTY_DTMF_COMPENSATE, ast_test_flag(&dialog->flags[1], SIP_PAGE2_RFC2833_COMPENSATE)); 05315 05316 ast_rtp_instance_set_qos(dialog->rtp, global_tos_audio, global_cos_audio, "SIP RTP"); 05317 05318 do_setnat(dialog); 05319 05320 return 0; 05321 }
| static int dialog_needdestroy | ( | void * | dialogobj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Match dialogs that need to be destroyed.
This is used with ao2_callback to unlink/delete all dialogs that are marked needdestroy.
Definition at line 17725 of file chan_sip.c.
References ast_debug, ast_rtp_instance_get_bridged(), dialog_unlink_all(), sip_methods, sip_pvt_trylock, sip_pvt_unlock, and cfsip_methods::text.
Referenced by do_monitor().
17726 { 17727 struct sip_pvt *dialog = dialogobj; 17728 17729 if (sip_pvt_trylock(dialog)) { 17730 /* Don't block the monitor thread. This function is called often enough 17731 * that we can wait for the next time around. */ 17732 return 0; 17733 } 17734 17735 /* If we have sessions that needs to be destroyed, do it now */ 17736 /* Check if we have outstanding requests not responsed to or an active call 17737 - if that's the case, wait with destruction */ 17738 if (dialog->needdestroy && !dialog->packets && !dialog->owner) { 17739 /* We absolutely cannot destroy the rtp struct while a bridge is active or we WILL crash */ 17740 if (dialog->rtp && ast_rtp_instance_get_bridged(dialog->rtp)) { 17741 ast_debug(2, "Bridge still active. Delaying destruction of SIP dialog '%s' Method: %s\n", dialog->callid, sip_methods[dialog->method].text); 17742 sip_pvt_unlock(dialog); 17743 return 0; 17744 } 17745 17746 if (dialog->vrtp && ast_rtp_instance_get_bridged(dialog->vrtp)) { 17747 ast_debug(2, "Bridge still active. Delaying destroy of SIP dialog '%s' Method: %s\n", dialog->callid, sip_methods[dialog->method].text); 17748 sip_pvt_unlock(dialog); 17749 return 0; 17750 } 17751 17752 sip_pvt_unlock(dialog); 17753 /* no, the unlink should handle this: dialog_unref(dialog, "needdestroy: one more refcount decrement to allow dialog to be destroyed"); */ 17754 /* the CMP_MATCH will unlink this dialog from the dialog hash table */ 17755 dialog_unlink_all(dialog); 17756 return 0; /* the unlink_all should unlink this from the table, so.... no need to return a match */ 17757 } 17758 17759 sip_pvt_unlock(dialog); 17760 17761 return 0; 17762 }
| struct sip_pvt* dialog_ref_debug | ( | struct sip_pvt * | p, | |
| const char * | tag, | |||
| char * | file, | |||
| int | line, | |||
| const char * | func | |||
| ) | [read] |
Definition at line 2236 of file chan_sip.c.
References __ao2_ref_debug(), ao2_ref, ast_log(), and LOG_ERROR.
02237 { 02238 if (p) 02239 #ifdef REF_DEBUG 02240 __ao2_ref_debug(p, 1, tag, file, line, func); 02241 #else 02242 ao2_ref(p, 1); 02243 #endif 02244 else 02245 ast_log(LOG_ERROR, "Attempt to Ref a null pointer\n"); 02246 return p; 02247 }
| void dialog_unlink_all | ( | struct sip_pvt * | dialog | ) |
Unlink a dialog from the dialogs container, as well as any other places that it may be currently stored.
Definition at line 2971 of file chan_sip.c.
References ao2_t_unlink, ast_channel_name(), ast_channel_unlock, ast_channel_unref, ast_debug, ast_extension_state_del(), ast_free, AST_SCHED_DEL, AST_SCHED_DEL_UNREF, cb_extensionstate(), registry_unref(), sip_pvt_lock_full(), sip_pvt_unlock, stop_session_timer(), and ast_channel::tech_pvt.
Referenced by __sip_autodestruct(), __sip_subscribe_mwi_do(), cleanup_all_regs(), dialog_needdestroy(), handle_request_subscribe(), manager_sipnotify(), sip_cli_notify(), sip_destroy_peer(), sip_msg_send(), sip_poke_noanswer(), sip_poke_peer(), sip_registry_destroy(), sip_request_call(), sip_send_mwi_to_peer(), transmit_publish(), transmit_register(), and unload_module().
02972 { 02973 struct sip_pkt *cp; 02974 struct ast_channel *owner; 02975 02976 dialog_ref(dialog, "Let's bump the count in the unlink so it doesn't accidentally become dead before we are done"); 02977 02978 ao2_t_unlink(dialogs, dialog, "unlinking dialog via ao2_unlink"); 02979 ao2_t_unlink(dialogs_needdestroy, dialog, "unlinking dialog_needdestroy via ao2_unlink"); 02980 ao2_t_unlink(dialogs_rtpcheck, dialog, "unlinking dialog_rtpcheck via ao2_unlink"); 02981 02982 /* Unlink us from the owner (channel) if we have one */ 02983 owner = sip_pvt_lock_full(dialog); 02984 if (owner) { 02985 ast_debug(1, "Detaching from channel %s\n", ast_channel_name(owner)); 02986 owner->tech_pvt = dialog_unref(owner->tech_pvt, "resetting channel dialog ptr in unlink_all"); 02987 ast_channel_unlock(owner); 02988 ast_channel_unref(owner); 02989 dialog->owner = NULL; 02990 } 02991 sip_pvt_unlock(dialog); 02992 02993 if (dialog->registry) { 02994 if (dialog->registry->call == dialog) { 02995 dialog->registry->call = dialog_unref(dialog->registry->call, "nulling out the registry's call dialog field in unlink_all"); 02996 } 02997 dialog->registry = registry_unref(dialog->registry, "delete dialog->registry"); 02998 } 02999 if (dialog->stateid != -1) { 03000 ast_extension_state_del(dialog->stateid, cb_extensionstate); 03001 dialog->stateid = -1; 03002 } 03003 /* Remove link from peer to subscription of MWI */ 03004 if (dialog->relatedpeer && dialog->relatedpeer->mwipvt == dialog) { 03005 dialog->relatedpeer->mwipvt = dialog_unref(dialog->relatedpeer->mwipvt, "delete ->relatedpeer->mwipvt"); 03006 } 03007 if (dialog->relatedpeer && dialog->relatedpeer->call == dialog) { 03008 dialog->relatedpeer->call = dialog_unref(dialog->relatedpeer->call, "unset the relatedpeer->call field in tandem with relatedpeer field itself"); 03009 } 03010 03011 /* remove all current packets in this dialog */ 03012 while((cp = dialog->packets)) { 03013 dialog->packets = dialog->packets->next; 03014 AST_SCHED_DEL(sched, cp->retransid); 03015 dialog_unref(cp->owner, "remove all current packets in this dialog, and the pointer to the dialog too as part of __sip_destroy"); 03016 if (cp->data) { 03017 ast_free(cp->data); 03018 } 03019 ast_free(cp); 03020 } 03021 03022 AST_SCHED_DEL_UNREF(sched, dialog->waitid, dialog_unref(dialog, "when you delete the waitid sched, you should dec the refcount for the stored dialog ptr")); 03023 03024 AST_SCHED_DEL_UNREF(sched, dialog->initid, dialog_unref(dialog, "when you delete the initid sched, you should dec the refcount for the stored dialog ptr")); 03025 03026 if (dialog->autokillid > -1) { 03027 AST_SCHED_DEL_UNREF(sched, dialog->autokillid, dialog_unref(dialog, "when you delete the autokillid sched, you should dec the refcount for the stored dialog ptr")); 03028 } 03029 03030 if (dialog->request_queue_sched_id > -1) { 03031 AST_SCHED_DEL_UNREF(sched, dialog->request_queue_sched_id, dialog_unref(dialog, "when you delete the request_queue_sched_id sched, you should dec the refcount for the stored dialog ptr")); 03032 } 03033 03034 AST_SCHED_DEL_UNREF(sched, dialog->provisional_keepalive_sched_id, dialog_unref(dialog, "when you delete the provisional_keepalive_sched_id, you should dec the refcount for the stored dialog ptr")); 03035 03036 if (dialog->t38id > -1) { 03037 AST_SCHED_DEL_UNREF(sched, dialog->t38id, dialog_unref(dialog, "when you delete the t38id sched, you should dec the refcount for the stored dialog ptr")); 03038 } 03039 03040 if (dialog->stimer) { 03041 stop_session_timer(dialog); 03042 } 03043 03044 dialog_unref(dialog, "Let's unbump the count in the unlink so the poor pvt can disappear if it is time"); 03045 }
| struct sip_pvt* dialog_unref_debug | ( | struct sip_pvt * | p, | |
| const char * | tag, | |||
| char * | file, | |||
| int | line, | |||
| const char * | func | |||
| ) | [read] |
Definition at line 2249 of file chan_sip.c.
References __ao2_ref_debug(), and ao2_ref.
02250 { 02251 if (p) 02252 #ifdef REF_DEBUG 02253 __ao2_ref_debug(p, -1, tag, file, line, func); 02254 #else 02255 ao2_ref(p, -1); 02256 #endif 02257 return NULL; 02258 }
| static void disable_dsp_detect | ( | struct sip_pvt * | p | ) | [static] |
Definition at line 4297 of file chan_sip.c.
References ast_dsp_free().
Referenced by sip_dtmfmode(), sip_hangup(), and sip_setoption().
04298 { 04299 if (p->dsp) { 04300 ast_dsp_free(p->dsp); 04301 p->dsp = NULL; 04302 } 04303 }
| static void display_nat_warning | ( | const char * | cat, | |
| int | reason, | |||
| struct ast_flags * | flags | |||
| ) | [static] |
Definition at line 28962 of file chan_sip.c.
References AST_CLI_YESNO, ast_log(), ast_test_flag, CHANNEL_MODULE_LOAD, and LOG_WARNING.
Referenced by reload_config().
28962 { 28963 int global_nat, specific_nat; 28964 28965 if (reason == CHANNEL_MODULE_LOAD && (specific_nat = ast_test_flag(&flags[0], SIP_NAT_FORCE_RPORT)) != (global_nat = ast_test_flag(&global_flags[0], SIP_NAT_FORCE_RPORT))) { 28966 ast_log(LOG_WARNING, "!!! PLEASE NOTE: Setting 'nat' for a peer/user that differs from the global setting can make\n"); 28967 ast_log(LOG_WARNING, "!!! the name of that peer/user discoverable by an attacker. Replies for non-existent peers/users\n"); 28968 ast_log(LOG_WARNING, "!!! will be sent to a different port than replies for an existing peer/user. If at all possible,\n"); 28969 ast_log(LOG_WARNING, "!!! use the global 'nat' setting and do not set 'nat' per peer/user.\n"); 28970 ast_log(LOG_WARNING, "!!! (config category='%s' global force_rport='%s' peer/user force_rport='%s')\n", cat, AST_CLI_YESNO(global_nat), AST_CLI_YESNO(specific_nat)); 28971 } 28972 }
| static int do_magic_pickup | ( | struct ast_channel * | channel, | |
| const char * | extension, | |||
| const char * | context | |||
| ) | [static] |
Definition at line 22926 of file chan_sip.c.
References ast_debug, ast_log(), AST_MAX_CONTEXT, AST_MAX_EXTENSION, ast_str_alloca, ast_str_set(), LOG_ERROR, pbx_exec(), pbx_findapp(), sip_cfg, and str.
Referenced by handle_request_invite().
22927 { 22928 struct ast_str *str = ast_str_alloca(AST_MAX_EXTENSION + AST_MAX_CONTEXT + 2); 22929 struct ast_app *pickup = pbx_findapp("Pickup"); 22930 22931 if (!pickup) { 22932 ast_log(LOG_ERROR, "Unable to perform pickup: Application 'Pickup' not loaded (app_directed_pickup.so).\n"); 22933 return -1; 22934 } 22935 22936 ast_str_set(&str, 0, "%s@%s", extension, sip_cfg.notifycid == IGNORE_CONTEXT ? "PICKUPMARK" : context); 22937 22938 ast_debug(2, "About to call Pickup(%s)\n", str->str); 22939 22940 /* There is no point in capturing the return value since pickup_exec 22941 doesn't return anything meaningful unless the passed data is an empty 22942 string (which in our case it will not be) */ 22943 pbx_exec(channel, pickup, str->str); 22944 22945 return 0; 22946 }
| static int do_message_auth | ( | struct sip_pvt * | p, | |
| int | resp, | |||
| const char * | rest, | |||
| struct sip_request * | req, | |||
| uint32_t | seqno | |||
| ) | [static] |
Definition at line 21647 of file chan_sip.c.
References append_history, ast_debug, ast_log(), ast_sockaddr_stringify(), LOG_NOTICE, reply_digest(), sip_auth_headers(), and transmit_message().
Referenced by handle_response_message().
21648 { 21649 char *header; 21650 char *respheader; 21651 char digest[1024]; 21652 21653 if (p->options) { 21654 p->options->auth_type = (resp == 401 ? WWW_AUTH : PROXY_AUTH); 21655 } 21656 21657 if (p->authtries == MAX_AUTHTRIES) { 21658 ast_log(LOG_NOTICE, "Failed to authenticate MESSAGE with host '%s'\n", 21659 ast_sockaddr_stringify(&p->sa)); 21660 return -1; 21661 } 21662 21663 ++p->authtries; 21664 sip_auth_headers((resp == 401 ? WWW_AUTH : PROXY_AUTH), &header, &respheader); 21665 memset(digest, 0, sizeof(digest)); 21666 if (reply_digest(p, req, header, SIP_MESSAGE, digest, sizeof(digest))) { 21667 /* There's nothing to use for authentication */ 21668 ast_debug(1, "Nothing to use for MESSAGE authentication\n"); 21669 return -1; 21670 } 21671 21672 if (p->do_history) { 21673 append_history(p, "MessageAuth", "Try: %d", p->authtries); 21674 } 21675 21676 transmit_message(p, 0, 1); 21677 return 0; 21678 }
| static void * do_monitor | ( | void * | data | ) | [static] |
The SIP monitoring thread.
Definition at line 26807 of file chan_sip.c.
References ao2_t_callback, ast_debug, ast_io_add(), ast_io_change(), AST_IO_IN, ast_io_remove(), ast_io_wait(), ast_mutex_lock, ast_mutex_unlock, ast_sched_runq(), ast_sched_wait(), ast_verb, dialog_checkrtp_cb(), dialog_needdestroy(), FALSE, monlock, OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, sip_do_reload(), sip_reload_lock, and sipsock_read().
26808 { 26809 int res; 26810 time_t t; 26811 int reloading; 26812 26813 /* Add an I/O event to our SIP UDP socket */ 26814 if (sipsock > -1) { 26815 sipsock_read_id = ast_io_add(io, sipsock, sipsock_read, AST_IO_IN, NULL); 26816 } 26817 26818 /* From here on out, we die whenever asked */ 26819 for(;;) { 26820 /* Check for a reload request */ 26821 ast_mutex_lock(&sip_reload_lock); 26822 reloading = sip_reloading; 26823 sip_reloading = FALSE; 26824 ast_mutex_unlock(&sip_reload_lock); 26825 if (reloading) { 26826 ast_verb(1, "Reloading SIP\n"); 26827 sip_do_reload(sip_reloadreason); 26828 26829 /* Change the I/O fd of our UDP socket */ 26830 if (sipsock > -1) { 26831 if (sipsock_read_id) { 26832 sipsock_read_id = ast_io_change(io, sipsock_read_id, sipsock, NULL, 0, NULL); 26833 } else { 26834 sipsock_read_id = ast_io_add(io, sipsock, sipsock_read, AST_IO_IN, NULL); 26835 } 26836 } else if (sipsock_read_id) { 26837 ast_io_remove(io, sipsock_read_id); 26838 sipsock_read_id = NULL; 26839 } 26840 } 26841 26842 /* Check for dialogs needing to be killed */ 26843 t = time(NULL); 26844 26845 /* 26846 * Check dialogs with rtp and rtptimeout. 26847 * All dialogs which have rtp are in dialogs_rtpcheck. 26848 */ 26849 ao2_t_callback(dialogs_rtpcheck, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, 26850 dialog_checkrtp_cb, &t, 26851 "callback to check rtptimeout and hangup calls if necessary"); 26852 /* 26853 * Check dialogs marked to be destroyed. 26854 * All dialogs with needdestroy set are in dialogs_needdestroy. 26855 */ 26856 ao2_t_callback(dialogs_needdestroy, OBJ_NODATA | OBJ_MULTIPLE, dialog_needdestroy, 26857 NULL, "callback to check dialogs which need to be destroyed"); 26858 26859 /* XXX TODO The scheduler usage in this module does not have sufficient 26860 * synchronization being done between running the scheduler and places 26861 * scheduling tasks. As it is written, any scheduled item may not run 26862 * any sooner than about 1 second, regardless of whether a sooner time 26863 * was asked for. */ 26864 26865 pthread_testcancel(); 26866 /* Wait for sched or io */ 26867 res = ast_sched_wait(sched); 26868 if ((res < 0) || (res > 1000)) { 26869 res = 1000; 26870 } 26871 res = ast_io_wait(io, res); 26872 if (res > 20) { 26873 ast_debug(1, "chan_sip: ast_io_wait ran %d all at once\n", res); 26874 } 26875 ast_mutex_lock(&monlock); 26876 res = ast_sched_runq(sched); 26877 if (res >= 20) { 26878 ast_debug(1, "chan_sip: ast_sched_runq ran %d all at once\n", res); 26879 } 26880 ast_mutex_unlock(&monlock); 26881 } 26882 26883 /* Never reached */ 26884 return NULL; 26885 }
| static int do_proxy_auth | ( | struct sip_pvt * | p, | |
| struct sip_request * | req, | |||
| enum sip_auth_type | code, | |||
| int | sipmethod, | |||
| int | init | |||
| ) | [static] |
Add authentication on outbound SIP packet.
Definition at line 19883 of file chan_sip.c.
References ast_calloc, ast_debug, reply_digest(), sip_auth_headers(), sip_methods, cfsip_methods::text, and transmit_invite().
Referenced by handle_response(), handle_response_invite(), handle_response_notify(), handle_response_publish(), handle_response_refer(), handle_response_subscribe(), and handle_response_update().
19884 { 19885 char *header, *respheader; 19886 char digest[1024]; 19887 19888 if (!p->options && !(p->options = ast_calloc(1, sizeof(*p->options)))) 19889 return -2; 19890 19891 p->authtries++; 19892 sip_auth_headers(code, &header, &respheader); 19893 ast_debug(2, "Auth attempt %d on %s\n", p->authtries, sip_methods[sipmethod].text); 19894 memset(digest, 0, sizeof(digest)); 19895 if (reply_digest(p, req, header, sipmethod, digest, sizeof(digest) )) { 19896 /* No way to authenticate */ 19897 return -1; 19898 } 19899 /* Now we have a reply digest */ 19900 p->options->auth = digest; 19901 p->options->authheader = respheader; 19902 return transmit_invite(p, sipmethod, sipmethod == SIP_INVITE, init, NULL); 19903 }
| static int do_register_auth | ( | struct sip_pvt * | p, | |
| struct sip_request * | req, | |||
| enum sip_auth_type | code | |||
| ) | [static] |
Authenticate for outbound registration.
Definition at line 19859 of file chan_sip.c.
References append_history, ast_verbose, reply_digest(), sip_auth_headers(), sip_debug_test_pvt(), and transmit_register().
Referenced by handle_response_register().
19860 { 19861 char *header, *respheader; 19862 char digest[1024]; 19863 19864 p->authtries++; 19865 sip_auth_headers(code, &header, &respheader); 19866 memset(digest, 0, sizeof(digest)); 19867 if (reply_digest(p, req, header, SIP_REGISTER, digest, sizeof(digest))) { 19868 /* There's nothing to use for authentication */ 19869 /* No digest challenge in request */ 19870 if (sip_debug_test_pvt(p) && p->registry) 19871 ast_verbose("No authentication challenge, sending blank registration to domain/host name %s\n", p->registry->hostname); 19872 /* No old challenge */ 19873 return -1; 19874 } 19875 if (p->do_history) 19876 append_history(p, "RegistryAuth", "Try: %d", p->authtries); 19877 if (sip_debug_test_pvt(p) && p->registry) 19878 ast_verbose("Responding to challenge, registration to domain/host name %s\n", p->registry->hostname); 19879 return transmit_register(p->registry, SIP_REGISTER, digest, respheader); 19880 }
| static void do_setnat | ( | struct sip_pvt * | p | ) | [static] |
Set nat mode on the various data sockets.
Definition at line 5166 of file chan_sip.c.
References ast_debug, ast_rtp_instance_set_prop(), AST_RTP_PROPERTY_NAT, ast_test_flag, and ast_udptl_setnat().
Referenced by check_peer_ok(), dialog_initialize_rtp(), sip_alloc(), and transmit_response_using_temp().
05167 { 05168 const char *mode; 05169 int natflags; 05170 05171 natflags = ast_test_flag(&p->flags[1], SIP_PAGE2_SYMMETRICRTP); 05172 mode = natflags ? "On" : "Off"; 05173 05174 if (p->rtp) { 05175 ast_debug(1, "Setting NAT on RTP to %s\n", mode); 05176 ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_NAT, natflags); 05177 } 05178 if (p->vrtp) { 05179 ast_debug(1, "Setting NAT on VRTP to %s\n", mode); 05180 ast_rtp_instance_set_prop(p->vrtp, AST_RTP_PROPERTY_NAT, natflags); 05181 } 05182 if (p->udptl) { 05183 ast_debug(1, "Setting NAT on UDPTL to %s\n", mode); 05184 ast_udptl_setnat(p->udptl, natflags); 05185 } 05186 if (p->trtp) { 05187 ast_debug(1, "Setting NAT on TRTP to %s\n", mode); 05188 ast_rtp_instance_set_prop(p->trtp, AST_RTP_PROPERTY_NAT, natflags); 05189 } 05190 }
| static const char * domain_mode_to_text | ( | const enum domain_mode | mode | ) | [static] |
Print domain mode to cli.
Definition at line 17924 of file chan_sip.c.
Referenced by sip_show_domains().
17925 { 17926 switch (mode) { 17927 case SIP_DOMAIN_AUTO: 17928 return "[Automatic]"; 17929 case SIP_DOMAIN_CONFIG: 17930 return "[Configured]"; 17931 } 17932 17933 return ""; 17934 }
| static const char * dtmfmode2str | ( | int | mode | ) | [static] |
Convert DTMF mode to printable string.
Definition at line 17622 of file chan_sip.c.
References map_x_s().
Referenced by _sip_show_peer(), sip_show_channel(), and sip_show_settings().
| static void enable_dsp_detect | ( | struct sip_pvt * | p | ) | [static] |
Definition at line 4263 of file chan_sip.c.
References ast_dsp_new(), ast_dsp_set_digitmode(), ast_dsp_set_features(), AST_RTP_DTMF_MODE_INBAND, ast_rtp_instance_dtmf_mode_set(), ast_test_flag, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_RELAXDTMF, DSP_FEATURE_DIGIT_DETECT, and DSP_FEATURE_FAX_DETECT.
Referenced by sip_dtmfmode(), sip_new(), and sip_setoption().
04264 { 04265 int features = 0; 04266 04267 if (p->dsp) { 04268 return; 04269 } 04270 04271 if ((ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_INBAND) || 04272 (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO)) { 04273 if (p->rtp) { 04274 ast_rtp_instance_dtmf_mode_set(p->rtp, AST_RTP_DTMF_MODE_INBAND); 04275 } 04276 features |= DSP_FEATURE_DIGIT_DETECT; 04277 } 04278 04279 if (ast_test_flag(&p->flags[1], SIP_PAGE2_FAX_DETECT_CNG)) { 04280 features |= DSP_FEATURE_FAX_DETECT; 04281 } 04282 04283 if (!features) { 04284 return; 04285 } 04286 04287 if (!(p->dsp = ast_dsp_new())) { 04288 return; 04289 } 04290 04291 ast_dsp_set_features(p->dsp, features); 04292 if (global_relaxdtmf) { 04293 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | DSP_DIGITMODE_RELAXDTMF); 04294 } 04295 }
| static int esc_cmp_fn | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 996 of file chan_sip.c.
References CMP_MATCH, and CMP_STOP.
Referenced by initialize_escs().
00997 { 00998 struct sip_esc_entry *entry1 = obj; 00999 struct sip_esc_entry *entry2 = arg; 01000 01001 return (!strcmp(entry1->entity_tag, entry2->entity_tag)) ? (CMP_MATCH | CMP_STOP) : 0; 01002 }
| static void esc_entry_destructor | ( | void * | obj | ) | [static] |
Definition at line 982 of file chan_sip.c.
References AST_SCHED_DEL.
Referenced by create_esc_entry().
00983 { 00984 struct sip_esc_entry *esc_entry = obj; 00985 if (esc_entry->sched_id > -1) { 00986 AST_SCHED_DEL(sched, esc_entry->sched_id); 00987 } 00988 }
| static int esc_hash_fn | ( | const void * | obj, | |
| const int | flags | |||
| ) | [static] |
Definition at line 990 of file chan_sip.c.
References ast_str_hash().
Referenced by initialize_escs().
00991 { 00992 const struct sip_esc_entry *entry = obj; 00993 return ast_str_hash(entry->entity_tag); 00994 }
| static int expire_register | ( | const void * | data | ) | [static] |
Expire registration of SIP peer.
Definition at line 14158 of file chan_sip.c.
References ao2_ref, ao2_t_unlink, ast_debug, AST_DEVICE_UNKNOWN, ast_devstate_changed(), ast_sockaddr_isnull(), ast_test_flag, destroy_association(), EVENT_FLAG_SYSTEM, FALSE, manager_event, register_peer_exten(), set_socket_transport(), sip_unref_peer(), and unlink_peer_from_tables().
Referenced by parse_register_contact(), realtime_peer(), reg_source_db(), sip_show_sched(), and sip_unregister().
14159 { 14160 struct sip_peer *peer = (struct sip_peer *)data; 14161 14162 if (!peer) { /* Hmmm. We have no peer. Weird. */ 14163 return 0; 14164 } 14165 14166 peer->expire = -1; 14167 peer->portinuri = 0; 14168 14169 destroy_association(peer); /* remove registration data from storage */ 14170 set_socket_transport(&peer->socket, peer->default_outbound_transport); 14171 14172 if (peer->socket.tcptls_session) { 14173 ao2_ref(peer->socket.tcptls_session, -1); 14174 peer->socket.tcptls_session = NULL; 14175 } 14176 14177 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: SIP\r\nPeer: SIP/%s\r\nPeerStatus: Unregistered\r\nCause: Expired\r\n", peer->name); 14178 register_peer_exten(peer, FALSE); /* Remove regexten */ 14179 ast_devstate_changed(AST_DEVICE_UNKNOWN, "SIP/%s", peer->name); 14180 14181 /* Do we need to release this peer from memory? 14182 Only for realtime peers and autocreated peers 14183 */ 14184 if (peer->is_realtime) { 14185 ast_debug(3, "-REALTIME- peer expired registration. Name: %s. Realtime peer objects now %d\n", peer->name, rpeerobjs); 14186 } 14187 14188 if (peer->selfdestruct || 14189 ast_test_flag(&peer->flags[1], SIP_PAGE2_RTAUTOCLEAR)) { 14190 unlink_peer_from_tables(peer); 14191 } else if (!ast_sockaddr_isnull(&peer->addr)) { 14192 /* If we aren't self-destructing a temp_peer, we still need to unlink the peer 14193 * from the peers_by_ip table, otherwise we end up with multiple copies hanging 14194 * around each time a registration expires and the peer re-registers. */ 14195 ao2_t_unlink(peers_by_ip, peer, "ao2_unlink of peer from peers_by_ip table"); 14196 } 14197 14198 /* Only clear the addr after we check for destruction. The addr must remain 14199 * in order to unlink from the peers_by_ip container correctly */ 14200 memset(&peer->addr, 0, sizeof(peer->addr)); 14201 14202 sip_unref_peer(peer, "removing peer ref for expire_register"); 14203 14204 return 0; 14205 }
| static void extract_host_from_hostport | ( | char ** | hostport | ) | [static] |
Terminate a host:port at the ':'.
| hostport | The address of the hostport string |
Definition at line 15173 of file chan_sip.c.
References ast_sockaddr_split_hostport(), and PARSE_PORT_IGNORE.
Referenced by check_user_full(), get_destination(), register_verify(), and sip_msg_send().
15174 { 15175 char *dont_care; 15176 ast_sockaddr_split_hostport(*hostport, hostport, &dont_care, PARSE_PORT_IGNORE); 15177 }
| static void extract_uri | ( | struct sip_pvt * | p, | |
| struct sip_request * | req | |||
| ) | [static] |
Check Contact: URI of SIP message.
Definition at line 12303 of file chan_sip.c.
References ast_copy_string(), ast_string_field_set, ast_strlen_zero(), get_in_brackets(), remove_uri_parameters(), and sip_get_header().
Referenced by handle_incoming(), and handle_request_invite().
12304 { 12305 char stripped[SIPBUFSIZE]; 12306 char *c; 12307 12308 ast_copy_string(stripped, sip_get_header(req, "Contact"), sizeof(stripped)); 12309 c = get_in_brackets(stripped); 12310 /* Cut the URI at the at sign after the @, not in the username part */ 12311 c = remove_uri_parameters(c); 12312 if (!ast_strlen_zero(c)) { 12313 ast_string_field_set(p, uri, c); 12314 } 12315 12316 }
| static const char* faxec2str | ( | int | faxec | ) | [static] |
Definition at line 18088 of file chan_sip.c.
References map_x_s().
Referenced by _sip_show_peer(), and sip_show_settings().
18089 { 18090 return map_x_s(faxecmodes, faxec, "Unknown"); 18091 }
| static int finalize_content | ( | struct sip_request * | req | ) | [static] |
Add 'Content-Length' header and content to SIP message.
Definition at line 10165 of file chan_sip.c.
References add_header(), ast_log(), ast_str_append(), ast_str_buffer(), ast_str_strlen(), and LOG_WARNING.
Referenced by send_request(), and send_response().
10166 { 10167 char clen[10]; 10168 10169 if (req->lines) { 10170 ast_log(LOG_WARNING, "finalize_content() called on a message that has already been finalized\n"); 10171 return -1; 10172 } 10173 10174 snprintf(clen, sizeof(clen), "%zd", ast_str_strlen(req->content)); 10175 add_header(req, "Content-Length", clen); 10176 10177 if (ast_str_strlen(req->content)) { 10178 ast_str_append(&req->data, 0, "\r\n%s", ast_str_buffer(req->content)); 10179 } 10180 req->lines = ast_str_strlen(req->content) ? 1 : 0; 10181 return 0; 10182 }
| static const char * find_alias | ( | const char * | name, | |
| const char * | _default | |||
| ) | [static] |
| static int find_by_callid_helper | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 1699 of file chan_sip.c.
References CMP_MATCH, CMP_STOP, and ast_cc_agent::private_data.
Referenced by find_sip_cc_agent_by_original_callid().
01700 { 01701 struct ast_cc_agent *agent = obj; 01702 struct sip_cc_agent_pvt *agent_pvt = agent->private_data; 01703 struct sip_pvt *call_pvt = arg; 01704 01705 return !strcmp(agent_pvt->original_callid, call_pvt->callid) ? CMP_MATCH | CMP_STOP : 0; 01706 }
| static int find_by_name | ( | void * | obj, | |
| void * | arg, | |||
| void * | data, | |||
| int | flags | |||
| ) | [static] |
Definition at line 5065 of file chan_sip.c.
References CMP_MATCH, CMP_STOP, and match().
Referenced by sip_find_peer_full().
05066 { 05067 struct sip_peer *search = obj, *match = arg; 05068 int *which_objects = data; 05069 05070 /* Usernames in SIP uri's are case sensitive. Domains are not */ 05071 if (strcmp(search->name, match->name)) { 05072 return 0; 05073 } 05074 05075 switch (*which_objects) { 05076 case FINDUSERS: 05077 if (!(search->type & SIP_TYPE_USER)) { 05078 return 0; 05079 } 05080 break; 05081 case FINDPEERS: 05082 if (!(search->type & SIP_TYPE_PEER)) { 05083 return 0; 05084 } 05085 break; 05086 case FINDALLDEVICES: 05087 break; 05088 } 05089 05090 return CMP_MATCH | CMP_STOP; 05091 }
| static int find_by_notify_uri_helper | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 1669 of file chan_sip.c.
References CMP_MATCH, CMP_STOP, ast_cc_agent::private_data, and sip_uri_cmp().
Referenced by find_sip_cc_agent_by_notify_uri().
01670 { 01671 struct ast_cc_agent *agent = obj; 01672 struct sip_cc_agent_pvt *agent_pvt = agent->private_data; 01673 const char *uri = arg; 01674 01675 return !sip_uri_cmp(agent_pvt->notify_uri, uri) ? CMP_MATCH | CMP_STOP : 0; 01676 }
| static int find_by_subscribe_uri_helper | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 1684 of file chan_sip.c.
References CMP_MATCH, CMP_STOP, ast_cc_agent::private_data, and sip_uri_cmp().
Referenced by find_sip_cc_agent_by_subscribe_uri().
01685 { 01686 struct ast_cc_agent *agent = obj; 01687 struct sip_cc_agent_pvt *agent_pvt = agent->private_data; 01688 const char *uri = arg; 01689 01690 return !sip_uri_cmp(agent_pvt->subscribe_uri, uri) ? CMP_MATCH | CMP_STOP : 0; 01691 }
| static struct sip_pvt * find_call | ( | struct sip_request * | req, | |
| struct ast_sockaddr * | addr, | |||
| const int | intended_method | |||
| ) | [static, read] |
find or create a dialog structure for an incoming SIP message. Connect incoming SIP message to current dialog or create new dialog structure Returns a reference to the sip_pvt object, remember to give it back once done. Called by handle_request_do
Definition at line 8267 of file chan_sip.c.
References ao2_iterator_destroy(), ao2_iterator_next, ao2_t_callback, ao2_t_find, args, ast_debug, ast_skip_blanks(), ast_strlen_zero(), match_req_args::authentication_present, match_req_args::callid, dialog_find_multiple(), forked_invite_init(), free_via(), match_req_args::fromtag, gettag(), match_req_to_dialog(), match_req_args::method, OBJ_MULTIPLE, OBJ_POINTER, parse_via(), match_req_args::respid, match_req_args::ruri, match_req_args::seqno, sip_alloc(), sip_cfg, sip_get_header(), sip_methods, SIP_REQ_FORKED, SIP_REQ_LOOP_DETECTED, SIP_REQ_MATCH, SIP_REQ_NOT_MATCH, cfsip_methods::text, match_req_args::totag, transmit_response_using_temp(), match_req_args::viabranch, and match_req_args::viasentby.
Referenced by handle_request_do().
08268 { 08269 char totag[128]; 08270 char fromtag[128]; 08271 const char *callid = sip_get_header(req, "Call-ID"); 08272 const char *from = sip_get_header(req, "From"); 08273 const char *to = sip_get_header(req, "To"); 08274 const char *cseq = sip_get_header(req, "Cseq"); 08275 struct sip_pvt *sip_pvt_ptr; 08276 uint32_t seqno; 08277 /* Call-ID, to, from and Cseq are required by RFC 3261. (Max-forwards and via too - ignored now) */ 08278 /* sip_get_header always returns non-NULL so we must use ast_strlen_zero() */ 08279 if (ast_strlen_zero(callid) || ast_strlen_zero(to) || 08280 ast_strlen_zero(from) || ast_strlen_zero(cseq) || 08281 (sscanf(cseq, "%30u", &seqno) != 1)) { 08282 08283 /* RFC 3261 section 24.4.1. Send a 400 Bad Request if the request is malformed. */ 08284 if (intended_method != SIP_RESPONSE && intended_method != SIP_ACK) { 08285 transmit_response_using_temp(callid, addr, 1, intended_method, 08286 req, "400 Bad Request"); 08287 } 08288 return NULL; /* Invalid packet */ 08289 } 08290 08291 if (sip_cfg.pedanticsipchecking) { 08292 /* In principle Call-ID's uniquely identify a call, but with a forking SIP proxy 08293 we need more to identify a branch - so we have to check branch, from 08294 and to tags to identify a call leg. 08295 For Asterisk to behave correctly, you need to turn on pedanticsipchecking 08296 in sip.conf 08297 */ 08298 if (gettag(req, "To", totag, sizeof(totag))) 08299 req->has_to_tag = 1; /* Used in handle_request/response */ 08300 gettag(req, "From", fromtag, sizeof(fromtag)); 08301 08302 ast_debug(5, "= Looking for Call ID: %s (Checking %s) --From tag %s --To-tag %s \n", callid, req->method==SIP_RESPONSE ? "To" : "From", fromtag, totag); 08303 08304 /* All messages must always have From: tag */ 08305 if (ast_strlen_zero(fromtag)) { 08306 ast_debug(5, "%s request has no from tag, dropping callid: %s from: %s\n", sip_methods[req->method].text , callid, from ); 08307 return NULL; 08308 } 08309 /* reject requests that must always have a To: tag */ 08310 if (ast_strlen_zero(totag) && (req->method == SIP_ACK || req->method == SIP_BYE || req->method == SIP_INFO )) { 08311 if (req->method != SIP_ACK) { 08312 transmit_response_using_temp(callid, addr, 1, intended_method, req, "481 Call leg/transaction does not exist"); 08313 } 08314 ast_debug(5, "%s must have a to tag. dropping callid: %s from: %s\n", sip_methods[req->method].text , callid, from ); 08315 return NULL; 08316 } 08317 } 08318 08319 if (!sip_cfg.pedanticsipchecking) { 08320 struct sip_pvt tmp_dialog = { 08321 .callid = callid, 08322 }; 08323 sip_pvt_ptr = ao2_t_find(dialogs, &tmp_dialog, OBJ_POINTER, "ao2_find in dialogs"); 08324 if (sip_pvt_ptr) { /* well, if we don't find it-- what IS in there? */ 08325 /* Found the call */ 08326 return sip_pvt_ptr; 08327 } 08328 } else { /* in pedantic mode! -- do the fancy search */ 08329 struct sip_pvt tmp_dialog = { 08330 .callid = callid, 08331 }; 08332 /* if a Outbound forked Request is detected, this pvt will point 08333 * to the dialog the Request is forking off of. */ 08334 struct sip_pvt *fork_pvt = NULL; 08335 struct match_req_args args = { 0, }; 08336 int found; 08337 struct ao2_iterator *iterator = ao2_t_callback(dialogs, 08338 OBJ_POINTER | OBJ_MULTIPLE, 08339 dialog_find_multiple, 08340 &tmp_dialog, 08341 "pedantic ao2_find in dialogs"); 08342 struct sip_via *via = NULL; 08343 08344 args.method = req->method; 08345 args.callid = NULL; /* we already matched this. */ 08346 args.totag = totag; 08347 args.fromtag = fromtag; 08348 args.seqno = seqno; 08349 /* get via header information. */ 08350 args.ruri = REQ_OFFSET_TO_STR(req, rlPart2); 08351 via = parse_via(sip_get_header(req, "Via")); 08352 if (via) { 08353 args.viasentby = via->sent_by; 08354 args.viabranch = via->branch; 08355 } 08356 /* determine if this is a Request with authentication credentials. */ 08357 if (!ast_strlen_zero(sip_get_header(req, "Authorization")) || 08358 !ast_strlen_zero(sip_get_header(req, "Proxy-Authorization"))) { 08359 args.authentication_present = 1; 08360 } 08361 /* if it is a response, get the response code */ 08362 if (req->method == SIP_RESPONSE) { 08363 const char* e = ast_skip_blanks(REQ_OFFSET_TO_STR(req, rlPart2)); 08364 int respid; 08365 if (!ast_strlen_zero(e) && (sscanf(e, "%30d", &respid) == 1)) { 08366 args.respid = respid; 08367 } 08368 } 08369 08370 /* Iterate a list of dialogs already matched by Call-id */ 08371 while (iterator && (sip_pvt_ptr = ao2_iterator_next(iterator))) { 08372 found = match_req_to_dialog(sip_pvt_ptr, &args); 08373 08374 switch (found) { 08375 case SIP_REQ_MATCH: 08376 ao2_iterator_destroy(iterator); 08377 dialog_unref(fork_pvt, "unref fork_pvt"); 08378 free_via(via); 08379 return sip_pvt_ptr; /* return pvt with ref */ 08380 case SIP_REQ_LOOP_DETECTED: 08381 /* This is likely a forked Request that somehow resulted in us receiving multiple parts of the fork. 08382 * RFC 3261 section 8.2.2.2, Indicate that we want to merge requests by sending a 482 response. */ 08383 transmit_response_using_temp(callid, addr, 1, intended_method, req, "482 (Loop Detected)"); 08384 dialog_unref(sip_pvt_ptr, "pvt did not match incoming SIP msg, unref from search."); 08385 ao2_iterator_destroy(iterator); 08386 dialog_unref(fork_pvt, "unref fork_pvt"); 08387 free_via(via); 08388 return NULL; 08389 case SIP_REQ_FORKED: 08390 dialog_unref(fork_pvt, "throwing way pvt to fork off of."); 08391 fork_pvt = dialog_ref(sip_pvt_ptr, "this pvt has a forked request, save this off to copy information into new dialog\n"); 08392 /* fall through */ 08393 case SIP_REQ_NOT_MATCH: 08394 default: 08395 dialog_unref(sip_pvt_ptr, "pvt did not match incoming SIP msg, unref from search"); 08396 } 08397 } 08398 if (iterator) { 08399 ao2_iterator_destroy(iterator); 08400 } 08401 08402 /* Handle any possible forked requests. This must be done only after transaction matching is complete. */ 08403 if (fork_pvt) { 08404 /* XXX right now we only support handling forked INVITE Requests. Any other 08405 * forked request type must be added here. */ 08406 if (fork_pvt->method == SIP_INVITE) { 08407 forked_invite_init(req, args.totag, fork_pvt, addr); 08408 dialog_unref(fork_pvt, "throwing way old forked pvt"); 08409 free_via(via); 08410 return NULL; 08411 } 08412 fork_pvt = dialog_unref(fork_pvt, "throwing way pvt to fork off of"); 08413 } 08414 08415 free_via(via); 08416 } /* end of pedantic mode Request/Reponse to Dialog matching */ 08417 08418 /* See if the method is capable of creating a dialog */ 08419 if (sip_methods[intended_method].can_create == CAN_CREATE_DIALOG) { 08420 struct sip_pvt *p = NULL; 08421 08422 if (intended_method == SIP_REFER) { 08423 /* We do support REFER, but not outside of a dialog yet */ 08424 transmit_response_using_temp(callid, addr, 1, intended_method, req, "603 Declined (no dialog)"); 08425 08426 /* Ok, time to create a new SIP dialog object, a pvt */ 08427 } else if (!(p = sip_alloc(callid, addr, 1, intended_method, req))) { 08428 /* We have a memory or file/socket error (can't allocate RTP sockets or something) so we're not 08429 getting a dialog from sip_alloc. 08430 08431 Without a dialog we can't retransmit and handle ACKs and all that, but at least 08432 send an error message. 08433 08434 Sorry, we apologize for the inconvienience 08435 */ 08436 transmit_response_using_temp(callid, addr, 1, intended_method, req, "500 Server internal error"); 08437 ast_debug(4, "Failed allocating SIP dialog, sending 500 Server internal error and giving up\n"); 08438 } 08439 return p; /* can be NULL */ 08440 } else if( sip_methods[intended_method].can_create == CAN_CREATE_DIALOG_UNSUPPORTED_METHOD) { 08441 /* A method we do not support, let's take it on the volley */ 08442 transmit_response_using_temp(callid, addr, 1, intended_method, req, "501 Method Not Implemented"); 08443 ast_debug(2, "Got a request with unsupported SIP method.\n"); 08444 } else if (intended_method != SIP_RESPONSE && intended_method != SIP_ACK) { 08445 /* This is a request outside of a dialog that we don't know about */ 08446 transmit_response_using_temp(callid, addr, 1, intended_method, req, "481 Call leg/transaction does not exist"); 08447 ast_debug(2, "That's odd... Got a request in unknown dialog. Callid %s\n", callid ? callid : "<unknown>"); 08448 } 08449 /* We do not respond to responses for dialogs that we don't know about, we just drop 08450 the session quickly */ 08451 if (intended_method == SIP_RESPONSE) 08452 ast_debug(2, "That's odd... Got a response on a call we don't know about. Callid %s\n", callid ? callid : "<unknown>"); 08453 08454 return NULL; 08455 }
| static int find_calling_channel | ( | void * | obj, | |
| void * | arg, | |||
| void * | data, | |||
| int | flags | |||
| ) | [static] |
Find the channel that is causing the RINGING update.
Definition at line 12940 of file chan_sip.c.
References ast_channel_lock, ast_channel_unlock, CMP_MATCH, CMP_STOP, ast_channel::context, ast_channel::exten, ast_channel::macroexten, ast_channel::pbx, and sip_cfg.
Referenced by state_notify_build_xml().
12941 { 12942 struct ast_channel *c = obj; 12943 struct sip_pvt *p = data; 12944 int res; 12945 12946 ast_channel_lock(c); 12947 12948 res = (c->pbx && 12949 (!strcasecmp(c->macroexten, p->exten) || !strcasecmp(c->exten, p->exten)) && 12950 (sip_cfg.notifycid == IGNORE_CONTEXT || !strcasecmp(c->context, p->context))); 12951 12952 ast_channel_unlock(c); 12953 12954 return res ? CMP_MATCH | CMP_STOP : 0; 12955 }
| const char* find_closing_quote | ( | const char * | start, | |
| const char * | lim | |||
| ) |
Locate closing quote in a string, skipping escaped quotes. optionally with a limit on the search. start must be past the first quote.
Definition at line 4441 of file chan_sip.c.
Referenced by get_comma(), get_in_brackets_full(), and parse_moved_contact().
04442 { 04443 char last_char = '\0'; 04444 const char *s; 04445 for (s = start; *s && s != lim; last_char = *s++) { 04446 if (*s == '"' && last_char != '\\') 04447 break; 04448 } 04449 return s; 04450 }
| static const char* find_full_alias | ( | const char * | name, | |
| const char * | _default | |||
| ) | [static] |
Find full SIP alias.
Definition at line 7445 of file chan_sip.c.
References ARRAY_LEN.
Referenced by set_message_vars_from_req().
07446 { 07447 int x; 07448 07449 if (strlen(name) == 1) { 07450 /* We have a short header name to convert. */ 07451 for (x = 0; x < ARRAY_LEN(aliases); ++x) { 07452 if (!strcasecmp(aliases[x].shortname, name)) 07453 return aliases[x].fullname; 07454 } 07455 } 07456 07457 return _default; 07458 }
| static struct sip_auth * find_realm_authentication | ( | struct sip_auth_container * | credentials, | |
| const char * | realm | |||
| ) | [static, read] |
Definition at line 28055 of file chan_sip.c.
References AST_LIST_TRAVERSE.
Referenced by build_reply_digest().
28056 { 28057 struct sip_auth *auth; 28058 28059 if (credentials) { 28060 AST_LIST_TRAVERSE(&credentials->list, auth, node) { 28061 if (!strcasecmp(auth->realm, realm)) { 28062 break; 28063 } 28064 } 28065 } else { 28066 auth = NULL; 28067 } 28068 28069 return auth; 28070 }
| static int find_sdp | ( | struct sip_request * | req | ) | [static] |
Determine whether a SIP message contains an SDP in its body.
| req | the SIP request to process |
Definition at line 8813 of file chan_sip.c.
References ast_log(), ast_strdupa, ast_strlen_zero(), FALSE, LOG_WARNING, sip_get_header(), strcasestr(), and TRUE.
Referenced by handle_incoming(), handle_request_invite(), handle_response(), and handle_response_invite().
08814 { 08815 const char *content_type; 08816 const char *content_length; 08817 const char *search; 08818 char *boundary; 08819 unsigned int x; 08820 int boundaryisquoted = FALSE; 08821 int found_application_sdp = FALSE; 08822 int found_end_of_headers = FALSE; 08823 08824 content_length = sip_get_header(req, "Content-Length"); 08825 08826 if (!ast_strlen_zero(content_length)) { 08827 if (sscanf(content_length, "%30u", &x) != 1) { 08828 ast_log(LOG_WARNING, "Invalid Content-Length: %s\n", content_length); 08829 return 0; 08830 } 08831 08832 /* Content-Length of zero means there can't possibly be an 08833 SDP here, even if the Content-Type says there is */ 08834 if (x == 0) 08835 return 0; 08836 } 08837 08838 content_type = sip_get_header(req, "Content-Type"); 08839 08840 /* if the body contains only SDP, this is easy */ 08841 if (!strncasecmp(content_type, "application/sdp", 15)) { 08842 req->sdp_start = 0; 08843 req->sdp_count = req->lines; 08844 return req->lines ? 1 : 0; 08845 } 08846 08847 /* if it's not multipart/mixed, there cannot be an SDP */ 08848 if (strncasecmp(content_type, "multipart/mixed", 15)) 08849 return 0; 08850 08851 /* if there is no boundary marker, it's invalid */ 08852 if ((search = strcasestr(content_type, ";boundary="))) 08853 search += 10; 08854 else if ((search = strcasestr(content_type, "; boundary="))) 08855 search += 11; 08856 else 08857 return 0; 08858 08859 if (ast_strlen_zero(search)) 08860 return 0; 08861 08862 /* If the boundary is quoted with ", remove quote */ 08863 if (*search == '\"') { 08864 search++; 08865 boundaryisquoted = TRUE; 08866 } 08867 08868 /* make a duplicate of the string, with two extra characters 08869 at the beginning */ 08870 boundary = ast_strdupa(search - 2); 08871 boundary[0] = boundary[1] = '-'; 08872 /* Remove final quote */ 08873 if (boundaryisquoted) 08874 boundary[strlen(boundary) - 1] = '\0'; 08875 08876 /* search for the boundary marker, the empty line delimiting headers from 08877 sdp part and the end boundry if it exists */ 08878 08879 for (x = 0; x < (req->lines); x++) { 08880 const char *line = REQ_OFFSET_TO_STR(req, line[x]); 08881 if (!strncasecmp(line, boundary, strlen(boundary))){ 08882 if (found_application_sdp && found_end_of_headers) { 08883 req->sdp_count = (x - 1) - req->sdp_start; 08884 return 1; 08885 } 08886 found_application_sdp = FALSE; 08887 } 08888 if (!strcasecmp(line, "Content-Type: application/sdp")) 08889 found_application_sdp = TRUE; 08890 08891 if (ast_strlen_zero(line)) { 08892 if (found_application_sdp && !found_end_of_headers){ 08893 req->sdp_start = x; 08894 found_end_of_headers = TRUE; 08895 } 08896 } 08897 } 08898 if (found_application_sdp && found_end_of_headers) { 08899 req->sdp_count = x - req->sdp_start; 08900 return TRUE; 08901 } 08902 return FALSE; 08903 }
| static struct ast_cc_agent* find_sip_cc_agent_by_notify_uri | ( | const char *const | uri | ) | [static, read] |
Definition at line 1678 of file chan_sip.c.
References ast_cc_agent_callback(), and find_by_notify_uri_helper().
Referenced by get_destination().
01679 { 01680 struct ast_cc_agent *agent = ast_cc_agent_callback(0, find_by_notify_uri_helper, (char *)uri, "SIP"); 01681 return agent; 01682 }
| static struct ast_cc_agent* find_sip_cc_agent_by_original_callid | ( | struct sip_pvt * | pvt | ) | [static, read] |
Definition at line 1708 of file chan_sip.c.
References ast_cc_agent_callback(), and find_by_callid_helper().
Referenced by add_cc_call_info_to_response().
01709 { 01710 struct ast_cc_agent *agent = ast_cc_agent_callback(0, find_by_callid_helper, pvt, "SIP"); 01711 return agent; 01712 }
| static struct ast_cc_agent* find_sip_cc_agent_by_subscribe_uri | ( | const char *const | uri | ) | [static, read] |
Definition at line 1693 of file chan_sip.c.
References ast_cc_agent_callback(), and find_by_subscribe_uri_helper().
Referenced by handle_cc_subscribe().
01694 { 01695 struct ast_cc_agent *agent = ast_cc_agent_callback(0, find_by_subscribe_uri_helper, (char *)uri, "SIP"); 01696 return agent; 01697 }
| static int find_sip_method | ( | const char * | msg | ) | [static] |
find_sip_method: Find SIP method from header
Definition at line 3190 of file chan_sip.c.
References ARRAY_LEN, ast_strlen_zero(), cfsip_methods::id, method_match(), and sip_methods.
Referenced by __sip_pretend_ack(), handle_request_do(), handle_response(), mark_parsed_methods(), and sip_hangup().
03191 { 03192 int i, res = 0; 03193 03194 if (ast_strlen_zero(msg)) { 03195 return 0; 03196 } 03197 for (i = 1; i < ARRAY_LEN(sip_methods) && !res; i++) { 03198 if (method_match(i, msg)) { 03199 res = sip_methods[i].id; 03200 } 03201 } 03202 return res; 03203 }
| static int find_sip_monitor_instance_by_subscription_pvt | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 1906 of file chan_sip.c.
References CMP_MATCH, and CMP_STOP.
Referenced by handle_cc_notify(), and handle_response_subscribe().
01907 { 01908 struct sip_monitor_instance *monitor_instance = obj; 01909 return monitor_instance->subscription_pvt == arg ? CMP_MATCH | CMP_STOP : 0; 01910 }
| static int find_sip_monitor_instance_by_suspension_entry | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 1912 of file chan_sip.c.
References CMP_MATCH, and CMP_STOP.
Referenced by cc_handle_publish_error().
01913 { 01914 struct sip_monitor_instance *monitor_instance = obj; 01915 return monitor_instance->suspension_entry == arg ? CMP_MATCH | CMP_STOP : 0; 01916 }
| static struct epa_static_data* find_static_data | ( | const char *const | event_package | ) | [static, read] |
Definition at line 910 of file chan_sip.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, and AST_LIST_UNLOCK.
Referenced by create_epa_entry().
00911 { 00912 const struct epa_backend *backend = NULL; 00913 00914 AST_LIST_LOCK(&epa_static_data_list); 00915 AST_LIST_TRAVERSE(&epa_static_data_list, backend, next) { 00916 if (!strcmp(backend->static_data->name, event_package)) { 00917 break; 00918 } 00919 } 00920 AST_LIST_UNLOCK(&epa_static_data_list); 00921 return backend ? backend->static_data : NULL; 00922 }
| static struct cfsubscription_types * find_subscription_type | ( | enum subscriptiontype | subtype | ) | [static, read] |
Find subscription type in array.
Definition at line 18994 of file chan_sip.c.
References ARRAY_LEN, subscription_types, and type.
Referenced by transmit_state_notify().
18995 { 18996 int i; 18997 18998 for (i = 1; i < ARRAY_LEN(subscription_types); i++) { 18999 if (subscription_types[i].type == subtype) { 19000 return &subscription_types[i]; 19001 } 19002 } 19003 return &subscription_types[0]; 19004 }
| static void forked_invite_init | ( | struct sip_request * | req, | |
| const char * | new_theirtag, | |||
| struct sip_pvt * | original, | |||
| struct ast_sockaddr * | addr | |||
| ) | [static] |
This function creates a dialog to handle a forked request. This dialog exists only to properly terminiate the the forked request immediately.
Definition at line 8168 of file chan_sip.c.
References ast_copy_string(), ast_string_field_set, build_route(), copy_request(), parse_ok_contact(), pvt_set_needdestroy(), sip_alloc(), transmit_request(), and TRUE.
Referenced by find_call().
08169 { 08170 struct sip_pvt *p; 08171 08172 if (!(p = sip_alloc(original->callid, addr, 1, SIP_INVITE, req))) { 08173 return; /* alloc error */ 08174 } 08175 p->invitestate = INV_TERMINATED; 08176 p->ocseq = original->ocseq; 08177 p->branch = original->branch; 08178 08179 memcpy(&p->flags, &original->flags, sizeof(p->flags)); 08180 copy_request(&p->initreq, &original->initreq); 08181 ast_string_field_set(p, theirtag, new_theirtag); 08182 ast_copy_string(p->tag, original->tag, sizeof(p->tag)); 08183 ast_string_field_set(p, uri, original->uri); 08184 ast_string_field_set(p, our_contact, original->our_contact); 08185 ast_string_field_set(p, fullcontact, original->fullcontact); 08186 parse_ok_contact(p, req); 08187 build_route(p, req, 1); 08188 08189 transmit_request(p, SIP_ACK, p->ocseq, XMIT_UNRELIABLE, TRUE); 08190 transmit_request(p, SIP_BYE, 0, XMIT_RELIABLE, TRUE); 08191 08192 pvt_set_needdestroy(p, "forked request"); /* this dialog will terminate once the BYE is responed to or times out. */ 08193 dialog_unref(p, "setup forked invite termination"); 08194 }
| static void free_old_route | ( | struct sip_route * | route | ) | [static] |
Remove route from route list.
Definition at line 14613 of file chan_sip.c.
References ast_free.
Referenced by __sip_destroy(), and build_route().
14614 { 14615 struct sip_route *next; 14616 14617 while (route) { 14618 next = route->next; 14619 ast_free(route); 14620 route = next; 14621 } 14622 }
| static int func_check_sipdomain | ( | struct ast_channel * | chan, | |
| const char * | cmd, | |||
| char * | data, | |||
| char * | buf, | |||
| size_t | len | |||
| ) | [static] |
Dial plan function to check if domain is local.
Definition at line 20149 of file chan_sip.c.
References ast_copy_string(), ast_log(), ast_strlen_zero(), check_sip_domain(), and LOG_WARNING.
20150 { 20151 if (ast_strlen_zero(data)) { 20152 ast_log(LOG_WARNING, "CHECKSIPDOMAIN requires an argument - A domain name\n"); 20153 return -1; 20154 } 20155 if (check_sip_domain(data, NULL, 0)) 20156 ast_copy_string(buf, data, len); 20157 else 20158 buf[0] = '\0'; 20159 return 0; 20160 }
| static int func_header_read | ( | struct ast_channel * | chan, | |
| const char * | function, | |||
| char * | data, | |||
| char * | buf, | |||
| size_t | len | |||
| ) | [static] |
Read SIP header (dialplan function).
Definition at line 20090 of file chan_sip.c.
References __get_header(), args, AST_APP_ARG, ast_channel_lock, ast_channel_unlock, ast_copy_string(), AST_DECLARE_APP_ARGS, ast_log(), AST_STANDARD_APP_ARGS, ast_strlen_zero(), LOG_WARNING, ast_channel::tech, and ast_channel::tech_pvt.
20091 { 20092 struct sip_pvt *p; 20093 const char *content = NULL; 20094 AST_DECLARE_APP_ARGS(args, 20095 AST_APP_ARG(header); 20096 AST_APP_ARG(number); 20097 ); 20098 int i, number, start = 0; 20099 20100 if (ast_strlen_zero(data)) { 20101 ast_log(LOG_WARNING, "This function requires a header name.\n"); 20102 return -1; 20103 } 20104 20105 ast_channel_lock(chan); 20106 if (!IS_SIP_TECH(chan->tech)) { 20107 ast_log(LOG_WARNING, "This function can only be used on SIP channels.\n"); 20108 ast_channel_unlock(chan); 20109 return -1; 20110 } 20111 20112 AST_STANDARD_APP_ARGS(args, data); 20113 if (!args.number) { 20114 number = 1; 20115 } else { 20116 sscanf(args.number, "%30d", &number); 20117 if (number < 1) 20118 number = 1; 20119 } 20120 20121 p = chan->tech_pvt; 20122 20123 /* If there is no private structure, this channel is no longer alive */ 20124 if (!p) { 20125 ast_channel_unlock(chan); 20126 return -1; 20127 } 20128 20129 for (i = 0; i < number; i++) 20130 content = __get_header(&p->initreq, args.header, &start); 20131 20132 if (ast_strlen_zero(content)) { 20133 ast_channel_unlock(chan); 20134 return -1; 20135 } 20136 20137 ast_copy_string(buf, content, len); 20138 ast_channel_unlock(chan); 20139 20140 return 0; 20141 }
| static int function_sipchaninfo_read | ( | struct ast_channel * | chan, | |
| const char * | cmd, | |||
| char * | data, | |||
| char * | buf, | |||
| size_t | len | |||
| ) | [static] |
${SIPCHANINFO()} Dialplan function - reads sip channel data
Definition at line 20267 of file chan_sip.c.
References ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_log(), ast_sockaddr_stringify_addr(), LOG_WARNING, ast_channel::tech, and ast_channel::tech_pvt.
20268 { 20269 struct sip_pvt *p; 20270 static int deprecated = 0; 20271 20272 *buf = 0; 20273 20274 if (!data) { 20275 ast_log(LOG_WARNING, "This function requires a parameter name.\n"); 20276 return -1; 20277 } 20278 20279 ast_channel_lock(chan); 20280 if (!IS_SIP_TECH(chan->tech)) { 20281 ast_log(LOG_WARNING, "This function can only be used on SIP channels.\n"); 20282 ast_channel_unlock(chan); 20283 return -1; 20284 } 20285 20286 if (deprecated++ % 20 == 0) { 20287 /* Deprecated in 1.6.1 */ 20288 ast_log(LOG_WARNING, "SIPCHANINFO() is deprecated. Please transition to using CHANNEL().\n"); 20289 } 20290 20291 p = chan->tech_pvt; 20292 20293 /* If there is no private structure, this channel is no longer alive */ 20294 if (!p) { 20295 ast_channel_unlock(chan); 20296 return -1; 20297 } 20298 20299 if (!strcasecmp(data, "peerip")) { 20300 ast_copy_string(buf, ast_sockaddr_stringify_addr(&p->sa), len); 20301 } else if (!strcasecmp(data, "recvip")) { 20302 ast_copy_string(buf, ast_sockaddr_stringify_addr(&p->recv), len); 20303 } else if (!strcasecmp(data, "from")) { 20304 ast_copy_string(buf, p->from, len); 20305 } else if (!strcasecmp(data, "uri")) { 20306 ast_copy_string(buf, p->uri, len); 20307 } else if (!strcasecmp(data, "useragent")) { 20308 ast_copy_string(buf, p->useragent, len); 20309 } else if (!strcasecmp(data, "peername")) { 20310 ast_copy_string(buf, p->peername, len); 20311 } else if (!strcasecmp(data, "t38passthrough")) { 20312 if ((p->t38.state == T38_DISABLED) || (p->t38.state == T38_REJECTED)) { 20313 ast_copy_string(buf, "0", len); 20314 } else { /* T38 is offered or enabled in this call */ 20315 ast_copy_string(buf, "1", len); 20316 } 20317 } else { 20318 ast_channel_unlock(chan); 20319 return -1; 20320 } 20321 ast_channel_unlock(chan); 20322 20323 return 0; 20324 }
| static int function_sippeer | ( | struct ast_channel * | chan, | |
| const char * | cmd, | |||
| char * | data, | |||
| char * | buf, | |||
| size_t | len | |||
| ) | [static] |
${SIPPEER()} Dialplan function - reads peer data
Definition at line 20168 of file chan_sip.c.
References ast_codec_pref_index(), ast_copy_string(), ast_getformatname(), ast_getformatname_multiple(), ast_log(), ast_print_group(), ast_sockaddr_port, ast_sockaddr_stringify_addr(), ast_str_alloca, ast_test_flag, chanvar, FALSE, LOG_WARNING, ast_variable::name, ast_variable::next, peer_mailboxes_to_str(), peer_status(), sip_find_peer(), sip_unref_peer(), strsep(), TRUE, and ast_variable::value.
20169 { 20170 struct sip_peer *peer; 20171 char *colname; 20172 20173 if ((colname = strchr(data, ':'))) { /*! \todo Will be deprecated after 1.4 */ 20174 static int deprecation_warning = 0; 20175 *colname++ = '\0'; 20176 if (deprecation_warning++ % 10 == 0) 20177 ast_log(LOG_WARNING, "SIPPEER(): usage of ':' to separate arguments is deprecated. Please use ',' instead.\n"); 20178 } else if ((colname = strchr(data, ','))) 20179 *colname++ = '\0'; 20180 else 20181 colname = "ip"; 20182 20183 if (!(peer = sip_find_peer(data, NULL, TRUE, FINDPEERS, FALSE, 0))) 20184 return -1; 20185 20186 if (!strcasecmp(colname, "ip")) { 20187 ast_copy_string(buf, ast_sockaddr_stringify_addr(&peer->addr), len); 20188 } else if (!strcasecmp(colname, "port")) { 20189 snprintf(buf, len, "%d", ast_sockaddr_port(&peer->addr)); 20190 } else if (!strcasecmp(colname, "status")) { 20191 peer_status(peer, buf, len); 20192 } else if (!strcasecmp(colname, "language")) { 20193 ast_copy_string(buf, peer->language, len); 20194 } else if (!strcasecmp(colname, "regexten")) { 20195 ast_copy_string(buf, peer->regexten, len); 20196 } else if (!strcasecmp(colname, "limit")) { 20197 snprintf(buf, len, "%d", peer->call_limit); 20198 } else if (!strcasecmp(colname, "busylevel")) { 20199 snprintf(buf, len, "%d", peer->busy_level); 20200 } else if (!strcasecmp(colname, "curcalls")) { 20201 snprintf(buf, len, "%d", peer->inUse); 20202 } else if (!strcasecmp(colname, "maxforwards")) { 20203 snprintf(buf, len, "%d", peer->maxforwards); 20204 } else if (!strcasecmp(colname, "accountcode")) { 20205 ast_copy_string(buf, peer->accountcode, len); 20206 } else if (!strcasecmp(colname, "callgroup")) { 20207 ast_print_group(buf, len, peer->callgroup); 20208 } else if (!strcasecmp(colname, "pickupgroup")) { 20209 ast_print_group(buf, len, peer->pickupgroup); 20210 } else if (!strcasecmp(colname, "useragent")) { 20211 ast_copy_string(buf, peer->useragent, len); 20212 } else if (!strcasecmp(colname, "mailbox")) { 20213 struct ast_str *mailbox_str = ast_str_alloca(512); 20214 peer_mailboxes_to_str(&mailbox_str, peer); 20215 ast_copy_string(buf, mailbox_str->str, len); 20216 } else if (!strcasecmp(colname, "context")) { 20217 ast_copy_string(buf, peer->context, len); 20218 } else if (!strcasecmp(colname, "expire")) { 20219 snprintf(buf, len, "%d", peer->expire); 20220 } else if (!strcasecmp(colname, "dynamic")) { 20221 ast_copy_string(buf, peer->host_dynamic ? "yes" : "no", len); 20222 } else if (!strcasecmp(colname, "callerid_name")) { 20223 ast_copy_string(buf, peer->cid_name, len); 20224 } else if (!strcasecmp(colname, "callerid_num")) { 20225 ast_copy_string(buf, peer->cid_num, len); 20226 } else if (!strcasecmp(colname, "codecs")) { 20227 ast_getformatname_multiple(buf, len -1, peer->caps); 20228 } else if (!strcasecmp(colname, "encryption")) { 20229 snprintf(buf, len, "%d", ast_test_flag(&peer->flags[1], SIP_PAGE2_USE_SRTP)); 20230 } else if (!strncasecmp(colname, "chanvar[", 8)) { 20231 char *chanvar=colname + 8; 20232 struct ast_variable *v; 20233 20234 chanvar = strsep(&chanvar, "]"); 20235 for (v = peer->chanvars ; v ; v = v->next) { 20236 if (!strcasecmp(v->name, chanvar)) { 20237 ast_copy_string(buf, v->value, len); 20238 } 20239 } 20240 } else if (!strncasecmp(colname, "codec[", 6)) { 20241 char *codecnum; 20242 struct ast_format codec; 20243 20244 codecnum = colname + 6; /* move past the '[' */ 20245 codecnum = strsep(&codecnum, "]"); /* trim trailing ']' if any */ 20246 if((ast_codec_pref_index(&peer->prefs, atoi(codecnum), &codec))) { 20247 ast_copy_string(buf, ast_getformatname(&codec), len); 20248 } else { 20249 buf[0] = '\0'; 20250 } 20251 } else { 20252 buf[0] = '\0'; 20253 } 20254 20255 sip_unref_peer(peer, "sip_unref_peer from function_sippeer, just before return"); 20256 20257 return 0; 20258 }
| static char * generate_random_string | ( | char * | buf, | |
| size_t | size | |||
| ) | [static] |
Generate 32 byte random string for callid's etc.
Definition at line 7658 of file chan_sip.c.
References ast_random().
Referenced by build_callid_pvt(), build_callid_registry(), calendar_query_exec(), construct_pidf_body(), do_notify(), and generate_uri().
07659 { 07660 long val[4]; 07661 int x; 07662 07663 for (x=0; x<4; x++) 07664 val[x] = ast_random(); 07665 snprintf(buf, size, "%08lx%08lx%08lx%08lx", val[0], val[1], val[2], val[3]); 07666 07667 return buf; 07668 }
| static char* generate_uri | ( | struct sip_pvt * | pvt, | |
| char * | buf, | |||
| size_t | size | |||
| ) | [static] |
Definition at line 7670 of file chan_sip.c.
References ast_copy_string(), ast_sockaddr_stringify_remote(), ast_str_alloca, ast_str_append(), ast_str_buffer(), ast_str_set(), and generate_random_string().
Referenced by add_cc_call_info_to_response(), and transmit_cc_notify().
07671 { 07672 struct ast_str *uri = ast_str_alloca(size); 07673 ast_str_set(&uri, 0, "%s", pvt->socket.type == SIP_TRANSPORT_TLS ? "sips:" : "sip:"); 07674 /* Here would be a great place to generate a UUID, but for now we'll 07675 * use the handy random string generation function we already have 07676 */ 07677 ast_str_append(&uri, 0, "%s", generate_random_string(buf, size)); 07678 ast_str_append(&uri, 0, "@%s", ast_sockaddr_stringify_remote(&pvt->ourip)); 07679 ast_copy_string(buf, ast_str_buffer(uri), size); 07680 return buf; 07681 }
| int get_address_family_filter | ( | const struct ast_sockaddr * | addr | ) | [static] |
Helper for dns resolution to filter by address family.
Definition at line 26441 of file chan_sip.c.
References ast_sockaddr_is_any(), ast_sockaddr_is_ipv6(), and ast_sockaddr::ss.
Referenced by __sip_subscribe_mwi_do(), ast_sockaddr_resolve_first(), build_peer(), proxy_update(), realtime_peer_by_name(), and transmit_register().
26442 { 26443 if (ast_sockaddr_is_ipv6(addr) && ast_sockaddr_is_any(addr)) { 26444 return 0; 26445 } 26446 26447 return addr->ss.ss_family; 26448 }
| static int get_also_info | ( | struct sip_pvt * | p, | |
| struct sip_request * | oreq | |||
| ) | [static] |
Call transfer support (old way, deprecated by the IETF).
Definition at line 16224 of file chan_sip.c.
References ast_canmatch_extension(), ast_copy_string(), ast_debug, ast_exists_extension(), ast_log(), ast_string_field_set, ast_strlen_zero(), ast_verbose, context, get_in_brackets(), LOG_WARNING, parse_uri_legacy_check(), pbx_builtin_getvar_helper(), S_OR, sip_cfg, sip_debug_test_pvt(), sip_get_header(), SIP_PEDANTIC_DECODE, and sip_refer_allocate().
Referenced by handle_request_bye().
16225 { 16226 char tmp[256] = "", *c, *a; 16227 struct sip_request *req = oreq ? oreq : &p->initreq; 16228 struct sip_refer *referdata = NULL; 16229 const char *transfer_context = NULL; 16230 16231 if (!p->refer && !sip_refer_allocate(p)) 16232 return -1; 16233 16234 referdata = p->refer; 16235 16236 ast_copy_string(tmp, sip_get_header(req, "Also"), sizeof(tmp)); 16237 c = get_in_brackets(tmp); 16238 16239 if (parse_uri_legacy_check(c, "sip:,sips:", &c, NULL, &a, NULL)) { 16240 ast_log(LOG_WARNING, "Huh? Not a SIP header in Also: transfer (%s)?\n", c); 16241 return -1; 16242 } 16243 16244 SIP_PEDANTIC_DECODE(c); 16245 SIP_PEDANTIC_DECODE(a); 16246 16247 if (!ast_strlen_zero(a)) { 16248 ast_copy_string(referdata->refer_to_domain, a, sizeof(referdata->refer_to_domain)); 16249 } 16250 16251 if (sip_debug_test_pvt(p)) 16252 ast_verbose("Looking for %s in %s\n", c, p->context); 16253 16254 if (p->owner) /* Mimic behaviour in res_features.c */ 16255 transfer_context = pbx_builtin_getvar_helper(p->owner, "TRANSFER_CONTEXT"); 16256 16257 /* By default, use the context in the channel sending the REFER */ 16258 if (ast_strlen_zero(transfer_context)) { 16259 transfer_context = S_OR(p->owner->macrocontext, 16260 S_OR(p->context, sip_cfg.default_context)); 16261 } 16262 if (ast_exists_extension(NULL, transfer_context, c, 1, NULL)) { 16263 /* This is a blind transfer */ 16264 ast_debug(1, "SIP Bye-also transfer to Extension %s@%s \n", c, transfer_context); 16265 ast_copy_string(referdata->refer_to, c, sizeof(referdata->refer_to)); 16266 ast_copy_string(referdata->referred_by, "", sizeof(referdata->referred_by)); 16267 ast_copy_string(referdata->refer_contact, "", sizeof(referdata->refer_contact)); 16268 referdata->refer_call = dialog_unref(referdata->refer_call, "unreffing referdata->refer_call"); 16269 /* Set new context */ 16270 ast_string_field_set(p, context, transfer_context); 16271 return 0; 16272 } else if (ast_canmatch_extension(NULL, p->context, c, 1, NULL)) { 16273 return 1; 16274 } 16275 16276 return -1; 16277 }
| static char* get_body | ( | struct sip_request * | req, | |
| char * | name, | |||
| char | delimiter | |||
| ) | [static] |
Get a specific line from the message body.
Definition at line 7387 of file chan_sip.c.
References get_body_by_line(), and len().
Referenced by handle_cc_notify(), handle_request_info(), and handle_request_notify().
07388 { 07389 int x; 07390 int len = strlen(name); 07391 char *r; 07392 07393 for (x = 0; x < req->lines; x++) { 07394 r = get_body_by_line(REQ_OFFSET_TO_STR(req, line[x]), name, len, delimiter); 07395 if (r[0] != '\0') { 07396 return r; 07397 } 07398 } 07399 07400 return ""; 07401 }
| static char* get_body_by_line | ( | const char * | line, | |
| const char * | name, | |||
| int | nameLen, | |||
| char | delimiter | |||
| ) | [static] |
Reads one line of SIP message body.
Definition at line 7331 of file chan_sip.c.
References ast_skip_blanks().
Referenced by get_body(), and get_sdp_iterate().
07332 { 07333 if (!strncasecmp(line, name, nameLen) && line[nameLen] == delimiter) { 07334 return ast_skip_blanks(line + nameLen + 1); 07335 } 07336 07337 return ""; 07338 }
| static int get_cached_mwi | ( | struct sip_peer * | peer, | |
| int * | new, | |||
| int * | old | |||
| ) | [static] |
Get cached MWI info.
Definition at line 26583 of file chan_sip.c.
References ast_event_destroy(), ast_event_get_cached(), ast_event_get_ie_uint(), AST_EVENT_IE_CONTEXT, AST_EVENT_IE_END, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_MWI, AST_LIST_TRAVERSE, mailbox, and S_OR.
Referenced by sip_send_mwi_to_peer().
26584 { 26585 struct sip_mailbox *mailbox; 26586 int in_cache; 26587 26588 in_cache = 0; 26589 AST_LIST_TRAVERSE(&peer->mailboxes, mailbox, entry) { 26590 struct ast_event *event; 26591 event = ast_event_get_cached(AST_EVENT_MWI, 26592 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox->mailbox, 26593 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, S_OR(mailbox->context, "default"), 26594 AST_EVENT_IE_END); 26595 if (!event) 26596 continue; 26597 *new += ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS); 26598 *old += ast_event_get_ie_uint(event, AST_EVENT_IE_OLDMSGS); 26599 ast_event_destroy(event); 26600 in_cache = 1; 26601 } 26602 26603 return in_cache; 26604 }
| static void get_crypto_attrib | ( | struct sip_pvt * | p, | |
| struct sip_srtp * | srtp, | |||
| const char ** | a_crypto | |||
| ) | [static] |
Definition at line 11586 of file chan_sip.c.
References ast_log(), ast_test_flag, LOG_WARNING, sdp_crypto_attrib(), sdp_crypto_offer(), and sdp_crypto_setup().
Referenced by add_sdp().
11587 { 11588 int taglen = 80; 11589 11590 /* Set encryption properties */ 11591 if (srtp) { 11592 if (!srtp->crypto) { 11593 srtp->crypto = sdp_crypto_setup(); 11594 } 11595 11596 /* set the key length based on INVITE or settings */ 11597 if (ast_test_flag(srtp, SRTP_CRYPTO_TAG_80)) { 11598 taglen = 80; 11599 } else if (ast_test_flag(&p->flags[2], SIP_PAGE3_SRTP_TAG_32) || 11600 ast_test_flag(srtp, SRTP_CRYPTO_TAG_32)) { 11601 taglen = 32; 11602 } 11603 11604 if (srtp->crypto && (sdp_crypto_offer(srtp->crypto, taglen) >= 0)) { 11605 *a_crypto = sdp_crypto_attrib(srtp->crypto); 11606 } 11607 11608 if (!*a_crypto) { 11609 ast_log(LOG_WARNING, "No SRTP key management enabled\n"); 11610 } 11611 } 11612 }
| static enum sip_get_dest_result get_destination | ( | struct sip_pvt * | p, | |
| struct sip_request * | oreq, | |||
| int * | cc_recall_core_id | |||
| ) | [static] |
Find out who the call is for.
We use the request uri as a destination. This code assumes authentication has been done, so that the device (peer/user) context is already set.
Definition at line 15774 of file chan_sip.c.
References ao2_ref, ast_canmatch_extension(), ast_cc_agent_recalling(), ast_copy_string(), ast_debug, ast_exists_extension(), ast_get_hint(), AST_LIST_EMPTY, ast_log(), AST_MAX_EXTENSION, ast_pickup_ext(), ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_uri_decode(), ast_uri_sip_user, ast_verbose, check_sip_domain(), context, ast_cc_agent::core_id, ast_cc_agent::device_name, exten, extract_host_from_hostport(), find_sip_cc_agent_by_notify_uri(), get_in_brackets(), LOG_WARNING, parse_uri_legacy_check(), ast_cc_agent::private_data, S_OR, sip_cfg, sip_debug_test_pvt(), sip_get_header(), sip_methods, SIP_PEDANTIC_DECODE, and cfsip_methods::text.
Referenced by handle_request_invite(), handle_request_options(), handle_request_subscribe(), and receive_message().
15775 { 15776 char tmp[256] = "", *uri, *unused_password, *domain; 15777 char tmpf[256] = "", *from = NULL; 15778 struct sip_request *req; 15779 char *decoded_uri; 15780 15781 req = oreq; 15782 if (!req) { 15783 req = &p->initreq; 15784 } 15785 15786 /* Find the request URI */ 15787 if (req->rlPart2) 15788 ast_copy_string(tmp, REQ_OFFSET_TO_STR(req, rlPart2), sizeof(tmp)); 15789 15790 uri = ast_strdupa(get_in_brackets(tmp)); 15791 15792 if (parse_uri_legacy_check(uri, "sip:,sips:", &uri, &unused_password, &domain, NULL)) { 15793 ast_log(LOG_WARNING, "Not a SIP header (%s)?\n", uri); 15794 return SIP_GET_DEST_INVALID_URI; 15795 } 15796 15797 SIP_PEDANTIC_DECODE(domain); 15798 SIP_PEDANTIC_DECODE(uri); 15799 15800 extract_host_from_hostport(&domain); 15801 15802 if (ast_strlen_zero(uri)) { 15803 /* 15804 * Either there really was no extension found or the request 15805 * URI had encoded nulls that made the string "empty". Use "s" 15806 * as the extension. 15807 */ 15808 uri = "s"; 15809 } 15810 15811 ast_string_field_set(p, domain, domain); 15812 15813 /* Now find the From: caller ID and name */ 15814 /* XXX Why is this done in get_destination? Isn't it already done? 15815 Needs to be checked 15816 */ 15817 ast_copy_string(tmpf, sip_get_header(req, "From"), sizeof(tmpf)); 15818 if (!ast_strlen_zero(tmpf)) { 15819 from = get_in_brackets(tmpf); 15820 if (parse_uri_legacy_check(from, "sip:,sips:", &from, NULL, &domain, NULL)) { 15821 ast_log(LOG_WARNING, "Not a SIP header (%s)?\n", from); 15822 return SIP_GET_DEST_INVALID_URI; 15823 } 15824 15825 SIP_PEDANTIC_DECODE(from); 15826 SIP_PEDANTIC_DECODE(domain); 15827 15828 extract_host_from_hostport(&domain); 15829 15830 ast_string_field_set(p, fromdomain, domain); 15831 } 15832 15833 if (!AST_LIST_EMPTY(&domain_list)) { 15834 char domain_context[AST_MAX_EXTENSION]; 15835 15836 domain_context[0] = '\0'; 15837 if (!check_sip_domain(p->domain, domain_context, sizeof(domain_context))) { 15838 if (!sip_cfg.allow_external_domains && (req->method == SIP_INVITE || req->method == SIP_REFER)) { 15839 ast_debug(1, "Got SIP %s to non-local domain '%s'; refusing request.\n", sip_methods[req->method].text, p->domain); 15840 return SIP_GET_DEST_REFUSED; 15841 } 15842 } 15843 /* If we don't have a peer (i.e. we're a guest call), 15844 * overwrite the original context */ 15845 if (!ast_test_flag(&p->flags[1], SIP_PAGE2_HAVEPEERCONTEXT) && !ast_strlen_zero(domain_context)) { 15846 ast_string_field_set(p, context, domain_context); 15847 } 15848 } 15849 15850 /* If the request coming in is a subscription and subscribecontext has been specified use it */ 15851 if (req->method == SIP_SUBSCRIBE && !ast_strlen_zero(p->subscribecontext)) { 15852 ast_string_field_set(p, context, p->subscribecontext); 15853 } 15854 15855 if (sip_debug_test_pvt(p)) { 15856 ast_verbose("Looking for %s in %s (domain %s)\n", uri, p->context, p->domain); 15857 } 15858 15859 /* Since extensions.conf can have unescaped characters, try matching a 15860 * decoded uri in addition to the non-decoded uri. */ 15861 decoded_uri = ast_strdupa(uri); 15862 ast_uri_decode(decoded_uri, ast_uri_sip_user); 15863 15864 /* If this is a subscription we actually just need to see if a hint exists for the extension */ 15865 if (req->method == SIP_SUBSCRIBE) { 15866 char hint[AST_MAX_EXTENSION]; 15867 int which = 0; 15868 if (ast_get_hint(hint, sizeof(hint), NULL, 0, NULL, p->context, uri) || 15869 (ast_get_hint(hint, sizeof(hint), NULL, 0, NULL, p->context, decoded_uri) && (which = 1))) { 15870 if (!oreq) { 15871 ast_string_field_set(p, exten, which ? decoded_uri : uri); 15872 } 15873 return SIP_GET_DEST_EXTEN_FOUND; 15874 } else { 15875 return SIP_GET_DEST_EXTEN_NOT_FOUND; 15876 } 15877 } else { 15878 struct ast_cc_agent *agent; 15879 /* Check the dialplan for the username part of the request URI, 15880 the domain will be stored in the SIPDOMAIN variable 15881 Return 0 if we have a matching extension */ 15882 if (ast_exists_extension(NULL, p->context, uri, 1, S_OR(p->cid_num, from))) { 15883 if (!oreq) { 15884 ast_string_field_set(p, exten, uri); 15885 } 15886 return SIP_GET_DEST_EXTEN_FOUND; 15887 } 15888 if (ast_exists_extension(NULL, p->context, decoded_uri, 1, S_OR(p->cid_num, from)) 15889 || !strcmp(decoded_uri, ast_pickup_ext())) { 15890 if (!oreq) { 15891 ast_string_field_set(p, exten, decoded_uri); 15892 } 15893 return SIP_GET_DEST_EXTEN_FOUND; 15894 } 15895 if ((agent = find_sip_cc_agent_by_notify_uri(tmp))) { 15896 struct sip_cc_agent_pvt *agent_pvt = agent->private_data; 15897 /* This is a CC recall. We can set p's extension to the exten from 15898 * the original INVITE 15899 */ 15900 ast_string_field_set(p, exten, agent_pvt->original_exten); 15901 /* And we need to let the CC core know that the caller is attempting 15902 * his recall 15903 */ 15904 ast_cc_agent_recalling(agent->core_id, "SIP caller %s is attempting recall", 15905 agent->device_name); 15906 if (cc_recall_core_id) { 15907 *cc_recall_core_id = agent->core_id; 15908 } 15909 ao2_ref(agent, -1); 15910 return SIP_GET_DEST_EXTEN_FOUND; 15911 } 15912 } 15913 15914 if (ast_test_flag(&global_flags[1], SIP_PAGE2_ALLOWOVERLAP) 15915 && (ast_canmatch_extension(NULL, p->context, uri, 1, S_OR(p->cid_num, from)) 15916 || ast_canmatch_extension(NULL, p->context, decoded_uri, 1, S_OR(p->cid_num, from)) 15917 || !strncmp(decoded_uri, ast_pickup_ext(), strlen(decoded_uri)))) { 15918 /* Overlap dialing is enabled and we need more digits to match an extension. */ 15919 return SIP_GET_DEST_EXTEN_MATCHMORE; 15920 } 15921 15922 return SIP_GET_DEST_EXTEN_NOT_FOUND; 15923 }
| static int get_domain | ( | const char * | str, | |
| char * | domain, | |||
| int | len | |||
| ) | [static] |
Extract domain from SIP To/From header.
Definition at line 10993 of file chan_sip.c.
References ast_copy_string(), ast_log(), ast_strlen_zero(), get_in_brackets(), and LOG_WARNING.
Referenced by get_realm().
10994 { 10995 char tmpf[256]; 10996 char *a, *from; 10997 10998 *domain = '\0'; 10999 ast_copy_string(tmpf, str, sizeof(tmpf)); 11000 from = get_in_brackets(tmpf); 11001 if (!ast_strlen_zero(from)) { 11002 if (strncasecmp(from, "sip:", 4)) { 11003 ast_log(LOG_WARNING, "Huh? Not a SIP header (%s)?\n", from); 11004 return -1; 11005 } 11006 from += 4; 11007 } else 11008 from = NULL; 11009 11010 if (from) { 11011 int bracket = 0; 11012 11013 /* Strip any params or options from user */ 11014 if ((a = strchr(from, ';'))) 11015 *a = '\0'; 11016 /* Strip port from domain if present */ 11017 for (a = from; *a != '\0'; ++a) { 11018 if (*a == ':' && bracket == 0) { 11019 *a = '\0'; 11020 break; 11021 } else if (*a == '[') { 11022 ++bracket; 11023 } else if (*a == ']') { 11024 --bracket; 11025 } 11026 } 11027 if ((a = strchr(from, '@'))) { 11028 *a = '\0'; 11029 ast_copy_string(domain, a + 1, len); 11030 } else 11031 ast_copy_string(domain, from, len); 11032 } 11033 11034 return ast_strlen_zero(domain); 11035 }
| static struct event_state_compositor* get_esc | ( | const char *const | event_package | ) | [static, read] |
Definition at line 1004 of file chan_sip.c.
References ARRAY_LEN, event_state_compositors, and name.
Referenced by create_new_sip_etag(), handle_request_publish(), and publish_expire().
01004 { 01005 int i; 01006 for (i = 0; i < ARRAY_LEN(event_state_compositors); i++) { 01007 if (!strcasecmp(event_package, event_state_compositors[i].name)) { 01008 return &event_state_compositors[i]; 01009 } 01010 } 01011 return NULL; 01012 }
| static struct sip_esc_entry* get_esc_entry | ( | const char * | entity_tag, | |
| struct event_state_compositor * | esc | |||
| ) | [static, read] |
Definition at line 1014 of file chan_sip.c.
References ao2_find, ast_copy_string(), event_state_compositor::compositor, and OBJ_POINTER.
Referenced by handle_sip_publish_modify(), handle_sip_publish_refresh(), and handle_sip_publish_remove().
01014 { 01015 struct sip_esc_entry *entry; 01016 struct sip_esc_entry finder; 01017 01018 ast_copy_string(finder.entity_tag, entity_tag, sizeof(finder.entity_tag)); 01019 01020 entry = ao2_find(esc->compositor, &finder, OBJ_POINTER); 01021 01022 return entry; 01023 }
| static struct ast_variable * get_insecure_variable_from_config | ( | struct ast_config * | config | ) | [static, read] |
Definition at line 4712 of file chan_sip.c.
References ast_category_browse(), ast_category_root(), ast_test_flag, ast_variable_retrieve(), set_insecure_flags(), and var.
Referenced by get_insecure_variable_from_sippeers().
04713 { 04714 struct ast_variable *var = NULL; 04715 struct ast_flags flags = {0}; 04716 char *cat = NULL; 04717 const char *insecure; 04718 while ((cat = ast_category_browse(cfg, cat))) { 04719 insecure = ast_variable_retrieve(cfg, cat, "insecure"); 04720 set_insecure_flags(&flags, insecure, -1); 04721 if (ast_test_flag(&flags, SIP_INSECURE_PORT)) { 04722 var = ast_category_root(cfg, cat); 04723 break; 04724 } 04725 } 04726 return var; 04727 }
| static struct ast_variable* get_insecure_variable_from_sippeers | ( | const char * | column, | |
| const char * | value | |||
| ) | [static, read] |
Definition at line 4729 of file chan_sip.c.
References ast_config_destroy(), ast_load_realtime_multientry(), ast_variables_dup(), get_insecure_variable_from_config(), SENTINEL, and var.
Referenced by realtime_peer_by_addr().
04730 { 04731 struct ast_config *peerlist; 04732 struct ast_variable *var = NULL; 04733 if ((peerlist = ast_load_realtime_multientry("sippeers", column, value, "insecure LIKE", "%port%", SENTINEL))) { 04734 if ((var = get_insecure_variable_from_config(peerlist))) { 04735 /* Must clone, because var will get freed along with 04736 * peerlist. */ 04737 var = ast_variables_dup(var); 04738 } 04739 ast_config_destroy(peerlist); 04740 } 04741 return var; 04742 }
| static struct ast_variable* get_insecure_variable_from_sipregs | ( | const char * | column, | |
| const char * | value, | |||
| struct ast_variable ** | var | |||
| ) | [static, read] |
Definition at line 4749 of file chan_sip.c.
References ast_category_browse(), ast_category_root(), ast_config_destroy(), ast_load_realtime_multientry(), ast_test_flag, ast_variable_retrieve(), ast_variables_destroy(), ast_variables_dup(), SENTINEL, and set_insecure_flags().
Referenced by realtime_peer_by_addr().
04750 { 04751 struct ast_variable *varregs = NULL; 04752 struct ast_config *regs, *peers; 04753 char *regscat; 04754 const char *regname; 04755 04756 if (!(regs = ast_load_realtime_multientry("sipregs", column, value, SENTINEL))) { 04757 return NULL; 04758 } 04759 04760 /* Load *all* peers that are probably insecure=port */ 04761 if (!(peers = ast_load_realtime_multientry("sippeers", "insecure LIKE", "%port%", SENTINEL))) { 04762 ast_config_destroy(regs); 04763 return NULL; 04764 } 04765 04766 /* Loop over the sipregs that match IP address and attempt to find an 04767 * insecure=port match to it in sippeers. */ 04768 regscat = NULL; 04769 while ((regscat = ast_category_browse(regs, regscat)) && (regname = ast_variable_retrieve(regs, regscat, "name"))) { 04770 char *peerscat; 04771 const char *peername; 04772 04773 peerscat = NULL; 04774 while ((peerscat = ast_category_browse(peers, peerscat)) && (peername = ast_variable_retrieve(peers, peerscat, "name"))) { 04775 if (!strcasecmp(regname, peername)) { 04776 /* Ensure that it really is insecure=port and 04777 * not something else. */ 04778 const char *insecure = ast_variable_retrieve(peers, peerscat, "insecure"); 04779 struct ast_flags flags = {0}; 04780 set_insecure_flags(&flags, insecure, -1); 04781 if (ast_test_flag(&flags, SIP_INSECURE_PORT)) { 04782 /* ENOMEM checks till the bitter end. */ 04783 if ((varregs = ast_variables_dup(ast_category_root(regs, regscat)))) { 04784 if (!(*var = ast_variables_dup(ast_category_root(peers, peerscat)))) { 04785 ast_variables_destroy(varregs); 04786 varregs = NULL; 04787 } 04788 } 04789 goto done; 04790 } 04791 } 04792 } 04793 } 04794 04795 done: 04796 ast_config_destroy(regs); 04797 ast_config_destroy(peers); 04798 return varregs; 04799 }
| static int get_ip_and_port_from_sdp | ( | struct sip_request * | req, | |
| const enum media_type | media, | |||
| struct ast_sockaddr * | addr | |||
| ) | [static] |
Definition at line 8935 of file chan_sip.c.
References ast_log(), ast_sockaddr_resolve_first_af(), ast_strlen_zero(), get_sdp_iterate(), len(), and LOG_WARNING.
Referenced by handle_request_invite().
08936 { 08937 const char *m; 08938 const char *c; 08939 int miterator = req->sdp_start; 08940 int citerator = req->sdp_start; 08941 int x = 0; 08942 int numberofports; 08943 int len; 08944 int af; 08945 char proto[4], host[258] = ""; /*Initialize to empty so we will know if we have any input */ 08946 08947 c = get_sdp_iterate(&citerator, req, "c"); 08948 if (sscanf(c, "IN %3s %256s", proto, host) != 2) { 08949 ast_log(LOG_WARNING, "Invalid host in c= line, '%s'\n", c); 08950 /* Continue since there may be a valid host in a c= line specific to the audio stream */ 08951 } 08952 /* We only want the m and c lines for audio */ 08953 for (m = get_sdp_iterate(&miterator, req, "m"); !ast_strlen_zero(m); m = get_sdp_iterate(&miterator, req, "m")) { 08954 if ((media == SDP_AUDIO && ((sscanf(m, "audio %30u/%30u RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) || 08955 (sscanf(m, "audio %30u RTP/AVP %n", &x, &len) == 1 && len > 0))) || 08956 (media == SDP_VIDEO && ((sscanf(m, "video %30u/%30u RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) || 08957 (sscanf(m, "video %30u RTP/AVP %n", &x, &len) == 1 && len > 0)))) { 08958 /* See if there's a c= line for this media stream. 08959 * XXX There is no guarantee that we'll be grabbing the c= line for this 08960 * particular media stream here. However, this is the same logic used in process_sdp. 08961 */ 08962 c = get_sdp_iterate(&citerator, req, "c"); 08963 if (!ast_strlen_zero(c)) { 08964 sscanf(c, "IN %3s %256s", proto, host); 08965 } 08966 break; 08967 } 08968 } 08969 08970 if (!strcmp("IP4", proto)) { 08971 af = AF_INET; 08972 } else if (!strcmp("IP6", proto)) { 08973 af = AF_INET6; 08974 } else { 08975 ast_log(LOG_WARNING, "Unknown protocol '%s'.\n", proto); 08976 return -1; 08977 } 08978 08979 if (ast_strlen_zero(host) || x == 0) { 08980 ast_log(LOG_WARNING, "Failed to read an alternate host or port in SDP. Expect %s problems\n", media == SDP_AUDIO ? "audio" : "video"); 08981 return -1; 08982 } 08983 08984 if (ast_sockaddr_resolve_first_af(addr, host, 0, af)) { 08985 ast_log(LOG_WARNING, "Could not look up IP address of alternate hostname. Expect %s problems\n", media == SDP_AUDIO? "audio" : "video"); 08986 return -1; 08987 } 08988 08989 return 0; 08990 }
| static int get_msg_text | ( | char * | buf, | |
| int | len, | |||
| struct sip_request * | req | |||
| ) | [static] |
Get message body from a SIP request.
| buf | Destination buffer | |
| len | Destination buffer size | |
| req | The SIP request |
Definition at line 16753 of file chan_sip.c.
Referenced by handle_request_info(), and handle_request_notify().
16754 { 16755 int x; 16756 int linelen; 16757 16758 buf[0] = '\0'; 16759 --len; /* reserve strncat null */ 16760 for (x = 0; len && x < req->lines; ++x) { 16761 const char *line = REQ_OFFSET_TO_STR(req, line[x]); 16762 strncat(buf, line, len); /* safe */ 16763 linelen = strlen(buf); 16764 buf += linelen; 16765 len -= linelen; 16766 if (len) { 16767 strcat(buf, "\n"); /* safe */ 16768 ++buf; 16769 --len; 16770 } 16771 } 16772 return 0; 16773 }
| static int get_msg_text2 | ( | struct ast_str ** | buf, | |
| struct sip_request * | req | |||
| ) | [static] |
Definition at line 16775 of file chan_sip.c.
References ast_str_append(), and ast_str_reset().
Referenced by receive_message().
16776 { 16777 int i, res = 0; 16778 16779 ast_str_reset(*buf); 16780 16781 for (i = 0; res >= 0 && i < req->lines; i++) { 16782 const char *line = REQ_OFFSET_TO_STR(req, line[i]); 16783 16784 res = ast_str_append(buf, 0, "%s\n", line); 16785 } 16786 16787 return res < 0 ? -1 : 0; 16788 }
| static const char * get_name_from_variable | ( | const struct ast_variable * | var | ) | [static] |
Definition at line 4801 of file chan_sip.c.
References ast_strlen_zero(), ast_variable::name, ast_variable::next, and ast_variable::value.
Referenced by realtime_peer_by_addr(), and realtime_peer_get_sippeer_helper().
04802 { 04803 /* Don't expect this to return non-NULL. Both NULL and empty 04804 * values can cause the option to get removed from the variable 04805 * list. This is called on ast_variables gotten from both 04806 * ast_load_realtime and ast_load_realtime_multientry. 04807 * - ast_load_realtime removes options with empty values 04808 * - ast_load_realtime_multientry does not! 04809 * For consistent behaviour, we check for the empty name and 04810 * return NULL instead. */ 04811 const struct ast_variable *tmp; 04812 for (tmp = var; tmp; tmp = tmp->next) { 04813 if (!strcasecmp(tmp->name, "name")) { 04814 if (!ast_strlen_zero(tmp->value)) { 04815 return tmp->value; 04816 } 04817 break; 04818 } 04819 } 04820 return NULL; 04821 }
| static void get_our_media_address | ( | struct sip_pvt * | p, | |
| int | needvideo, | |||
| int | needtext, | |||
| struct ast_sockaddr * | addr, | |||
| struct ast_sockaddr * | vaddr, | |||
| struct ast_sockaddr * | taddr, | |||
| struct ast_sockaddr * | dest, | |||
| struct ast_sockaddr * | vdest, | |||
| struct ast_sockaddr * | tdest | |||
| ) | [static] |
Set all IP media addresses for this call.
Definition at line 11493 of file chan_sip.c.
References ast_rtp_instance_get_local_address(), ast_sockaddr_cmp_addr(), ast_sockaddr_copy(), ast_sockaddr_is_any(), ast_sockaddr_isnull(), ast_sockaddr_port, ast_sockaddr_set_port, and media_address.
Referenced by add_sdp().
11497 { 11498 int use_externip = 0; 11499 11500 /* First, get our address */ 11501 ast_rtp_instance_get_local_address(p->rtp, addr); 11502 if (p->vrtp) { 11503 ast_rtp_instance_get_local_address(p->vrtp, vaddr); 11504 } 11505 if (p->trtp) { 11506 ast_rtp_instance_get_local_address(p->trtp, taddr); 11507 } 11508 11509 /* If our real IP differs from the local address returned by the RTP engine, use it. */ 11510 /* The premise is that if we are already using that IP to communicate with the client, */ 11511 /* we should be using it for RTP too. */ 11512 use_externip = ast_sockaddr_cmp_addr(&p->ourip, addr); 11513 11514 /* Now, try to figure out where we want them to send data */ 11515 /* Is this a re-invite to move the media out, then use the original offer from caller */ 11516 if (!ast_sockaddr_isnull(&p->redirip)) { /* If we have a redirection IP, use it */ 11517 ast_sockaddr_copy(dest, &p->redirip); 11518 } else { 11519 /* 11520 * Audio Destination IP: 11521 * 11522 * 1. Specifically configured media address. 11523 * 2. Local address as specified by the RTP engine. 11524 * 3. The local IP as defined by chan_sip. 11525 * 11526 * Audio Destination Port: 11527 * 11528 * 1. Provided by the RTP engine. 11529 */ 11530 ast_sockaddr_copy(dest, 11531 !ast_sockaddr_isnull(&media_address) ? &media_address : 11532 !ast_sockaddr_is_any(addr) && !use_externip ? addr : 11533 &p->ourip); 11534 ast_sockaddr_set_port(dest, ast_sockaddr_port(addr)); 11535 } 11536 11537 if (needvideo) { 11538 /* Determine video destination */ 11539 if (!ast_sockaddr_isnull(&p->vredirip)) { 11540 ast_sockaddr_copy(vdest, &p->vredirip); 11541 } else { 11542 /* 11543 * Video Destination IP: 11544 * 11545 * 1. Specifically configured media address. 11546 * 2. Local address as specified by the RTP engine. 11547 * 3. The local IP as defined by chan_sip. 11548 * 11549 * Video Destination Port: 11550 * 11551 * 1. Provided by the RTP engine. 11552 */ 11553 ast_sockaddr_copy(vdest, 11554 !ast_sockaddr_isnull(&media_address) ? &media_address : 11555 !ast_sockaddr_is_any(vaddr) && !use_externip ? vaddr : 11556 &p->ourip); 11557 ast_sockaddr_set_port(vdest, ast_sockaddr_port(vaddr)); 11558 } 11559 } 11560 11561 if (needtext) { 11562 /* Determine text destination */ 11563 if (!ast_sockaddr_isnull(&p->tredirip)) { 11564 ast_sockaddr_copy(tdest, &p->tredirip); 11565 } else { 11566 /* 11567 * Text Destination IP: 11568 * 11569 * 1. Specifically configured media address. 11570 * 2. Local address as specified by the RTP engine. 11571 * 3. The local IP as defined by chan_sip. 11572 * 11573 * Text Destination Port: 11574 * 11575 * 1. Provided by the RTP engine. 11576 */ 11577 ast_sockaddr_copy(tdest, 11578 !ast_sockaddr_isnull(&media_address) ? &media_address : 11579 !ast_sockaddr_is_any(taddr) && !use_externip ? taddr : 11580 &p->ourip); 11581 ast_sockaddr_set_port(tdest, ast_sockaddr_port(taddr)); 11582 } 11583 } 11584 }
| static int get_pai | ( | struct sip_pvt * | p, | |
| struct sip_request * | req | |||
| ) | [static] |
Parse the parts of the P-Asserted-Identity header on an incoming packet. Returns 1 if a valid header is found and it is different from the current caller id.
Definition at line 15503 of file chan_sip.c.
References ast_copy_string(), ast_free, ast_is_shrinkable_phonenumber(), AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED, AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED, ast_set_callerid(), ast_shrink_phone_number(), ast_string_field_set, ast_strlen_zero(), cid_name, cid_num, get_in_brackets(), get_name_and_number(), and sip_get_header().
Referenced by get_rpid().
15504 { 15505 char pai[256]; 15506 char privacy[64]; 15507 char *cid_num = NULL; 15508 char *cid_name = NULL; 15509 char emptyname[1] = ""; 15510 int callingpres = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED; 15511 char *uri = NULL; 15512 int is_anonymous = 0, do_update = 1, no_name = 0; 15513 15514 ast_copy_string(pai, sip_get_header(req, "P-Asserted-Identity"), sizeof(pai)); 15515 15516 if (ast_strlen_zero(pai)) { 15517 return 0; 15518 } 15519 15520 /* use the reqresp_parser function get_name_and_number*/ 15521 if (get_name_and_number(pai, &cid_name, &cid_num)) { 15522 return 0; 15523 } 15524 15525 if (global_shrinkcallerid && ast_is_shrinkable_phonenumber(cid_num)) { 15526 ast_shrink_phone_number(cid_num); 15527 } 15528 15529 uri = get_in_brackets(pai); 15530 if (!strncasecmp(uri, "sip:anonymous@anonymous.invalid", 31)) { 15531 callingpres = AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED; 15532 /*XXX Assume no change in cid_num. Perhaps it should be 15533 * blanked? 15534 */ 15535 ast_free(cid_num); 15536 is_anonymous = 1; 15537 cid_num = (char *)p->cid_num; 15538 } 15539 15540 ast_copy_string(privacy, sip_get_header(req, "Privacy"), sizeof(privacy)); 15541 if (!ast_strlen_zero(privacy) && strncmp(privacy, "id", 2)) { 15542 callingpres = AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED; 15543 } 15544 if (!cid_name) { 15545 no_name = 1; 15546 cid_name = (char *)emptyname; 15547 } 15548 /* Only return true if the supplied caller id is different */ 15549 if (!strcasecmp(p->cid_num, cid_num) && !strcasecmp(p->cid_name, cid_name) && p->callingpres == callingpres) { 15550 do_update = 0; 15551 } else { 15552 15553 ast_string_field_set(p, cid_num, cid_num); 15554 ast_string_field_set(p, cid_name, cid_name); 15555 p->callingpres = callingpres; 15556 15557 if (p->owner) { 15558 ast_set_callerid(p->owner, cid_num, cid_name, NULL); 15559 p->owner->caller.id.name.presentation = callingpres; 15560 p->owner->caller.id.number.presentation = callingpres; 15561 } 15562 } 15563 15564 /* get_name_and_number allocates memory for cid_num and cid_name so we have to free it */ 15565 if (!is_anonymous) { 15566 ast_free(cid_num); 15567 } 15568 if (!no_name) { 15569 ast_free(cid_name); 15570 } 15571 15572 return do_update; 15573 }
| static int get_rdnis | ( | struct sip_pvt * | p, | |
| struct sip_request * | oreq, | |||
| char ** | name, | |||
| char ** | number, | |||
| int * | reason | |||
| ) | [static] |
Get referring dnis.
Definition at line 15676 of file chan_sip.c.
References ast_copy_string(), ast_log(), ast_strdup, ast_strip_quoted(), ast_strlen_zero(), ast_verbose, exten, get_in_brackets(), LOG_WARNING, pbx_builtin_setvar_helper(), sip_debug_test_pvt(), sip_get_header(), sip_reason_str_to_code(), sip_set_redirstr(), strcasestr(), and strsep().
Referenced by change_redirecting_information().
15677 { 15678 char tmp[256], *exten, *rexten, *rdomain, *rname = NULL; 15679 char *params, *reason_param = NULL; 15680 struct sip_request *req; 15681 15682 req = oreq ? oreq : &p->initreq; 15683 15684 ast_copy_string(tmp, sip_get_header(req, "Diversion"), sizeof(tmp)); 15685 if (ast_strlen_zero(tmp)) 15686 return -1; 15687 15688 if ((params = strchr(tmp, '>'))) { 15689 params = strchr(params, ';'); 15690 } 15691 15692 exten = get_in_brackets(tmp); 15693 if (!strncasecmp(exten, "sip:", 4)) { 15694 exten += 4; 15695 } else if (!strncasecmp(exten, "sips:", 5)) { 15696 exten += 5; 15697 } else { 15698 ast_log(LOG_WARNING, "Huh? Not an RDNIS SIP header (%s)?\n", exten); 15699 return -1; 15700 } 15701 15702 /* Get diversion-reason param if present */ 15703 if (params) { 15704 *params = '\0'; /* Cut off parameters */ 15705 params++; 15706 while (*params == ';' || *params == ' ') 15707 params++; 15708 /* Check if we have a reason parameter */ 15709 if ((reason_param = strcasestr(params, "reason="))) { 15710 char *end; 15711 reason_param+=7; 15712 if ((end = strchr(reason_param, ';'))) { 15713 *end = '\0'; 15714 } 15715 /* Remove enclosing double-quotes */ 15716 if (*reason_param == '"') 15717 ast_strip_quoted(reason_param, "\"", "\""); 15718 if (!ast_strlen_zero(reason_param)) { 15719 sip_set_redirstr(p, reason_param); 15720 if (p->owner) { 15721 pbx_builtin_setvar_helper(p->owner, "__PRIREDIRECTREASON", p->redircause); 15722 pbx_builtin_setvar_helper(p->owner, "__SIPREDIRECTREASON", reason_param); 15723 } 15724 } 15725 } 15726 } 15727 15728 rdomain = exten; 15729 rexten = strsep(&rdomain, "@"); /* trim anything after @ */ 15730 if (p->owner) 15731 pbx_builtin_setvar_helper(p->owner, "__SIPRDNISDOMAIN", rdomain); 15732 15733 if (sip_debug_test_pvt(p)) 15734 ast_verbose("RDNIS for this call is %s (reason %s)\n", exten, reason ? reason_param : ""); 15735 15736 /*ast_string_field_set(p, rdnis, rexten);*/ 15737 15738 if (*tmp == '\"') { 15739 char *end_quote; 15740 rname = tmp + 1; 15741 end_quote = strchr(rname, '\"'); 15742 *end_quote = '\0'; 15743 } 15744 15745 if (number) { 15746 *number = ast_strdup(rexten); 15747 } 15748 15749 if (name && rname) { 15750 *name = ast_strdup(rname); 15751 } 15752 15753 if (reason && !ast_strlen_zero(reason_param)) { 15754 *reason = sip_reason_str_to_code(reason_param); 15755 } 15756 15757 return 0; 15758 }
| static void get_realm | ( | struct sip_pvt * | p, | |
| const struct sip_request * | req | |||
| ) | [static] |
Choose realm based on From header and then To header or use globaly configured realm. Realm from From/To header should be listed among served domains in config file: domain=...
Definition at line 11041 of file chan_sip.c.
References AST_LIST_EMPTY, ast_string_field_set, ast_strlen_zero(), check_sip_domain(), get_domain(), MAXHOSTNAMELEN, sip_cfg, and sip_get_header().
Referenced by transmit_response_with_auth().
11042 { 11043 char domain[MAXHOSTNAMELEN]; 11044 11045 if (!ast_strlen_zero(p->realm)) 11046 return; 11047 11048 if (sip_cfg.domainsasrealm && 11049 !AST_LIST_EMPTY(&domain_list)) 11050 { 11051 /* Check From header first */ 11052 if (!get_domain(sip_get_header(req, "From"), domain, sizeof(domain))) { 11053 if (check_sip_domain(domain, NULL, 0)) { 11054 ast_string_field_set(p, realm, domain); 11055 return; 11056 } 11057 } 11058 /* Check To header */ 11059 if (!get_domain(sip_get_header(req, "To"), domain, sizeof(domain))) { 11060 if (check_sip_domain(domain, NULL, 0)) { 11061 ast_string_field_set(p, realm, domain); 11062 return; 11063 } 11064 } 11065 } 11066 11067 /* Use default realm from config file */ 11068 ast_string_field_set(p, realm, sip_cfg.realm); 11069 }
| static int get_refer_info | ( | struct sip_pvt * | transferer, | |
| struct sip_request * | outgoing_req | |||
| ) | [static] |
Call transfer support (the REFER method) Extracts Refer headers into pvt dialog structure.
Definition at line 16017 of file chan_sip.c.
References ast_bridged_channel(), ast_copy_string(), ast_debug, ast_exists_extension(), ast_log(), ast_strdupa, ast_strlen_zero(), ast_uri_decode(), ast_uri_sip_user, ast_verbose, ast_channel::context, get_in_brackets(), LOG_WARNING, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), S_OR, sip_cfg, sip_debug_test_pvt(), sip_get_header(), SIP_PEDANTIC_DECODE, and strcasestr().
Referenced by handle_request_refer().
16018 { 16019 16020 const char *p_referred_by = NULL; 16021 char *h_refer_to = NULL; 16022 char *h_referred_by = NULL; 16023 char *refer_to; 16024 const char *p_refer_to; 16025 char *referred_by_uri = NULL; 16026 char *ptr; 16027 struct sip_request *req = NULL; 16028 const char *transfer_context = NULL; 16029 struct sip_refer *referdata; 16030 16031 16032 req = outgoing_req; 16033 referdata = transferer->refer; 16034 16035 if (!req) { 16036 req = &transferer->initreq; 16037 } 16038 16039 p_refer_to = sip_get_header(req, "Refer-To"); 16040 if (ast_strlen_zero(p_refer_to)) { 16041 ast_log(LOG_WARNING, "Refer-To Header missing. Skipping transfer.\n"); 16042 return -2; /* Syntax error */ 16043 } 16044 h_refer_to = ast_strdupa(p_refer_to); 16045 refer_to = get_in_brackets(h_refer_to); 16046 if (!strncasecmp(refer_to, "sip:", 4)) { 16047 refer_to += 4; /* Skip sip: */ 16048 } else if (!strncasecmp(refer_to, "sips:", 5)) { 16049 refer_to += 5; 16050 } else { 16051 ast_log(LOG_WARNING, "Can't transfer to non-sip: URI. (Refer-to: %s)?\n", refer_to); 16052 return -3; 16053 } 16054 16055 /* Get referred by header if it exists */ 16056 p_referred_by = sip_get_header(req, "Referred-By"); 16057 16058 /* Give useful transfer information to the dialplan */ 16059 if (transferer->owner) { 16060 struct ast_channel *peer = ast_bridged_channel(transferer->owner); 16061 if (peer) { 16062 pbx_builtin_setvar_helper(peer, "SIPREFERRINGCONTEXT", transferer->context); 16063 pbx_builtin_setvar_helper(peer, "SIPREFERREDBYHDR", p_referred_by); 16064 } 16065 } 16066 16067 if (!ast_strlen_zero(p_referred_by)) { 16068 char *lessthan; 16069 h_referred_by = ast_strdupa(p_referred_by); 16070 16071 /* Store referrer's caller ID name */ 16072 ast_copy_string(referdata->referred_by_name, h_referred_by, sizeof(referdata->referred_by_name)); 16073 if ((lessthan = strchr(referdata->referred_by_name, '<'))) { 16074 *(lessthan - 1) = '\0'; /* Space */ 16075 } 16076 16077 referred_by_uri = get_in_brackets(h_referred_by); 16078 16079 if (!strncasecmp(referred_by_uri, "sip:", 4)) { 16080 referred_by_uri += 4; /* Skip sip: */ 16081 } else if (!strncasecmp(referred_by_uri, "sips:", 5)) { 16082 referred_by_uri += 5; /* Skip sips: */ 16083 } else { 16084 ast_log(LOG_WARNING, "Huh? Not a sip: header (Referred-by: %s). Skipping.\n", referred_by_uri); 16085 referred_by_uri = NULL; 16086 } 16087 } 16088 16089 /* Check for arguments in the refer_to header */ 16090 if ((ptr = strcasestr(refer_to, "replaces="))) { 16091 char *to = NULL, *from = NULL; 16092 16093 /* This is an attended transfer */ 16094 referdata->attendedtransfer = 1; 16095 ast_copy_string(referdata->replaces_callid, ptr+9, sizeof(referdata->replaces_callid)); 16096 ast_uri_decode(referdata->replaces_callid, ast_uri_sip_user); 16097 if ((ptr = strchr(referdata->replaces_callid, ';'))) /* Find options */ { 16098 *ptr++ = '\0'; 16099 } 16100 16101 if (ptr) { 16102 /* Find the different tags before we destroy the string */ 16103 to = strcasestr(ptr, "to-tag="); 16104 from = strcasestr(ptr, "from-tag="); 16105 } 16106 16107 /* Grab the to header */ 16108 if (to) { 16109 ptr = to + 7; 16110 if ((to = strchr(ptr, '&'))) { 16111 *to = '\0'; 16112 } 16113 if ((to = strchr(ptr, ';'))) { 16114 *to = '\0'; 16115 } 16116 ast_copy_string(referdata->replaces_callid_totag, ptr, sizeof(referdata->replaces_callid_totag)); 16117 } 16118 16119 if (from) { 16120 ptr = from + 9; 16121 if ((to = strchr(ptr, '&'))) { 16122 *to = '\0'; 16123 } 16124 if ((to = strchr(ptr, ';'))) { 16125 *to = '\0'; 16126 } 16127 ast_copy_string(referdata->replaces_callid_fromtag, ptr, sizeof(referdata->replaces_callid_fromtag)); 16128 } 16129 16130 if (!strcmp(referdata->replaces_callid, transferer->callid) && 16131 (!sip_cfg.pedanticsipchecking || 16132 (!strcmp(referdata->replaces_callid_fromtag, transferer->theirtag) && 16133 !strcmp(referdata->replaces_callid_totag, transferer->tag)))) { 16134 ast_log(LOG_WARNING, "Got an attempt to replace own Call-ID on %s\n", transferer->callid); 16135 return -4; 16136 } 16137 16138 if (!sip_cfg.pedanticsipchecking) { 16139 ast_debug(2, "Attended transfer: Will use Replace-Call-ID : %s (No check of from/to tags)\n", referdata->replaces_callid ); 16140 } else { 16141 ast_debug(2, "Attended transfer: Will use Replace-Call-ID : %s F-tag: %s T-tag: %s\n", referdata->replaces_callid, referdata->replaces_callid_fromtag ? referdata->replaces_callid_fromtag : "<none>", referdata->replaces_callid_totag ? referdata->replaces_callid_totag : "<none>" ); 16142 } 16143 } 16144 16145 if ((ptr = strchr(refer_to, '@'))) { /* Separate domain */ 16146 char *urioption = NULL, *domain; 16147 int bracket = 0; 16148 *ptr++ = '\0'; 16149 16150 if ((urioption = strchr(ptr, ';'))) { /* Separate urioptions */ 16151 *urioption++ = '\0'; 16152 } 16153 16154 domain = ptr; 16155 16156 /* Remove :port */ 16157 for (; *ptr != '\0'; ++ptr) { 16158 if (*ptr == ':' && bracket == 0) { 16159 *ptr = '\0'; 16160 break; 16161 } else if (*ptr == '[') { 16162 ++bracket; 16163 } else if (*ptr == ']') { 16164 --bracket; 16165 } 16166 } 16167 16168 SIP_PEDANTIC_DECODE(domain); 16169 SIP_PEDANTIC_DECODE(urioption); 16170 16171 /* Save the domain for the dial plan */ 16172 ast_copy_string(referdata->refer_to_domain, domain, sizeof(referdata->refer_to_domain)); 16173 if (urioption) { 16174 ast_copy_string(referdata->refer_to_urioption, urioption, sizeof(referdata->refer_to_urioption)); 16175 } 16176 } 16177 16178 if ((ptr = strchr(refer_to, ';'))) /* Remove options */ 16179 *ptr = '\0'; 16180 16181 SIP_PEDANTIC_DECODE(refer_to); 16182 ast_copy_string(referdata->refer_to, refer_to, sizeof(referdata->refer_to)); 16183 16184 if (referred_by_uri) { 16185 if ((ptr = strchr(referred_by_uri, ';'))) /* Remove options */ 16186 *ptr = '\0'; 16187 SIP_PEDANTIC_DECODE(referred_by_uri); 16188 ast_copy_string(referdata->referred_by, referred_by_uri, sizeof(referdata->referred_by)); 16189 } else { 16190 referdata->referred_by[0] = '\0'; 16191 } 16192 16193 /* Determine transfer context */ 16194 if (transferer->owner) /* Mimic behaviour in res_features.c */ 16195 transfer_context = pbx_builtin_getvar_helper(transferer->owner, "TRANSFER_CONTEXT"); 16196 16197 /* By default, use the context in the channel sending the REFER */ 16198 if (ast_strlen_zero(transfer_context)) { 16199 transfer_context = S_OR(transferer->owner->macrocontext, 16200 S_OR(transferer->context, sip_cfg.default_context)); 16201 } 16202 16203 ast_copy_string(referdata->refer_to_context, transfer_context, sizeof(referdata->refer_to_context)); 16204 16205 /* Either an existing extension or the parking extension */ 16206 if (referdata->attendedtransfer || ast_exists_extension(NULL, transfer_context, refer_to, 1, NULL) ) { 16207 if (sip_debug_test_pvt(transferer)) { 16208 ast_verbose("SIP transfer to extension %s@%s by %s\n", refer_to, transfer_context, referred_by_uri); 16209 } 16210 /* We are ready to transfer to the extension */ 16211 return 0; 16212 } 16213 if (sip_debug_test_pvt(transferer)) 16214 ast_verbose("Failed SIP Transfer to non-existing extension %s in context %s\n n", refer_to, transfer_context); 16215 16216 /* Failure, we can't find this extension */ 16217 return -1; 16218 }
| static int get_rpid | ( | struct sip_pvt * | p, | |
| struct sip_request * | oreq | |||
| ) | [static] |
Get name, number and presentation from remote party id header, returns true if a valid header was found and it was different from the current caller id.
Definition at line 15579 of file chan_sip.c.
References ast_copy_string(), ast_is_shrinkable_phonenumber(), AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED, AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED, AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN, ast_set_callerid(), ast_shrink_phone_number(), ast_skip_blanks(), ast_string_field_set, ast_strlen_zero(), ast_test_flag, cid_name, cid_num, get_pai(), and sip_get_header().
Referenced by check_peer_ok(), check_user_full(), handle_request_invite(), handle_request_update(), and handle_response_invite().
15580 { 15581 char tmp[256]; 15582 struct sip_request *req; 15583 char *cid_num = ""; 15584 char *cid_name = ""; 15585 int callingpres = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED; 15586 char *privacy = ""; 15587 char *screen = ""; 15588 char *start, *end; 15589 15590 if (!ast_test_flag(&p->flags[0], SIP_TRUSTRPID)) 15591 return 0; 15592 req = oreq; 15593 if (!req) 15594 req = &p->initreq; 15595 ast_copy_string(tmp, sip_get_header(req, "Remote-Party-ID"), sizeof(tmp)); 15596 if (ast_strlen_zero(tmp)) { 15597 return get_pai(p, req); 15598 } 15599 15600 start = tmp; 15601 if (*start == '"') { 15602 *start++ = '\0'; 15603 end = strchr(start, '"'); 15604 if (!end) 15605 return 0; 15606 *end++ = '\0'; 15607 cid_name = start; 15608 start = ast_skip_blanks(end); 15609 } 15610 15611 if (*start != '<') 15612 return 0; 15613 *start++ = '\0'; 15614 end = strchr(start, '@'); 15615 if (!end) 15616 return 0; 15617 *end++ = '\0'; 15618 if (strncasecmp(start, "sip:", 4)) 15619 return 0; 15620 cid_num = start + 4; 15621 if (global_shrinkcallerid && ast_is_shrinkable_phonenumber(cid_num)) 15622 ast_shrink_phone_number(cid_num); 15623 start = end; 15624 15625 end = strchr(start, '>'); 15626 if (!end) 15627 return 0; 15628 *end++ = '\0'; 15629 if (*end) { 15630 start = end; 15631 if (*start != ';') 15632 return 0; 15633 *start++ = '\0'; 15634 while (!ast_strlen_zero(start)) { 15635 end = strchr(start, ';'); 15636 if (end) 15637 *end++ = '\0'; 15638 if (!strncasecmp(start, "privacy=", 8)) 15639 privacy = start + 8; 15640 else if (!strncasecmp(start, "screen=", 7)) 15641 screen = start + 7; 15642 start = end; 15643 } 15644 15645 if (!strcasecmp(privacy, "full")) { 15646 if (!strcasecmp(screen, "yes")) 15647 callingpres = AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN; 15648 else if (!strcasecmp(screen, "no")) 15649 callingpres = AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED; 15650 } else { 15651 if (!strcasecmp(screen, "yes")) 15652 callingpres = AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN; 15653 else if (!strcasecmp(screen, "no")) 15654 callingpres = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED; 15655 } 15656 } 15657 15658 /* Only return true if the supplied caller id is different */ 15659 if (!strcasecmp(p->cid_num, cid_num) && !strcasecmp(p->cid_name, cid_name) && p->callingpres == callingpres) 15660 return 0; 15661 15662 ast_string_field_set(p, cid_num, cid_num); 15663 ast_string_field_set(p, cid_name, cid_name); 15664 p->callingpres = callingpres; 15665 15666 if (p->owner) { 15667 ast_set_callerid(p->owner, cid_num, cid_name, NULL); 15668 p->owner->caller.id.name.presentation = callingpres; 15669 p->owner->caller.id.number.presentation = callingpres; 15670 } 15671 15672 return 1; 15673 }
| static const char * get_sdp_iterate | ( | int * | start, | |
| struct sip_request * | req, | |||
| const char * | name | |||
| ) | [static] |
Lookup 'name' in the SDP starting at the 'start' line. Returns the matching line, and 'start' is updated with the next line number.
Definition at line 7344 of file chan_sip.c.
References get_body_by_line(), and len().
07345 { 07346 int len = strlen(name); 07347 07348 while (*start < (req->sdp_start + req->sdp_count)) { 07349 const char *r = get_body_by_line(REQ_OFFSET_TO_STR(req, line[(*start)++]), name, len, '='); 07350 if (r[0] != '\0') 07351 return r; 07352 } 07353 07354 /* if the line was not found, ensure that *start points past the SDP */ 07355 (*start)++; 07356 07357 return ""; 07358 }
| static char get_sdp_line | ( | int * | start, | |
| int | stop, | |||
| struct sip_request * | req, | |||
| const char ** | value | |||
| ) | [static] |
Fetches the next valid SDP line between the 'start' line (inclusive) and the 'stop' line (exclusive). Returns the type ('a', 'c', ...) and matching line in reference 'start' is updated with the next line number.
Definition at line 7365 of file chan_sip.c.
References ast_skip_blanks(), and type.
Referenced by process_sdp().
07366 { 07367 char type = '\0'; 07368 const char *line = NULL; 07369 07370 if (stop > (req->sdp_start + req->sdp_count)) { 07371 stop = req->sdp_start + req->sdp_count; 07372 } 07373 07374 while (*start < stop) { 07375 line = REQ_OFFSET_TO_STR(req, line[(*start)++]); 07376 if (line[1] == '=') { 07377 type = line[0]; 07378 *value = ast_skip_blanks(line + 2); 07379 break; 07380 } 07381 } 07382 07383 return type; 07384 }
| static struct sip_pvt * get_sip_pvt_byid_locked | ( | const char * | callid, | |
| const char * | totag, | |||
| const char * | fromtag | |||
| ) | [static, read] |
Lock dialog lock and find matching pvt lock.
Definition at line 15928 of file chan_sip.c.
References ao2_t_find, ast_channel_trylock, ast_debug, ast_strlen_zero(), OBJ_POINTER, sip_cfg, sip_pvt_lock, sip_pvt_unlock, and TRUE.
Referenced by handle_request_invite(), and local_attended_transfer().
15929 { 15930 struct sip_pvt *sip_pvt_ptr; 15931 struct sip_pvt tmp_dialog = { 15932 .callid = callid, 15933 }; 15934 15935 if (totag) { 15936 ast_debug(4, "Looking for callid %s (fromtag %s totag %s)\n", callid, fromtag ? fromtag : "<no fromtag>", totag ? totag : "<no totag>"); 15937 } 15938 15939 /* Search dialogs and find the match */ 15940 15941 sip_pvt_ptr = ao2_t_find(dialogs, &tmp_dialog, OBJ_POINTER, "ao2_find of dialog in dialogs table"); 15942 if (sip_pvt_ptr) { 15943 /* Go ahead and lock it (and its owner) before returning */ 15944 sip_pvt_lock(sip_pvt_ptr); 15945 if (sip_cfg.pedanticsipchecking) { 15946 unsigned char frommismatch = 0, tomismatch = 0; 15947 15948 if (ast_strlen_zero(fromtag)) { 15949 sip_pvt_unlock(sip_pvt_ptr); 15950 ast_debug(4, "Matched %s call for callid=%s - no from tag specified, pedantic check fails\n", 15951 sip_pvt_ptr->outgoing_call == TRUE ? "OUTGOING": "INCOMING", sip_pvt_ptr->callid); 15952 return NULL; 15953 } 15954 15955 if (ast_strlen_zero(totag)) { 15956 sip_pvt_unlock(sip_pvt_ptr); 15957 ast_debug(4, "Matched %s call for callid=%s - no to tag specified, pedantic check fails\n", 15958 sip_pvt_ptr->outgoing_call == TRUE ? "OUTGOING": "INCOMING", sip_pvt_ptr->callid); 15959 return NULL; 15960 } 15961 /* RFC 3891 15962 * > 3. User Agent Server Behavior: Receiving a Replaces Header 15963 * > The Replaces header contains information used to match an existing 15964 * > SIP dialog (call-id, to-tag, and from-tag). Upon receiving an INVITE 15965 * > with a Replaces header, the User Agent (UA) attempts to match this 15966 * > information with a confirmed or early dialog. The User Agent Server 15967 * > (UAS) matches the to-tag and from-tag parameters as if they were tags 15968 * > present in an incoming request. In other words, the to-tag parameter 15969 * > is compared to the local tag, and the from-tag parameter is compared 15970 * > to the remote tag. 15971 * 15972 * Thus, the totag is always compared to the local tag, regardless if 15973 * this our call is an incoming or outgoing call. 15974 */ 15975 frommismatch = !!strcmp(fromtag, sip_pvt_ptr->theirtag); 15976 tomismatch = !!strcmp(totag, sip_pvt_ptr->tag); 15977 15978 if (frommismatch || tomismatch) { 15979 sip_pvt_unlock(sip_pvt_ptr); 15980 if (frommismatch) { 15981 ast_debug(4, "Matched %s call for callid=%s - pedantic from tag check fails; their tag is %s our tag is %s\n", 15982 sip_pvt_ptr->outgoing_call == TRUE ? "OUTGOING": "INCOMING", sip_pvt_ptr->callid, 15983 fromtag, sip_pvt_ptr->theirtag); 15984 } 15985 if (tomismatch) { 15986 ast_debug(4, "Matched %s call for callid=%s - pedantic to tag check fails; their tag is %s our tag is %s\n", 15987 sip_pvt_ptr->outgoing_call == TRUE ? "OUTGOING": "INCOMING", sip_pvt_ptr->callid, 15988 totag, sip_pvt_ptr->tag); 15989 } 15990 return NULL; 15991 } 15992 } 15993 15994 if (totag) 15995 ast_debug(4, "Matched %s call - their tag is %s Our tag is %s\n", 15996 sip_pvt_ptr->outgoing_call == TRUE ? "OUTGOING": "INCOMING", 15997 sip_pvt_ptr->theirtag, sip_pvt_ptr->tag); 15998 15999 /* deadlock avoidance... */ 16000 while (sip_pvt_ptr->owner && ast_channel_trylock(sip_pvt_ptr->owner)) { 16001 sip_pvt_unlock(sip_pvt_ptr); 16002 usleep(1); 16003 sip_pvt_lock(sip_pvt_ptr); 16004 } 16005 } 16006 16007 return sip_pvt_ptr; 16008 }
| static const char* get_srv_protocol | ( | enum sip_transport | t | ) | [inline, static] |
Return protocol string for srv dns query.
Definition at line 3312 of file chan_sip.c.
Referenced by __sip_subscribe_mwi_do(), build_peer(), create_addr(), and transmit_register().
03313 { 03314 switch (t) { 03315 case SIP_TRANSPORT_UDP: 03316 return "udp"; 03317 case SIP_TRANSPORT_TLS: 03318 case SIP_TRANSPORT_TCP: 03319 return "tcp"; 03320 } 03321 03322 return "udp"; 03323 }
| static const char* get_srv_service | ( | enum sip_transport | t | ) | [inline, static] |
Return service string for srv dns query.
Definition at line 3326 of file chan_sip.c.
Referenced by __sip_subscribe_mwi_do(), build_peer(), create_addr(), and transmit_register().
03327 { 03328 switch (t) { 03329 case SIP_TRANSPORT_TCP: 03330 case SIP_TRANSPORT_UDP: 03331 return "sip"; 03332 case SIP_TRANSPORT_TLS: 03333 return "sips"; 03334 } 03335 return "sip"; 03336 }
| static const char* get_transport_list | ( | unsigned int | transports | ) | [inline, static] |
Return configuration of transports for a device.
Definition at line 3276 of file chan_sip.c.
Referenced by _sip_show_peer(), peers_data_provider_get(), and sip_show_settings().
03276 { 03277 switch (transports) { 03278 case SIP_TRANSPORT_UDP: 03279 return "UDP"; 03280 case SIP_TRANSPORT_TCP: 03281 return "TCP"; 03282 case SIP_TRANSPORT_TLS: 03283 return "TLS"; 03284 case SIP_TRANSPORT_UDP | SIP_TRANSPORT_TCP: 03285 return "TCP,UDP"; 03286 case SIP_TRANSPORT_UDP | SIP_TRANSPORT_TLS: 03287 return "TLS,UDP"; 03288 case SIP_TRANSPORT_TCP | SIP_TRANSPORT_TLS: 03289 return "TLS,TCP"; 03290 default: 03291 return transports ? 03292 "TLS,TCP,UDP" : "UNKNOWN"; 03293 } 03294 }
| static const char* get_transport_pvt | ( | struct sip_pvt * | p | ) | [inline, static] |
Return transport of dialog.
Definition at line 3344 of file chan_sip.c.
References set_socket_transport(), and sip_get_transport().
Referenced by __sip_xmit(), and build_via().
03345 { 03346 if (p->outboundproxy && p->outboundproxy->transport) { 03347 set_socket_transport(&p->socket, p->outboundproxy->transport); 03348 } 03349 03350 return sip_get_transport(p->socket.type); 03351 }
| static int get_transport_str2enum | ( | const char * | transport | ) | [static] |
Return int representing a bit field of transport types found in const char *transport.
Definition at line 3254 of file chan_sip.c.
References ast_strlen_zero().
Referenced by __set_address_from_contact(), and parse_register_contact().
03255 { 03256 int res = 0; 03257 03258 if (ast_strlen_zero(transport)) { 03259 return res; 03260 } 03261 03262 if (!strcasecmp(transport, "udp")) { 03263 res |= SIP_TRANSPORT_UDP; 03264 } 03265 if (!strcasecmp(transport, "tcp")) { 03266 res |= SIP_TRANSPORT_TCP; 03267 } 03268 if (!strcasecmp(transport, "tls")) { 03269 res |= SIP_TRANSPORT_TLS; 03270 } 03271 03272 return res; 03273 }
| static const char * gettag | ( | const struct sip_request * | req, | |
| const char * | header, | |||
| char * | tagbuf, | |||
| int | tagbufsize | |||
| ) | [static] |
Get tag from packet.
Definition at line 22467 of file chan_sip.c.
References ast_copy_string(), sip_get_header(), strcasestr(), and strsep().
Referenced by find_call(), handle_incoming(), handle_request_subscribe(), and handle_response().
22468 { 22469 const char *thetag; 22470 22471 if (!tagbuf) 22472 return NULL; 22473 tagbuf[0] = '\0'; /* reset the buffer */ 22474 thetag = sip_get_header(req, header); 22475 thetag = strcasestr(thetag, ";tag="); 22476 if (thetag) { 22477 thetag += 5; 22478 ast_copy_string(tagbuf, thetag, tagbufsize); 22479 return strsep(&tagbuf, ";"); 22480 } 22481 return NULL; 22482 }
| static int handle_cc_notify | ( | struct sip_pvt * | pvt, | |
| struct sip_request * | req | |||
| ) | [static] |
Definition at line 22484 of file chan_sip.c.
References ao2_callback, ao2_ref, ast_cc_monitor_callee_available(), ast_cc_monitor_request_acked(), ast_string_field_set, ast_strlen_zero(), construct_pidf_body(), find_sip_monitor_instance_by_subscription_pvt(), get_body(), get_in_brackets(), sip_get_header(), status, transmit_publish(), and transmit_response().
Referenced by handle_request_notify().
22485 { 22486 struct sip_monitor_instance *monitor_instance = ao2_callback(sip_monitor_instances, 0, 22487 find_sip_monitor_instance_by_subscription_pvt, pvt); 22488 const char *status = get_body(req, "cc-state", ':'); 22489 struct cc_epa_entry *cc_entry; 22490 char *uri; 22491 22492 if (!monitor_instance) { 22493 transmit_response(pvt, "400 Bad Request", req); 22494 return -1; 22495 } 22496 22497 if (ast_strlen_zero(status)) { 22498 ao2_ref(monitor_instance, -1); 22499 transmit_response(pvt, "400 Bad Request", req); 22500 return -1; 22501 } 22502 22503 if (!strcmp(status, "queued")) { 22504 /* We've been told that we're queued. This is the endpoint's way of telling 22505 * us that it has accepted our CC request. We need to alert the core of this 22506 * development 22507 */ 22508 ast_cc_monitor_request_acked(monitor_instance->core_id, "SIP endpoint %s accepted request", monitor_instance->device_name); 22509 transmit_response(pvt, "200 OK", req); 22510 ao2_ref(monitor_instance, -1); 22511 return 0; 22512 } 22513 22514 /* It's open! Yay! */ 22515 uri = get_body(req, "cc-URI", ':'); 22516 if (ast_strlen_zero(uri)) { 22517 uri = get_in_brackets((char *)sip_get_header(req, "From")); 22518 } 22519 22520 ast_string_field_set(monitor_instance, notify_uri, uri); 22521 if (monitor_instance->suspension_entry) { 22522 cc_entry = monitor_instance->suspension_entry->instance_data; 22523 if (cc_entry->current_state == CC_CLOSED) { 22524 /* If we've created a suspension entry and the current state is closed, then that means 22525 * we got a notice from the CC core earlier to suspend monitoring, but because this particular 22526 * call leg had not yet notified us that it was ready for recall, it meant that we 22527 * could not yet send a PUBLISH. Now, however, we can. 22528 */ 22529 construct_pidf_body(CC_CLOSED, monitor_instance->suspension_entry->body, 22530 sizeof(monitor_instance->suspension_entry->body), monitor_instance->peername); 22531 transmit_publish(monitor_instance->suspension_entry, SIP_PUBLISH_INITIAL, monitor_instance->notify_uri); 22532 } else { 22533 ast_cc_monitor_callee_available(monitor_instance->core_id, "SIP monitored callee has become available"); 22534 } 22535 } else { 22536 ast_cc_monitor_callee_available(monitor_instance->core_id, "SIP monitored callee has become available"); 22537 } 22538 ao2_ref(monitor_instance, -1); 22539 transmit_response(pvt, "200 OK", req); 22540 22541 return 0; 22542 }
| static int handle_cc_subscribe | ( | struct sip_pvt * | p, | |
| struct sip_request * | req | |||
| ) | [static] |
Definition at line 25453 of file chan_sip.c.
References ao2_ref, ast_cc_agent_accept_request(), ast_cc_failed(), ast_log(), ast_strlen_zero(), ast_cc_agent::core_id, ast_cc_agent::device_name, find_sip_cc_agent_by_subscribe_uri(), LOG_WARNING, ast_cc_agent::private_data, sip_get_header(), and transmit_response().
Referenced by handle_request_subscribe().
25454 { 25455 const char *uri = REQ_OFFSET_TO_STR(req, rlPart2); 25456 char *param_separator; 25457 struct ast_cc_agent *agent; 25458 struct sip_cc_agent_pvt *agent_pvt; 25459 const char *expires_str = sip_get_header(req, "Expires"); 25460 int expires = -1; /* Just need it to be non-zero */ 25461 25462 if (!ast_strlen_zero(expires_str)) { 25463 sscanf(expires_str, "%30d", &expires); 25464 } 25465 25466 if ((param_separator = strchr(uri, ';'))) { 25467 *param_separator = '\0'; 25468 } 25469 25470 p->subscribed = CALL_COMPLETION; 25471 25472 if (!(agent = find_sip_cc_agent_by_subscribe_uri(uri))) { 25473 if (!expires) { 25474 /* Typically, if a 0 Expires reaches us and we can't find 25475 * the corresponding agent, it means that the CC transaction 25476 * has completed and so the calling side is just trying to 25477 * clean up its subscription. We'll just respond with a 25478 * 200 OK and be done with it 25479 */ 25480 transmit_response(p, "200 OK", req); 25481 return 0; 25482 } 25483 ast_log(LOG_WARNING, "Invalid URI '%s' in CC subscribe\n", uri); 25484 transmit_response(p, "404 Not Found", req); 25485 return -1; 25486 } 25487 25488 agent_pvt = agent->private_data; 25489 25490 if (!expires) { 25491 /* We got sent a SUBSCRIBE and found an agent. This means that CC 25492 * is being canceled. 25493 */ 25494 ast_cc_failed(agent->core_id, "CC is being canceled by %s", agent->device_name); 25495 transmit_response(p, "200 OK", req); 25496 ao2_ref(agent, -1); 25497 return 0; 25498 } 25499 25500 agent_pvt->subscribe_pvt = dialog_ref(p, "SIP CC agent gains reference to subscription dialog"); 25501 ast_cc_agent_accept_request(agent->core_id, "SIP caller %s has requested CC via SUBSCRIBE", 25502 agent->device_name); 25503 25504 /* We don't send a response here. That is done in the agent's ack callback or in the 25505 * agent destructor, should a failure occur before we have responded 25506 */ 25507 ao2_ref(agent, -1); 25508 return 0; 25509 }
| static int handle_common_options | ( | struct ast_flags * | flags, | |
| struct ast_flags * | mask, | |||
| struct ast_variable * | v | |||
| ) | [static] |
Handle flag-type options common to configuration of devices - peers.
| flags | array of three struct ast_flags | |
| mask | array of three struct ast_flags | |
| v | linked list of config variables to process |
Definition at line 27754 of file chan_sip.c.
References ast_clear_flag, ast_copy_string(), ast_false(), ast_log(), ast_set2_flag, ast_set_flag, ast_strdupa, ast_true(), ast_variable::lineno, LOG_WARNING, ast_variable::name, set_insecure_flags(), sip_parse_nat_option(), strsep(), ast_variable::value, and word.
Referenced by build_peer(), and reload_config().
27755 { 27756 int res = 1; 27757 27758 if (!strcasecmp(v->name, "trustrpid")) { 27759 ast_set_flag(&mask[0], SIP_TRUSTRPID); 27760 ast_set2_flag(&flags[0], ast_true(v->value), SIP_TRUSTRPID); 27761 } else if (!strcasecmp(v->name, "sendrpid")) { 27762 ast_set_flag(&mask[0], SIP_SENDRPID); 27763 if (!strcasecmp(v->value, "pai")) { 27764 ast_set_flag(&flags[0], SIP_SENDRPID_PAI); 27765 } else if (!strcasecmp(v->value, "rpid")) { 27766 ast_set_flag(&flags[0], SIP_SENDRPID_RPID); 27767 } else if (ast_true(v->value)) { 27768 ast_set_flag(&flags[0], SIP_SENDRPID_RPID); 27769 } 27770 } else if (!strcasecmp(v->name, "rpid_update")) { 27771 ast_set_flag(&mask[1], SIP_PAGE2_RPID_UPDATE); 27772 ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_RPID_UPDATE); 27773 } else if (!strcasecmp(v->name, "rpid_immediate")) { 27774 ast_set_flag(&mask[1], SIP_PAGE2_RPID_IMMEDIATE); 27775 ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_RPID_IMMEDIATE); 27776 } else if (!strcasecmp(v->name, "g726nonstandard")) { 27777 ast_set_flag(&mask[0], SIP_G726_NONSTANDARD); 27778 ast_set2_flag(&flags[0], ast_true(v->value), SIP_G726_NONSTANDARD); 27779 } else if (!strcasecmp(v->name, "useclientcode")) { 27780 ast_set_flag(&mask[0], SIP_USECLIENTCODE); 27781 ast_set2_flag(&flags[0], ast_true(v->value), SIP_USECLIENTCODE); 27782 } else if (!strcasecmp(v->name, "dtmfmode")) { 27783 ast_set_flag(&mask[0], SIP_DTMF); 27784 ast_clear_flag(&flags[0], SIP_DTMF); 27785 if (!strcasecmp(v->value, "inband")) 27786 ast_set_flag(&flags[0], SIP_DTMF_INBAND); 27787 else if (!strcasecmp(v->value, "rfc2833")) 27788 ast_set_flag(&flags[0], SIP_DTMF_RFC2833); 27789 else if (!strcasecmp(v->value, "info")) 27790 ast_set_flag(&flags[0], SIP_DTMF_INFO); 27791 else if (!strcasecmp(v->value, "shortinfo")) 27792 ast_set_flag(&flags[0], SIP_DTMF_SHORTINFO); 27793 else if (!strcasecmp(v->value, "auto")) 27794 ast_set_flag(&flags[0], SIP_DTMF_AUTO); 27795 else { 27796 ast_log(LOG_WARNING, "Unknown dtmf mode '%s' on line %d, using rfc2833\n", v->value, v->lineno); 27797 ast_set_flag(&flags[0], SIP_DTMF_RFC2833); 27798 } 27799 } else if (!strcasecmp(v->name, "nat")) { 27800 sip_parse_nat_option(v->value, mask, flags); 27801 } else if (!strcasecmp(v->name, "directmedia") || !strcasecmp(v->name, "canreinvite")) { 27802 ast_set_flag(&mask[0], SIP_REINVITE); 27803 ast_clear_flag(&flags[0], SIP_REINVITE); 27804 if (ast_true(v->value)) { 27805 ast_set_flag(&flags[0], SIP_DIRECT_MEDIA | SIP_DIRECT_MEDIA_NAT); 27806 } else if (!ast_false(v->value)) { 27807 char buf[64]; 27808 char *word, *next = buf; 27809 27810 ast_copy_string(buf, v->value, sizeof(buf)); 27811 while ((word = strsep(&next, ","))) { 27812 if (!strcasecmp(word, "update")) { 27813 ast_set_flag(&flags[0], SIP_REINVITE_UPDATE | SIP_DIRECT_MEDIA); 27814 } else if (!strcasecmp(word, "nonat")) { 27815 ast_set_flag(&flags[0], SIP_DIRECT_MEDIA); 27816 ast_clear_flag(&flags[0], SIP_DIRECT_MEDIA_NAT); 27817 } else { 27818 ast_log(LOG_WARNING, "Unknown directmedia mode '%s' on line %d\n", v->value, v->lineno); 27819 } 27820 } 27821 } 27822 } else if (!strcasecmp(v->name, "insecure")) { 27823 ast_set_flag(&mask[0], SIP_INSECURE); 27824 ast_clear_flag(&flags[0], SIP_INSECURE); 27825 set_insecure_flags(&flags[0], v->value, v->lineno); 27826 } else if (!strcasecmp(v->name, "progressinband")) { 27827 ast_set_flag(&mask[0], SIP_PROG_INBAND); 27828 ast_clear_flag(&flags[0], SIP_PROG_INBAND); 27829 if (ast_true(v->value)) 27830 ast_set_flag(&flags[0], SIP_PROG_INBAND_YES); 27831 else if (strcasecmp(v->value, "never")) 27832 ast_set_flag(&flags[0], SIP_PROG_INBAND_NO); 27833 } else if (!strcasecmp(v->name, "promiscredir")) { 27834 ast_set_flag(&mask[0], SIP_PROMISCREDIR); 27835 ast_set2_flag(&flags[0], ast_true(v->value), SIP_PROMISCREDIR); 27836 } else if (!strcasecmp(v->name, "videosupport")) { 27837 if (!strcasecmp(v->value, "always")) { 27838 ast_set_flag(&mask[1], SIP_PAGE2_VIDEOSUPPORT_ALWAYS); 27839 ast_set_flag(&flags[1], SIP_PAGE2_VIDEOSUPPORT_ALWAYS); 27840 } else { 27841 ast_set_flag(&mask[1], SIP_PAGE2_VIDEOSUPPORT); 27842 ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_VIDEOSUPPORT); 27843 } 27844 } else if (!strcasecmp(v->name, "textsupport")) { 27845 ast_set_flag(&mask[1], SIP_PAGE2_TEXTSUPPORT); 27846 ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_TEXTSUPPORT); 27847 res = 1; 27848 } else if (!strcasecmp(v->name, "allowoverlap")) { 27849 ast_set_flag(&mask[1], SIP_PAGE2_ALLOWOVERLAP); 27850 ast_clear_flag(&flags[1], SIP_PAGE2_ALLOWOVERLAP); 27851 if (ast_true(v->value)) { 27852 ast_set_flag(&flags[1], SIP_PAGE2_ALLOWOVERLAP_YES); 27853 } else if (!strcasecmp(v->value, "dtmf")){ 27854 ast_set_flag(&flags[1], SIP_PAGE2_ALLOWOVERLAP_DTMF); 27855 } 27856 } else if (!strcasecmp(v->name, "allowsubscribe")) { 27857 ast_set_flag(&mask[1], SIP_PAGE2_ALLOWSUBSCRIBE); 27858 ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_ALLOWSUBSCRIBE); 27859 } else if (!strcasecmp(v->name, "ignoresdpversion")) { 27860 ast_set_flag(&mask[1], SIP_PAGE2_IGNORESDPVERSION); 27861 ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_IGNORESDPVERSION); 27862 } else if (!strcasecmp(v->name, "faxdetect")) { 27863 ast_set_flag(&mask[1], SIP_PAGE2_FAX_DETECT); 27864 if (ast_true(v->value)) { 27865 ast_set_flag(&flags[1], SIP_PAGE2_FAX_DETECT_BOTH); 27866 } else if (ast_false(v->value)) { 27867 ast_clear_flag(&flags[1], SIP_PAGE2_FAX_DETECT_BOTH); 27868 } else { 27869 char *buf = ast_strdupa(v->value); 27870 char *word, *next = buf; 27871 27872 while ((word = strsep(&next, ","))) { 27873 if (!strcasecmp(word, "cng")) { 27874 ast_set_flag(&flags[1], SIP_PAGE2_FAX_DETECT_CNG); 27875 } else if (!strcasecmp(word, "t38")) { 27876 ast_set_flag(&flags[1], SIP_PAGE2_FAX_DETECT_T38); 27877 } else { 27878 ast_log(LOG_WARNING, "Unknown faxdetect mode '%s' on line %d.\n", word, v->lineno); 27879 } 27880 } 27881 } 27882 } else if (!strcasecmp(v->name, "rfc2833compensate")) { 27883 ast_set_flag(&mask[1], SIP_PAGE2_RFC2833_COMPENSATE); 27884 ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_RFC2833_COMPENSATE); 27885 } else if (!strcasecmp(v->name, "buggymwi")) { 27886 ast_set_flag(&mask[1], SIP_PAGE2_BUGGY_MWI); 27887 ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_BUGGY_MWI); 27888 } else 27889 res = 0; 27890 27891 return res; 27892 }
| static int handle_incoming | ( | struct sip_pvt * | p, | |
| struct sip_request * | req, | |||
| struct ast_sockaddr * | addr, | |||
| int * | recount, | |||
| int * | nounlock | |||
| ) | [static] |
Handle incoming SIP requests (methods).
called with p and p->owner locked
Definition at line 25973 of file chan_sip.c.
References __get_header(), __sip_ack(), ast_channel_name(), ast_channel_ref, ast_channel_unlock, ast_channel_unref, ast_debug, ast_log(), ast_random(), ast_skip_blanks(), ast_sockaddr_stringify(), ast_string_field_set, ast_strlen_zero(), ast_verbose, check_pendings(), debug, extract_uri(), find_sdp(), gettag(), handle_request_bye(), handle_request_cancel(), handle_request_info(), handle_request_invite(), handle_request_message(), handle_request_notify(), handle_request_options(), handle_request_publish(), handle_request_refer(), handle_request_register(), handle_request_subscribe(), handle_request_update(), handle_response(), cfsip_methods::id, len(), LOG_ERROR, LOG_NOTICE, LOG_WARNING, pbx_builtin_setvar_helper(), process_sdp(), pvt_set_needdestroy(), sip_cfg, sip_debug_test_pvt(), sip_get_header(), sip_methods, sip_pvt_lock, sip_pvt_unlock, sip_report_security_event(), sip_scheddestroy(), cfsip_methods::text, transmit_response(), transmit_response_reliable(), transmit_response_with_allow(), and transmit_response_with_retry_after().
Referenced by handle_request_do().
25974 { 25975 /* Called with p->lock held, as well as p->owner->lock if appropriate, keeping things 25976 relatively static */ 25977 const char *cmd; 25978 const char *cseq; 25979 const char *useragent; 25980 const char *via; 25981 const char *callid; 25982 int via_pos = 0; 25983 uint32_t seqno; 25984 int len; 25985 int respid; 25986 int res = 0; 25987 int debug = sip_debug_test_pvt(p); 25988 const char *e; 25989 int error = 0; 25990 int oldmethod = p->method; 25991 int acked = 0; 25992 25993 /* RFC 3261 - 8.1.1 A valid SIP request must contain To, From, CSeq, Call-ID and Via. 25994 * 8.2.6.2 Response must have To, From, Call-ID CSeq, and Via related to the request, 25995 * so we can check to make sure these fields exist for all requests and responses */ 25996 cseq = sip_get_header(req, "Cseq"); 25997 cmd = REQ_OFFSET_TO_STR(req, header[0]); 25998 /* Save the via_pos so we can check later that responses only have 1 Via header */ 25999 via = __get_header(req, "Via", &via_pos); 26000 /* This must exist already because we've called find_call by now */ 26001 callid = sip_get_header(req, "Call-ID"); 26002 26003 /* Must have Cseq */ 26004 if (ast_strlen_zero(cmd) || ast_strlen_zero(cseq) || ast_strlen_zero(via)) { 26005 ast_log(LOG_ERROR, "Dropping this SIP message with Call-ID '%s', it's incomplete.\n", callid); 26006 error = 1; 26007 } 26008 if (!error && sscanf(cseq, "%30u%n", &seqno, &len) != 1) { 26009 ast_log(LOG_ERROR, "No seqno in '%s'. Dropping incomplete message.\n", cmd); 26010 error = 1; 26011 } 26012 if (error) { 26013 if (!p->initreq.headers) { /* New call */ 26014 pvt_set_needdestroy(p, "no headers"); 26015 } 26016 return -1; 26017 } 26018 /* Get the command XXX */ 26019 26020 cmd = REQ_OFFSET_TO_STR(req, rlPart1); 26021 e = ast_skip_blanks(REQ_OFFSET_TO_STR(req, rlPart2)); 26022 26023 /* Save useragent of the client */ 26024 useragent = sip_get_header(req, "User-Agent"); 26025 if (!ast_strlen_zero(useragent)) 26026 ast_string_field_set(p, useragent, useragent); 26027 26028 /* Find out SIP method for incoming request */ 26029 if (req->method == SIP_RESPONSE) { /* Response to our request */ 26030 /* ignore means "don't do anything with it" but still have to 26031 * respond appropriately. 26032 * But in this case this is a response already, so we really 26033 * have nothing to do with this message, and even setting the 26034 * ignore flag is pointless. 26035 */ 26036 if (ast_strlen_zero(e)) { 26037 return 0; 26038 } 26039 if (sscanf(e, "%30d %n", &respid, &len) != 1) { 26040 ast_log(LOG_WARNING, "Invalid response: '%s'\n", e); 26041 return 0; 26042 } 26043 if (respid <= 0) { 26044 ast_log(LOG_WARNING, "Invalid SIP response code: '%d'\n", respid); 26045 return 0; 26046 } 26047 /* RFC 3261 - 8.1.3.3 If more than one Via header field value is present in a reponse 26048 * the UAC SHOULD discard the message. This is not perfect, as it will not catch multiple 26049 * headers joined with a comma. Fixing that would pretty much involve writing a new parser */ 26050 if (!ast_strlen_zero(__get_header(req, "via", &via_pos))) { 26051 ast_log(LOG_WARNING, "Misrouted SIP response '%s' with Call-ID '%s', too many vias\n", e, callid); 26052 return 0; 26053 } 26054 if (p->ocseq && (p->ocseq < seqno)) { 26055 ast_debug(1, "Ignoring out of order response %u (expecting %u)\n", seqno, p->ocseq); 26056 return -1; 26057 } else { 26058 char causevar[256], causeval[256]; 26059 26060 if ((respid == 200) || ((respid >= 300) && (respid <= 399))) { 26061 extract_uri(p, req); 26062 } 26063 26064 handle_response(p, respid, e + len, req, seqno); 26065 26066 if (global_store_sip_cause && p->owner) { 26067 struct ast_channel *owner = p->owner; 26068 26069 snprintf(causevar, sizeof(causevar), "MASTER_CHANNEL(HASH(SIP_CAUSE,%s))", ast_channel_name(owner)); 26070 snprintf(causeval, sizeof(causeval), "SIP %s", REQ_OFFSET_TO_STR(req, rlPart2)); 26071 26072 ast_channel_ref(owner); 26073 sip_pvt_unlock(p); 26074 ast_channel_unlock(owner); 26075 *nounlock = 1; 26076 pbx_builtin_setvar_helper(owner, causevar, causeval); 26077 ast_channel_unref(owner); 26078 sip_pvt_lock(p); 26079 } 26080 } 26081 return 0; 26082 } 26083 26084 /* New SIP request coming in 26085 (could be new request in existing SIP dialog as well...) 26086 */ 26087 p->method = req->method; /* Find out which SIP method they are using */ 26088 ast_debug(4, "**** Received %s (%d) - Command in SIP %s\n", sip_methods[p->method].text, sip_methods[p->method].id, cmd); 26089 26090 if (p->icseq && (p->icseq > seqno) ) { 26091 if (p->pendinginvite && seqno == p->pendinginvite && (req->method == SIP_ACK || req->method == SIP_CANCEL)) { 26092 ast_debug(2, "Got CANCEL or ACK on INVITE with transactions in between.\n"); 26093 } else { 26094 ast_debug(1, "Ignoring too old SIP packet packet %u (expecting >= %u)\n", seqno, p->icseq); 26095 if (req->method == SIP_INVITE) { 26096 unsigned int ran = (ast_random() % 10) + 1; 26097 char seconds[4]; 26098 snprintf(seconds, sizeof(seconds), "%u", ran); 26099 transmit_response_with_retry_after(p, "500 Server error", req, seconds); /* respond according to RFC 3261 14.2 with Retry-After betwewn 0 and 10 */ 26100 } else if (req->method != SIP_ACK) { 26101 transmit_response(p, "500 Server error", req); /* We must respond according to RFC 3261 sec 12.2 */ 26102 } 26103 return -1; 26104 } 26105 } else if (p->icseq && 26106 p->icseq == seqno && 26107 req->method != SIP_ACK && 26108 (p->method != SIP_CANCEL || p->alreadygone)) { 26109 /* ignore means "don't do anything with it" but still have to 26110 respond appropriately. We do this if we receive a repeat of 26111 the last sequence number */ 26112 req->ignore = 1; 26113 ast_debug(3, "Ignoring SIP message because of retransmit (%s Seqno %u, ours %u)\n", sip_methods[p->method].text, p->icseq, seqno); 26114 } 26115 26116 /* RFC 3261 section 9. "CANCEL has no effect on a request to which a UAS has 26117 * already given a final response." */ 26118 if (!p->pendinginvite && (req->method == SIP_CANCEL)) { 26119 transmit_response(p, "481 Call/Transaction Does Not Exist", req); 26120 return res; 26121 } 26122 26123 if (seqno >= p->icseq) 26124 /* Next should follow monotonically (but not necessarily 26125 incrementally -- thanks again to the genius authors of SIP -- 26126 increasing */ 26127 p->icseq = seqno; 26128 26129 /* Find their tag if we haven't got it */ 26130 if (ast_strlen_zero(p->theirtag)) { 26131 char tag[128]; 26132 26133 gettag(req, "From", tag, sizeof(tag)); 26134 ast_string_field_set(p, theirtag, tag); 26135 } 26136 snprintf(p->lastmsg, sizeof(p->lastmsg), "Rx: %s", cmd); 26137 26138 if (sip_cfg.pedanticsipchecking) { 26139 /* If this is a request packet without a from tag, it's not 26140 correct according to RFC 3261 */ 26141 /* Check if this a new request in a new dialog with a totag already attached to it, 26142 RFC 3261 - section 12.2 - and we don't want to mess with recovery */ 26143 if (!p->initreq.headers && req->has_to_tag) { 26144 /* If this is a first request and it got a to-tag, it is not for us */ 26145 if (!req->ignore && req->method == SIP_INVITE) { 26146 transmit_response_reliable(p, "481 Call/Transaction Does Not Exist", req); 26147 /* Will cease to exist after ACK */ 26148 } else if (req->method != SIP_ACK) { 26149 transmit_response(p, "481 Call/Transaction Does Not Exist", req); 26150 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 26151 } else { 26152 ast_debug(1, "Got ACK for unknown dialog... strange.\n"); 26153 } 26154 return res; 26155 } 26156 } 26157 26158 if (!e && (p->method == SIP_INVITE || p->method == SIP_SUBSCRIBE || p->method == SIP_REGISTER || p->method == SIP_NOTIFY || p->method == SIP_PUBLISH)) { 26159 transmit_response(p, "400 Bad request", req); 26160 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 26161 return -1; 26162 } 26163 26164 /* Handle various incoming SIP methods in requests */ 26165 switch (p->method) { 26166 case SIP_OPTIONS: 26167 res = handle_request_options(p, req, addr, e); 26168 break; 26169 case SIP_INVITE: 26170 res = handle_request_invite(p, req, debug, seqno, addr, recount, e, nounlock); 26171 26172 if (res < 9) { 26173 sip_report_security_event(p, req, res); 26174 } 26175 26176 switch (res) { 26177 case INV_REQ_SUCCESS: 26178 res = 1; 26179 break; 26180 case INV_REQ_FAILED: 26181 res = 0; 26182 break; 26183 case INV_REQ_ERROR: 26184 res = -1; 26185 break; 26186 default: 26187 res = 0; 26188 break; 26189 } 26190 26191 break; 26192 case SIP_REFER: 26193 res = handle_request_refer(p, req, debug, seqno, nounlock); 26194 break; 26195 case SIP_CANCEL: 26196 res = handle_request_cancel(p, req); 26197 break; 26198 case SIP_BYE: 26199 res = handle_request_bye(p, req); 26200 break; 26201 case SIP_MESSAGE: 26202 res = handle_request_message(p, req, addr, e); 26203 break; 26204 case SIP_PUBLISH: 26205 res = handle_request_publish(p, req, addr, seqno, e); 26206 break; 26207 case SIP_SUBSCRIBE: 26208 res = handle_request_subscribe(p, req, addr, seqno, e); 26209 break; 26210 case SIP_REGISTER: 26211 res = handle_request_register(p, req, addr, e); 26212 sip_report_security_event(p, req, res); 26213 break; 26214 case SIP_INFO: 26215 if (req->debug) 26216 ast_verbose("Receiving INFO!\n"); 26217 if (!req->ignore) 26218 handle_request_info(p, req); 26219 else /* if ignoring, transmit response */ 26220 transmit_response(p, "200 OK", req); 26221 break; 26222 case SIP_NOTIFY: 26223 res = handle_request_notify(p, req, addr, seqno, e); 26224 break; 26225 case SIP_UPDATE: 26226 res = handle_request_update(p, req); 26227 break; 26228 case SIP_ACK: 26229 /* Make sure we don't ignore this */ 26230 if (seqno == p->pendinginvite) { 26231 p->invitestate = INV_TERMINATED; 26232 p->pendinginvite = 0; 26233 acked = __sip_ack(p, seqno, 1 /* response */, 0); 26234 if (find_sdp(req)) { 26235 if (process_sdp(p, req, SDP_T38_NONE)) 26236 return -1; 26237 } 26238 check_pendings(p); 26239 } else if (p->glareinvite == seqno) { 26240 /* handle ack for the 491 pending sent for glareinvite */ 26241 p->glareinvite = 0; 26242 acked = __sip_ack(p, seqno, 1, 0); 26243 } 26244 if (!acked) { 26245 /* Got an ACK that did not match anything. Ignore 26246 * silently and restore previous method */ 26247 p->method = oldmethod; 26248 } 26249 if (!p->lastinvite && ast_strlen_zero(p->randdata)) { 26250 pvt_set_needdestroy(p, "unmatched ACK"); 26251 } 26252 break; 26253 default: 26254 transmit_response_with_allow(p, "501 Method Not Implemented", req, 0); 26255 ast_log(LOG_NOTICE, "Unknown SIP command '%s' from '%s'\n", 26256 cmd, ast_sockaddr_stringify(&p->sa)); 26257 /* If this is some new method, and we don't have a call, destroy it now */ 26258 if (!p->initreq.headers) { 26259 pvt_set_needdestroy(p, "unimplemented method"); 26260 } 26261 break; 26262 } 26263 return res; 26264 }
| static int handle_invite_replaces | ( | struct sip_pvt * | p, | |
| struct sip_request * | req, | |||
| int | debug, | |||
| uint32_t | seqno, | |||
| struct ast_sockaddr * | addr, | |||
| int * | nounlock | |||
| ) | [static] |
Handle the transfer part of INVITE with a replaces: header, meaning a target pickup or an attended transfer. Used only once. XXX 'ignore' is unused.
Definition at line 22802 of file chan_sip.c.
References ast_channel::_state, append_history, ast_bridged_channel(), AST_CAUSE_SWITCH_CONGESTION, ast_channel_lock, ast_channel_masquerade(), ast_channel_name(), ast_channel_ref, ast_channel_unlock, ast_channel_unref, ast_debug, ast_do_masquerade(), ast_hangup(), ast_log(), ast_quiet_chan(), ast_set_flag, ast_setstate(), AST_STATE_DOWN, AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, FALSE, ast_channel::hangupcause, LOG_ERROR, LOG_NOTICE, LOG_WARNING, sip_pvt_lock, sip_pvt_unlock, sip_scheddestroy(), ast_channel::tech_pvt, transmit_response(), transmit_response_reliable(), and transmit_response_with_sdp().
Referenced by handle_request_invite().
22803 { 22804 int earlyreplace = 0; 22805 int oneleggedreplace = 0; /* Call with no bridge, propably IVR or voice message */ 22806 struct ast_channel *c = p->owner; /* Our incoming call */ 22807 struct ast_channel *replacecall = p->refer->refer_call->owner; /* The channel we're about to take over */ 22808 struct ast_channel *targetcall; /* The bridge to the take-over target */ 22809 22810 /* Check if we're in ring state */ 22811 if (replacecall->_state == AST_STATE_RING) 22812 earlyreplace = 1; 22813 22814 /* Check if we have a bridge */ 22815 if (!(targetcall = ast_bridged_channel(replacecall))) { 22816 /* We have no bridge */ 22817 if (!earlyreplace) { 22818 ast_debug(2, " Attended transfer attempted to replace call with no bridge (maybe ringing). Channel %s!\n", ast_channel_name(replacecall)); 22819 oneleggedreplace = 1; 22820 } 22821 } 22822 if (targetcall && targetcall->_state == AST_STATE_RINGING) 22823 ast_debug(4, "SIP transfer: Target channel is in ringing state\n"); 22824 22825 if (targetcall) 22826 ast_debug(4, "SIP transfer: Invite Replace incoming channel should bridge to channel %s while hanging up channel %s\n", ast_channel_name(targetcall), ast_channel_name(replacecall)); 22827 else 22828 ast_debug(4, "SIP transfer: Invite Replace incoming channel should replace and hang up channel %s (one call leg)\n", ast_channel_name(replacecall)); 22829 22830 if (req->ignore) { 22831 ast_log(LOG_NOTICE, "Ignoring this INVITE with replaces in a stupid way.\n"); 22832 /* We should answer something here. If we are here, the 22833 call we are replacing exists, so an accepted 22834 can't harm */ 22835 transmit_response_with_sdp(p, "200 OK", req, XMIT_RELIABLE, FALSE, FALSE); 22836 /* Do something more clever here */ 22837 if (c) { 22838 *nounlock = 1; 22839 ast_channel_unlock(c); 22840 } 22841 ast_channel_unlock(replacecall); 22842 sip_pvt_unlock(p->refer->refer_call); 22843 return 1; 22844 } 22845 if (!c) { 22846 /* What to do if no channel ??? */ 22847 ast_log(LOG_ERROR, "Unable to create new channel. Invite/replace failed.\n"); 22848 transmit_response_reliable(p, "503 Service Unavailable", req); 22849 append_history(p, "Xfer", "INVITE/Replace Failed. No new channel."); 22850 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 22851 ast_channel_unlock(replacecall); 22852 sip_pvt_unlock(p->refer->refer_call); 22853 return 1; 22854 } 22855 append_history(p, "Xfer", "INVITE/Replace received"); 22856 /* We have three channels to play with 22857 channel c: New incoming call 22858 targetcall: Call from PBX to target 22859 p->refer->refer_call: SIP pvt dialog from transferer to pbx. 22860 replacecall: The owner of the previous 22861 We need to masq C into refer_call to connect to 22862 targetcall; 22863 If we are talking to internal audio stream, target call is null. 22864 */ 22865 22866 /* Fake call progress */ 22867 transmit_response(p, "100 Trying", req); 22868 ast_setstate(c, AST_STATE_RING); 22869 22870 /* Masquerade the new call into the referred call to connect to target call 22871 Targetcall is not touched by the masq */ 22872 22873 /* Answer the incoming call and set channel to UP state */ 22874 transmit_response_with_sdp(p, "200 OK", req, XMIT_RELIABLE, FALSE, FALSE); 22875 22876 ast_setstate(c, AST_STATE_UP); 22877 22878 /* Stop music on hold and other generators */ 22879 ast_quiet_chan(replacecall); 22880 ast_quiet_chan(targetcall); 22881 ast_debug(4, "Invite/Replaces: preparing to masquerade %s into %s\n", ast_channel_name(c), ast_channel_name(replacecall)); 22882 22883 /* Make sure that the masq does not free our PVT for the old call */ 22884 if (! earlyreplace && ! oneleggedreplace ) 22885 ast_set_flag(&p->refer->refer_call->flags[0], SIP_DEFER_BYE_ON_TRANSFER); /* Delay hangup */ 22886 22887 /* Prepare the masquerade - if this does not happen, we will be gone */ 22888 if(ast_channel_masquerade(replacecall, c)) 22889 ast_log(LOG_ERROR, "Failed to masquerade C into Replacecall\n"); 22890 else 22891 ast_debug(4, "Invite/Replaces: Going to masquerade %s into %s\n", ast_channel_name(c), ast_channel_name(replacecall)); 22892 22893 /* C should now be in place of replacecall. all channel locks and pvt locks should be removed 22894 * before issuing the masq. Since we are unlocking both the pvt (p) and its owner channel (c) 22895 * it is possible for channel c to be destroyed on us. To prevent this, we must give c a reference 22896 * before any unlocking takes place and remove it only once we are completely done with it */ 22897 ast_channel_ref(c); 22898 ast_channel_unlock(replacecall); 22899 ast_channel_unlock(c); 22900 sip_pvt_unlock(p->refer->refer_call); 22901 sip_pvt_unlock(p); 22902 if (ast_do_masquerade(replacecall)) { 22903 ast_log(LOG_WARNING, "Failed to perform masquerade with INVITE replaces\n"); 22904 } 22905 ast_channel_lock(c); 22906 if (earlyreplace || oneleggedreplace ) { 22907 c->hangupcause = AST_CAUSE_SWITCH_CONGESTION; 22908 } 22909 ast_setstate(c, AST_STATE_DOWN); 22910 ast_channel_unlock(c); 22911 22912 /* The call should be down with no ast_channel, so hang it up */ 22913 c->tech_pvt = dialog_unref(c->tech_pvt, "unref dialog c->tech_pvt"); 22914 22915 /* c and c's tech pvt must be unlocked at this point for ast_hangup */ 22916 ast_hangup(c); 22917 /* this indicates to handle_request_do that the owner channel has already been unlocked */ 22918 *nounlock = 1; 22919 /* lock PVT structure again after hangup */ 22920 sip_pvt_lock(p); 22921 ast_channel_unref(c); 22922 return 0; 22923 }
| static int handle_request_bye | ( | struct sip_pvt * | p, | |
| struct sip_request * | req | |||
| ) | [static] |
Handle incoming BYE request.
Definition at line 24611 of file chan_sip.c.
References __sip_pretend_ack(), append_history, ARRAY_LEN, ast_async_goto(), ast_bridged_channel(), AST_CAUSE_PROTOCOL_ERROR, ast_channel_lock, ast_channel_name(), ast_channel_trylock, ast_channel_unlock, ast_clear_flag, AST_CONTROL_UNHOLD, ast_debug, ast_log(), AST_MAX_USER_FIELD, ast_queue_control(), ast_queue_hangup(), ast_queue_hangup_with_cause(), ast_rtp_instance_get_quality(), ast_rtp_instance_set_stats_vars(), AST_RTP_INSTANCE_STAT_FIELD_QUALITY, AST_RTP_INSTANCE_STAT_FIELD_QUALITY_JITTER, AST_RTP_INSTANCE_STAT_FIELD_QUALITY_LOSS, AST_RTP_INSTANCE_STAT_FIELD_QUALITY_RTT, ast_set_hangupsource(), ast_sockaddr_stringify(), ast_string_field_set, ast_strlen_zero(), ast_test_flag, check_via(), ast_channel::context, context, copy_request(), get_also_info(), LOG_NOTICE, LOG_WARNING, parse_sip_options(), pbx_builtin_setvar_helper(), quality, sip_alreadygone(), sip_cfg, sip_get_header(), sip_methods, sip_pvt_lock, sip_pvt_unlock, sip_scheddestroy_final(), stop_media_flows(), stop_session_timer(), ast_channel::tech, ast_channel::tech_pvt, cfsip_methods::text, transmit_response(), transmit_response_reliable(), and transmit_response_with_unsupported().
Referenced by handle_incoming().
24612 { 24613 struct ast_channel *c=NULL; 24614 int res; 24615 struct ast_channel *bridged_to; 24616 const char *required; 24617 24618 /* If we have an INCOMING invite that we haven't answered, terminate that transaction */ 24619 if (p->pendinginvite && !ast_test_flag(&p->flags[0], SIP_OUTGOING) && !req->ignore) { 24620 transmit_response_reliable(p, "487 Request Terminated", &p->initreq); 24621 } 24622 24623 __sip_pretend_ack(p); 24624 24625 p->invitestate = INV_TERMINATED; 24626 24627 copy_request(&p->initreq, req); 24628 if (sipdebug) 24629 ast_debug(1, "Initializing initreq for method %s - callid %s\n", sip_methods[req->method].text, p->callid); 24630 check_via(p, req); 24631 sip_alreadygone(p); 24632 24633 /* Get RTCP quality before end of call */ 24634 if (p->do_history || p->owner) { 24635 char quality_buf[AST_MAX_USER_FIELD], *quality; 24636 struct ast_channel *bridge = p->owner ? ast_bridged_channel(p->owner) : NULL; 24637 24638 /* We need to get the lock on bridge because ast_rtp_instance_set_stats_vars will attempt 24639 * to lock the bridge. This may get hairy... 24640 */ 24641 while (bridge && ast_channel_trylock(bridge)) { 24642 ast_channel_unlock(p->owner); 24643 do { 24644 /* Can't use DEADLOCK_AVOIDANCE since p is an ao2 object */ 24645 sip_pvt_unlock(p); 24646 usleep(1); 24647 sip_pvt_lock(p); 24648 } while (p->owner && ast_channel_trylock(p->owner)); 24649 bridge = p->owner ? ast_bridged_channel(p->owner) : NULL; 24650 } 24651 24652 24653 if (p->rtp && (quality = ast_rtp_instance_get_quality(p->rtp, AST_RTP_INSTANCE_STAT_FIELD_QUALITY, quality_buf, sizeof(quality_buf)))) { 24654 if (p->do_history) { 24655 append_history(p, "RTCPaudio", "Quality:%s", quality); 24656 24657 if ((quality = ast_rtp_instance_get_quality(p->rtp, AST_RTP_INSTANCE_STAT_FIELD_QUALITY_JITTER, quality_buf, sizeof(quality_buf)))) { 24658 append_history(p, "RTCPaudioJitter", "Quality:%s", quality); 24659 } 24660 if ((quality = ast_rtp_instance_get_quality(p->rtp, AST_RTP_INSTANCE_STAT_FIELD_QUALITY_LOSS, quality_buf, sizeof(quality_buf)))) { 24661 append_history(p, "RTCPaudioLoss", "Quality:%s", quality); 24662 } 24663 if ((quality = ast_rtp_instance_get_quality(p->rtp, AST_RTP_INSTANCE_STAT_FIELD_QUALITY_RTT, quality_buf, sizeof(quality_buf)))) { 24664 append_history(p, "RTCPaudioRTT", "Quality:%s", quality); 24665 } 24666 } 24667 24668 if (p->owner) { 24669 ast_rtp_instance_set_stats_vars(p->owner, p->rtp); 24670 } 24671 24672 } 24673 24674 if (bridge) { 24675 struct sip_pvt *q = bridge->tech_pvt; 24676 24677 if (IS_SIP_TECH(bridge->tech) && q && q->rtp) { 24678 ast_rtp_instance_set_stats_vars(bridge, q->rtp); 24679 } 24680 ast_channel_unlock(bridge); 24681 } 24682 24683 if (p->vrtp && (quality = ast_rtp_instance_get_quality(p->vrtp, AST_RTP_INSTANCE_STAT_FIELD_QUALITY, quality_buf, sizeof(quality_buf)))) { 24684 if (p->do_history) { 24685 append_history(p, "RTCPvideo", "Quality:%s", quality); 24686 } 24687 if (p->owner) { 24688 pbx_builtin_setvar_helper(p->owner, "RTPVIDEOQOS", quality); 24689 } 24690 } 24691 if (p->trtp && (quality = ast_rtp_instance_get_quality(p->trtp, AST_RTP_INSTANCE_STAT_FIELD_QUALITY, quality_buf, sizeof(quality_buf)))) { 24692 if (p->do_history) { 24693 append_history(p, "RTCPtext", "Quality:%s", quality); 24694 } 24695 if (p->owner) { 24696 pbx_builtin_setvar_helper(p->owner, "RTPTEXTQOS", quality); 24697 } 24698 } 24699 } 24700 24701 stop_media_flows(p); /* Immediately stop RTP, VRTP and UDPTL as applicable */ 24702 stop_session_timer(p); /* Stop Session-Timer */ 24703 24704 if (!ast_strlen_zero(sip_get_header(req, "Also"))) { 24705 ast_log(LOG_NOTICE, "Client '%s' using deprecated BYE/Also transfer method. Ask vendor to support REFER instead\n", 24706 ast_sockaddr_stringify(&p->recv)); 24707 if (ast_strlen_zero(p->context)) 24708 ast_string_field_set(p, context, sip_cfg.default_context); 24709 res = get_also_info(p, req); 24710 if (!res) { 24711 c = p->owner; 24712 if (c) { 24713 bridged_to = ast_bridged_channel(c); 24714 if (bridged_to) { 24715 /* Don't actually hangup here... */ 24716 ast_queue_control(c, AST_CONTROL_UNHOLD); 24717 ast_channel_unlock(c); /* async_goto can do a masquerade, no locks can be held during a masq */ 24718 ast_async_goto(bridged_to, p->context, p->refer->refer_to, 1); 24719 ast_channel_lock(c); 24720 } else 24721 ast_queue_hangup(p->owner); 24722 } 24723 } else { 24724 ast_log(LOG_WARNING, "Invalid transfer information from '%s'\n", ast_sockaddr_stringify(&p->recv)); 24725 if (p->owner) 24726 ast_queue_hangup_with_cause(p->owner, AST_CAUSE_PROTOCOL_ERROR); 24727 } 24728 } else if (p->owner) { 24729 ast_set_hangupsource(p->owner, ast_channel_name(p->owner), 0); 24730 ast_queue_hangup(p->owner); 24731 sip_scheddestroy_final(p, DEFAULT_TRANS_TIMEOUT); 24732 ast_debug(3, "Received bye, issuing owner hangup\n"); 24733 } else { 24734 sip_scheddestroy_final(p, DEFAULT_TRANS_TIMEOUT); 24735 ast_debug(3, "Received bye, no owner, selfdestruct soon.\n"); 24736 } 24737 ast_clear_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED); 24738 24739 /* Find out what they require */ 24740 required = sip_get_header(req, "Require"); 24741 if (!ast_strlen_zero(required)) { 24742 char unsupported[256] = { 0, }; 24743 parse_sip_options(required, unsupported, ARRAY_LEN(unsupported)); 24744 /* If there are any options required that we do not support, 24745 * then send a 420 with only those unsupported options listed */ 24746 if (!ast_strlen_zero(unsupported)) { 24747 transmit_response_with_unsupported(p, "420 Bad extension (unsupported)", req, unsupported); 24748 ast_log(LOG_WARNING, "Received SIP BYE with unsupported required extension: required:%s unsupported:%s\n", required, unsupported); 24749 } else { 24750 transmit_response(p, "200 OK", req); 24751 } 24752 } else { 24753 transmit_response(p, "200 OK", req); 24754 } 24755 24756 return 1; 24757 }
| static int handle_request_cancel | ( | struct sip_pvt * | p, | |
| struct sip_request * | req | |||
| ) | [static] |
Handle incoming CANCEL request.
Definition at line 24542 of file chan_sip.c.
References __sip_pretend_ack(), ast_channel_name(), ast_debug, ast_free, ast_queue_hangup(), AST_SCHED_DEL, ast_set_hangupsource(), AST_STATE_UP, ast_str_strlen(), ast_test_flag, check_via(), sip_alreadygone(), sip_scheddestroy(), stop_media_flows(), transmit_response(), transmit_response_reliable(), UNLINK, and update_call_counter().
Referenced by handle_incoming().
24543 { 24544 24545 check_via(p, req); 24546 sip_alreadygone(p); 24547 24548 if (p->owner && p->owner->_state == AST_STATE_UP) { 24549 /* This call is up, cancel is ignored, we need a bye */ 24550 transmit_response(p, "200 OK", req); 24551 ast_debug(1, "Got CANCEL on an answered call. Ignoring... \n"); 24552 return 0; 24553 } 24554 24555 /* At this point, we could have cancelled the invite at the same time 24556 as the other side sends a CANCEL. Our final reply with error code 24557 might not have been received by the other side before the CANCEL 24558 was sent, so let's just give up retransmissions and waiting for 24559 ACK on our error code. The call is hanging up any way. */ 24560 if (p->invitestate == INV_TERMINATED || p->invitestate == INV_COMPLETED) { 24561 __sip_pretend_ack(p); 24562 } 24563 if (p->invitestate != INV_TERMINATED) 24564 p->invitestate = INV_CANCELLED; 24565 24566 if (ast_test_flag(&p->flags[0], SIP_INC_COUNT) || ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD)) 24567 update_call_counter(p, DEC_CALL_LIMIT); 24568 24569 stop_media_flows(p); /* Immediately stop RTP, VRTP and UDPTL as applicable */ 24570 if (p->owner) { 24571 ast_set_hangupsource(p->owner, ast_channel_name(p->owner), 0); 24572 ast_queue_hangup(p->owner); 24573 } 24574 else 24575 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 24576 if (ast_str_strlen(p->initreq.data) > 0) { 24577 struct sip_pkt *pkt, *prev_pkt; 24578 /* If the CANCEL we are receiving is a retransmission, and we already have scheduled 24579 * a reliable 487, then we don't want to schedule another one on top of the previous 24580 * one. 24581 * 24582 * As odd as this may sound, we can't rely on the previously-transmitted "reliable" 24583 * response in this situation. What if we've sent all of our reliable responses 24584 * already and now all of a sudden, we get this second CANCEL? 24585 * 24586 * The only way to do this correctly is to cancel our previously-scheduled reliably- 24587 * transmitted response and send a new one in its place. 24588 */ 24589 for (pkt = p->packets, prev_pkt = NULL; pkt; prev_pkt = pkt, pkt = pkt->next) { 24590 if (pkt->seqno == p->lastinvite && pkt->response_code == 487) { 24591 AST_SCHED_DEL(sched, pkt->retransid); 24592 UNLINK(pkt, p->packets, prev_pkt); 24593 dialog_unref(pkt->owner, "unref packet->owner from dialog"); 24594 if (pkt->data) { 24595 ast_free(pkt->data); 24596 } 24597 ast_free(pkt); 24598 break; 24599 } 24600 } 24601 transmit_response_reliable(p, "487 Request Terminated", &p->initreq); 24602 transmit_response(p, "200 OK", req); 24603 return 1; 24604 } else { 24605 transmit_response(p, "481 Call Leg Does Not Exist", req); 24606 return 0; 24607 } 24608 }
| static int handle_request_do | ( | struct sip_request * | req, | |
| struct ast_sockaddr * | addr | |||
| ) | [static] |
Handle incoming SIP message - request or response.
This is used for all transports (udp, tcp and tcp/tls)
Definition at line 26316 of file chan_sip.c.
References ao2_t_ref, append_history, ast_channel_unlock, ast_channel_unref, ast_debug, ast_mutex_lock, ast_mutex_unlock, ast_sockaddr_copy(), ast_sockaddr_stringify(), ast_str_reset(), ast_str_strlen(), ast_update_use_count(), ast_verbose, copy_socket_data(), find_call(), find_sip_method(), handle_incoming(), lws2sws(), netlock, parse_request(), sip_cfg, sip_debug_test_addr(), sip_get_header(), sip_get_transport(), sip_pvt_lock_full(), and sip_pvt_unlock.
Referenced by _sip_tcp_helper_thread(), and sipsock_read().
26317 { 26318 struct sip_pvt *p; 26319 struct ast_channel *owner_chan_ref = NULL; 26320 int recount = 0; 26321 int nounlock = 0; 26322 26323 if (sip_debug_test_addr(addr)) /* Set the debug flag early on packet level */ 26324 req->debug = 1; 26325 if (sip_cfg.pedanticsipchecking) 26326 lws2sws(req->data); /* Fix multiline headers */ 26327 if (req->debug) { 26328 ast_verbose("\n<--- SIP read from %s:%s --->\n%s\n<------------->\n", 26329 sip_get_transport(req->socket.type), ast_sockaddr_stringify(addr), req->data->str); 26330 } 26331 26332 if (parse_request(req) == -1) { /* Bad packet, can't parse */ 26333 ast_str_reset(req->data); /* nulling this out is NOT a good idea here. */ 26334 return 1; 26335 } 26336 req->method = find_sip_method(REQ_OFFSET_TO_STR(req, rlPart1)); 26337 26338 if (req->debug) 26339 ast_verbose("--- (%d headers %d lines)%s ---\n", req->headers, req->lines, (req->headers + req->lines == 0) ? " Nat keepalive" : ""); 26340 26341 if (req->headers < 2) { /* Must have at least two headers */ 26342 ast_str_reset(req->data); /* nulling this out is NOT a good idea here. */ 26343 return 1; 26344 } 26345 ast_mutex_lock(&netlock); 26346 26347 /* Find the active SIP dialog or create a new one */ 26348 p = find_call(req, addr, req->method); /* returns p with a reference only. _NOT_ locked*/ 26349 if (p == NULL) { 26350 ast_debug(1, "Invalid SIP message - rejected , no callid, len %zu\n", ast_str_strlen(req->data)); 26351 ast_mutex_unlock(&netlock); 26352 return 1; 26353 } 26354 26355 /* Lock both the pvt and the owner if owner is present. This will 26356 * not fail. */ 26357 owner_chan_ref = sip_pvt_lock_full(p); 26358 26359 copy_socket_data(&p->socket, &req->socket); 26360 ast_sockaddr_copy(&p->recv, addr); 26361 26362 /* if we have an owner, then this request has been authenticated */ 26363 if (p->owner) { 26364 req->authenticated = 1; 26365 } 26366 26367 if (p->do_history) /* This is a request or response, note what it was for */ 26368 append_history(p, "Rx", "%s / %s / %s", req->data->str, sip_get_header(req, "CSeq"), REQ_OFFSET_TO_STR(req, rlPart2)); 26369 26370 if (handle_incoming(p, req, addr, &recount, &nounlock) == -1) { 26371 /* Request failed */ 26372 ast_debug(1, "SIP message could not be handled, bad request: %-70.70s\n", p->callid[0] ? p->callid : "<no callid>"); 26373 } 26374 26375 if (recount) { 26376 ast_update_use_count(); 26377 } 26378 26379 if (p->owner && !nounlock) { 26380 ast_channel_unlock(p->owner); 26381 } 26382 if (owner_chan_ref) { 26383 ast_channel_unref(owner_chan_ref); 26384 } 26385 sip_pvt_unlock(p); 26386 ao2_t_ref(p, -1, "throw away dialog ptr from find_call at end of routine"); /* p is gone after the return */ 26387 ast_mutex_unlock(&netlock); 26388 26389 return 1; 26390 }
| static void handle_request_info | ( | struct sip_pvt * | p, | |
| struct sip_request * | req | |||
| ) | [static] |
Receive SIP INFO Message.
Definition at line 19483 of file chan_sip.c.
References ast_bridged_channel(), ast_cdr_setuserfield(), AST_CONTROL_FLASH, AST_CONTROL_VIDUPDATE, ast_copy_string(), ast_debug, ast_find_call_feature(), AST_FRAME_CONTROL, AST_FRAME_DTMF, ast_log(), AST_LOG_WARNING, ast_queue_control(), ast_queue_frame(), ast_rdlock_call_features(), ast_strlen_zero(), ast_test_flag, ast_unlock_call_features(), ast_verbose, ast_channel::cdr, ast_call_feature::exten, f, get_body(), get_msg_text(), ast_frame_subclass::integer, ast_frame::len, LOG_ERROR, LOG_WARNING, sip_get_header(), sip_scheddestroy(), ast_frame::subclass, and transmit_response().
Referenced by handle_incoming().
19484 { 19485 char buf[1024] = ""; 19486 unsigned int event; 19487 const char *c = sip_get_header(req, "Content-Type"); 19488 19489 /* Need to check the media/type */ 19490 if (!strcasecmp(c, "application/dtmf-relay") || 19491 !strcasecmp(c, "application/vnd.nortelnetworks.digits") || 19492 !strcasecmp(c, "application/dtmf")) { 19493 unsigned int duration = 0; 19494 19495 if (!p->owner) { /* not a PBX call */ 19496 transmit_response(p, "481 Call leg/transaction does not exist", req); 19497 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 19498 return; 19499 } 19500 19501 /* If dtmf-relay or vnd.nortelnetworks.digits, parse the signal and duration; 19502 * otherwise use the body as the signal */ 19503 if (strcasecmp(c, "application/dtmf")) { 19504 const char *msg_body; 19505 19506 if ( ast_strlen_zero(msg_body = get_body(req, "Signal", '=')) 19507 && ast_strlen_zero(msg_body = get_body(req, "d", '='))) { 19508 ast_log(LOG_WARNING, "Unable to retrieve DTMF signal for INFO message on " 19509 "call %s\n", p->callid); 19510 transmit_response(p, "200 OK", req); 19511 return; 19512 } 19513 ast_copy_string(buf, msg_body, sizeof(buf)); 19514 19515 if (!ast_strlen_zero((msg_body = get_body(req, "Duration", '=')))) { 19516 sscanf(msg_body, "%30u", &duration); 19517 } 19518 } else { 19519 /* Type is application/dtmf, simply use what's in the message body */ 19520 get_msg_text(buf, sizeof(buf), req); 19521 } 19522 19523 /* An empty message body requires us to send a 200 OK */ 19524 if (ast_strlen_zero(buf)) { 19525 transmit_response(p, "200 OK", req); 19526 return; 19527 } 19528 19529 if (!duration) { 19530 duration = 100; /* 100 ms */ 19531 } 19532 19533 if (buf[0] == '*') { 19534 event = 10; 19535 } else if (buf[0] == '#') { 19536 event = 11; 19537 } else if (buf[0] == '!') { 19538 event = 16; 19539 } else if ('A' <= buf[0] && buf[0] <= 'D') { 19540 event = 12 + buf[0] - 'A'; 19541 } else if ('a' <= buf[0] && buf[0] <= 'd') { 19542 event = 12 + buf[0] - 'a'; 19543 } else if ((sscanf(buf, "%30u", &event) != 1) || event > 16) { 19544 ast_log(AST_LOG_WARNING, "Unable to convert DTMF event signal code to a valid " 19545 "value for INFO message on call %s\n", p->callid); 19546 transmit_response(p, "200 OK", req); 19547 return; 19548 } 19549 19550 if (event == 16) { 19551 /* send a FLASH event */ 19552 struct ast_frame f = { AST_FRAME_CONTROL, { AST_CONTROL_FLASH, } }; 19553 ast_queue_frame(p->owner, &f); 19554 if (sipdebug) { 19555 ast_verbose("* DTMF-relay event received: FLASH\n"); 19556 } 19557 } else { 19558 /* send a DTMF event */ 19559 struct ast_frame f = { AST_FRAME_DTMF, }; 19560 if (event < 10) { 19561 f.subclass.integer = '0' + event; 19562 } else if (event == 10) { 19563 f.subclass.integer = '*'; 19564 } else if (event == 11) { 19565 f.subclass.integer = '#'; 19566 } else { 19567 f.subclass.integer = 'A' + (event - 12); 19568 } 19569 f.len = duration; 19570 ast_queue_frame(p->owner, &f); 19571 if (sipdebug) { 19572 ast_verbose("* DTMF-relay event received: %c\n", (int) f.subclass.integer); 19573 } 19574 } 19575 transmit_response(p, "200 OK", req); 19576 return; 19577 } else if (!strcasecmp(c, "application/media_control+xml")) { 19578 /* Eh, we'll just assume it's a fast picture update for now */ 19579 if (p->owner) { 19580 ast_queue_control(p->owner, AST_CONTROL_VIDUPDATE); 19581 } 19582 transmit_response(p, "200 OK", req); 19583 return; 19584 } else if (!ast_strlen_zero(c = sip_get_header(req, "X-ClientCode"))) { 19585 /* Client code (from SNOM phone) */ 19586 if (ast_test_flag(&p->flags[0], SIP_USECLIENTCODE)) { 19587 if (p->owner && p->owner->cdr) { 19588 ast_cdr_setuserfield(p->owner, c); 19589 } 19590 if (p->owner && ast_bridged_channel(p->owner) && ast_bridged_channel(p->owner)->cdr) { 19591 ast_cdr_setuserfield(ast_bridged_channel(p->owner), c); 19592 } 19593 transmit_response(p, "200 OK", req); 19594 } else { 19595 transmit_response(p, "403 Forbidden", req); 19596 } 19597 return; 19598 } else if (!ast_strlen_zero(c = sip_get_header(req, "Record"))) { 19599 /* INFO messages generated by some phones to start/stop recording 19600 * on phone calls. 19601 */ 19602 19603 struct ast_call_feature *feat = NULL; 19604 int j; 19605 struct ast_frame f = { AST_FRAME_DTMF, }; 19606 int suppress_warning = 0; /* Supress warning if the feature is blank */ 19607 19608 if (!p->owner) { /* not a PBX call */ 19609 transmit_response(p, "481 Call leg/transaction does not exist", req); 19610 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 19611 return; 19612 } 19613 19614 /* first, get the feature string, if it exists */ 19615 ast_rdlock_call_features(); 19616 if (p->relatedpeer) { 19617 if (!strcasecmp(c, "on")) { 19618 if (ast_strlen_zero(p->relatedpeer->record_on_feature)) { 19619 suppress_warning = 1; 19620 } else { 19621 feat = ast_find_call_feature(p->relatedpeer->record_on_feature); 19622 } 19623 } else if (!strcasecmp(c, "off")) { 19624 if (ast_strlen_zero(p->relatedpeer->record_on_feature)) { 19625 suppress_warning = 1; 19626 } else { 19627 feat = ast_find_call_feature(p->relatedpeer->record_off_feature); 19628 } 19629 } else { 19630 ast_log(LOG_ERROR, "Received INFO requesting to record with invalid value: %s\n", c); 19631 } 19632 } 19633 if (!feat || ast_strlen_zero(feat->exten)) { 19634 if (!suppress_warning) { 19635 ast_log(LOG_WARNING, "Recording requested, but no One Touch Monitor registered. (See features.conf)\n"); 19636 } 19637 /* 403 means that we don't support this feature, so don't request it again */ 19638 transmit_response(p, "403 Forbidden", req); 19639 ast_unlock_call_features(); 19640 return; 19641 } 19642 /* Send the feature code to the PBX as DTMF, just like the handset had sent it */ 19643 f.len = 100; 19644 for (j=0; j < strlen(feat->exten); j++) { 19645 f.subclass.integer = feat->exten[j]; 19646 ast_queue_frame(p->owner, &f); 19647 if (sipdebug) { 19648 ast_verbose("* DTMF-relay event faked: %c\n", f.subclass.integer); 19649 } 19650 } 19651 ast_unlock_call_features(); 19652 19653 ast_debug(1, "Got a Request to Record the channel, state %s\n", c); 19654 transmit_response(p, "200 OK", req); 19655 return; 19656 } else if (ast_strlen_zero(c = sip_get_header(req, "Content-Length")) || !strcasecmp(c, "0")) { 19657 /* This is probably just a packet making sure the signalling is still up, just send back a 200 OK */ 19658 transmit_response(p, "200 OK", req); 19659 return; 19660 } 19661 19662 /* Other type of INFO message, not really understood by Asterisk */ 19663 /* if (get_msg_text(buf, sizeof(buf), req)) { */ 19664 19665 ast_log(LOG_WARNING, "Unable to parse INFO message from %s. Content %s\n", p->callid, buf); 19666 transmit_response(p, "415 Unsupported media type", req); 19667 return; 19668 }
| static int handle_request_invite | ( | struct sip_pvt * | p, | |
| struct sip_request * | req, | |||
| int | debug, | |||
| uint32_t | seqno, | |||
| struct ast_sockaddr * | addr, | |||
| int * | recount, | |||
| const char * | e, | |||
| int * | nounlock | |||
| ) | [static] |
Handle incoming INVITE request.
This is a spiral. What we need to do is to just change the outgoing INVITE so that it now routes to the new Request URI. Since we created the INVITE ourselves that should be all we need to do.
Definition at line 23018 of file chan_sip.c.
References __sip_ack(), ast_channel::_state, append_history, ARRAY_LEN, AST_CAUSE_FAILURE, ast_cc_agent_set_interfaces_chanvar(), ast_channel_name(), ast_channel_queue_connected_line_update(), ast_channel_set_redirecting(), ast_channel_unlock, ast_clear_flag, AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER, AST_CONTROL_BUSY, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, AST_CONTROL_UPDATE_RTP_PEER, ast_copy_string(), ast_debug, ast_format_cap_copy(), ast_format_cap_is_empty(), ast_hangup(), ast_log(), AST_MAX_CONTEXT, AST_MAX_EXTENSION, ast_null_frame, ast_party_connected_line_init(), ast_party_redirecting_free(), ast_party_redirecting_init(), AST_PBX_CALL_LIMIT, AST_PBX_FAILED, ast_pbx_start(), AST_PBX_SUCCESS, ast_pickup_ext(), ast_queue_control(), ast_queue_frame(), ast_rtp_instance_set_alt_remote_address(), ast_rtp_instance_set_prop(), AST_RTP_PROPERTY_DTMF, AST_RTP_PROPERTY_DTMF_COMPENSATE, ast_sched_add(), AST_SCHED_DEL_UNREF, ast_set_flag, ast_setstate(), ast_setup_cc_recall_datastore(), ast_skip_blanks(), ast_sockaddr_stringify(), AST_STATE_DOWN, AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_uri_decode(), ast_uri_sip_user, ast_verbose, build_contact(), build_route(), change_hold_state(), change_redirecting_information(), check_user_full(), check_via(), connected, context, copy_request(), do_magic_pickup(), ast_channel::exten, exten, extract_uri(), FALSE, find_sdp(), get_destination(), get_ip_and_port_from_sdp(), get_rpid(), get_sip_pvt_byid_locked(), handle_invite_replaces(), ast_channel::hangupcause, ast_party_connected_line::id, ast_set_party_connected_line::id, LOG_ERROR, LOG_NOTICE, LOG_WARNING, make_our_tag(), ast_party_id::name, ast_set_party_id::name, ast_party_id::number, ast_set_party_id::number, parse_minse(), parse_ok_contact(), parse_session_expires(), parse_sip_options(), ast_party_name::presentation, ast_party_number::presentation, process_sdp(), restart_session_timer(), S_OR, set_pvt_allowed_methods(), sip_alreadygone(), sip_cancel_destroy(), sip_cfg, sip_get_header(), sip_methods, sip_new(), sip_pickup(), sip_pvt_lock, sip_pvt_unlock, sip_ref_peer(), sip_refer_allocate(), sip_scheddestroy(), sip_st_alloc(), sip_t38_abort(), sip_unref_peer(), sip_uri_cmp(), ast_party_connected_line::source, st_get_mode(), st_get_refresher(), st_get_se(), start_session_timer(), ast_party_name::str, ast_party_number::str, strcasestr(), strsep(), ast_party_id::tag, cfsip_methods::text, transmit_fake_auth_response(), transmit_provisional_response(), transmit_response(), transmit_response_reliable(), transmit_response_with_minse(), transmit_response_with_sdp(), transmit_response_with_t38_sdp(), transmit_response_with_unsupported(), TRUE, update_call_counter(), update_redirecting(), ast_party_name::valid, and ast_party_number::valid.
Referenced by handle_incoming().
23019 { 23020 int res = INV_REQ_SUCCESS; 23021 int gotdest; 23022 const char *p_replaces; 23023 char *replace_id = NULL; 23024 int refer_locked = 0; 23025 const char *required; 23026 unsigned int required_profile = 0; 23027 struct ast_channel *c = NULL; /* New channel */ 23028 struct sip_peer *authpeer = NULL; /* Matching Peer */ 23029 int reinvite = 0; 23030 int rtn; 23031 struct ast_party_redirecting redirecting; 23032 struct ast_set_party_redirecting update_redirecting; 23033 23034 const char *p_uac_se_hdr; /* UAC's Session-Expires header string */ 23035 const char *p_uac_min_se; /* UAC's requested Min-SE interval (char string) */ 23036 int uac_max_se = -1; /* UAC's Session-Expires in integer format */ 23037 int uac_min_se = -1; /* UAC's Min-SE in integer format */ 23038 int st_active = FALSE; /* Session-Timer on/off boolean */ 23039 int st_interval = 0; /* Session-Timer negotiated refresh interval */ 23040 enum st_refresher st_ref; /* Session-Timer session refresher */ 23041 int dlg_min_se = -1; 23042 struct { 23043 char exten[AST_MAX_EXTENSION]; 23044 char context[AST_MAX_CONTEXT]; 23045 } pickup = { 23046 .exten = "", 23047 }; 23048 st_ref = SESSION_TIMER_REFRESHER_AUTO; 23049 23050 /* Find out what they support */ 23051 if (!p->sipoptions) { 23052 const char *supported = sip_get_header(req, "Supported"); 23053 if (!ast_strlen_zero(supported)) { 23054 p->sipoptions = parse_sip_options(supported, NULL, 0); 23055 } 23056 } 23057 23058 /* Find out what they require */ 23059 required = sip_get_header(req, "Require"); 23060 if (!ast_strlen_zero(required)) { 23061 char unsupported[256] = { 0, }; 23062 required_profile = parse_sip_options(required, unsupported, ARRAY_LEN(unsupported)); 23063 23064 /* If there are any options required that we do not support, 23065 * then send a 420 with only those unsupported options listed */ 23066 if (!ast_strlen_zero(unsupported)) { 23067 transmit_response_with_unsupported(p, "420 Bad extension (unsupported)", req, unsupported); 23068 ast_log(LOG_WARNING, "Received SIP INVITE with unsupported required extension: required:%s unsupported:%s\n", required, unsupported); 23069 p->invitestate = INV_COMPLETED; 23070 if (!p->lastinvite) 23071 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 23072 res = INV_REQ_ERROR; 23073 goto request_invite_cleanup; 23074 } 23075 } 23076 23077 /* The option tags may be present in Supported: or Require: headers. 23078 Include the Require: option tags for further processing as well */ 23079 p->sipoptions |= required_profile; 23080 p->reqsipoptions = required_profile; 23081 23082 /* Check if this is a loop */ 23083 if (ast_test_flag(&p->flags[0], SIP_OUTGOING) && p->owner && (p->invitestate != INV_TERMINATED && p->invitestate != INV_CONFIRMED) && p->owner->_state != AST_STATE_UP) { 23084 /* This is a call to ourself. Send ourselves an error code and stop 23085 processing immediately, as SIP really has no good mechanism for 23086 being able to call yourself */ 23087 /* If pedantic is on, we need to check the tags. If they're different, this is 23088 in fact a forked call through a SIP proxy somewhere. */ 23089 int different; 23090 const char *initial_rlPart2 = REQ_OFFSET_TO_STR(&p->initreq, rlPart2); 23091 const char *this_rlPart2 = REQ_OFFSET_TO_STR(req, rlPart2); 23092 if (sip_cfg.pedanticsipchecking) 23093 different = sip_uri_cmp(initial_rlPart2, this_rlPart2); 23094 else 23095 different = strcmp(initial_rlPart2, this_rlPart2); 23096 if (!different) { 23097 transmit_response(p, "482 Loop Detected", req); 23098 p->invitestate = INV_COMPLETED; 23099 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 23100 res = INV_REQ_FAILED; 23101 goto request_invite_cleanup; 23102 } else { 23103 /*! This is a spiral. What we need to do is to just change the outgoing INVITE 23104 * so that it now routes to the new Request URI. Since we created the INVITE ourselves 23105 * that should be all we need to do. 23106 * 23107 * \todo XXX This needs to be reviewed. YOu don't change the request URI really, you route the packet 23108 * correctly instead... 23109 */ 23110 char *uri = ast_strdupa(this_rlPart2); 23111 char *at = strchr(uri, '@'); 23112 char *peerorhost; 23113 ast_debug(2, "Potential spiral detected. Original RURI was %s, new RURI is %s\n", initial_rlPart2, this_rlPart2); 23114 transmit_response(p, "100 Trying", req); 23115 if (at) { 23116 *at = '\0'; 23117 } 23118 /* Parse out "sip:" */ 23119 if ((peerorhost = strchr(uri, ':'))) { 23120 *peerorhost++ = '\0'; 23121 } 23122 ast_string_field_set(p, theirtag, NULL); 23123 /* Treat this as if there were a call forward instead... 23124 */ 23125 ast_channel_call_forward_set(p->owner, peerorhost); 23126 ast_queue_control(p->owner, AST_CONTROL_BUSY); 23127 res = INV_REQ_FAILED; 23128 goto request_invite_cleanup; 23129 } 23130 } 23131 23132 if (!req->ignore && p->pendinginvite) { 23133 if (!ast_test_flag(&p->flags[0], SIP_OUTGOING) && (p->invitestate == INV_COMPLETED || p->invitestate == INV_TERMINATED)) { 23134 /* What do these circumstances mean? We have received an INVITE for an "incoming" dialog for which we 23135 * have sent a final response. We have not yet received an ACK, though (which is why p->pendinginvite is non-zero). 23136 * We also know that the INVITE is not a retransmission, because otherwise the "ignore" flag would be set. 23137 * This means that either we are receiving a reinvite for a terminated dialog, or we are receiving an INVITE with 23138 * credentials based on one we challenged earlier. 23139 * 23140 * The action to take in either case is to treat the INVITE as though it contains an implicit ACK for the previous 23141 * transaction. Calling __sip_ack will take care of this by clearing the p->pendinginvite and removing the response 23142 * from the previous transaction from the list of outstanding packets. 23143 */ 23144 __sip_ack(p, p->pendinginvite, 1, 0); 23145 } else { 23146 /* We already have a pending invite. Sorry. You are on hold. */ 23147 p->glareinvite = seqno; 23148 if (p->rtp && find_sdp(req)) { 23149 struct ast_sockaddr addr; 23150 if (get_ip_and_port_from_sdp(req, SDP_AUDIO, &addr)) { 23151 ast_log(LOG_WARNING, "Failed to set an alternate media source on glared reinvite. Audio may not work properly on this call.\n"); 23152 } else { 23153 ast_rtp_instance_set_alt_remote_address(p->rtp, &addr); 23154 } 23155 if (p->vrtp) { 23156 if (get_ip_and_port_from_sdp(req, SDP_VIDEO, &addr)) { 23157 ast_log(LOG_WARNING, "Failed to set an alternate media source on glared reinvite. Video may not work properly on this call.\n"); 23158 } else { 23159 ast_rtp_instance_set_alt_remote_address(p->vrtp, &addr); 23160 } 23161 } 23162 } 23163 transmit_response_reliable(p, "491 Request Pending", req); 23164 ast_debug(1, "Got INVITE on call where we already have pending INVITE, deferring that - %s\n", p->callid); 23165 /* Don't destroy dialog here */ 23166 res = INV_REQ_FAILED; 23167 goto request_invite_cleanup; 23168 } 23169 } 23170 23171 p_replaces = sip_get_header(req, "Replaces"); 23172 if (!ast_strlen_zero(p_replaces)) { 23173 /* We have a replaces header */ 23174 char *ptr; 23175 char *fromtag = NULL; 23176 char *totag = NULL; 23177 char *start, *to; 23178 int error = 0; 23179 23180 if (p->owner) { 23181 ast_debug(3, "INVITE w Replaces on existing call? Refusing action. [%s]\n", p->callid); 23182 transmit_response_reliable(p, "400 Bad request", req); /* The best way to not not accept the transfer */ 23183 /* Do not destroy existing call */ 23184 res = INV_REQ_ERROR; 23185 goto request_invite_cleanup; 23186 } 23187 23188 if (sipdebug) 23189 ast_debug(3, "INVITE part of call transfer. Replaces [%s]\n", p_replaces); 23190 /* Create a buffer we can manipulate */ 23191 replace_id = ast_strdupa(p_replaces); 23192 ast_uri_decode(replace_id, ast_uri_sip_user); 23193 23194 if (!p->refer && !sip_refer_allocate(p)) { 23195 transmit_response_reliable(p, "500 Server Internal Error", req); 23196 append_history(p, "Xfer", "INVITE/Replace Failed. Out of memory."); 23197 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 23198 p->invitestate = INV_COMPLETED; 23199 res = INV_REQ_ERROR; 23200 goto request_invite_cleanup; 23201 } 23202 23203 /* Todo: (When we find phones that support this) 23204 if the replaces header contains ";early-only" 23205 we can only replace the call in early 23206 stage, not after it's up. 23207 23208 If it's not in early mode, 486 Busy. 23209 */ 23210 23211 /* Skip leading whitespace */ 23212 replace_id = ast_skip_blanks(replace_id); 23213 23214 start = replace_id; 23215 while ( (ptr = strsep(&start, ";")) ) { 23216 ptr = ast_skip_blanks(ptr); /* XXX maybe unnecessary ? */ 23217 if ( (to = strcasestr(ptr, "to-tag=") ) ) 23218 totag = to + 7; /* skip the keyword */ 23219 else if ( (to = strcasestr(ptr, "from-tag=") ) ) { 23220 fromtag = to + 9; /* skip the keyword */ 23221 fromtag = strsep(&fromtag, "&"); /* trim what ? */ 23222 } 23223 } 23224 23225 if (sipdebug) 23226 ast_debug(4, "Invite/replaces: Will use Replace-Call-ID : %s Fromtag: %s Totag: %s\n", 23227 replace_id, 23228 fromtag ? fromtag : "<no from tag>", 23229 totag ? totag : "<no to tag>"); 23230 23231 /* Try to find call that we are replacing. 23232 If we have a Replaces header, we need to cancel that call if we succeed with this call. 23233 First we cheat a little and look for a magic call-id from phones that support 23234 dialog-info+xml so we can do technology independent pickup... */ 23235 if (strncmp(replace_id, "pickup-", 7) == 0) { 23236 struct sip_pvt *subscription = NULL; 23237 replace_id += 7; /* Worst case we are looking at \0 */ 23238 23239 if ((subscription = get_sip_pvt_byid_locked(replace_id, totag, fromtag)) == NULL) { 23240 ast_log(LOG_NOTICE, "Unable to find subscription with call-id: %s\n", replace_id); 23241 transmit_response_reliable(p, "481 Call Leg Does Not Exist (Replaces)", req); 23242 error = 1; 23243 } else { 23244 ast_log(LOG_NOTICE, "Trying to pick up %s@%s\n", subscription->exten, subscription->context); 23245 ast_copy_string(pickup.exten, subscription->exten, sizeof(pickup.exten)); 23246 ast_copy_string(pickup.context, subscription->context, sizeof(pickup.context)); 23247 sip_pvt_unlock(subscription); 23248 if (subscription->owner) { 23249 ast_channel_unlock(subscription->owner); 23250 } 23251 } 23252 } 23253 23254 /* This locks both refer_call pvt and refer_call pvt's owner!!!*/ 23255 if (!error && ast_strlen_zero(pickup.exten) && (p->refer->refer_call = get_sip_pvt_byid_locked(replace_id, totag, fromtag)) == NULL) { 23256 ast_log(LOG_NOTICE, "Supervised transfer attempted to replace non-existent call id (%s)!\n", replace_id); 23257 transmit_response_reliable(p, "481 Call Leg Does Not Exist (Replaces)", req); 23258 error = 1; 23259 } else { 23260 refer_locked = 1; 23261 } 23262 23263 /* The matched call is the call from the transferer to Asterisk . 23264 We want to bridge the bridged part of the call to the 23265 incoming invite, thus taking over the refered call */ 23266 23267 if (p->refer->refer_call == p) { 23268 ast_log(LOG_NOTICE, "INVITE with replaces into it's own call id (%s == %s)!\n", replace_id, p->callid); 23269 p->refer->refer_call = dialog_unref(p->refer->refer_call, "unref dialog p->refer->refer_call"); 23270 transmit_response_reliable(p, "400 Bad request", req); /* The best way to not not accept the transfer */ 23271 error = 1; 23272 } 23273 23274 if (!error && ast_strlen_zero(pickup.exten) && !p->refer->refer_call->owner) { 23275 /* Oops, someting wrong anyway, no owner, no call */ 23276 ast_log(LOG_NOTICE, "Supervised transfer attempted to replace non-existing call id (%s)!\n", replace_id); 23277 /* Check for better return code */ 23278 transmit_response_reliable(p, "481 Call Leg Does Not Exist (Replace)", req); 23279 error = 1; 23280 } 23281 23282 if (!error && ast_strlen_zero(pickup.exten) && p->refer->refer_call->owner->_state != AST_STATE_RINGING && p->refer->refer_call->owner->_state != AST_STATE_RING && p->refer->refer_call->owner->_state != AST_STATE_UP) { 23283 ast_log(LOG_NOTICE, "Supervised transfer attempted to replace non-ringing or active call id (%s)!\n", replace_id); 23284 transmit_response_reliable(p, "603 Declined (Replaces)", req); 23285 error = 1; 23286 } 23287 23288 if (error) { /* Give up this dialog */ 23289 append_history(p, "Xfer", "INVITE/Replace Failed."); 23290 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 23291 sip_pvt_unlock(p); 23292 if (p->refer->refer_call) { 23293 sip_pvt_unlock(p->refer->refer_call); 23294 if (p->refer->refer_call->owner) { 23295 ast_channel_unlock(p->refer->refer_call->owner); 23296 } 23297 } 23298 refer_locked = 0; 23299 p->invitestate = INV_COMPLETED; 23300 res = INV_REQ_ERROR; 23301 goto request_invite_cleanup; 23302 } 23303 } 23304 23305 /* Check if this is an INVITE that sets up a new dialog or 23306 a re-invite in an existing dialog */ 23307 23308 if (!req->ignore) { 23309 int newcall = (p->initreq.headers ? TRUE : FALSE); 23310 23311 if (sip_cancel_destroy(p)) 23312 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 23313 /* This also counts as a pending invite */ 23314 p->pendinginvite = seqno; 23315 check_via(p, req); 23316 23317 copy_request(&p->initreq, req); /* Save this INVITE as the transaction basis */ 23318 if (sipdebug) 23319 ast_debug(1, "Initializing initreq for method %s - callid %s\n", sip_methods[req->method].text, p->callid); 23320 if (!p->owner) { /* Not a re-invite */ 23321 if (debug) 23322 ast_verbose("Using INVITE request as basis request - %s\n", p->callid); 23323 if (newcall) 23324 append_history(p, "Invite", "New call: %s", p->callid); 23325 parse_ok_contact(p, req); 23326 } else { /* Re-invite on existing call */ 23327 ast_clear_flag(&p->flags[0], SIP_OUTGOING); /* This is now an inbound dialog */ 23328 if (get_rpid(p, req)) { 23329 struct ast_party_connected_line connected; 23330 struct ast_set_party_connected_line update_connected; 23331 23332 ast_party_connected_line_init(&connected); 23333 memset(&update_connected, 0, sizeof(update_connected)); 23334 23335 update_connected.id.number = 1; 23336 connected.id.number.valid = 1; 23337 connected.id.number.str = (char *) p->cid_num; 23338 connected.id.number.presentation = p->callingpres; 23339 23340 update_connected.id.name = 1; 23341 connected.id.name.valid = 1; 23342 connected.id.name.str = (char *) p->cid_name; 23343 connected.id.name.presentation = p->callingpres; 23344 23345 connected.id.tag = (char *) p->cid_tag; 23346 connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER; 23347 ast_channel_queue_connected_line_update(p->owner, &connected, 23348 &update_connected); 23349 } 23350 /* Handle SDP here if we already have an owner */ 23351 if (find_sdp(req)) { 23352 if (process_sdp(p, req, SDP_T38_INITIATE)) { 23353 if (!ast_strlen_zero(sip_get_header(req, "Content-Encoding"))) { 23354 /* Asterisk does not yet support any Content-Encoding methods. Always 23355 * attempt to process the sdp, but return a 415 if a Content-Encoding header 23356 * was present after processing failed. */ 23357 transmit_response_reliable(p, "415 Unsupported Media type", req); 23358 } else { 23359 transmit_response_reliable(p, "488 Not acceptable here", req); 23360 } 23361 if (!p->lastinvite) 23362 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 23363 res = INV_REQ_ERROR; 23364 goto request_invite_cleanup; 23365 } 23366 ast_queue_control(p->owner, AST_CONTROL_SRCUPDATE); 23367 } else { 23368 ast_format_cap_copy(p->jointcaps, p->caps); 23369 ast_debug(1, "Hm.... No sdp for the moment\n"); 23370 /* Some devices signal they want to be put off hold by sending a re-invite 23371 *without* an SDP, which is supposed to mean "Go back to your state" 23372 and since they put os on remote hold, we go back to off hold */ 23373 if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD)) { 23374 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 23375 /* Activate a re-invite */ 23376 ast_queue_frame(p->owner, &ast_null_frame); 23377 change_hold_state(p, req, FALSE, 0); 23378 } 23379 } 23380 if (p->do_history) /* This is a response, note what it was for */ 23381 append_history(p, "ReInv", "Re-invite received"); 23382 } 23383 } else if (debug) 23384 ast_verbose("Ignoring this INVITE request\n"); 23385 23386 if (!p->lastinvite && !req->ignore && !p->owner) { 23387 /* This is a new invite */ 23388 /* Handle authentication if this is our first invite */ 23389 int cc_recall_core_id = -1; 23390 set_pvt_allowed_methods(p, req); 23391 res = check_user_full(p, req, SIP_INVITE, e, XMIT_RELIABLE, addr, &authpeer); 23392 if (res == AUTH_CHALLENGE_SENT) { 23393 p->invitestate = INV_COMPLETED; /* Needs to restart in another INVITE transaction */ 23394 goto request_invite_cleanup; 23395 } 23396 if (res < 0) { /* Something failed in authentication */ 23397 if (res == AUTH_FAKE_AUTH) { 23398 ast_log(LOG_NOTICE, "Sending fake auth rejection for device %s\n", sip_get_header(req, "From")); 23399 transmit_fake_auth_response(p, SIP_INVITE, req, XMIT_RELIABLE); 23400 } else { 23401 ast_log(LOG_NOTICE, "Failed to authenticate device %s\n", sip_get_header(req, "From")); 23402 transmit_response_reliable(p, "403 Forbidden", req); 23403 } 23404 p->invitestate = INV_COMPLETED; 23405 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 23406 goto request_invite_cleanup; 23407 } 23408 23409 /* Successful authentication and peer matching so record the peer related to this pvt (for easy access to peer settings) */ 23410 if (p->relatedpeer) { 23411 p->relatedpeer = sip_unref_peer(p->relatedpeer,"unsetting the relatedpeer field in the dialog, before it is set to something else."); 23412 } 23413 if (authpeer) { 23414 p->relatedpeer = sip_ref_peer(authpeer, "setting dialog's relatedpeer pointer"); 23415 } 23416 23417 req->authenticated = 1; 23418 23419 /* We have a successful authentication, process the SDP portion if there is one */ 23420 if (find_sdp(req)) { 23421 if (process_sdp(p, req, SDP_T38_INITIATE)) { 23422 /* Asterisk does not yet support any Content-Encoding methods. Always 23423 * attempt to process the sdp, but return a 415 if a Content-Encoding header 23424 * was present after processing fails. */ 23425 if (!ast_strlen_zero(sip_get_header(req, "Content-Encoding"))) { 23426 transmit_response_reliable(p, "415 Unsupported Media type", req); 23427 } else { 23428 /* Unacceptable codecs */ 23429 transmit_response_reliable(p, "488 Not acceptable here", req); 23430 } 23431 p->invitestate = INV_COMPLETED; 23432 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 23433 ast_debug(1, "No compatible codecs for this SIP call.\n"); 23434 res = INV_REQ_ERROR; 23435 goto request_invite_cleanup; 23436 } 23437 } else { /* No SDP in invite, call control session */ 23438 ast_format_cap_copy(p->jointcaps, p->caps); 23439 ast_debug(2, "No SDP in Invite, third party call control\n"); 23440 } 23441 23442 /* Queue NULL frame to prod ast_rtp_bridge if appropriate */ 23443 /* This seems redundant ... see !p-owner above */ 23444 if (p->owner) 23445 ast_queue_frame(p->owner, &ast_null_frame); 23446 23447 23448 /* Initialize the context if it hasn't been already */ 23449 if (ast_strlen_zero(p->context)) 23450 ast_string_field_set(p, context, sip_cfg.default_context); 23451 23452 23453 /* Check number of concurrent calls -vs- incoming limit HERE */ 23454 ast_debug(1, "Checking SIP call limits for device %s\n", p->username); 23455 if ((res = update_call_counter(p, INC_CALL_LIMIT))) { 23456 if (res < 0) { 23457 ast_log(LOG_NOTICE, "Failed to place call for device %s, too many calls\n", p->username); 23458 transmit_response_reliable(p, "480 Temporarily Unavailable (Call limit) ", req); 23459 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 23460 p->invitestate = INV_COMPLETED; 23461 23462 res = AUTH_SESSION_LIMIT; 23463 } 23464 23465 goto request_invite_cleanup; 23466 } 23467 gotdest = get_destination(p, NULL, &cc_recall_core_id); /* Get destination right away */ 23468 extract_uri(p, req); /* Get the Contact URI */ 23469 build_contact(p); /* Build our contact header */ 23470 23471 if (p->rtp) { 23472 ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_DTMF, ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833); 23473 ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_DTMF_COMPENSATE, ast_test_flag(&p->flags[1], SIP_PAGE2_RFC2833_COMPENSATE)); 23474 } 23475 23476 if (!replace_id && (gotdest != SIP_GET_DEST_EXTEN_FOUND)) { /* No matching extension found */ 23477 switch(gotdest) { 23478 case SIP_GET_DEST_INVALID_URI: 23479 transmit_response_reliable(p, "416 Unsupported URI scheme", req); 23480 break; 23481 case SIP_GET_DEST_EXTEN_MATCHMORE: 23482 if (ast_test_flag(&p->flags[1], SIP_PAGE2_ALLOWOVERLAP) 23483 == SIP_PAGE2_ALLOWOVERLAP_YES) { 23484 transmit_response_reliable(p, "484 Address Incomplete", req); 23485 break; 23486 } 23487 /* 23488 * XXX We would have to implement collecting more digits in 23489 * chan_sip for any other schemes of overlap dialing. 23490 * 23491 * For SIP_PAGE2_ALLOWOVERLAP_DTMF it is better to do this in 23492 * the dialplan using the Incomplete application rather than 23493 * having the channel driver do it. 23494 */ 23495 /* Fall through */ 23496 case SIP_GET_DEST_EXTEN_NOT_FOUND: 23497 case SIP_GET_DEST_REFUSED: 23498 default: 23499 { 23500 char *decoded_exten = ast_strdupa(p->exten); 23501 transmit_response_reliable(p, "404 Not Found", req); 23502 ast_uri_decode(decoded_exten, ast_uri_sip_user); 23503 ast_log(LOG_NOTICE, "Call from '%s' (%s) to extension" 23504 " '%s' rejected because extension not found in context '%s'.\n", 23505 S_OR(p->username, p->peername), ast_sockaddr_stringify(&p->recv), decoded_exten, p->context); 23506 } 23507 } /* end switch */ 23508 23509 p->invitestate = INV_COMPLETED; 23510 update_call_counter(p, DEC_CALL_LIMIT); 23511 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 23512 res = INV_REQ_FAILED; 23513 goto request_invite_cleanup; 23514 } else { 23515 23516 /* If no extension was specified, use the s one */ 23517 /* Basically for calling to IP/Host name only */ 23518 if (ast_strlen_zero(p->exten)) 23519 ast_string_field_set(p, exten, "s"); 23520 /* Initialize our tag */ 23521 23522 make_our_tag(p->tag, sizeof(p->tag)); 23523 /* First invitation - create the channel. Allocation 23524 * failures are handled below. */ 23525 c = sip_new(p, AST_STATE_DOWN, S_OR(p->peername, NULL), NULL); 23526 if (cc_recall_core_id != -1) { 23527 ast_setup_cc_recall_datastore(c, cc_recall_core_id); 23528 ast_cc_agent_set_interfaces_chanvar(c); 23529 } 23530 *recount = 1; 23531 23532 /* Save Record-Route for any later requests we make on this dialogue */ 23533 build_route(p, req, 0); 23534 23535 if (c) { 23536 ast_party_redirecting_init(&redirecting); 23537 memset(&update_redirecting, 0, sizeof(update_redirecting)); 23538 change_redirecting_information(p, req, &redirecting, &update_redirecting, 23539 FALSE); /*Will return immediately if no Diversion header is present */ 23540 ast_channel_set_redirecting(c, &redirecting, &update_redirecting); 23541 ast_party_redirecting_free(&redirecting); 23542 } 23543 } 23544 } else { 23545 ast_party_redirecting_init(&redirecting); 23546 memset(&update_redirecting, 0, sizeof(update_redirecting)); 23547 if (sipdebug) { 23548 if (!req->ignore) 23549 ast_debug(2, "Got a SIP re-invite for call %s\n", p->callid); 23550 else 23551 ast_debug(2, "Got a SIP re-transmit of INVITE for call %s\n", p->callid); 23552 } 23553 if (!req->ignore) 23554 reinvite = 1; 23555 c = p->owner; 23556 change_redirecting_information(p, req, &redirecting, &update_redirecting, FALSE); /*Will return immediately if no Diversion header is present */ 23557 if (c) { 23558 ast_channel_set_redirecting(c, &redirecting, &update_redirecting); 23559 } 23560 ast_party_redirecting_free(&redirecting); 23561 } 23562 23563 /* Session-Timers */ 23564 if ((p->sipoptions & SIP_OPT_TIMER) && !ast_strlen_zero(sip_get_header(req, "Session-Expires"))) { 23565 /* The UAC has requested session-timers for this session. Negotiate 23566 the session refresh interval and who will be the refresher */ 23567 ast_debug(2, "Incoming INVITE with 'timer' option supported and \"Session-Expires\" header.\n"); 23568 23569 /* Allocate Session-Timers struct w/in the dialog */ 23570 if (!p->stimer) 23571 sip_st_alloc(p); 23572 23573 /* Parse the Session-Expires header */ 23574 p_uac_se_hdr = sip_get_header(req, "Session-Expires"); 23575 rtn = parse_session_expires(p_uac_se_hdr, &uac_max_se, &st_ref); 23576 if (rtn != 0) { 23577 transmit_response_reliable(p, "400 Session-Expires Invalid Syntax", req); 23578 p->invitestate = INV_COMPLETED; 23579 if (!p->lastinvite) { 23580 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 23581 } 23582 res = INV_REQ_ERROR; 23583 goto request_invite_cleanup; 23584 } 23585 23586 /* Parse the Min-SE header */ 23587 p_uac_min_se = sip_get_header(req, "Min-SE"); 23588 if (!ast_strlen_zero(p_uac_min_se)) { 23589 rtn = parse_minse(p_uac_min_se, &uac_min_se); 23590 if (rtn != 0) { 23591 transmit_response_reliable(p, "400 Min-SE Invalid Syntax", req); 23592 p->invitestate = INV_COMPLETED; 23593 if (!p->lastinvite) { 23594 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 23595 } 23596 res = INV_REQ_ERROR; 23597 goto request_invite_cleanup; 23598 } 23599 } 23600 23601 dlg_min_se = st_get_se(p, FALSE); 23602 switch (st_get_mode(p, 1)) { 23603 case SESSION_TIMER_MODE_ACCEPT: 23604 case SESSION_TIMER_MODE_ORIGINATE: 23605 if (uac_max_se > 0 && uac_max_se < dlg_min_se) { 23606 transmit_response_with_minse(p, "422 Session Interval Too Small", req, dlg_min_se); 23607 p->invitestate = INV_COMPLETED; 23608 if (!p->lastinvite) { 23609 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 23610 } 23611 res = INV_REQ_ERROR; 23612 goto request_invite_cleanup; 23613 } 23614 23615 p->stimer->st_active_peer_ua = TRUE; 23616 st_active = TRUE; 23617 if (st_ref == SESSION_TIMER_REFRESHER_AUTO) { 23618 st_ref = st_get_refresher(p); 23619 } 23620 23621 if (uac_max_se > 0) { 23622 int dlg_max_se = st_get_se(p, TRUE); 23623 if (dlg_max_se >= uac_min_se) { 23624 st_interval = (uac_max_se < dlg_max_se) ? uac_max_se : dlg_max_se; 23625 } else { 23626 st_interval = uac_max_se; 23627 } 23628 } else { 23629 /* Set to default max value */ 23630 st_interval = global_max_se; 23631 } 23632 break; 23633 23634 case SESSION_TIMER_MODE_REFUSE: 23635 if (p->reqsipoptions & SIP_OPT_TIMER) { 23636 transmit_response_with_unsupported(p, "420 Option Disabled", req, required); 23637 ast_log(LOG_WARNING, "Received SIP INVITE with supported but disabled option: %s\n", required); 23638 p->invitestate = INV_COMPLETED; 23639 if (!p->lastinvite) { 23640 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 23641 } 23642 res = INV_REQ_ERROR; 23643 goto request_invite_cleanup; 23644 } 23645 break; 23646 23647 default: 23648 ast_log(LOG_ERROR, "Internal Error %d at %s:%d\n", st_get_mode(p, 1), __FILE__, __LINE__); 23649 break; 23650 } 23651 } else { 23652 /* The UAC did not request session-timers. Asterisk (UAS), will now decide 23653 (based on session-timer-mode in sip.conf) whether to run session-timers for 23654 this session or not. */ 23655 switch (st_get_mode(p, 1)) { 23656 case SESSION_TIMER_MODE_ORIGINATE: 23657 st_active = TRUE; 23658 st_interval = st_get_se(p, TRUE); 23659 st_ref = SESSION_TIMER_REFRESHER_UAS; 23660 p->stimer->st_active_peer_ua = FALSE; 23661 break; 23662 23663 default: 23664 break; 23665 } 23666 } 23667 23668 if (reinvite == 0) { 23669 /* Session-Timers: Start session refresh timer based on negotiation/config */ 23670 if (st_active == TRUE) { 23671 p->stimer->st_active = TRUE; 23672 p->stimer->st_interval = st_interval; 23673 p->stimer->st_ref = st_ref; 23674 start_session_timer(p); 23675 } 23676 } else { 23677 if (p->stimer->st_active == TRUE) { 23678 /* Session-Timers: A re-invite request sent within a dialog will serve as 23679 a refresh request, no matter whether the re-invite was sent for refreshing 23680 the session or modifying it.*/ 23681 ast_debug (2, "Restarting session-timers on a refresh - %s\n", p->callid); 23682 23683 /* The UAC may be adjusting the session-timers mid-session */ 23684 if (st_interval > 0) { 23685 p->stimer->st_interval = st_interval; 23686 p->stimer->st_ref = st_ref; 23687 } 23688 23689 restart_session_timer(p); 23690 if (p->stimer->st_expirys > 0) { 23691 p->stimer->st_expirys--; 23692 } 23693 } 23694 } 23695 23696 if (!req->ignore && p) 23697 p->lastinvite = seqno; 23698 23699 if (c && replace_id) { /* Attended transfer or call pickup - we're the target */ 23700 if (!ast_strlen_zero(pickup.exten)) { 23701 append_history(p, "Xfer", "INVITE/Replace received"); 23702 23703 /* Let the caller know we're giving it a shot */ 23704 transmit_response(p, "100 Trying", req); 23705 p->invitestate = INV_PROCEEDING; 23706 ast_setstate(c, AST_STATE_RING); 23707 23708 /* Do the pickup itself */ 23709 ast_channel_unlock(c); 23710 *nounlock = 1; 23711 23712 /* since p->owner (c) is unlocked, we need to go ahead and unlock pvt for both 23713 * magic pickup and ast_hangup. Both of these functions will attempt to lock 23714 * p->owner again, which can cause a deadlock if we already hold a lock on p. 23715 * Locking order is, channel then pvt. Dead lock avoidance must be used if 23716 * called the other way around. */ 23717 sip_pvt_unlock(p); 23718 do_magic_pickup(c, pickup.exten, pickup.context); 23719 /* Now we're either masqueraded or we failed to pickup, in either case we... */ 23720 ast_hangup(c); 23721 sip_pvt_lock(p); /* pvt is expected to remain locked on return, so re-lock it */ 23722 23723 res = INV_REQ_FAILED; 23724 goto request_invite_cleanup; 23725 } else { 23726 /* Go and take over the target call */ 23727 if (sipdebug) 23728 ast_debug(4, "Sending this call to the invite/replcaes handler %s\n", p->callid); 23729 res = handle_invite_replaces(p, req, debug, seqno, addr, nounlock); 23730 refer_locked = 0; 23731 goto request_invite_cleanup; 23732 } 23733 } 23734 23735 23736 if (c) { /* We have a call -either a new call or an old one (RE-INVITE) */ 23737 enum ast_channel_state c_state = c->_state; 23738 23739 if (c_state != AST_STATE_UP && reinvite && 23740 (p->invitestate == INV_TERMINATED || p->invitestate == INV_CONFIRMED)) { 23741 /* If these conditions are true, and the channel is still in the 'ringing' 23742 * state, then this likely means that we have a situation where the initial 23743 * INVITE transaction has completed *but* the channel's state has not yet been 23744 * changed to UP. The reason this could happen is if the reinvite is received 23745 * on the SIP socket prior to an application calling ast_read on this channel 23746 * to read the answer frame we earlier queued on it. In this case, the reinvite 23747 * is completely legitimate so we need to handle this the same as if the channel 23748 * were already UP. Thus we are purposely falling through to the AST_STATE_UP case. 23749 */ 23750 c_state = AST_STATE_UP; 23751 } 23752 23753 switch(c_state) { 23754 case AST_STATE_DOWN: 23755 ast_debug(2, "%s: New call is still down.... Trying... \n", ast_channel_name(c)); 23756 transmit_provisional_response(p, "100 Trying", req, 0); 23757 p->invitestate = INV_PROCEEDING; 23758 ast_setstate(c, AST_STATE_RING); 23759 if (strcmp(p->exten, ast_pickup_ext())) { /* Call to extension -start pbx on this call */ 23760 enum ast_pbx_result result; 23761 23762 result = ast_pbx_start(c); 23763 23764 switch(result) { 23765 case AST_PBX_FAILED: 23766 ast_log(LOG_WARNING, "Failed to start PBX :(\n"); 23767 p->invitestate = INV_COMPLETED; 23768 transmit_response_reliable(p, "503 Unavailable", req); 23769 break; 23770 case AST_PBX_CALL_LIMIT: 23771 ast_log(LOG_WARNING, "Failed to start PBX (call limit reached) \n"); 23772 p->invitestate = INV_COMPLETED; 23773 transmit_response_reliable(p, "480 Temporarily Unavailable", req); 23774 res = AUTH_SESSION_LIMIT; 23775 break; 23776 case AST_PBX_SUCCESS: 23777 /* nothing to do */ 23778 break; 23779 } 23780 23781 if (result) { 23782 23783 /* Unlock locks so ast_hangup can do its magic */ 23784 ast_channel_unlock(c); 23785 *nounlock = 1; 23786 sip_pvt_unlock(p); 23787 ast_hangup(c); 23788 sip_pvt_lock(p); 23789 c = NULL; 23790 } 23791 } else { /* Pickup call in call group */ 23792 if (sip_pickup(c)) { 23793 ast_log(LOG_WARNING, "Failed to start Group pickup by %s\n", ast_channel_name(c)); 23794 transmit_response_reliable(p, "480 Temporarily Unavailable", req); 23795 sip_alreadygone(p); 23796 c->hangupcause = AST_CAUSE_FAILURE; 23797 23798 /* Unlock locks so ast_hangup can do its magic */ 23799 ast_channel_unlock(c); 23800 *nounlock = 1; 23801 23802 p->invitestate = INV_COMPLETED; 23803 sip_pvt_unlock(p); 23804 ast_hangup(c); 23805 sip_pvt_lock(p); 23806 c = NULL; 23807 } 23808 } 23809 break; 23810 case AST_STATE_RING: 23811 transmit_provisional_response(p, "100 Trying", req, 0); 23812 p->invitestate = INV_PROCEEDING; 23813 break; 23814 case AST_STATE_RINGING: 23815 transmit_provisional_response(p, "180 Ringing", req, 0); 23816 p->invitestate = INV_PROCEEDING; 23817 break; 23818 case AST_STATE_UP: 23819 ast_debug(2, "%s: This call is UP.... \n", ast_channel_name(c)); 23820 23821 transmit_response(p, "100 Trying", req); 23822 23823 if (p->t38.state == T38_PEER_REINVITE) { 23824 if (p->t38id > -1) { 23825 /* reset t38 abort timer */ 23826 AST_SCHED_DEL_UNREF(sched, p->t38id, dialog_unref(p, "remove ref for t38id")); 23827 } 23828 p->t38id = ast_sched_add(sched, 5000, sip_t38_abort, dialog_ref(p, "passing dialog ptr into sched structure based on t38id for sip_t38_abort.")); 23829 } else if (p->t38.state == T38_ENABLED) { 23830 ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED); 23831 transmit_response_with_t38_sdp(p, "200 OK", req, (reinvite ? XMIT_RELIABLE : (req->ignore ? XMIT_UNRELIABLE : XMIT_CRITICAL))); 23832 } else if ((p->t38.state == T38_DISABLED) || (p->t38.state == T38_REJECTED)) { 23833 /* If this is not a re-invite or something to ignore - it's critical */ 23834 if (p->srtp && !ast_test_flag(p->srtp, SRTP_CRYPTO_OFFER_OK)) { 23835 ast_log(LOG_WARNING, "Target does not support required crypto\n"); 23836 transmit_response_reliable(p, "488 Not Acceptable Here (crypto)", req); 23837 } else { 23838 ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED); 23839 transmit_response_with_sdp(p, "200 OK", req, (reinvite ? XMIT_RELIABLE : (req->ignore ? XMIT_UNRELIABLE : XMIT_CRITICAL)), p->session_modify == TRUE ? FALSE : TRUE, FALSE); 23840 ast_queue_control(p->owner, AST_CONTROL_UPDATE_RTP_PEER); 23841 } 23842 } 23843 23844 p->invitestate = INV_TERMINATED; 23845 break; 23846 default: 23847 ast_log(LOG_WARNING, "Don't know how to handle INVITE in state %d\n", c->_state); 23848 transmit_response(p, "100 Trying", req); 23849 break; 23850 } 23851 } else { 23852 if (p && (p->autokillid == -1)) { 23853 const char *msg; 23854 23855 if ((ast_format_cap_is_empty(p->jointcaps))) 23856 msg = "488 Not Acceptable Here (codec error)"; 23857 else { 23858 ast_log(LOG_NOTICE, "Unable to create/find SIP channel for this INVITE\n"); 23859 msg = "503 Unavailable"; 23860 } 23861 transmit_response_reliable(p, msg, req); 23862 p->invitestate = INV_COMPLETED; 23863 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 23864 } 23865 } 23866 23867 request_invite_cleanup: 23868 23869 if (refer_locked && p->refer && p->refer->refer_call) { 23870 sip_pvt_unlock(p->refer->refer_call); 23871 if (p->refer->refer_call->owner) { 23872 ast_channel_unlock(p->refer->refer_call->owner); 23873 } 23874 } 23875 if (authpeer) { 23876 authpeer = sip_unref_peer(authpeer, "sip_unref_peer, from handle_request_invite authpeer"); 23877 } 23878 23879 return res; 23880 }
| static int handle_request_message | ( | struct sip_pvt * | p, | |
| struct sip_request * | req, | |||
| struct ast_sockaddr * | addr, | |||
| const char * | e | |||
| ) | [static] |
Handle incoming MESSAGE request.
Definition at line 24760 of file chan_sip.c.
References ast_verbose, receive_message(), and transmit_response().
Referenced by handle_incoming().
24761 { 24762 if (!req->ignore) { 24763 if (req->debug) 24764 ast_verbose("Receiving message!\n"); 24765 receive_message(p, req, addr, e); 24766 } else 24767 transmit_response(p, "202 Accepted", req); 24768 return 1; 24769 }
| static int handle_request_notify | ( | struct sip_pvt * | p, | |
| struct sip_request * | req, | |||
| struct ast_sockaddr * | addr, | |||
| uint32_t | seqno, | |||
| const char * | e | |||
| ) | [static] |
Handle incoming notifications.
Definition at line 22545 of file chan_sip.c.
References AST_CONTROL_TRANSFER, ast_debug, AST_EVENT_IE_CONTEXT, AST_EVENT_IE_END, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_IE_PLTYPE_UINT, AST_EVENT_MWI, ast_event_new(), ast_event_queue_and_cache(), ast_log(), ast_queue_control_data(), ast_skip_blanks(), ast_strdupa, ast_strlen_zero(), AST_TRANSFER_FAILED, AST_TRANSFER_SUCCESS, FALSE, get_body(), get_msg_text(), handle_cc_notify(), LOG_NOTICE, LOG_WARNING, mailbox, sip_find_peer(), sip_get_header(), sip_scheddestroy(), sip_unref_peer(), strsep(), transmit_response(), and TRUE.
Referenced by handle_incoming().
22546 { 22547 /* This is mostly a skeleton for future improvements */ 22548 /* Mostly created to return proper answers on notifications on outbound REFER's */ 22549 int res = 0; 22550 const char *event = sip_get_header(req, "Event"); 22551 char *sep; 22552 22553 if( (sep = strchr(event, ';')) ) { /* XXX bug here - overwriting string ? */ 22554 *sep++ = '\0'; 22555 } 22556 22557 if (sipdebug) 22558 ast_debug(2, "Got NOTIFY Event: %s\n", event); 22559 22560 if (!strcmp(event, "refer")) { 22561 /* Save nesting depth for now, since there might be other events we will 22562 support in the future */ 22563 22564 /* Handle REFER notifications */ 22565 22566 char buf[1024]; 22567 char *cmd, *code; 22568 int respcode; 22569 int success = TRUE; 22570 22571 /* EventID for each transfer... EventID is basically the REFER cseq 22572 22573 We are getting notifications on a call that we transfered 22574 We should hangup when we are getting a 200 OK in a sipfrag 22575 Check if we have an owner of this event */ 22576 22577 /* Check the content type */ 22578 if (strncasecmp(sip_get_header(req, "Content-Type"), "message/sipfrag", strlen("message/sipfrag"))) { 22579 /* We need a sipfrag */ 22580 transmit_response(p, "400 Bad request", req); 22581 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 22582 return -1; 22583 } 22584 22585 /* Get the text of the attachment */ 22586 if (get_msg_text(buf, sizeof(buf), req)) { 22587 ast_log(LOG_WARNING, "Unable to retrieve attachment from NOTIFY %s\n", p->callid); 22588 transmit_response(p, "400 Bad request", req); 22589 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 22590 return -1; 22591 } 22592 22593 /* 22594 From the RFC... 22595 A minimal, but complete, implementation can respond with a single 22596 NOTIFY containing either the body: 22597 SIP/2.0 100 Trying 22598 22599 if the subscription is pending, the body: 22600 SIP/2.0 200 OK 22601 if the reference was successful, the body: 22602 SIP/2.0 503 Service Unavailable 22603 if the reference failed, or the body: 22604 SIP/2.0 603 Declined 22605 22606 if the REFER request was accepted before approval to follow the 22607 reference could be obtained and that approval was subsequently denied 22608 (see Section 2.4.7). 22609 22610 If there are several REFERs in the same dialog, we need to 22611 match the ID of the event header... 22612 */ 22613 ast_debug(3, "* SIP Transfer NOTIFY Attachment: \n---%s\n---\n", buf); 22614 cmd = ast_skip_blanks(buf); 22615 code = cmd; 22616 /* We are at SIP/2.0 */ 22617 while(*code && (*code > 32)) { /* Search white space */ 22618 code++; 22619 } 22620 *code++ = '\0'; 22621 code = ast_skip_blanks(code); 22622 sep = code; 22623 sep++; 22624 while(*sep && (*sep > 32)) { /* Search white space */ 22625 sep++; 22626 } 22627 *sep++ = '\0'; /* Response string */ 22628 respcode = atoi(code); 22629 switch (respcode) { 22630 case 200: /* OK: The new call is up, hangup this call */ 22631 /* Hangup the call that we are replacing */ 22632 break; 22633 case 301: /* Moved permenantly */ 22634 case 302: /* Moved temporarily */ 22635 /* Do we get the header in the packet in this case? */ 22636 success = FALSE; 22637 break; 22638 case 503: /* Service Unavailable: The new call failed */ 22639 case 603: /* Declined: Not accepted */ 22640 /* Cancel transfer, continue the current call */ 22641 success = FALSE; 22642 break; 22643 case 0: /* Parse error */ 22644 /* Cancel transfer, continue the current call */ 22645 ast_log(LOG_NOTICE, "Error parsing sipfrag in NOTIFY in response to REFER.\n"); 22646 success = FALSE; 22647 break; 22648 default: 22649 if (respcode < 200) { 22650 /* ignore provisional responses */ 22651 success = -1; 22652 } else { 22653 ast_log(LOG_NOTICE, "Got unknown code '%d' in NOTIFY in response to REFER.\n", respcode); 22654 success = FALSE; 22655 } 22656 break; 22657 } 22658 if (success == FALSE) { 22659 ast_log(LOG_NOTICE, "Transfer failed. Sorry. Nothing further to do with this call\n"); 22660 } 22661 22662 if (p->owner && success != -1) { 22663 enum ast_control_transfer message = success ? AST_TRANSFER_SUCCESS : AST_TRANSFER_FAILED; 22664 ast_queue_control_data(p->owner, AST_CONTROL_TRANSFER, &message, sizeof(message)); 22665 } 22666 /* Confirm that we received this packet */ 22667 transmit_response(p, "200 OK", req); 22668 } else if (!strcmp(event, "message-summary")) { 22669 const char *mailbox = NULL; 22670 char *c = ast_strdupa(get_body(req, "Voice-Message", ':')); 22671 22672 if (!p->mwi) { 22673 struct sip_peer *peer = sip_find_peer(NULL, &p->recv, TRUE, FINDPEERS, FALSE, p->socket.type); 22674 22675 if (peer) { 22676 mailbox = ast_strdupa(peer->unsolicited_mailbox); 22677 sip_unref_peer(peer, "removing unsolicited mwi ref"); 22678 } 22679 } else { 22680 mailbox = p->mwi->mailbox; 22681 } 22682 22683 if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(c)) { 22684 char *old = strsep(&c, " "); 22685 char *new = strsep(&old, "/"); 22686 struct ast_event *event; 22687 22688 if ((event = ast_event_new(AST_EVENT_MWI, 22689 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox, 22690 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, "SIP_Remote", 22691 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, atoi(new), 22692 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, atoi(old), 22693 AST_EVENT_IE_END))) { 22694 ast_event_queue_and_cache(event); 22695 } 22696 transmit_response(p, "200 OK", req); 22697 } else { 22698 transmit_response(p, "489 Bad event", req); 22699 res = -1; 22700 } 22701 } else if (!strcmp(event, "keep-alive")) { 22702 /* Used by Sipura/Linksys for NAT pinhole, 22703 * just confirm that we received the packet. */ 22704 transmit_response(p, "200 OK", req); 22705 } else if (!strcmp(event, "call-completion")) { 22706 res = handle_cc_notify(p, req); 22707 } else { 22708 /* We don't understand this event. */ 22709 transmit_response(p, "489 Bad event", req); 22710 res = -1; 22711 } 22712 22713 if (!p->lastinvite) 22714 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 22715 22716 return res; 22717 }
| static int handle_request_options | ( | struct sip_pvt * | p, | |
| struct sip_request * | req, | |||
| struct ast_sockaddr * | addr, | |||
| const char * | e | |||
| ) | [static] |
Handle incoming OPTIONS request An OPTIONS request should be answered like an INVITE from the same UA, including SDP.
Definition at line 22722 of file chan_sip.c.
References ast_log(), ast_shutting_down(), ast_string_field_set, ast_strlen_zero(), build_contact(), check_user(), context, copy_request(), get_destination(), LOG_NOTICE, set_pvt_allowed_methods(), sip_cfg, sip_get_header(), sip_scheddestroy(), transmit_fake_auth_response(), transmit_response(), and transmit_response_with_allow().
Referenced by handle_incoming().
22723 { 22724 const char *msg; 22725 enum sip_get_dest_result gotdest; 22726 int res; 22727 22728 if (p->lastinvite) { 22729 /* if this is a request in an active dialog, just confirm that the dialog exists. */ 22730 transmit_response_with_allow(p, "200 OK", req, 0); 22731 return 0; 22732 } 22733 22734 if (sip_cfg.auth_options_requests) { 22735 /* Do authentication if this OPTIONS request began the dialog */ 22736 copy_request(&p->initreq, req); 22737 set_pvt_allowed_methods(p, req); 22738 res = check_user(p, req, SIP_OPTIONS, e, XMIT_UNRELIABLE, addr); 22739 if (res == AUTH_CHALLENGE_SENT) { 22740 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 22741 return 0; 22742 } 22743 if (res < 0) { /* Something failed in authentication */ 22744 if (res == AUTH_FAKE_AUTH) { 22745 ast_log(LOG_NOTICE, "Sending fake auth rejection for device %s\n", sip_get_header(req, "From")); 22746 transmit_fake_auth_response(p, SIP_OPTIONS, req, XMIT_UNRELIABLE); 22747 } else { 22748 ast_log(LOG_NOTICE, "Failed to authenticate device %s\n", sip_get_header(req, "From")); 22749 transmit_response(p, "403 Forbidden", req); 22750 } 22751 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 22752 return 0; 22753 } 22754 } 22755 22756 /* must go through authentication before getting here */ 22757 gotdest = get_destination(p, req, NULL); 22758 build_contact(p); 22759 22760 if (ast_strlen_zero(p->context)) 22761 ast_string_field_set(p, context, sip_cfg.default_context); 22762 22763 if (ast_shutting_down()) { 22764 msg = "503 Unavailable"; 22765 } else { 22766 msg = "404 Not Found"; 22767 switch (gotdest) { 22768 case SIP_GET_DEST_INVALID_URI: 22769 msg = "416 Unsupported URI scheme"; 22770 break; 22771 case SIP_GET_DEST_EXTEN_MATCHMORE: 22772 case SIP_GET_DEST_REFUSED: 22773 case SIP_GET_DEST_EXTEN_NOT_FOUND: 22774 //msg = "404 Not Found"; 22775 break; 22776 case SIP_GET_DEST_EXTEN_FOUND: 22777 msg = "200 OK"; 22778 break; 22779 } 22780 } 22781 transmit_response_with_allow(p, msg, req, 0); 22782 22783 /* Destroy if this OPTIONS was the opening request, but not if 22784 it's in the middle of a normal call flow. */ 22785 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 22786 22787 return 0; 22788 }
| static int handle_request_publish | ( | struct sip_pvt * | p, | |
| struct sip_request * | req, | |||
| struct ast_sockaddr * | addr, | |||
| const uint32_t | seqno, | |||
| const char * | uri | |||
| ) | [static] |
Definition at line 25345 of file chan_sip.c.
References __sip_ack(), ast_log(), ast_string_field_set, ast_strlen_zero(), check_user(), determine_sip_publish_type(), get_esc(), handle_sip_publish_initial(), handle_sip_publish_modify(), handle_sip_publish_refresh(), handle_sip_publish_remove(), LOG_NOTICE, pvt_set_needdestroy(), sip_get_header(), sip_scheddestroy(), transmit_fake_auth_response(), transmit_response(), transmit_response_reliable(), and transmit_response_with_minexpires().
Referenced by handle_incoming().
25346 { 25347 const char *etag = sip_get_header(req, "SIP-If-Match"); 25348 const char *event = sip_get_header(req, "Event"); 25349 struct event_state_compositor *esc; 25350 enum sip_publish_type publish_type; 25351 const char *expires_str = sip_get_header(req, "Expires"); 25352 int expires_int; 25353 int auth_result; 25354 int handler_result = -1; 25355 25356 if (ast_strlen_zero(event)) { 25357 transmit_response(p, "489 Bad Event", req); 25358 pvt_set_needdestroy(p, "missing Event: header"); 25359 return -1; 25360 } 25361 25362 if (!(esc = get_esc(event))) { 25363 transmit_response(p, "489 Bad Event", req); 25364 pvt_set_needdestroy(p, "unknown event package in publish"); 25365 return -1; 25366 } 25367 25368 auth_result = check_user(p, req, SIP_PUBLISH, uri, XMIT_RELIABLE, addr); 25369 if (auth_result == AUTH_CHALLENGE_SENT) { 25370 p->lastinvite = seqno; 25371 return 0; 25372 } else if (auth_result < 0) { 25373 if (auth_result == AUTH_FAKE_AUTH) { 25374 ast_log(LOG_NOTICE, "Sending fake auth rejection for device %s\n", sip_get_header(req, "From")); 25375 transmit_fake_auth_response(p, SIP_INVITE, req, XMIT_RELIABLE); 25376 } else { 25377 ast_log(LOG_NOTICE, "Failed to authenticate device %s\n", sip_get_header(req, "From")); 25378 transmit_response_reliable(p, "403 Forbidden", req); 25379 } 25380 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 25381 ast_string_field_set(p, theirtag, NULL); 25382 return 0; 25383 } else if (auth_result == AUTH_SUCCESSFUL && p->lastinvite) { 25384 /* We need to stop retransmitting the 401 */ 25385 __sip_ack(p, p->lastinvite, 1, 0); 25386 } 25387 25388 publish_type = determine_sip_publish_type(req, event, etag, expires_str, &expires_int); 25389 25390 if (expires_int > max_expiry) { 25391 expires_int = max_expiry; 25392 } else if (expires_int < min_expiry && expires_int > 0) { 25393 transmit_response_with_minexpires(p, "423 Interval too small", req); 25394 pvt_set_needdestroy(p, "Expires is less that the min expires allowed."); 25395 return 0; 25396 } 25397 p->expiry = expires_int; 25398 25399 /* It is the responsibility of these handlers to formulate any response 25400 * sent for a PUBLISH 25401 */ 25402 switch (publish_type) { 25403 case SIP_PUBLISH_UNKNOWN: 25404 transmit_response(p, "400 Bad Request", req); 25405 break; 25406 case SIP_PUBLISH_INITIAL: 25407 handler_result = handle_sip_publish_initial(p, req, esc, expires_int); 25408 break; 25409 case SIP_PUBLISH_REFRESH: 25410 handler_result = handle_sip_publish_refresh(p, req, esc, etag, expires_int); 25411 break; 25412 case SIP_PUBLISH_MODIFY: 25413 handler_result = handle_sip_publish_modify(p, req, esc, etag, expires_int); 25414 break; 25415 case SIP_PUBLISH_REMOVE: 25416 handler_result = handle_sip_publish_remove(p, req, esc, etag); 25417 break; 25418 default: 25419 transmit_response(p, "400 Impossible Condition", req); 25420 break; 25421 } 25422 if (!handler_result && p->expiry > 0) { 25423 sip_scheddestroy(p, (p->expiry + 10) * 1000); 25424 } else { 25425 pvt_set_needdestroy(p, "forcing expiration"); 25426 } 25427 25428 return handler_result; 25429 }
| static int handle_request_refer | ( | struct sip_pvt * | p, | |
| struct sip_request * | req, | |||
| int | debug, | |||
| uint32_t | seqno, | |||
| int * | nounlock | |||
| ) | [static] |
Chan1: Call between asterisk and transferer Chan2: Call between asterisk and transferee
Definition at line 24148 of file chan_sip.c.
References append_history, ast_async_goto(), ast_bridged_channel(), AST_CAUSE_NORMAL_CLEARING, AST_CEL_ATTENDEDTRANSFER, AST_CEL_BLINDTRANSFER, ast_cel_report_event(), ast_channel_lock, ast_channel_name(), ast_channel_ref, ast_channel_uniqueid(), ast_channel_unlock, ast_channel_unref, ast_clear_flag, AST_CONTROL_UNHOLD, ast_debug, ast_indicate(), AST_LIST_EMPTY, ast_manager_event_multichan, ast_parking_ext_valid(), ast_queue_control(), ast_set_flag, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_verbose, check_sip_domain(), context, EVENT_FLAG_CALL, FALSE, get_refer_info(), local_attended_transfer(), pbx_builtin_setvar_helper(), pvt_set_needdestroy(), sip_alreadygone(), sip_cfg, sip_park(), sip_pvt_lock, sip_pvt_unlock, sip_refer_allocate(), transmit_notify_with_sipfrag(), transmit_response(), and TRUE.
Referenced by handle_incoming().
24149 { 24150 /*! 24151 * Chan1: Call between asterisk and transferer 24152 * Chan2: Call between asterisk and transferee 24153 */ 24154 struct sip_dual current = { 0, }; 24155 struct ast_channel *chans[2] = { 0, }; 24156 char *refer_to = NULL; 24157 char *refer_to_domain = NULL; 24158 char *refer_to_context = NULL; 24159 char *referred_by = NULL; 24160 char *callid = NULL; 24161 int localtransfer = 0; 24162 int attendedtransfer = 0; 24163 int res = 0; 24164 24165 if (req->debug) { 24166 ast_verbose("Call %s got a SIP call transfer from %s: (REFER)!\n", 24167 p->callid, 24168 ast_test_flag(&p->flags[0], SIP_OUTGOING) ? "callee" : "caller"); 24169 } 24170 24171 if (!p->owner) { 24172 /* This is a REFER outside of an existing SIP dialog */ 24173 /* We can't handle that, so decline it */ 24174 ast_debug(3, "Call %s: Declined REFER, outside of dialog...\n", p->callid); 24175 transmit_response(p, "603 Declined (No dialog)", req); 24176 if (!req->ignore) { 24177 append_history(p, "Xfer", "Refer failed. Outside of dialog."); 24178 sip_alreadygone(p); 24179 pvt_set_needdestroy(p, "outside of dialog"); 24180 } 24181 res = 0; 24182 goto handle_refer_cleanup; 24183 } 24184 24185 /* Check if transfer is allowed from this device */ 24186 if (p->allowtransfer == TRANSFER_CLOSED ) { 24187 /* Transfer not allowed, decline */ 24188 transmit_response(p, "603 Declined (policy)", req); 24189 append_history(p, "Xfer", "Refer failed. Allowtransfer == closed."); 24190 /* Do not destroy SIP session */ 24191 res = 0; 24192 goto handle_refer_cleanup; 24193 } 24194 24195 if (!req->ignore && ast_test_flag(&p->flags[0], SIP_GOTREFER)) { 24196 /* Already have a pending REFER */ 24197 transmit_response(p, "491 Request pending", req); 24198 append_history(p, "Xfer", "Refer failed. Request pending."); 24199 res = 0; 24200 goto handle_refer_cleanup; 24201 } 24202 24203 /* Allocate memory for call transfer data */ 24204 if (!p->refer && !sip_refer_allocate(p)) { 24205 transmit_response(p, "500 Internal Server Error", req); 24206 append_history(p, "Xfer", "Refer failed. Memory allocation error."); 24207 res = -3; 24208 goto handle_refer_cleanup; 24209 } 24210 24211 res = get_refer_info(p, req); /* Extract headers */ 24212 24213 p->refer->status = REFER_SENT; 24214 24215 if (res != 0) { 24216 switch (res) { 24217 case -2: /* Syntax error */ 24218 transmit_response(p, "400 Bad Request (Refer-to missing)", req); 24219 append_history(p, "Xfer", "Refer failed. Refer-to missing."); 24220 if (req->debug) { 24221 ast_debug(1, "SIP transfer to black hole can't be handled (no refer-to: )\n"); 24222 } 24223 break; 24224 case -3: 24225 transmit_response(p, "603 Declined (Non sip: uri)", req); 24226 append_history(p, "Xfer", "Refer failed. Non SIP uri"); 24227 if (req->debug) { 24228 ast_debug(1, "SIP transfer to non-SIP uri denied\n"); 24229 } 24230 break; 24231 default: 24232 /* Refer-to extension not found, fake a failed transfer */ 24233 transmit_response(p, "202 Accepted", req); 24234 append_history(p, "Xfer", "Refer failed. Bad extension."); 24235 transmit_notify_with_sipfrag(p, seqno, "404 Not found", TRUE); 24236 ast_clear_flag(&p->flags[0], SIP_GOTREFER); 24237 if (req->debug) { 24238 ast_debug(1, "SIP transfer to bad extension: %s\n", p->refer->refer_to); 24239 } 24240 break; 24241 } 24242 res = 0; 24243 goto handle_refer_cleanup; 24244 } 24245 if (ast_strlen_zero(p->context)) { 24246 ast_string_field_set(p, context, sip_cfg.default_context); 24247 } 24248 24249 /* If we do not support SIP domains, all transfers are local */ 24250 if (sip_cfg.allow_external_domains && check_sip_domain(p->refer->refer_to_domain, NULL, 0)) { 24251 p->refer->localtransfer = 1; 24252 if (sipdebug) { 24253 ast_debug(3, "This SIP transfer is local : %s\n", p->refer->refer_to_domain); 24254 } 24255 } else if (AST_LIST_EMPTY(&domain_list) || check_sip_domain(p->refer->refer_to_domain, NULL, 0)) { 24256 /* This PBX doesn't bother with SIP domains or domain is local, so this transfer is local */ 24257 p->refer->localtransfer = 1; 24258 } else if (sipdebug) { 24259 ast_debug(3, "This SIP transfer is to a remote SIP extension (remote domain %s)\n", p->refer->refer_to_domain); 24260 } 24261 24262 /* Is this a repeat of a current request? Ignore it */ 24263 /* Don't know what else to do right now. */ 24264 if (req->ignore) { 24265 goto handle_refer_cleanup; 24266 } 24267 24268 /* If this is a blind transfer, we have the following 24269 channels to work with: 24270 - chan1, chan2: The current call between transferer and transferee (2 channels) 24271 - target_channel: A new call from the transferee to the target (1 channel) 24272 We need to stay tuned to what happens in order to be able 24273 to bring back the call to the transferer */ 24274 24275 /* If this is a attended transfer, we should have all call legs within reach: 24276 - chan1, chan2: The call between the transferer and transferee (2 channels) 24277 - target_channel, targetcall_pvt: The call between the transferer and the target (2 channels) 24278 We want to bridge chan2 with targetcall_pvt! 24279 24280 The replaces call id in the refer message points 24281 to the call leg between Asterisk and the transferer. 24282 So we need to connect the target and the transferee channel 24283 and hangup the two other channels silently 24284 24285 If the target is non-local, the call ID could be on a remote 24286 machine and we need to send an INVITE with replaces to the 24287 target. We basically handle this as a blind transfer 24288 and let the sip_call function catch that we need replaces 24289 header in the INVITE. 24290 */ 24291 24292 /* Get the transferer's channel */ 24293 chans[0] = current.chan1 = p->owner; 24294 24295 /* Find the other part of the bridge (2) - transferee */ 24296 chans[1] = current.chan2 = ast_bridged_channel(current.chan1); 24297 24298 ast_channel_ref(current.chan1); 24299 if (current.chan2) { 24300 ast_channel_ref(current.chan2); 24301 } 24302 24303 if (sipdebug) { 24304 ast_debug(3, "SIP %s transfer: Transferer channel %s, transferee channel %s\n", 24305 p->refer->attendedtransfer ? "attended" : "blind", 24306 ast_channel_name(current.chan1), 24307 current.chan2 ? ast_channel_name(current.chan2) : "<none>"); 24308 } 24309 24310 if (!current.chan2 && !p->refer->attendedtransfer) { 24311 /* No bridged channel, propably IVR or echo or similar... */ 24312 /* Guess we should masquerade or something here */ 24313 /* Until we figure it out, refuse transfer of such calls */ 24314 if (sipdebug) { 24315 ast_debug(3, "Refused SIP transfer on non-bridged channel.\n"); 24316 } 24317 p->refer->status = REFER_FAILED; 24318 append_history(p, "Xfer", "Refer failed. Non-bridged channel."); 24319 transmit_response(p, "603 Declined", req); 24320 res = -1; 24321 goto handle_refer_cleanup; 24322 } 24323 24324 if (current.chan2) { 24325 if (sipdebug) { 24326 ast_debug(4, "Got SIP transfer, applying to bridged peer '%s'\n", ast_channel_name(current.chan2)); 24327 } 24328 ast_queue_control(current.chan1, AST_CONTROL_UNHOLD); 24329 } 24330 24331 ast_set_flag(&p->flags[0], SIP_GOTREFER); 24332 24333 /* From here on failures will be indicated with NOTIFY requests */ 24334 transmit_response(p, "202 Accepted", req); 24335 24336 /* Attended transfer: Find all call legs and bridge transferee with target*/ 24337 if (p->refer->attendedtransfer) { 24338 /* both p and p->owner _MUST_ be locked while calling local_attended_transfer */ 24339 if ((res = local_attended_transfer(p, ¤t, req, seqno, nounlock))) { 24340 goto handle_refer_cleanup; /* We're done with the transfer */ 24341 } 24342 /* Fall through for remote transfers that we did not find locally */ 24343 if (sipdebug) { 24344 ast_debug(4, "SIP attended transfer: Still not our call - generating INVITE with replaces\n"); 24345 } 24346 /* Fallthrough if we can't find the call leg internally */ 24347 } 24348 24349 /* Copy data we can not safely access after letting the pvt lock go. */ 24350 refer_to = ast_strdupa(p->refer->refer_to); 24351 refer_to_domain = ast_strdupa(p->refer->refer_to_domain); 24352 refer_to_context = ast_strdupa(p->refer->refer_to_context); 24353 referred_by = ast_strdupa(p->refer->referred_by); 24354 callid = ast_strdupa(p->callid); 24355 localtransfer = p->refer->localtransfer; 24356 attendedtransfer = p->refer->attendedtransfer; 24357 24358 if (!*nounlock) { 24359 ast_channel_unlock(p->owner); 24360 *nounlock = 1; 24361 } 24362 sip_pvt_unlock(p); 24363 24364 /* Parking a call. DO NOT hold any locks while calling ast_parking_ext_valid() */ 24365 if (localtransfer && ast_parking_ext_valid(refer_to, current.chan1, current.chan1->context)) { 24366 sip_pvt_lock(p); 24367 ast_clear_flag(&p->flags[0], SIP_GOTREFER); 24368 p->refer->status = REFER_200OK; 24369 append_history(p, "Xfer", "REFER to call parking."); 24370 sip_pvt_unlock(p); 24371 24372 ast_manager_event_multichan(EVENT_FLAG_CALL, "Transfer", 2, chans, 24373 "TransferMethod: SIP\r\n" 24374 "TransferType: Blind\r\n" 24375 "Channel: %s\r\n" 24376 "Uniqueid: %s\r\n" 24377 "SIP-Callid: %s\r\n" 24378 "TargetChannel: %s\r\n" 24379 "TargetUniqueid: %s\r\n" 24380 "TransferExten: %s\r\n" 24381 "Transfer2Parking: Yes\r\n", 24382 ast_channel_name(current.chan1), 24383 ast_channel_uniqueid(current.chan1), 24384 callid, 24385 ast_channel_name(current.chan2), 24386 ast_channel_uniqueid(current.chan2), 24387 refer_to); 24388 24389 if (sipdebug) { 24390 ast_debug(4, "SIP transfer to parking: trying to park %s. Parked by %s\n", ast_channel_name(current.chan2), ast_channel_name(current.chan1)); 24391 } 24392 24393 /* DO NOT hold any locks while calling sip_park */ 24394 if (sip_park(current.chan2, current.chan1, req, seqno, refer_to, current.chan1->context)) { 24395 sip_pvt_lock(p); 24396 transmit_notify_with_sipfrag(p, seqno, "500 Internal Server Error", TRUE); 24397 } else { 24398 sip_pvt_lock(p); 24399 } 24400 goto handle_refer_cleanup; 24401 } 24402 24403 /* Blind transfers and remote attended xfers. 24404 * Locks should not be held while calling pbx_builtin_setvar_helper. This function 24405 * locks the channel being passed into it.*/ 24406 if (current.chan1 && current.chan2) { 24407 ast_debug(3, "chan1->name: %s\n", ast_channel_name(current.chan1)); 24408 pbx_builtin_setvar_helper(current.chan1, "BLINDTRANSFER", ast_channel_name(current.chan2)); 24409 } 24410 24411 if (current.chan2) { 24412 pbx_builtin_setvar_helper(current.chan2, "BLINDTRANSFER", ast_channel_name(current.chan1)); 24413 pbx_builtin_setvar_helper(current.chan2, "SIPDOMAIN", refer_to_domain); 24414 pbx_builtin_setvar_helper(current.chan2, "SIPTRANSFER", "yes"); 24415 /* One for the new channel */ 24416 pbx_builtin_setvar_helper(current.chan2, "_SIPTRANSFER", "yes"); 24417 /* Attended transfer to remote host, prepare headers for the INVITE */ 24418 if (!ast_strlen_zero(referred_by)) { 24419 pbx_builtin_setvar_helper(current.chan2, "_SIPTRANSFER_REFERER", referred_by); 24420 } 24421 } 24422 24423 sip_pvt_lock(p); 24424 /* Generate a Replaces string to be used in the INVITE during attended transfer */ 24425 if (!ast_strlen_zero(p->refer->replaces_callid)) { 24426 char tempheader[SIPBUFSIZE]; 24427 snprintf(tempheader, sizeof(tempheader), "%s%s%s%s%s", p->refer->replaces_callid, 24428 p->refer->replaces_callid_totag ? ";to-tag=" : "", 24429 p->refer->replaces_callid_totag, 24430 p->refer->replaces_callid_fromtag ? ";from-tag=" : "", 24431 p->refer->replaces_callid_fromtag); 24432 24433 if (current.chan2) { 24434 sip_pvt_unlock(p); 24435 pbx_builtin_setvar_helper(current.chan2, "_SIPTRANSFER_REPLACES", tempheader); 24436 sip_pvt_lock(p); 24437 } 24438 } 24439 24440 /* Connect the call */ 24441 24442 /* FAKE ringing if not attended transfer */ 24443 if (!p->refer->attendedtransfer) { 24444 transmit_notify_with_sipfrag(p, seqno, "180 Ringing", FALSE); 24445 } 24446 24447 /* For blind transfer, this will lead to a new call */ 24448 /* For attended transfer to remote host, this will lead to 24449 a new SIP call with a replaces header, if the dial plan allows it 24450 */ 24451 if (!current.chan2) { 24452 /* We have no bridge, so we're talking with Asterisk somehow */ 24453 /* We need to masquerade this call */ 24454 /* What to do to fix this situation: 24455 * Set up the new call in a new channel 24456 * Let the new channel masq into this channel 24457 Please add that code here :-) 24458 */ 24459 p->refer->status = REFER_FAILED; 24460 transmit_notify_with_sipfrag(p, seqno, "503 Service Unavailable (can't handle one-legged xfers)", TRUE); 24461 ast_clear_flag(&p->flags[0], SIP_GOTREFER); 24462 append_history(p, "Xfer", "Refer failed (only bridged calls)."); 24463 res = -1; 24464 goto handle_refer_cleanup; 24465 } 24466 ast_set_flag(&p->flags[0], SIP_DEFER_BYE_ON_TRANSFER); /* Delay hangup */ 24467 24468 /* Do not hold the pvt lock during the indicate and async_goto. Those functions 24469 * lock channels which will invalidate locking order if the pvt lock is held.*/ 24470 /* For blind transfers, move the call to the new extensions. For attended transfers on multiple 24471 * servers - generate an INVITE with Replaces. Either way, let the dial plan decided 24472 * indicate before masquerade so the indication actually makes it to the real channel 24473 * when using local channels with MOH passthru */ 24474 sip_pvt_unlock(p); 24475 ast_indicate(current.chan2, AST_CONTROL_UNHOLD); 24476 res = ast_async_goto(current.chan2, refer_to_context, refer_to, 1); 24477 24478 if (!res) { 24479 ast_manager_event_multichan(EVENT_FLAG_CALL, "Transfer", 2, chans, 24480 "TransferMethod: SIP\r\n" 24481 "TransferType: Blind\r\n" 24482 "Channel: %s\r\n" 24483 "Uniqueid: %s\r\n" 24484 "SIP-Callid: %s\r\n" 24485 "TargetChannel: %s\r\n" 24486 "TargetUniqueid: %s\r\n" 24487 "TransferExten: %s\r\n" 24488 "TransferContext: %s\r\n", 24489 ast_channel_name(current.chan1), 24490 ast_channel_uniqueid(current.chan1), 24491 callid, 24492 ast_channel_name(current.chan2), 24493 ast_channel_uniqueid(current.chan2), 24494 refer_to, 24495 refer_to_context); 24496 /* Success - we have a new channel */ 24497 ast_debug(3, "%s transfer succeeded. Telling transferer.\n", attendedtransfer? "Attended" : "Blind"); 24498 24499 /* XXX - what to we put in CEL 'extra' for attended transfers to external systems? NULL for now */ 24500 ast_channel_lock(current.chan1); 24501 ast_cel_report_event(current.chan1, p->refer->attendedtransfer? AST_CEL_ATTENDEDTRANSFER : AST_CEL_BLINDTRANSFER, NULL, p->refer->attendedtransfer ? NULL : p->refer->refer_to, current.chan2); 24502 ast_channel_unlock(current.chan1); 24503 24504 sip_pvt_lock(p); 24505 transmit_notify_with_sipfrag(p, seqno, "200 Ok", TRUE); 24506 if (p->refer->localtransfer) { 24507 p->refer->status = REFER_200OK; 24508 } 24509 if (p->owner) { 24510 p->owner->hangupcause = AST_CAUSE_NORMAL_CLEARING; 24511 } 24512 append_history(p, "Xfer", "Refer succeeded."); 24513 ast_clear_flag(&p->flags[0], SIP_GOTREFER); 24514 /* Do not hangup call, the other side do that when we say 200 OK */ 24515 /* We could possibly implement a timer here, auto congestion */ 24516 res = 0; 24517 } else { 24518 sip_pvt_lock(p); 24519 ast_clear_flag(&p->flags[0], SIP_DEFER_BYE_ON_TRANSFER); /* Don't delay hangup */ 24520 ast_debug(3, "%s transfer failed. Resuming original call.\n", p->refer->attendedtransfer? "Attended" : "Blind"); 24521 append_history(p, "Xfer", "Refer failed."); 24522 /* Failure of some kind */ 24523 p->refer->status = REFER_FAILED; 24524 transmit_notify_with_sipfrag(p, seqno, "503 Service Unavailable", TRUE); 24525 ast_clear_flag(&p->flags[0], SIP_GOTREFER); 24526 res = -1; 24527 } 24528 24529 handle_refer_cleanup: 24530 if (current.chan1) { 24531 ast_channel_unref(current.chan1); 24532 } 24533 if (current.chan2) { 24534 ast_channel_unref(current.chan2); 24535 } 24536 24537 /* Make sure we exit with the pvt locked */ 24538 return res; 24539 }
| static int handle_request_register | ( | struct sip_pvt * | p, | |
| struct sip_request * | req, | |||
| struct ast_sockaddr * | sin, | |||
| const char * | e | |||
| ) | [static] |
Handle incoming REGISTER request.
Definition at line 25899 of file chan_sip.c.
References append_history, ast_debug, ast_log(), ast_sockaddr_stringify(), check_via(), copy_request(), LOG_NOTICE, LOG_WARNING, register_verify(), sip_get_header(), sip_methods, sip_scheddestroy(), and cfsip_methods::text.
Referenced by handle_incoming().
25900 { 25901 enum check_auth_result res; 25902 25903 /* If this is not the intial request, and the initial request isn't 25904 * a register, something screwy happened, so bail */ 25905 if (p->initreq.headers && p->initreq.method != SIP_REGISTER) { 25906 ast_log(LOG_WARNING, "Ignoring spurious REGISTER with Call-ID: %s\n", p->callid); 25907 return -1; 25908 } 25909 25910 /* Use this as the basis */ 25911 copy_request(&p->initreq, req); 25912 if (sipdebug) 25913 ast_debug(4, "Initializing initreq for method %s - callid %s\n", sip_methods[req->method].text, p->callid); 25914 check_via(p, req); 25915 25916 if ((res = register_verify(p, addr, req, e)) < 0) { 25917 const char *reason; 25918 25919 switch (res) { 25920 case AUTH_SECRET_FAILED: 25921 reason = "Wrong password"; 25922 break; 25923 case AUTH_USERNAME_MISMATCH: 25924 reason = "Username/auth name mismatch"; 25925 break; 25926 case AUTH_NOT_FOUND: 25927 reason = "No matching peer found"; 25928 break; 25929 case AUTH_UNKNOWN_DOMAIN: 25930 reason = "Not a local domain"; 25931 break; 25932 case AUTH_PEER_NOT_DYNAMIC: 25933 reason = "Peer is not supposed to register"; 25934 break; 25935 case AUTH_ACL_FAILED: 25936 reason = "Device does not match ACL"; 25937 break; 25938 case AUTH_BAD_TRANSPORT: 25939 reason = "Device not configured to use this transport type"; 25940 break; 25941 case AUTH_RTP_FAILED: 25942 reason = "RTP initialization failed"; 25943 break; 25944 default: 25945 reason = "Unknown failure"; 25946 break; 25947 } 25948 ast_log(LOG_NOTICE, "Registration from '%s' failed for '%s' - %s\n", 25949 sip_get_header(req, "To"), ast_sockaddr_stringify(addr), 25950 reason); 25951 append_history(p, "RegRequest", "Failed : Account %s : %s", sip_get_header(req, "To"), reason); 25952 } else { 25953 req->authenticated = 1; 25954 append_history(p, "RegRequest", "Succeeded : Account %s", sip_get_header(req, "To")); 25955 } 25956 25957 if (res != AUTH_CHALLENGE_SENT) { 25958 /* Destroy the session, but keep us around for just a bit in case they don't 25959 get our 200 OK */ 25960 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 25961 } 25962 25963 return res; 25964 }
| static int handle_request_subscribe | ( | struct sip_pvt * | p, | |
| struct sip_request * | req, | |||
| struct ast_sockaddr * | addr, | |||
| uint32_t | seqno, | |||
| const char * | e | |||
| ) | [static] |
Handle incoming SUBSCRIBE request.
Definition at line 25512 of file chan_sip.c.
References __get_header(), add_peer_mwi_subs(), ao2_lock, ao2_unlock, append_history, ast_debug, ast_extension_state(), ast_extension_state2str(), ast_extension_state_add_destroy(), ast_extension_state_del(), AST_LIST_EMPTY, ast_log(), ast_set_flag, ast_sockaddr_stringify(), ast_strdupa, ast_string_field_build, ast_strlen_zero(), ast_test_flag, ast_verbose, build_contact(), build_route(), cb_extensionstate(), cb_extensionstate_destroy(), check_user_full(), check_via(), copy_request(), dialog_unlink_all(), FALSE, get_destination(), gettag(), handle_cc_subscribe(), LOG_NOTICE, LOG_WARNING, make_our_tag(), NONE, option_debug, parse_ok_contact(), pvt_set_needdestroy(), S_OR, set_pvt_allowed_methods(), sip_cancel_destroy(), sip_cfg, sip_get_header(), sip_methods, sip_ref_peer(), sip_scheddestroy(), sip_send_mwi_to_peer(), sip_unref_peer(), cfsip_methods::text, transmit_fake_auth_response(), transmit_response(), transmit_response_reliable(), transmit_response_with_minexpires(), and transmit_state_notify().
Referenced by handle_incoming().
25513 { 25514 int gotdest = 0; 25515 int res = 0; 25516 int firststate; 25517 struct sip_peer *authpeer = NULL; 25518 const char *eventheader = sip_get_header(req, "Event"); /* Get Event package name */ 25519 int resubscribe = (p->subscribed != NONE) && !req->ignore; 25520 char *temp, *event; 25521 25522 if (p->initreq.headers) { 25523 /* We already have a dialog */ 25524 if (p->initreq.method != SIP_SUBSCRIBE) { 25525 /* This is a SUBSCRIBE within another SIP dialog, which we do not support */ 25526 /* For transfers, this could happen, but since we haven't seen it happening, let us just refuse this */ 25527 transmit_response(p, "403 Forbidden (within dialog)", req); 25528 /* Do not destroy session, since we will break the call if we do */ 25529 ast_debug(1, "Got a subscription within the context of another call, can't handle that - %s (Method %s)\n", p->callid, sip_methods[p->initreq.method].text); 25530 return 0; 25531 } else if (req->debug) { 25532 if (resubscribe) 25533 ast_debug(1, "Got a re-subscribe on existing subscription %s\n", p->callid); 25534 else 25535 ast_debug(1, "Got a new subscription %s (possibly with auth) or retransmission\n", p->callid); 25536 } 25537 } 25538 25539 /* Check if we have a global disallow setting on subscriptions. 25540 if so, we don't have to check peer settings after auth, which saves a lot of processing 25541 */ 25542 if (!sip_cfg.allowsubscribe) { 25543 transmit_response(p, "403 Forbidden (policy)", req); 25544 pvt_set_needdestroy(p, "forbidden"); 25545 return 0; 25546 } 25547 25548 if (!req->ignore && !resubscribe) { /* Set up dialog, new subscription */ 25549 const char *to = sip_get_header(req, "To"); 25550 char totag[128]; 25551 set_pvt_allowed_methods(p, req); 25552 25553 /* Check to see if a tag was provided, if so this is actually a resubscription of a dialog we no longer know about */ 25554 if (!ast_strlen_zero(to) && gettag(req, "To", totag, sizeof(totag))) { 25555 if (req->debug) 25556 ast_verbose("Received resubscription for a dialog we no longer know about. Telling remote side to subscribe again.\n"); 25557 transmit_response(p, "481 Subscription does not exist", req); 25558 pvt_set_needdestroy(p, "subscription does not exist"); 25559 return 0; 25560 } 25561 25562 /* Use this as the basis */ 25563 if (req->debug) 25564 ast_verbose("Creating new subscription\n"); 25565 25566 copy_request(&p->initreq, req); 25567 if (sipdebug) 25568 ast_debug(4, "Initializing initreq for method %s - callid %s\n", sip_methods[req->method].text, p->callid); 25569 check_via(p, req); 25570 build_route(p, req, 0); 25571 } else if (req->debug && req->ignore) 25572 ast_verbose("Ignoring this SUBSCRIBE request\n"); 25573 25574 /* Find parameters to Event: header value and remove them for now */ 25575 if (ast_strlen_zero(eventheader)) { 25576 transmit_response(p, "489 Bad Event", req); 25577 ast_debug(2, "Received SIP subscribe for unknown event package: <none>\n"); 25578 pvt_set_needdestroy(p, "unknown event package in subscribe"); 25579 return 0; 25580 } 25581 25582 if ( (strchr(eventheader, ';'))) { 25583 event = ast_strdupa(eventheader); /* Since eventheader is a const, we can't change it */ 25584 temp = strchr(event, ';'); 25585 *temp = '\0'; /* Remove any options for now */ 25586 /* We might need to use them later :-) */ 25587 } else 25588 event = (char *) eventheader; /* XXX is this legal ? */ 25589 25590 /* Handle authentication if we're new and not a retransmission. We can't just 25591 * use if !req->ignore, because then we'll end up sending 25592 * a 200 OK if someone retransmits without sending auth */ 25593 if (p->subscribed == NONE || resubscribe) { 25594 res = check_user_full(p, req, SIP_SUBSCRIBE, e, 0, addr, &authpeer); 25595 25596 /* if an authentication response was sent, we are done here */ 25597 if (res == AUTH_CHALLENGE_SENT) /* authpeer = NULL here */ 25598 return 0; 25599 if (res != AUTH_SUCCESSFUL) { 25600 if (res == AUTH_FAKE_AUTH) { 25601 ast_log(LOG_NOTICE, "Sending fake auth rejection for device %s\n", sip_get_header(req, "From")); 25602 transmit_fake_auth_response(p, SIP_SUBSCRIBE, req, XMIT_UNRELIABLE); 25603 } else { 25604 ast_log(LOG_NOTICE, "Failed to authenticate device %s for SUBSCRIBE\n", sip_get_header(req, "From")); 25605 transmit_response_reliable(p, "403 Forbidden", req); 25606 } 25607 25608 pvt_set_needdestroy(p, "authentication failed"); 25609 return 0; 25610 } 25611 } 25612 25613 /* At this point, we hold a reference to authpeer (if not NULL). It 25614 * must be released when done. 25615 */ 25616 25617 /* Check if this device is allowed to subscribe at all */ 25618 if (!ast_test_flag(&p->flags[1], SIP_PAGE2_ALLOWSUBSCRIBE)) { 25619 transmit_response(p, "403 Forbidden (policy)", req); 25620 pvt_set_needdestroy(p, "subscription not allowed"); 25621 if (authpeer) { 25622 sip_unref_peer(authpeer, "sip_unref_peer, from handle_request_subscribe (authpeer 1)"); 25623 } 25624 return 0; 25625 } 25626 25627 if (strcmp(event, "message-summary") && strcmp(event, "call-completion")) { 25628 /* Get destination right away */ 25629 gotdest = get_destination(p, NULL, NULL); 25630 } 25631 25632 /* Get full contact header - this needs to be used as a request URI in NOTIFY's */ 25633 parse_ok_contact(p, req); 25634 25635 build_contact(p); 25636 if (gotdest != SIP_GET_DEST_EXTEN_FOUND) { 25637 if (gotdest == SIP_GET_DEST_INVALID_URI) { 25638 transmit_response(p, "416 Unsupported URI scheme", req); 25639 } else { 25640 transmit_response(p, "404 Not Found", req); 25641 } 25642 pvt_set_needdestroy(p, "subscription target not found"); 25643 if (authpeer) { 25644 sip_unref_peer(authpeer, "sip_unref_peer, from handle_request_subscribe (authpeer 2)"); 25645 } 25646 return 0; 25647 } 25648 25649 /* Initialize tag for new subscriptions */ 25650 if (ast_strlen_zero(p->tag)) 25651 make_our_tag(p->tag, sizeof(p->tag)); 25652 25653 if (!strcmp(event, "presence") || !strcmp(event, "dialog")) { /* Presence, RFC 3842 */ 25654 unsigned int pidf_xml; 25655 const char *accept; 25656 int start = 0; 25657 enum subscriptiontype subscribed = NONE; 25658 const char *unknown_acceptheader = NULL; 25659 25660 /* Header from Xten Eye-beam Accept: multipart/related, application/rlmi+xml, application/pidf+xml, application/xpidf+xml */ 25661 accept = __get_header(req, "Accept", &start); 25662 while ((subscribed == NONE) && !ast_strlen_zero(accept)) { 25663 pidf_xml = strstr(accept, "application/pidf+xml") ? 1 : 0; 25664 25665 /* Older versions of Polycom firmware will claim pidf+xml, but really 25666 * they only support xpidf+xml. */ 25667 if (pidf_xml && strstr(p->useragent, "Polycom")) { 25668 subscribed = XPIDF_XML; 25669 } else if (pidf_xml) { 25670 subscribed = PIDF_XML; /* RFC 3863 format */ 25671 } else if (strstr(accept, "application/dialog-info+xml")) { 25672 subscribed = DIALOG_INFO_XML; 25673 /* IETF draft: draft-ietf-sipping-dialog-package-05.txt */ 25674 } else if (strstr(accept, "application/cpim-pidf+xml")) { 25675 subscribed = CPIM_PIDF_XML; /* RFC 3863 format */ 25676 } else if (strstr(accept, "application/xpidf+xml")) { 25677 subscribed = XPIDF_XML; /* Early pre-RFC 3863 format with MSN additions (Microsoft Messenger) */ 25678 } else { 25679 unknown_acceptheader = accept; 25680 } 25681 /* check to see if there is another Accept header present */ 25682 accept = __get_header(req, "Accept", &start); 25683 } 25684 25685 if (!start) { 25686 if (p->subscribed == NONE) { /* if the subscribed field is not already set, and there is no accept header... */ 25687 transmit_response(p, "489 Bad Event", req); 25688 ast_log(LOG_WARNING,"SUBSCRIBE failure: no Accept header: pvt: " 25689 "stateid: %d, laststate: %d, dialogver: %u, subscribecont: " 25690 "'%s', subscribeuri: '%s'\n", 25691 p->stateid, 25692 p->laststate, 25693 p->dialogver, 25694 p->subscribecontext, 25695 p->subscribeuri); 25696 pvt_set_needdestroy(p, "no Accept header"); 25697 if (authpeer) { 25698 sip_unref_peer(authpeer, "sip_unref_peer, from handle_request_subscribe (authpeer 2)"); 25699 } 25700 return 0; 25701 } 25702 /* if p->subscribed is non-zero, then accept is not obligatory; according to rfc 3265 section 3.1.3, at least. 25703 so, we'll just let it ride, keeping the value from a previous subscription, and not abort the subscription */ 25704 } else if (subscribed == NONE) { 25705 /* Can't find a format for events that we know about */ 25706 char mybuf[200]; 25707 if (!ast_strlen_zero(unknown_acceptheader)) { 25708 snprintf(mybuf, sizeof(mybuf), "489 Bad Event (format %s)", unknown_acceptheader); 25709 } else { 25710 snprintf(mybuf, sizeof(mybuf), "489 Bad Event"); 25711 } 25712 transmit_response(p, mybuf, req); 25713 ast_log(LOG_WARNING,"SUBSCRIBE failure: unrecognized format:" 25714 "'%s' pvt: subscribed: %d, stateid: %d, laststate: %d," 25715 "dialogver: %u, subscribecont: '%s', subscribeuri: '%s'\n", 25716 unknown_acceptheader, 25717 (int)p->subscribed, 25718 p->stateid, 25719 p->laststate, 25720 p->dialogver, 25721 p->subscribecontext, 25722 p->subscribeuri); 25723 pvt_set_needdestroy(p, "unrecognized format"); 25724 if (authpeer) { 25725 sip_unref_peer(authpeer, "sip_unref_peer, from handle_request_subscribe (authpeer 2)"); 25726 } 25727 return 0; 25728 } else { 25729 p->subscribed = subscribed; 25730 } 25731 } else if (!strcmp(event, "message-summary")) { 25732 int start = 0; 25733 int found_supported = 0; 25734 const char *acceptheader; 25735 25736 acceptheader = __get_header(req, "Accept", &start); 25737 while (!found_supported && !ast_strlen_zero(acceptheader)) { 25738 found_supported = strcmp(acceptheader, "application/simple-message-summary") ? 0 : 1; 25739 if (!found_supported && (option_debug > 2)) { 25740 ast_debug(1, "Received SIP mailbox subscription for unknown format: %s\n", acceptheader); 25741 } 25742 acceptheader = __get_header(req, "Accept", &start); 25743 } 25744 if (start && !found_supported) { 25745 /* Format requested that we do not support */ 25746 transmit_response(p, "406 Not Acceptable", req); 25747 ast_debug(2, "Received SIP mailbox subscription for unknown format: %s\n", acceptheader); 25748 pvt_set_needdestroy(p, "unknown format"); 25749 if (authpeer) { 25750 sip_unref_peer(authpeer, "sip_unref_peer, from handle_request_subscribe (authpeer 3)"); 25751 } 25752 return 0; 25753 } 25754 /* Looks like they actually want a mailbox status 25755 This version of Asterisk supports mailbox subscriptions 25756 The subscribed URI needs to exist in the dial plan 25757 In most devices, this is configurable to the voicemailmain extension you use 25758 */ 25759 if (!authpeer || AST_LIST_EMPTY(&authpeer->mailboxes)) { 25760 if (!authpeer) { 25761 transmit_response(p, "404 Not found", req); 25762 } else { 25763 transmit_response(p, "404 Not found (no mailbox)", req); 25764 ast_log(LOG_NOTICE, "Received SIP subscribe for peer without mailbox: %s\n", S_OR(authpeer->name, "")); 25765 } 25766 pvt_set_needdestroy(p, "received 404 response"); 25767 25768 if (authpeer) { 25769 sip_unref_peer(authpeer, "sip_unref_peer, from handle_request_subscribe (authpeer 3)"); 25770 } 25771 return 0; 25772 } 25773 25774 p->subscribed = MWI_NOTIFICATION; 25775 if (ast_test_flag(&authpeer->flags[1], SIP_PAGE2_SUBSCRIBEMWIONLY)) { 25776 ao2_unlock(p); 25777 add_peer_mwi_subs(authpeer); 25778 ao2_lock(p); 25779 } 25780 if (authpeer->mwipvt != p) { /* Destroy old PVT if this is a new one */ 25781 /* We only allow one subscription per peer */ 25782 if (authpeer->mwipvt) { 25783 dialog_unlink_all(authpeer->mwipvt); 25784 authpeer->mwipvt = dialog_unref(authpeer->mwipvt, "unref dialog authpeer->mwipvt"); 25785 } 25786 authpeer->mwipvt = dialog_ref(p, "setting peers' mwipvt to p"); 25787 } 25788 25789 if (p->relatedpeer != authpeer) { 25790 if (p->relatedpeer) { 25791 sip_unref_peer(p->relatedpeer, "Unref previously stored relatedpeer ptr"); 25792 } 25793 p->relatedpeer = sip_ref_peer(authpeer, "setting dialog's relatedpeer pointer"); 25794 } 25795 /* Do not release authpeer here */ 25796 } else if (!strcmp(event, "call-completion")) { 25797 handle_cc_subscribe(p, req); 25798 } else { /* At this point, Asterisk does not understand the specified event */ 25799 transmit_response(p, "489 Bad Event", req); 25800 ast_debug(2, "Received SIP subscribe for unknown event package: %s\n", event); 25801 pvt_set_needdestroy(p, "unknown event package"); 25802 if (authpeer) { 25803 sip_unref_peer(authpeer, "sip_unref_peer, from handle_request_subscribe (authpeer 5)"); 25804 } 25805 return 0; 25806 } 25807 25808 /* Add subscription for extension state from the PBX core */ 25809 if (p->subscribed != MWI_NOTIFICATION && p->subscribed != CALL_COMPLETION && !resubscribe) { 25810 if (p->stateid != -1) { 25811 ast_extension_state_del(p->stateid, cb_extensionstate); 25812 } 25813 dialog_ref(p, "copying dialog ptr into extension state struct"); 25814 p->stateid = ast_extension_state_add_destroy(p->context, p->exten, 25815 cb_extensionstate, cb_extensionstate_destroy, p); 25816 if (p->stateid == -1) { 25817 dialog_unref(p, "copying dialog ptr into extension state struct failed"); 25818 } 25819 } 25820 25821 if (!req->ignore && p) 25822 p->lastinvite = seqno; 25823 if (p && !p->needdestroy) { 25824 p->expiry = atoi(sip_get_header(req, "Expires")); 25825 25826 /* check if the requested expiry-time is within the approved limits from sip.conf */ 25827 if (p->expiry > max_expiry) { 25828 p->expiry = max_expiry; 25829 } else if (p->expiry < min_expiry && p->expiry > 0) { 25830 transmit_response_with_minexpires(p, "423 Interval too small", req); 25831 ast_log(LOG_WARNING, "Received subscription for extension \"%s\" context \"%s\" " 25832 "with Expire header less that 'minexpire' limit. Received \"Expire: %d\" min is %d\n", 25833 p->exten, p->context, p->expiry, min_expiry); 25834 pvt_set_needdestroy(p, "Expires is less that the min expires allowed."); 25835 if (authpeer) { 25836 sip_unref_peer(authpeer, "sip_unref_peer, from handle_request_subscribe (authpeer 6)"); 25837 } 25838 return 0; 25839 } 25840 25841 if (sipdebug) { 25842 if (p->subscribed == MWI_NOTIFICATION && p->relatedpeer) { 25843 ast_debug(2, "Adding subscription for mailbox notification - peer %s\n", p->relatedpeer->name); 25844 } else if (p->subscribed == CALL_COMPLETION) { 25845 ast_debug(2, "Adding CC subscription for peer %s\n", p->username); 25846 } else { 25847 ast_debug(2, "Adding subscription for extension %s context %s for peer %s\n", p->exten, p->context, p->username); 25848 } 25849 } 25850 if (p->autokillid > -1 && sip_cancel_destroy(p)) /* Remove subscription expiry for renewals */ 25851 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 25852 if (p->expiry > 0) 25853 sip_scheddestroy(p, (p->expiry + 10) * 1000); /* Set timer for destruction of call at expiration */ 25854 25855 if (p->subscribed == MWI_NOTIFICATION) { 25856 ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED); 25857 transmit_response(p, "200 OK", req); 25858 if (p->relatedpeer) { /* Send first notification */ 25859 struct sip_peer *peer = p->relatedpeer; 25860 sip_ref_peer(peer, "ensure a peer ref is held during MWI sending"); 25861 ao2_unlock(p); 25862 sip_send_mwi_to_peer(peer, 0); 25863 ao2_lock(p); 25864 sip_unref_peer(peer, "release a peer ref now that MWI is sent"); 25865 } 25866 } else if (p->subscribed != CALL_COMPLETION) { 25867 25868 if ((firststate = ast_extension_state(NULL, p->context, p->exten)) < 0) { 25869 25870 ast_log(LOG_NOTICE, "Got SUBSCRIBE for extension %s@%s from %s, but there is no hint for that extension.\n", p->exten, p->context, ast_sockaddr_stringify(&p->sa)); 25871 transmit_response(p, "404 Not found", req); 25872 pvt_set_needdestroy(p, "no extension for SUBSCRIBE"); 25873 if (authpeer) { 25874 sip_unref_peer(authpeer, "sip_unref_peer, from handle_request_subscribe (authpeer 6)"); 25875 } 25876 return 0; 25877 } 25878 ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED); 25879 transmit_response(p, "200 OK", req); 25880 transmit_state_notify(p, firststate, 1, FALSE); /* Send first notification */ 25881 append_history(p, "Subscribestatus", "%s", ast_extension_state2str(firststate)); 25882 /* hide the 'complete' exten/context in the refer_to field for later display */ 25883 ast_string_field_build(p, subscribeuri, "%s@%s", p->exten, p->context); 25884 /* Deleted the slow iteration of all sip dialogs to find old subscribes from this peer for exten@context */ 25885 25886 } 25887 if (!p->expiry) { 25888 pvt_set_needdestroy(p, "forcing expiration"); 25889 } 25890 } 25891 25892 if (authpeer) { 25893 sip_unref_peer(authpeer, "unref pointer into (*authpeer)"); 25894 } 25895 return 1; 25896 }
| static int handle_request_update | ( | struct sip_pvt * | p, | |
| struct sip_request * | req | |||
| ) | [static] |
bare-bones support for SIP UPDATE
XXX This is not even close to being RFC 3311-compliant. We don't advertise that we support the UPDATE method, so no one should ever try sending us an UPDATE anyway. However, Asterisk can send an UPDATE to change connected line information, so we need to be prepared to handle this. The way we distinguish such an UPDATE is through the X-Asterisk-rpid-update header.
Actually updating the media session may be some future work.
Definition at line 22980 of file chan_sip.c.
References ast_channel_queue_connected_line_update(), AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER, ast_party_connected_line_init(), ast_strlen_zero(), connected, get_rpid(), ast_party_connected_line::id, ast_set_party_connected_line::id, ast_party_id::name, ast_set_party_id::name, ast_party_id::number, ast_set_party_id::number, ast_party_name::presentation, ast_party_number::presentation, sip_get_header(), ast_party_connected_line::source, ast_party_name::str, ast_party_number::str, ast_party_id::tag, transmit_response(), ast_party_name::valid, and ast_party_number::valid.
Referenced by handle_incoming().
22981 { 22982 if (ast_strlen_zero(sip_get_header(req, "X-Asterisk-rpid-update"))) { 22983 transmit_response(p, "501 Method Not Implemented", req); 22984 return 0; 22985 } 22986 if (get_rpid(p, req)) { 22987 struct ast_party_connected_line connected; 22988 struct ast_set_party_connected_line update_connected; 22989 22990 ast_party_connected_line_init(&connected); 22991 memset(&update_connected, 0, sizeof(update_connected)); 22992 22993 update_connected.id.number = 1; 22994 connected.id.number.valid = 1; 22995 connected.id.number.str = (char *) p->cid_num; 22996 connected.id.number.presentation = p->callingpres; 22997 22998 update_connected.id.name = 1; 22999 connected.id.name.valid = 1; 23000 connected.id.name.str = (char *) p->cid_name; 23001 connected.id.name.presentation = p->callingpres; 23002 23003 connected.id.tag = (char *) p->cid_tag; 23004 connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER; 23005 ast_channel_queue_connected_line_update(p->owner, &connected, &update_connected); 23006 } 23007 transmit_response(p, "200 OK", req); 23008 return 0; 23009 }
| static void handle_response | ( | struct sip_pvt * | p, | |
| int | resp, | |||
| const char * | rest, | |||
| struct sip_request * | req, | |||
| uint32_t | seqno | |||
| ) | [static] |
Handle SIP response in dialogue.
Definition at line 21748 of file chan_sip.c.
References __sip_ack(), __sip_semi_ack(), append_history, AST_CAUSE_PROTOCOL_ERROR, AST_CC_CCBS, ast_channel_name(), ast_channel_set_redirecting(), ast_clear_flag, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_PROGRESS, ast_debug, ast_log(), ast_party_redirecting_free(), ast_party_redirecting_init(), ast_queue_control(), ast_queue_hangup_with_cause(), ast_set_flag, ast_skip_blanks(), ast_skip_nonblanks(), ast_sockaddr_stringify(), ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_verb, ast_verbose, change_redirecting_information(), do_proxy_auth(), FALSE, find_sdp(), find_sip_method(), gettag(), handle_response_info(), handle_response_invite(), handle_response_message(), handle_response_notify(), handle_response_peerpoke(), handle_response_publish(), handle_response_refer(), handle_response_register(), handle_response_subscribe(), handle_response_update(), hangup_sip2cause(), ast_channel::hangupcause, LOG_NOTICE, LOG_WARNING, mark_method_allowed(), mark_method_unallowed(), process_sdp(), pvt_set_needdestroy(), rh, sip_alreadygone(), sip_cancel_destroy(), sip_get_header(), sip_handle_cc(), sip_methods, stop_media_flows(), text, transmit_request(), TRUE, and update_redirecting().
21749 { 21750 struct ast_channel *owner; 21751 int sipmethod; 21752 const char *c = sip_get_header(req, "Cseq"); 21753 /* GCC 4.2 complains if I try to cast c as a char * when passing it to ast_skip_nonblanks, so make a copy of it */ 21754 char *c_copy = ast_strdupa(c); 21755 /* Skip the Cseq and its subsequent spaces */ 21756 const char *msg = ast_skip_blanks(ast_skip_nonblanks(c_copy)); 21757 21758 if (!msg) 21759 msg = ""; 21760 21761 sipmethod = find_sip_method(msg); 21762 21763 owner = p->owner; 21764 if (owner) { 21765 const char *rp = NULL, *rh = NULL; 21766 21767 owner->hangupcause = 0; 21768 if (ast_test_flag(&p->flags[1], SIP_PAGE2_Q850_REASON) && (rh = sip_get_header(req, "Reason"))) { 21769 rh = ast_skip_blanks(rh); 21770 if (!strncasecmp(rh, "Q.850", 5)) { 21771 rp = strstr(rh, "cause="); 21772 if (rp && sscanf(rp + 6, "%30d", &owner->hangupcause) == 1) { 21773 owner->hangupcause &= 0x7f; 21774 if (req->debug) 21775 ast_verbose("Using Reason header for cause code: %d\n", owner->hangupcause); 21776 } 21777 } 21778 } 21779 21780 if (!owner->hangupcause) 21781 owner->hangupcause = hangup_sip2cause(resp); 21782 } 21783 21784 if (p->socket.type == SIP_TRANSPORT_UDP) { 21785 int ack_res = FALSE; 21786 21787 /* Acknowledge whatever it is destined for */ 21788 if ((resp >= 100) && (resp <= 199)) { 21789 /* NON-INVITE messages do not ack a 1XX response. RFC 3261 section 17.1.2.2 */ 21790 if (sipmethod == SIP_INVITE) { 21791 ack_res = __sip_semi_ack(p, seqno, 0, sipmethod); 21792 } 21793 } else { 21794 ack_res = __sip_ack(p, seqno, 0, sipmethod); 21795 } 21796 21797 if (ack_res == FALSE) { 21798 /* RFC 3261 13.2.2.4 and 17.1.1.2 - We must re-send ACKs to re-transmitted final responses */ 21799 if (sipmethod == SIP_INVITE && resp >= 200) { 21800 transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, resp < 300 ? TRUE: FALSE); 21801 } 21802 21803 append_history(p, "Ignore", "Ignoring this retransmit\n"); 21804 return; 21805 } 21806 } 21807 21808 /* If this is a NOTIFY for a subscription clear the flag that indicates that we have a NOTIFY pending */ 21809 if (!p->owner && sipmethod == SIP_NOTIFY && p->pendinginvite) 21810 p->pendinginvite = 0; 21811 21812 /* Get their tag if we haven't already */ 21813 if (ast_strlen_zero(p->theirtag) || (resp >= 200)) { 21814 char tag[128]; 21815 21816 gettag(req, "To", tag, sizeof(tag)); 21817 ast_string_field_set(p, theirtag, tag); 21818 } 21819 /* This needs to be configurable on a channel/peer level, 21820 not mandatory for all communication. Sadly enough, NAT implementations 21821 are not so stable so we can always rely on these headers. 21822 Temporarily disabled, while waiting for fix. 21823 Fix assigned to Rizzo :-) 21824 */ 21825 /* check_via_response(p, req); */ 21826 21827 /* RFC 3261 Section 15 specifies that if we receive a 408 or 481 21828 * in response to a BYE, then we should end the current dialog 21829 * and session. It is known that at least one phone manufacturer 21830 * potentially will send a 404 in response to a BYE, so we'll be 21831 * liberal in what we accept and end the dialog and session if we 21832 * receive any of those responses to a BYE. 21833 */ 21834 if ((resp == 404 || resp == 408 || resp == 481) && sipmethod == SIP_BYE) { 21835 pvt_set_needdestroy(p, "received 4XX response to a BYE"); 21836 return; 21837 } 21838 21839 if (p->relatedpeer && sipmethod == SIP_OPTIONS) { 21840 /* We don't really care what the response is, just that it replied back. 21841 Well, as long as it's not a 100 response... since we might 21842 need to hang around for something more "definitive" */ 21843 if (resp != 100) 21844 handle_response_peerpoke(p, resp, req); 21845 } else if (sipmethod == SIP_REFER && resp >= 200) { 21846 handle_response_refer(p, resp, rest, req, seqno); 21847 } else if (sipmethod == SIP_PUBLISH) { 21848 /* SIP PUBLISH transcends this morass of doodoo and instead 21849 * we just always call the response handler. Good gravy! 21850 */ 21851 handle_response_publish(p, resp, rest, req, seqno); 21852 } else if (sipmethod == SIP_INFO) { 21853 /* More good gravy! */ 21854 handle_response_info(p, resp, rest, req, seqno); 21855 } else if (sipmethod == SIP_MESSAGE) { 21856 /* More good gravy! */ 21857 handle_response_message(p, resp, rest, req, seqno); 21858 } else if (sipmethod == SIP_NOTIFY) { 21859 /* The gravy train continues to roll */ 21860 handle_response_notify(p, resp, rest, req, seqno); 21861 } else if (ast_test_flag(&p->flags[0], SIP_OUTGOING)) { 21862 switch(resp) { 21863 case 100: /* 100 Trying */ 21864 case 101: /* 101 Dialog establishment */ 21865 case 183: /* 183 Session Progress */ 21866 case 180: /* 180 Ringing */ 21867 case 182: /* 182 Queued */ 21868 case 181: /* 181 Call Is Being Forwarded */ 21869 if (sipmethod == SIP_INVITE) 21870 handle_response_invite(p, resp, rest, req, seqno); 21871 break; 21872 case 200: /* 200 OK */ 21873 p->authtries = 0; /* Reset authentication counter */ 21874 if (sipmethod == SIP_INVITE) { 21875 handle_response_invite(p, resp, rest, req, seqno); 21876 } else if (sipmethod == SIP_REGISTER) { 21877 handle_response_register(p, resp, rest, req, seqno); 21878 } else if (sipmethod == SIP_SUBSCRIBE) { 21879 ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED); 21880 handle_response_subscribe(p, resp, rest, req, seqno); 21881 } else if (sipmethod == SIP_BYE) { /* Ok, we're ready to go */ 21882 pvt_set_needdestroy(p, "received 200 response"); 21883 ast_clear_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED); 21884 } 21885 break; 21886 case 401: /* Not www-authorized on SIP method */ 21887 case 407: /* Proxy auth required */ 21888 if (sipmethod == SIP_INVITE) 21889 handle_response_invite(p, resp, rest, req, seqno); 21890 else if (sipmethod == SIP_SUBSCRIBE) 21891 handle_response_subscribe(p, resp, rest, req, seqno); 21892 else if (p->registry && sipmethod == SIP_REGISTER) 21893 handle_response_register(p, resp, rest, req, seqno); 21894 else if (sipmethod == SIP_UPDATE) { 21895 handle_response_update(p, resp, rest, req, seqno); 21896 } else if (sipmethod == SIP_BYE) { 21897 if (p->options) 21898 p->options->auth_type = resp; 21899 if (ast_strlen_zero(p->authname)) { 21900 ast_log(LOG_WARNING, "Asked to authenticate %s, to %s but we have no matching peer!\n", 21901 msg, ast_sockaddr_stringify(&p->recv)); 21902 pvt_set_needdestroy(p, "unable to authenticate BYE"); 21903 } else if ((p->authtries == MAX_AUTHTRIES) || do_proxy_auth(p, req, resp, sipmethod, 0)) { 21904 ast_log(LOG_NOTICE, "Failed to authenticate on %s to '%s'\n", msg, sip_get_header(&p->initreq, "From")); 21905 pvt_set_needdestroy(p, "failed to authenticate BYE"); 21906 } 21907 } else { 21908 ast_log(LOG_WARNING, "Got authentication request (%d) on %s to '%s'\n", resp, sip_methods[sipmethod].text, sip_get_header(req, "To")); 21909 pvt_set_needdestroy(p, "received 407 response"); 21910 } 21911 break; 21912 case 403: /* Forbidden - we failed authentication */ 21913 if (sipmethod == SIP_INVITE) 21914 handle_response_invite(p, resp, rest, req, seqno); 21915 else if (sipmethod == SIP_SUBSCRIBE) 21916 handle_response_subscribe(p, resp, rest, req, seqno); 21917 else if (p->registry && sipmethod == SIP_REGISTER) 21918 handle_response_register(p, resp, rest, req, seqno); 21919 else { 21920 ast_log(LOG_WARNING, "Forbidden - maybe wrong password on authentication for %s\n", msg); 21921 pvt_set_needdestroy(p, "received 403 response"); 21922 } 21923 break; 21924 case 404: /* Not found */ 21925 if (p->registry && sipmethod == SIP_REGISTER) 21926 handle_response_register(p, resp, rest, req, seqno); 21927 else if (sipmethod == SIP_INVITE) 21928 handle_response_invite(p, resp, rest, req, seqno); 21929 else if (sipmethod == SIP_SUBSCRIBE) 21930 handle_response_subscribe(p, resp, rest, req, seqno); 21931 else if (owner) 21932 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 21933 break; 21934 case 423: /* Interval too brief */ 21935 if (sipmethod == SIP_REGISTER) 21936 handle_response_register(p, resp, rest, req, seqno); 21937 break; 21938 case 408: /* Request timeout - terminate dialog */ 21939 if (sipmethod == SIP_INVITE) 21940 handle_response_invite(p, resp, rest, req, seqno); 21941 else if (sipmethod == SIP_REGISTER) 21942 handle_response_register(p, resp, rest, req, seqno); 21943 else if (sipmethod == SIP_BYE) { 21944 pvt_set_needdestroy(p, "received 408 response"); 21945 ast_debug(4, "Got timeout on bye. Thanks for the answer. Now, kill this call\n"); 21946 } else { 21947 if (owner) 21948 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 21949 pvt_set_needdestroy(p, "received 408 response"); 21950 } 21951 break; 21952 21953 case 428: 21954 case 422: /* Session-Timers: Session Interval Too Small */ 21955 if (sipmethod == SIP_INVITE) { 21956 handle_response_invite(p, resp, rest, req, seqno); 21957 } 21958 break; 21959 21960 case 481: /* Call leg does not exist */ 21961 if (sipmethod == SIP_INVITE) { 21962 handle_response_invite(p, resp, rest, req, seqno); 21963 } else if (sipmethod == SIP_SUBSCRIBE) { 21964 handle_response_subscribe(p, resp, rest, req, seqno); 21965 } else if (sipmethod == SIP_BYE) { 21966 /* The other side has no transaction to bye, 21967 just assume it's all right then */ 21968 ast_log(LOG_WARNING, "Remote host can't match request %s to call '%s'. Giving up.\n", sip_methods[sipmethod].text, p->callid); 21969 } else if (sipmethod == SIP_CANCEL) { 21970 /* The other side has no transaction to cancel, 21971 just assume it's all right then */ 21972 ast_log(LOG_WARNING, "Remote host can't match request %s to call '%s'. Giving up.\n", sip_methods[sipmethod].text, p->callid); 21973 } else { 21974 ast_log(LOG_WARNING, "Remote host can't match request %s to call '%s'. Giving up.\n", sip_methods[sipmethod].text, p->callid); 21975 /* Guessing that this is not an important request */ 21976 } 21977 break; 21978 case 487: 21979 if (sipmethod == SIP_INVITE) 21980 handle_response_invite(p, resp, rest, req, seqno); 21981 break; 21982 case 415: /* Unsupported media type */ 21983 case 488: /* Not acceptable here - codec error */ 21984 case 606: /* Not Acceptable */ 21985 if (sipmethod == SIP_INVITE) 21986 handle_response_invite(p, resp, rest, req, seqno); 21987 break; 21988 case 491: /* Pending */ 21989 if (sipmethod == SIP_INVITE) 21990 handle_response_invite(p, resp, rest, req, seqno); 21991 else { 21992 ast_debug(1, "Got 491 on %s, unsupported. Call ID %s\n", sip_methods[sipmethod].text, p->callid); 21993 pvt_set_needdestroy(p, "received 491 response"); 21994 } 21995 break; 21996 case 405: /* Method not allowed */ 21997 case 501: /* Not Implemented */ 21998 mark_method_unallowed(&p->allowed_methods, sipmethod); 21999 if (p->relatedpeer) { 22000 mark_method_allowed(&p->relatedpeer->disallowed_methods, sipmethod); 22001 } 22002 if (sipmethod == SIP_INVITE) 22003 handle_response_invite(p, resp, rest, req, seqno); 22004 else 22005 ast_log(LOG_WARNING, "Host '%s' does not implement '%s'\n", ast_sockaddr_stringify(&p->sa), msg); 22006 break; 22007 default: 22008 if ((resp >= 200) && (resp < 300)) { /* on any 2XX response do the following */ 22009 if (sipmethod == SIP_INVITE) { 22010 handle_response_invite(p, resp, rest, req, seqno); 22011 } 22012 } else if ((resp >= 300) && (resp < 700)) { 22013 /* Fatal response */ 22014 if ((resp != 487)) 22015 ast_verb(3, "Got SIP response %d \"%s\" back from %s\n", resp, rest, ast_sockaddr_stringify(&p->sa)); 22016 22017 if (sipmethod == SIP_INVITE) 22018 stop_media_flows(p); /* Immediately stop RTP, VRTP and UDPTL as applicable */ 22019 22020 /* XXX Locking issues?? XXX */ 22021 switch(resp) { 22022 case 300: /* Multiple Choices */ 22023 case 301: /* Moved permanently */ 22024 case 302: /* Moved temporarily */ 22025 case 305: /* Use Proxy */ 22026 if (p->owner) { 22027 struct ast_party_redirecting redirecting; 22028 struct ast_set_party_redirecting update_redirecting; 22029 22030 ast_party_redirecting_init(&redirecting); 22031 change_redirecting_information(p, req, &redirecting, 22032 &update_redirecting, TRUE); 22033 ast_channel_set_redirecting(p->owner, &redirecting, 22034 &update_redirecting); 22035 ast_party_redirecting_free(&redirecting); 22036 } 22037 /* Fall through */ 22038 case 486: /* Busy here */ 22039 case 600: /* Busy everywhere */ 22040 case 603: /* Decline */ 22041 if (p->owner) { 22042 sip_handle_cc(p, req, AST_CC_CCBS); 22043 ast_queue_control(p->owner, AST_CONTROL_BUSY); 22044 } 22045 break; 22046 case 482: /* Loop Detected */ 22047 case 480: /* Temporarily Unavailable */ 22048 case 404: /* Not Found */ 22049 case 410: /* Gone */ 22050 case 400: /* Bad Request */ 22051 case 500: /* Server error */ 22052 if (sipmethod == SIP_SUBSCRIBE) { 22053 handle_response_subscribe(p, resp, rest, req, seqno); 22054 break; 22055 } 22056 /* Fall through */ 22057 case 502: /* Bad gateway */ 22058 case 503: /* Service Unavailable */ 22059 case 504: /* Server Timeout */ 22060 if (owner) 22061 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 22062 break; 22063 case 484: /* Address Incomplete */ 22064 if (owner && sipmethod != SIP_BYE) { 22065 switch (ast_test_flag(&p->flags[1], SIP_PAGE2_ALLOWOVERLAP)) { 22066 case SIP_PAGE2_ALLOWOVERLAP_YES: 22067 ast_queue_hangup_with_cause(p->owner, hangup_sip2cause(resp)); 22068 break; 22069 default: 22070 ast_queue_hangup_with_cause(p->owner, hangup_sip2cause(404)); 22071 break; 22072 } 22073 } 22074 break; 22075 default: 22076 /* Send hangup */ 22077 if (owner && sipmethod != SIP_BYE) 22078 ast_queue_hangup_with_cause(p->owner, AST_CAUSE_PROTOCOL_ERROR); 22079 break; 22080 } 22081 /* ACK on invite */ 22082 if (sipmethod == SIP_INVITE) 22083 transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); 22084 sip_alreadygone(p); 22085 if (!p->owner) { 22086 pvt_set_needdestroy(p, "transaction completed"); 22087 } 22088 } else if ((resp >= 100) && (resp < 200)) { 22089 if (sipmethod == SIP_INVITE) { 22090 if (!req->ignore && sip_cancel_destroy(p)) 22091 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 22092 if (find_sdp(req)) 22093 process_sdp(p, req, SDP_T38_NONE); 22094 if (p->owner) { 22095 /* Queue a progress frame */ 22096 ast_queue_control(p->owner, AST_CONTROL_PROGRESS); 22097 } 22098 } 22099 } else 22100 ast_log(LOG_NOTICE, "Don't know how to handle a %d %s response from %s\n", resp, rest, p->owner ? ast_channel_name(p->owner) : ast_sockaddr_stringify(&p->sa)); 22101 } 22102 } else { 22103 /* Responses to OUTGOING SIP requests on INCOMING calls 22104 get handled here. As well as out-of-call message responses */ 22105 if (req->debug) 22106 ast_verbose("SIP Response message for INCOMING dialog %s arrived\n", msg); 22107 22108 if (sipmethod == SIP_INVITE && resp == 200) { 22109 /* Tags in early session is replaced by the tag in 200 OK, which is 22110 the final reply to our INVITE */ 22111 char tag[128]; 22112 22113 gettag(req, "To", tag, sizeof(tag)); 22114 ast_string_field_set(p, theirtag, tag); 22115 } 22116 22117 switch(resp) { 22118 case 200: 22119 if (sipmethod == SIP_INVITE) { 22120 handle_response_invite(p, resp, rest, req, seqno); 22121 } else if (sipmethod == SIP_CANCEL) { 22122 ast_debug(1, "Got 200 OK on CANCEL\n"); 22123 22124 /* Wait for 487, then destroy */ 22125 } else if (sipmethod == SIP_BYE) { 22126 pvt_set_needdestroy(p, "transaction completed"); 22127 } 22128 break; 22129 case 401: /* www-auth */ 22130 case 407: 22131 if (sipmethod == SIP_INVITE) 22132 handle_response_invite(p, resp, rest, req, seqno); 22133 else if (sipmethod == SIP_BYE) { 22134 if (p->authtries == MAX_AUTHTRIES || do_proxy_auth(p, req, resp, sipmethod, 0)) { 22135 ast_log(LOG_NOTICE, "Failed to authenticate on %s to '%s'\n", msg, sip_get_header(&p->initreq, "From")); 22136 pvt_set_needdestroy(p, "failed to authenticate BYE"); 22137 } 22138 } 22139 break; 22140 case 481: /* Call leg does not exist */ 22141 if (sipmethod == SIP_INVITE) { 22142 /* Re-invite failed */ 22143 handle_response_invite(p, resp, rest, req, seqno); 22144 } else if (sipmethod == SIP_BYE) { 22145 pvt_set_needdestroy(p, "received 481 response"); 22146 } else if (sipdebug) { 22147 ast_debug(1, "Remote host can't match request %s to call '%s'. Giving up\n", sip_methods[sipmethod].text, p->callid); 22148 } 22149 break; 22150 case 501: /* Not Implemented */ 22151 if (sipmethod == SIP_INVITE) 22152 handle_response_invite(p, resp, rest, req, seqno); 22153 break; 22154 default: /* Errors without handlers */ 22155 if ((resp >= 100) && (resp < 200)) { 22156 if (sipmethod == SIP_INVITE) { /* re-invite */ 22157 if (!req->ignore && sip_cancel_destroy(p)) 22158 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 22159 } 22160 } else if ((resp >= 200) && (resp < 300)) { /* on any unrecognized 2XX response do the following */ 22161 if (sipmethod == SIP_INVITE) { 22162 handle_response_invite(p, resp, rest, req, seqno); 22163 } 22164 } else if ((resp >= 300) && (resp < 700)) { 22165 if ((resp != 487)) 22166 ast_verb(3, "Incoming call: Got SIP response %d \"%s\" back from %s\n", resp, rest, ast_sockaddr_stringify(&p->sa)); 22167 switch(resp) { 22168 case 415: /* Unsupported media type */ 22169 case 488: /* Not acceptable here - codec error */ 22170 case 603: /* Decline */ 22171 case 500: /* Server error */ 22172 case 502: /* Bad gateway */ 22173 case 503: /* Service Unavailable */ 22174 case 504: /* Server timeout */ 22175 22176 /* re-invite failed */ 22177 if (sipmethod == SIP_INVITE && sip_cancel_destroy(p)) 22178 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 22179 break; 22180 } 22181 } 22182 break; 22183 } 22184 } 22185 }
| static void handle_response_info | ( | struct sip_pvt * | p, | |
| int | resp, | |||
| const char * | rest, | |||
| struct sip_request * | req, | |||
| uint32_t | seqno | |||
| ) | [static] |
Definition at line 21614 of file chan_sip.c.
References ast_log(), ast_sockaddr_stringify(), ast_verb, LOG_WARNING, mark_method_allowed(), mark_method_unallowed(), sip_methods, text, and cfsip_methods::text.
Referenced by handle_response().
21615 { 21616 int sipmethod = SIP_INFO; 21617 21618 switch (resp) { 21619 case 401: /* Not www-authorized on SIP method */ 21620 case 407: /* Proxy auth required */ 21621 ast_log(LOG_WARNING, "Host '%s' requests authentication (%d) for '%s'\n", 21622 ast_sockaddr_stringify(&p->sa), resp, sip_methods[sipmethod].text); 21623 break; 21624 case 405: /* Method not allowed */ 21625 case 501: /* Not Implemented */ 21626 mark_method_unallowed(&p->allowed_methods, sipmethod); 21627 if (p->relatedpeer) { 21628 mark_method_allowed(&p->relatedpeer->disallowed_methods, sipmethod); 21629 } 21630 ast_log(LOG_WARNING, "Host '%s' does not implement '%s'\n", 21631 ast_sockaddr_stringify(&p->sa), sip_methods[sipmethod].text); 21632 break; 21633 default: 21634 if (300 <= resp && resp < 700) { 21635 ast_verb(3, "Got SIP %s response %d \"%s\" back from host '%s'\n", 21636 sip_methods[sipmethod].text, resp, rest, ast_sockaddr_stringify(&p->sa)); 21637 } 21638 break; 21639 } 21640 }
| static void handle_response_invite | ( | struct sip_pvt * | p, | |
| int | resp, | |||
| const char * | rest, | |||
| struct sip_request * | req, | |||
| uint32_t | seqno | |||
| ) | [static] |
Handle SIP response to INVITE dialogue.
Definition at line 20699 of file chan_sip.c.
References append_history, AST_CAUSE_CONGESTION, AST_CAUSE_NORMAL_CLEARING, AST_CC_CCNR, ast_channel_name(), ast_channel_queue_connected_line_update(), ast_channel_queue_redirecting_update(), ast_channel_uniqueid(), AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER, AST_CONTROL_ANSWER, AST_CONTROL_CONGESTION, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, AST_CONTROL_UPDATE_RTP_PEER, ast_debug, ast_log(), ast_null_frame, ast_party_connected_line_init(), ast_party_redirecting_free(), ast_party_redirecting_init(), AST_PRES_ALLOWED, AST_PRES_RESTRICTION, ast_queue_control(), ast_queue_frame(), ast_queue_hangup_with_cause(), ast_random(), ast_rtp_instance_activate(), ast_sched_add(), AST_SCHED_DEL_UNREF, ast_set_flag, ast_set_hangupsource(), ast_setstate(), AST_STATE_RINGING, AST_STATE_UP, ast_string_field_set, ast_strlen_zero(), ast_test_flag, build_route(), change_redirecting_information(), change_t38_state(), check_pendings(), connected, do_proxy_auth(), EVENT_FLAG_SYSTEM, FALSE, find_sdp(), get_rpid(), ast_party_connected_line::id, ast_set_party_connected_line::id, LOG_NOTICE, LOG_WARNING, manager_event, ast_party_id::name, ast_set_party_id::name, ast_party_id::number, ast_set_party_id::number, parse_ok_contact(), parse_session_expires(), ast_party_name::presentation, ast_party_number::presentation, proc_422_rsp(), process_sdp(), pvt_set_needdestroy(), set_address_from_contact(), set_pvt_allowed_methods(), sip_alreadygone(), sip_cancel_destroy(), sip_cfg, sip_get_header(), sip_handle_cc(), sip_reinvite_retry(), sip_scheddestroy(), ast_party_connected_line::source, st_get_mode(), start_session_timer(), ast_party_name::str, ast_party_number::str, ast_party_id::tag, transmit_reinvite_with_sdp(), transmit_request(), TRUE, update_call_counter(), update_redirecting(), ast_party_name::valid, and ast_party_number::valid.
Referenced by handle_response().
20700 { 20701 int outgoing = ast_test_flag(&p->flags[0], SIP_OUTGOING); 20702 int res = 0; 20703 int xmitres = 0; 20704 int reinvite = (p->owner && p->owner->_state == AST_STATE_UP); 20705 char *p_hdrval; 20706 int rtn; 20707 struct ast_party_connected_line connected; 20708 struct ast_set_party_connected_line update_connected; 20709 20710 if (reinvite) { 20711 ast_debug(4, "SIP response %d to RE-invite on %s call %s\n", resp, outgoing ? "outgoing" : "incoming", p->callid); 20712 } else { 20713 ast_debug(4, "SIP response %d to standard invite\n", resp); 20714 } 20715 20716 if (p->alreadygone) { /* This call is already gone */ 20717 ast_debug(1, "Got response on call that is already terminated: %s (ignoring)\n", p->callid); 20718 return; 20719 } 20720 20721 /* Acknowledge sequence number - This only happens on INVITE from SIP-call */ 20722 /* Don't auto congest anymore since we've gotten something useful back */ 20723 AST_SCHED_DEL_UNREF(sched, p->initid, dialog_unref(p, "when you delete the initid sched, you should dec the refcount for the stored dialog ptr")); 20724 20725 /* RFC3261 says we must treat every 1xx response (but not 100) 20726 that we don't recognize as if it was 183. 20727 */ 20728 if (resp > 100 && resp < 200 && resp!=101 && resp != 180 && resp != 181 && resp != 182 && resp != 183) { 20729 resp = 183; 20730 } 20731 20732 /* For INVITE, treat all 2XX responses as we would a 200 response */ 20733 if ((resp >= 200) && (resp < 300)) { 20734 resp = 200; 20735 } 20736 20737 /* Any response between 100 and 199 is PROCEEDING */ 20738 if (resp >= 100 && resp < 200 && p->invitestate == INV_CALLING) { 20739 p->invitestate = INV_PROCEEDING; 20740 } 20741 20742 /* Final response, not 200 ? */ 20743 if (resp >= 300 && (p->invitestate == INV_CALLING || p->invitestate == INV_PROCEEDING || p->invitestate == INV_EARLY_MEDIA )) { 20744 p->invitestate = INV_COMPLETED; 20745 } 20746 20747 /* Final response, clear out pending invite */ 20748 if ((resp == 200 || resp >= 300) && p->pendinginvite && seqno == p->pendinginvite) { 20749 p->pendinginvite = 0; 20750 } 20751 20752 /* If this is a response to our initial INVITE, we need to set what we can use 20753 * for this peer. 20754 */ 20755 if (!reinvite) { 20756 set_pvt_allowed_methods(p, req); 20757 } 20758 20759 switch (resp) { 20760 case 100: /* Trying */ 20761 case 101: /* Dialog establishment */ 20762 if (!req->ignore && p->invitestate != INV_CANCELLED && sip_cancel_destroy(p)) { 20763 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 20764 } 20765 check_pendings(p); 20766 break; 20767 20768 case 180: /* 180 Ringing */ 20769 case 182: /* 182 Queued */ 20770 if (!req->ignore && p->invitestate != INV_CANCELLED && sip_cancel_destroy(p)) { 20771 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 20772 } 20773 /* Store Route-set from provisional SIP responses so 20774 * early-dialog request can be routed properly 20775 * */ 20776 parse_ok_contact(p, req); 20777 if (!reinvite) { 20778 build_route(p, req, 1); 20779 } 20780 if (!req->ignore && p->owner) { 20781 if (get_rpid(p, req)) { 20782 /* Queue a connected line update */ 20783 ast_party_connected_line_init(&connected); 20784 memset(&update_connected, 0, sizeof(update_connected)); 20785 20786 update_connected.id.number = 1; 20787 connected.id.number.valid = 1; 20788 connected.id.number.str = (char *) p->cid_num; 20789 connected.id.number.presentation = p->callingpres; 20790 20791 update_connected.id.name = 1; 20792 connected.id.name.valid = 1; 20793 connected.id.name.str = (char *) p->cid_name; 20794 connected.id.name.presentation = p->callingpres; 20795 20796 connected.id.tag = (char *) p->cid_tag; 20797 connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER; 20798 ast_channel_queue_connected_line_update(p->owner, &connected, 20799 &update_connected); 20800 } 20801 sip_handle_cc(p, req, AST_CC_CCNR); 20802 ast_queue_control(p->owner, AST_CONTROL_RINGING); 20803 if (p->owner->_state != AST_STATE_UP) { 20804 ast_setstate(p->owner, AST_STATE_RINGING); 20805 } 20806 } 20807 if (find_sdp(req)) { 20808 if (p->invitestate != INV_CANCELLED) { 20809 p->invitestate = INV_EARLY_MEDIA; 20810 } 20811 res = process_sdp(p, req, SDP_T38_NONE); 20812 if (!req->ignore && p->owner) { 20813 /* Queue a progress frame only if we have SDP in 180 or 182 */ 20814 ast_queue_control(p->owner, AST_CONTROL_PROGRESS); 20815 } 20816 ast_rtp_instance_activate(p->rtp); 20817 } 20818 check_pendings(p); 20819 break; 20820 20821 case 181: /* Call Is Being Forwarded */ 20822 if (!req->ignore && (p->invitestate != INV_CANCELLED) && sip_cancel_destroy(p)) 20823 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 20824 /* Store Route-set from provisional SIP responses so 20825 * early-dialog request can be routed properly 20826 * */ 20827 parse_ok_contact(p, req); 20828 if (!reinvite) { 20829 build_route(p, req, 1); 20830 } 20831 if (!req->ignore && p->owner) { 20832 struct ast_party_redirecting redirecting; 20833 struct ast_set_party_redirecting update_redirecting; 20834 20835 ast_party_redirecting_init(&redirecting); 20836 memset(&update_redirecting, 0, sizeof(update_redirecting)); 20837 change_redirecting_information(p, req, &redirecting, &update_redirecting, 20838 FALSE); 20839 ast_channel_queue_redirecting_update(p->owner, &redirecting, 20840 &update_redirecting); 20841 ast_party_redirecting_free(&redirecting); 20842 sip_handle_cc(p, req, AST_CC_CCNR); 20843 } 20844 check_pendings(p); 20845 break; 20846 20847 case 183: /* Session progress */ 20848 if (!req->ignore && (p->invitestate != INV_CANCELLED) && sip_cancel_destroy(p)) { 20849 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 20850 } 20851 /* Store Route-set from provisional SIP responses so 20852 * early-dialog request can be routed properly 20853 * */ 20854 parse_ok_contact(p, req); 20855 if (!reinvite) { 20856 build_route(p, req, 1); 20857 } 20858 if (!req->ignore && p->owner) { 20859 if (get_rpid(p, req)) { 20860 /* Queue a connected line update */ 20861 ast_party_connected_line_init(&connected); 20862 memset(&update_connected, 0, sizeof(update_connected)); 20863 20864 update_connected.id.number = 1; 20865 connected.id.number.valid = 1; 20866 connected.id.number.str = (char *) p->cid_num; 20867 connected.id.number.presentation = p->callingpres; 20868 20869 update_connected.id.name = 1; 20870 connected.id.name.valid = 1; 20871 connected.id.name.str = (char *) p->cid_name; 20872 connected.id.name.presentation = p->callingpres; 20873 20874 connected.id.tag = (char *) p->cid_tag; 20875 connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER; 20876 ast_channel_queue_connected_line_update(p->owner, &connected, 20877 &update_connected); 20878 } 20879 sip_handle_cc(p, req, AST_CC_CCNR); 20880 } 20881 if (find_sdp(req)) { 20882 if (p->invitestate != INV_CANCELLED) { 20883 p->invitestate = INV_EARLY_MEDIA; 20884 } 20885 res = process_sdp(p, req, SDP_T38_NONE); 20886 if (!req->ignore && p->owner) { 20887 /* Queue a progress frame */ 20888 ast_queue_control(p->owner, AST_CONTROL_PROGRESS); 20889 } 20890 ast_rtp_instance_activate(p->rtp); 20891 } else { 20892 /* Alcatel PBXs are known to send 183s with no SDP after sending 20893 * a 100 Trying response. We're just going to treat this sort of thing 20894 * the same as we would treat a 180 Ringing 20895 */ 20896 if (!req->ignore && p->owner) { 20897 ast_queue_control(p->owner, AST_CONTROL_RINGING); 20898 } 20899 } 20900 check_pendings(p); 20901 break; 20902 20903 case 200: /* 200 OK on invite - someone's answering our call */ 20904 if (!req->ignore && (p->invitestate != INV_CANCELLED) && sip_cancel_destroy(p)) { 20905 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 20906 } 20907 p->authtries = 0; 20908 if (find_sdp(req)) { 20909 if ((res = process_sdp(p, req, SDP_T38_ACCEPT)) && !req->ignore) 20910 if (!reinvite) 20911 /* This 200 OK's SDP is not acceptable, so we need to ack, then hangup */ 20912 /* For re-invites, we try to recover */ 20913 ast_set_flag(&p->flags[0], SIP_PENDINGBYE); 20914 ast_rtp_instance_activate(p->rtp); 20915 } 20916 20917 if (!req->ignore && p->owner) { 20918 int rpid_changed; 20919 20920 rpid_changed = get_rpid(p, req); 20921 if (rpid_changed || !reinvite) { 20922 /* Queue a connected line update */ 20923 ast_party_connected_line_init(&connected); 20924 memset(&update_connected, 0, sizeof(update_connected)); 20925 if (rpid_changed 20926 || !ast_strlen_zero(p->cid_num) 20927 || (p->callingpres & AST_PRES_RESTRICTION) != AST_PRES_ALLOWED) { 20928 update_connected.id.number = 1; 20929 connected.id.number.valid = 1; 20930 connected.id.number.str = (char *) p->cid_num; 20931 connected.id.number.presentation = p->callingpres; 20932 } 20933 if (rpid_changed 20934 || !ast_strlen_zero(p->cid_name) 20935 || (p->callingpres & AST_PRES_RESTRICTION) != AST_PRES_ALLOWED) { 20936 update_connected.id.name = 1; 20937 connected.id.name.valid = 1; 20938 connected.id.name.str = (char *) p->cid_name; 20939 connected.id.name.presentation = p->callingpres; 20940 } 20941 if (update_connected.id.number || update_connected.id.name) { 20942 connected.id.tag = (char *) p->cid_tag; 20943 connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER; 20944 ast_channel_queue_connected_line_update(p->owner, &connected, 20945 &update_connected); 20946 } 20947 } 20948 } 20949 20950 /* Parse contact header for continued conversation */ 20951 /* When we get 200 OK, we know which device (and IP) to contact for this call */ 20952 /* This is important when we have a SIP proxy between us and the phone */ 20953 if (outgoing) { 20954 update_call_counter(p, DEC_CALL_RINGING); 20955 parse_ok_contact(p, req); 20956 /* Save Record-Route for any later requests we make on this dialogue */ 20957 if (!reinvite) { 20958 build_route(p, req, 1); 20959 } 20960 20961 if(set_address_from_contact(p)) { 20962 /* Bad contact - we don't know how to reach this device */ 20963 /* We need to ACK, but then send a bye */ 20964 if (!p->route && !req->ignore) { 20965 ast_set_flag(&p->flags[0], SIP_PENDINGBYE); 20966 } 20967 } 20968 20969 } 20970 20971 if (!req->ignore && p->owner) { 20972 if (!reinvite) { 20973 ast_queue_control(p->owner, AST_CONTROL_ANSWER); 20974 if (sip_cfg.callevents) { 20975 manager_event(EVENT_FLAG_SYSTEM, "ChannelUpdate", 20976 "Channel: %s\r\nChanneltype: %s\r\nUniqueid: %s\r\nSIPcallid: %s\r\nSIPfullcontact: %s\r\nPeername: %s\r\n", 20977 ast_channel_name(p->owner), "SIP", ast_channel_uniqueid(p->owner), p->callid, p->fullcontact, p->peername); 20978 } 20979 } else { /* RE-invite */ 20980 if (p->t38.state == T38_DISABLED || p->t38.state == T38_REJECTED) { 20981 ast_queue_control(p->owner, AST_CONTROL_UPDATE_RTP_PEER); 20982 } else { 20983 ast_queue_frame(p->owner, &ast_null_frame); 20984 } 20985 } 20986 } else { 20987 /* It's possible we're getting an 200 OK after we've tried to disconnect 20988 by sending CANCEL */ 20989 /* First send ACK, then send bye */ 20990 if (!req->ignore) { 20991 ast_set_flag(&p->flags[0], SIP_PENDINGBYE); 20992 } 20993 } 20994 20995 /* Check for Session-Timers related headers */ 20996 if (st_get_mode(p, 0) != SESSION_TIMER_MODE_REFUSE && p->outgoing_call == TRUE && !reinvite) { 20997 p_hdrval = (char*)sip_get_header(req, "Session-Expires"); 20998 if (!ast_strlen_zero(p_hdrval)) { 20999 /* UAS supports Session-Timers */ 21000 enum st_refresher tmp_st_ref = SESSION_TIMER_REFRESHER_AUTO; 21001 int tmp_st_interval = 0; 21002 rtn = parse_session_expires(p_hdrval, &tmp_st_interval, &tmp_st_ref); 21003 if (rtn != 0) { 21004 ast_set_flag(&p->flags[0], SIP_PENDINGBYE); 21005 } 21006 if (tmp_st_ref == SESSION_TIMER_REFRESHER_UAC || 21007 tmp_st_ref == SESSION_TIMER_REFRESHER_UAS) { 21008 p->stimer->st_ref = tmp_st_ref; 21009 } 21010 if (tmp_st_interval) { 21011 p->stimer->st_interval = tmp_st_interval; 21012 } 21013 p->stimer->st_active = TRUE; 21014 p->stimer->st_active_peer_ua = TRUE; 21015 start_session_timer(p); 21016 } else { 21017 /* UAS doesn't support Session-Timers */ 21018 if (st_get_mode(p, 0) == SESSION_TIMER_MODE_ORIGINATE) { 21019 p->stimer->st_ref = SESSION_TIMER_REFRESHER_UAC; 21020 p->stimer->st_active_peer_ua = FALSE; 21021 start_session_timer(p); 21022 } 21023 } 21024 } 21025 21026 21027 /* If I understand this right, the branch is different for a non-200 ACK only */ 21028 p->invitestate = INV_TERMINATED; 21029 ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED); 21030 xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, TRUE); 21031 check_pendings(p); 21032 break; 21033 21034 case 407: /* Proxy authentication */ 21035 case 401: /* Www auth */ 21036 /* First we ACK */ 21037 xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); 21038 if (p->options) { 21039 p->options->auth_type = resp; 21040 } 21041 21042 /* Then we AUTH */ 21043 ast_string_field_set(p, theirtag, NULL); /* forget their old tag, so we don't match tags when getting response */ 21044 if (!req->ignore) { 21045 if (p->authtries < MAX_AUTHTRIES) { 21046 p->invitestate = INV_CALLING; 21047 } 21048 if (p->authtries == MAX_AUTHTRIES || do_proxy_auth(p, req, resp, SIP_INVITE, 1)) { 21049 ast_log(LOG_NOTICE, "Failed to authenticate on INVITE to '%s'\n", sip_get_header(&p->initreq, "From")); 21050 pvt_set_needdestroy(p, "failed to authenticate on INVITE"); 21051 sip_alreadygone(p); 21052 if (p->owner) { 21053 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 21054 } 21055 } 21056 } 21057 break; 21058 21059 case 403: /* Forbidden */ 21060 /* First we ACK */ 21061 xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); 21062 ast_log(LOG_WARNING, "Received response: \"Forbidden\" from '%s'\n", sip_get_header(&p->initreq, "From")); 21063 if (!req->ignore && p->owner) { 21064 ast_set_hangupsource(p->owner, ast_channel_name(p->owner), 0); 21065 ast_queue_hangup_with_cause(p->owner, AST_CAUSE_CONGESTION); 21066 } 21067 break; 21068 21069 case 404: /* Not found */ 21070 xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); 21071 if (p->owner && !req->ignore) { 21072 ast_set_hangupsource(p->owner, ast_channel_name(p->owner), 0); 21073 ast_queue_hangup_with_cause(p->owner, AST_CAUSE_CONGESTION); 21074 } 21075 break; 21076 21077 case 408: /* Request timeout */ 21078 case 481: /* Call leg does not exist */ 21079 /* Could be REFER caused INVITE with replaces */ 21080 ast_log(LOG_WARNING, "Re-invite to non-existing call leg on other UA. SIP dialog '%s'. Giving up.\n", p->callid); 21081 xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); 21082 if (p->owner) { 21083 ast_queue_hangup_with_cause(p->owner, AST_CAUSE_CONGESTION); 21084 } 21085 break; 21086 21087 case 422: /* Session-Timers: Session interval too small */ 21088 xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); 21089 ast_string_field_set(p, theirtag, NULL); 21090 proc_422_rsp(p, req); 21091 break; 21092 21093 case 428: /* Use identity header - rfc 4474 - not supported by Asterisk yet */ 21094 xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); 21095 append_history(p, "Identity", "SIP identity is required. Not supported by Asterisk."); 21096 ast_log(LOG_WARNING, "SIP identity required by proxy. SIP dialog '%s'. Giving up.\n", p->callid); 21097 if (p->owner && !req->ignore) { 21098 ast_queue_hangup_with_cause(p->owner, AST_CAUSE_CONGESTION); 21099 } 21100 break; 21101 21102 case 487: /* Cancelled transaction */ 21103 /* We have sent CANCEL on an outbound INVITE 21104 This transaction is already scheduled to be killed by sip_hangup(). 21105 */ 21106 xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); 21107 if (p->owner && !req->ignore) { 21108 ast_queue_hangup_with_cause(p->owner, AST_CAUSE_NORMAL_CLEARING); 21109 append_history(p, "Hangup", "Got 487 on CANCEL request from us. Queued AST hangup request"); 21110 } else if (!req->ignore) { 21111 update_call_counter(p, DEC_CALL_LIMIT); 21112 append_history(p, "Hangup", "Got 487 on CANCEL request from us on call without owner. Killing this dialog."); 21113 } 21114 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 21115 break; 21116 case 415: /* Unsupported media type */ 21117 case 488: /* Not acceptable here */ 21118 case 606: /* Not Acceptable */ 21119 xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); 21120 if (p->udptl && p->t38.state == T38_LOCAL_REINVITE) { 21121 change_t38_state(p, T38_REJECTED); 21122 /* Try to reset RTP timers */ 21123 /* XXX Why is this commented away??? */ 21124 //ast_rtp_set_rtptimers_onhold(p->rtp); 21125 21126 /* Trigger a reinvite back to audio */ 21127 transmit_reinvite_with_sdp(p, FALSE, FALSE); 21128 } else { 21129 /* We can't set up this call, so give up */ 21130 if (p->owner && !req->ignore) { 21131 ast_queue_hangup_with_cause(p->owner, AST_CAUSE_CONGESTION); 21132 } 21133 } 21134 break; 21135 case 491: /* Pending */ 21136 xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); 21137 if (p->owner && !req->ignore) { 21138 if (p->owner->_state != AST_STATE_UP) { 21139 ast_queue_hangup_with_cause(p->owner, AST_CAUSE_CONGESTION); 21140 } else { 21141 /* This is a re-invite that failed. */ 21142 /* Reset the flag after a while 21143 */ 21144 int wait; 21145 /* RFC 3261, if owner of call, wait between 2.1 to 4 seconds, 21146 * if not owner of call, wait 0 to 2 seconds */ 21147 if (p->outgoing_call) { 21148 wait = 2100 + ast_random() % 2000; 21149 } else { 21150 wait = ast_random() % 2000; 21151 } 21152 p->waitid = ast_sched_add(sched, wait, sip_reinvite_retry, dialog_ref(p, "passing dialog ptr into sched structure based on waitid for sip_reinvite_retry.")); 21153 ast_log(LOG_WARNING, "just did sched_add waitid(%d) for sip_reinvite_retry for dialog %s in handle_response_invite\n", p->waitid, p->callid); 21154 ast_debug(2, "Reinvite race. Waiting %d secs before retry\n", wait); 21155 } 21156 } 21157 break; 21158 21159 case 405: /* Not allowed */ 21160 case 501: /* Not implemented */ 21161 xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); 21162 if (p->owner) { 21163 ast_queue_hangup_with_cause(p->owner, AST_CAUSE_CONGESTION); 21164 } 21165 break; 21166 } 21167 if (xmitres == XMIT_ERROR) { 21168 ast_log(LOG_WARNING, "Could not transmit message in dialog %s\n", p->callid); 21169 } 21170 }
| static void handle_response_message | ( | struct sip_pvt * | p, | |
| int | resp, | |||
| const char * | rest, | |||
| struct sip_request * | req, | |||
| uint32_t | seqno | |||
| ) | [static] |
Definition at line 21688 of file chan_sip.c.
References ast_log(), ast_sockaddr_stringify(), ast_test_flag, ast_verb, do_message_auth(), LOG_WARNING, mark_method_allowed(), mark_method_unallowed(), pvt_set_needdestroy(), sip_methods, text, and cfsip_methods::text.
Referenced by handle_response().
21689 { 21690 int sipmethod = SIP_MESSAGE; 21691 int in_dialog = ast_test_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED); 21692 21693 switch (resp) { 21694 case 401: /* Not www-authorized on SIP method */ 21695 case 407: /* Proxy auth required */ 21696 if (do_message_auth(p, resp, rest, req, seqno) && !in_dialog) { 21697 pvt_set_needdestroy(p, "MESSAGE authentication failed"); 21698 } 21699 break; 21700 case 405: /* Method not allowed */ 21701 case 501: /* Not Implemented */ 21702 mark_method_unallowed(&p->allowed_methods, sipmethod); 21703 if (p->relatedpeer) { 21704 mark_method_allowed(&p->relatedpeer->disallowed_methods, sipmethod); 21705 } 21706 ast_log(LOG_WARNING, "Host '%s' does not implement '%s'\n", 21707 ast_sockaddr_stringify(&p->sa), sip_methods[sipmethod].text); 21708 if (!in_dialog) { 21709 pvt_set_needdestroy(p, "MESSAGE not implemented or allowed"); 21710 } 21711 break; 21712 default: 21713 if (100 <= resp && resp < 200) { 21714 /* Must allow provisional responses for out-of-dialog requests. */ 21715 } else if (200 <= resp && resp < 300) { 21716 p->authtries = 0; /* Reset authentication counter */ 21717 if (!in_dialog) { 21718 pvt_set_needdestroy(p, "MESSAGE delivery accepted"); 21719 } 21720 } else if (300 <= resp && resp < 700) { 21721 ast_verb(3, "Got SIP %s response %d \"%s\" back from host '%s'\n", 21722 sip_methods[sipmethod].text, resp, rest, ast_sockaddr_stringify(&p->sa)); 21723 if (!in_dialog) { 21724 pvt_set_needdestroy(p, (300 <= resp && resp < 600) 21725 ? "MESSAGE delivery failed" : "MESSAGE delivery refused"); 21726 } 21727 } 21728 break; 21729 } 21730 }
| static void handle_response_notify | ( | struct sip_pvt * | p, | |
| int | resp, | |||
| const char * | rest, | |||
| struct sip_request * | req, | |||
| uint32_t | seqno | |||
| ) | [static] |
Definition at line 21175 of file chan_sip.c.
References ast_channel_name(), ast_clear_flag, ast_debug, ast_log(), ast_sockaddr_stringify(), ast_string_field_set, ast_strlen_zero(), ast_test_flag, cb_extensionstate(), do_proxy_auth(), LOG_NOTICE, LOG_WARNING, NONE, pvt_set_needdestroy(), and sip_get_header().
Referenced by handle_response().
21176 { 21177 switch (resp) { 21178 case 200: /* Notify accepted */ 21179 /* They got the notify, this is the end */ 21180 if (p->owner) { 21181 if (p->refer) { 21182 ast_log(LOG_NOTICE, "Got OK on REFER Notify message\n"); 21183 } else { 21184 ast_log(LOG_WARNING, "Notify answer on an owned channel? - %s\n", ast_channel_name(p->owner)); 21185 } 21186 } else { 21187 if (p->subscribed == NONE && !p->refer) { 21188 ast_debug(4, "Got 200 accepted on NOTIFY %s\n", p->callid); 21189 pvt_set_needdestroy(p, "received 200 response"); 21190 } 21191 if (ast_test_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE)) { 21192 /* Ready to send the next state we have on queue */ 21193 ast_clear_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE); 21194 cb_extensionstate((char *)p->context, (char *)p->exten, p->laststate, (void *) p); 21195 } 21196 } 21197 break; 21198 case 401: /* Not www-authorized on SIP method */ 21199 case 407: /* Proxy auth */ 21200 if (!p->notify) { 21201 break; /* Only device notify can use NOTIFY auth */ 21202 } 21203 ast_string_field_set(p, theirtag, NULL); 21204 if (ast_strlen_zero(p->authname)) { 21205 ast_log(LOG_WARNING, "Asked to authenticate NOTIFY to %s but we have no matching peer or realm auth!\n", ast_sockaddr_stringify(&p->recv)); 21206 pvt_set_needdestroy(p, "unable to authenticate NOTIFY"); 21207 } 21208 if (p->authtries > 1 || do_proxy_auth(p, req, resp, SIP_NOTIFY, 0)) { 21209 ast_log(LOG_NOTICE, "Failed to authenticate on NOTIFY to '%s'\n", sip_get_header(&p->initreq, "From")); 21210 pvt_set_needdestroy(p, "failed to authenticate NOTIFY"); 21211 } 21212 break; 21213 case 481: /* Call leg does not exist */ 21214 pvt_set_needdestroy(p, "Received 481 response for NOTIFY"); 21215 break; 21216 } 21217 }
| static void handle_response_peerpoke | ( | struct sip_pvt * | p, | |
| int | resp, | |||
| struct sip_request * | req | |||
| ) | [static] |
Handle qualification responses (OPTIONS).
Definition at line 21547 of file chan_sip.c.
References ast_check_realtime(), AST_DEVICE_UNKNOWN, ast_devstate_changed(), ast_log(), AST_SCHED_REPLACE_UNREF, ast_tvdiff_ms(), ast_tvnow(), ast_update_realtime(), DEFAULT_FREQ_NOTOK, EVENT_FLAG_SYSTEM, LOG_NOTICE, manager_event, pvt_set_needdestroy(), register_peer_exten(), SENTINEL, sip_cfg, sip_poke_peer_s(), sip_ref_peer(), sip_unref_peer(), and TRUE.
Referenced by handle_response().
21548 { 21549 struct sip_peer *peer = /* sip_ref_peer( */ p->relatedpeer /* , "bump refcount on p, as it is being used in this function(handle_response_peerpoke)")*/ ; /* hope this is already refcounted! */ 21550 int statechanged, is_reachable, was_reachable; 21551 int pingtime = ast_tvdiff_ms(ast_tvnow(), peer->ps); 21552 21553 /* 21554 * Compute the response time to a ping (goes in peer->lastms.) 21555 * -1 means did not respond, 0 means unknown, 21556 * 1..maxms is a valid response, >maxms means late response. 21557 */ 21558 if (pingtime < 1) { /* zero = unknown, so round up to 1 */ 21559 pingtime = 1; 21560 } 21561 21562 if (!peer->maxms) { /* this should never happens */ 21563 pvt_set_needdestroy(p, "got OPTIONS response but qualify is not enabled"); 21564 return; 21565 } 21566 21567 /* Now determine new state and whether it has changed. 21568 * Use some helper variables to simplify the writing 21569 * of the expressions. 21570 */ 21571 was_reachable = peer->lastms > 0 && peer->lastms <= peer->maxms; 21572 is_reachable = pingtime <= peer->maxms; 21573 statechanged = peer->lastms == 0 /* yes, unknown before */ 21574 || was_reachable != is_reachable; 21575 21576 peer->lastms = pingtime; 21577 peer->call = dialog_unref(peer->call, "unref dialog peer->call"); 21578 if (statechanged) { 21579 const char *s = is_reachable ? "Reachable" : "Lagged"; 21580 char str_lastms[20]; 21581 snprintf(str_lastms, sizeof(str_lastms), "%d", pingtime); 21582 21583 ast_log(LOG_NOTICE, "Peer '%s' is now %s. (%dms / %dms)\n", 21584 peer->name, s, pingtime, peer->maxms); 21585 ast_devstate_changed(AST_DEVICE_UNKNOWN, "SIP/%s", peer->name); 21586 if (sip_cfg.peer_rtupdate) { 21587 ast_update_realtime(ast_check_realtime("sipregs") ? "sipregs" : "sippeers", "name", peer->name, "lastms", str_lastms, SENTINEL); 21588 } 21589 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", 21590 "ChannelType: SIP\r\nPeer: SIP/%s\r\nPeerStatus: %s\r\nTime: %d\r\n", 21591 peer->name, s, pingtime); 21592 if (is_reachable && sip_cfg.regextenonqualify) 21593 register_peer_exten(peer, TRUE); 21594 } 21595 21596 pvt_set_needdestroy(p, "got OPTIONS response"); 21597 21598 /* Try again eventually */ 21599 AST_SCHED_REPLACE_UNREF(peer->pokeexpire, sched, 21600 is_reachable ? peer->qualifyfreq : DEFAULT_FREQ_NOTOK, 21601 sip_poke_peer_s, peer, 21602 sip_unref_peer(_data, "removing poke peer ref"), 21603 sip_unref_peer(peer, "removing poke peer ref"), 21604 sip_ref_peer(peer, "adding poke peer ref")); 21605 }
| static void handle_response_publish | ( | struct sip_pvt * | p, | |
| int | resp, | |||
| const char * | rest, | |||
| struct sip_request * | req, | |||
| uint32_t | seqno | |||
| ) | [static] |
Definition at line 20648 of file chan_sip.c.
References ast_assert, ast_copy_string(), ast_log(), ast_string_field_set, ast_strlen_zero(), do_proxy_auth(), LOG_NOTICE, mark_method_unallowed(), pvt_set_needdestroy(), sip_alreadygone(), and sip_get_header().
Referenced by handle_response().
20649 { 20650 struct sip_epa_entry *epa_entry = p->epa_entry; 20651 const char *etag = sip_get_header(req, "Sip-ETag"); 20652 20653 ast_assert(epa_entry != NULL); 20654 20655 if (resp == 401 || resp == 407) { 20656 ast_string_field_set(p, theirtag, NULL); 20657 if (p->options) { 20658 p->options->auth_type = (resp == 401 ? WWW_AUTH : PROXY_AUTH); 20659 } 20660 if ((p->authtries == MAX_AUTHTRIES) || do_proxy_auth(p, req, resp, SIP_PUBLISH, 0)) { 20661 ast_log(LOG_NOTICE, "Failed to authenticate on PUBLISH to '%s'\n", sip_get_header(&p->initreq, "From")); 20662 pvt_set_needdestroy(p, "Failed to authenticate on PUBLISH"); 20663 sip_alreadygone(p); 20664 } 20665 return; 20666 } 20667 20668 if (resp == 501 || resp == 405) { 20669 mark_method_unallowed(&p->allowed_methods, SIP_PUBLISH); 20670 } 20671 20672 if (resp == 200) { 20673 p->authtries = 0; 20674 /* If I've read section 6, item 6 of RFC 3903 correctly, 20675 * an ESC will only generate a new etag when it sends a 200 OK 20676 */ 20677 if (!ast_strlen_zero(etag)) { 20678 ast_copy_string(epa_entry->entity_tag, etag, sizeof(epa_entry->entity_tag)); 20679 } 20680 /* The nominal case. Everything went well. Everybody is happy. 20681 * Each EPA will have a specific action to take as a result of this 20682 * development, so ... callbacks! 20683 */ 20684 if (epa_entry->static_data->handle_ok) { 20685 epa_entry->static_data->handle_ok(p, req, epa_entry); 20686 } 20687 } else { 20688 /* Rather than try to make individual callbacks for each error 20689 * type, there is just a single error callback. The callback 20690 * can distinguish between error messages and do what it needs to 20691 */ 20692 if (epa_entry->static_data->handle_error) { 20693 epa_entry->static_data->handle_error(p, resp, req, epa_entry); 20694 } 20695 } 20696 }
| static void handle_response_refer | ( | struct sip_pvt * | p, | |
| int | resp, | |||
| const char * | rest, | |||
| struct sip_request * | req, | |||
| uint32_t | seqno | |||
| ) | [static] |
Definition at line 21303 of file chan_sip.c.
References AST_CONTROL_CONGESTION, AST_CONTROL_TRANSFER, ast_debug, ast_log(), ast_queue_control(), ast_queue_control_data(), ast_sockaddr_stringify(), ast_strlen_zero(), AST_TRANSFER_FAILED, do_proxy_auth(), LOG_NOTICE, LOG_WARNING, pvt_set_needdestroy(), and sip_get_header().
Referenced by handle_response().
21304 { 21305 enum ast_control_transfer message = AST_TRANSFER_FAILED; 21306 21307 /* If no refer structure exists, then do nothing */ 21308 if (!p->refer) 21309 return; 21310 21311 switch (resp) { 21312 case 202: /* Transfer accepted */ 21313 /* We need to do something here */ 21314 /* The transferee is now sending INVITE to target */ 21315 p->refer->status = REFER_ACCEPTED; 21316 /* Now wait for next message */ 21317 ast_debug(3, "Got 202 accepted on transfer\n"); 21318 /* We should hang along, waiting for NOTIFY's here */ 21319 break; 21320 21321 case 401: /* Not www-authorized on SIP method */ 21322 case 407: /* Proxy auth */ 21323 if (ast_strlen_zero(p->authname)) { 21324 ast_log(LOG_WARNING, "Asked to authenticate REFER to %s but we have no matching peer or realm auth!\n", 21325 ast_sockaddr_stringify(&p->recv)); 21326 if (p->owner) { 21327 ast_queue_control_data(p->owner, AST_CONTROL_TRANSFER, &message, sizeof(message)); 21328 } 21329 pvt_set_needdestroy(p, "unable to authenticate REFER"); 21330 } 21331 if (p->authtries > 1 || do_proxy_auth(p, req, resp, SIP_REFER, 0)) { 21332 ast_log(LOG_NOTICE, "Failed to authenticate on REFER to '%s'\n", sip_get_header(&p->initreq, "From")); 21333 p->refer->status = REFER_NOAUTH; 21334 if (p->owner) { 21335 ast_queue_control_data(p->owner, AST_CONTROL_TRANSFER, &message, sizeof(message)); 21336 } 21337 pvt_set_needdestroy(p, "failed to authenticate REFER"); 21338 } 21339 break; 21340 21341 case 405: /* Method not allowed */ 21342 /* Return to the current call onhold */ 21343 /* Status flag needed to be reset */ 21344 ast_log(LOG_NOTICE, "SIP transfer to %s failed, REFER not allowed. \n", p->refer->refer_to); 21345 pvt_set_needdestroy(p, "received 405 response"); 21346 p->refer->status = REFER_FAILED; 21347 if (p->owner) { 21348 ast_queue_control_data(p->owner, AST_CONTROL_TRANSFER, &message, sizeof(message)); 21349 } 21350 break; 21351 21352 case 481: /* Call leg does not exist */ 21353 21354 /* A transfer with Replaces did not work */ 21355 /* OEJ: We should Set flag, cancel the REFER, go back 21356 to original call - but right now we can't */ 21357 ast_log(LOG_WARNING, "Remote host can't match REFER request to call '%s'. Giving up.\n", p->callid); 21358 if (p->owner) 21359 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 21360 pvt_set_needdestroy(p, "received 481 response"); 21361 break; 21362 21363 case 500: /* Server error */ 21364 case 501: /* Method not implemented */ 21365 /* Return to the current call onhold */ 21366 /* Status flag needed to be reset */ 21367 ast_log(LOG_NOTICE, "SIP transfer to %s failed, call miserably fails. \n", p->refer->refer_to); 21368 pvt_set_needdestroy(p, "received 500/501 response"); 21369 p->refer->status = REFER_FAILED; 21370 if (p->owner) { 21371 ast_queue_control_data(p->owner, AST_CONTROL_TRANSFER, &message, sizeof(message)); 21372 } 21373 break; 21374 case 603: /* Transfer declined */ 21375 ast_log(LOG_NOTICE, "SIP transfer to %s declined, call miserably fails. \n", p->refer->refer_to); 21376 p->refer->status = REFER_FAILED; 21377 pvt_set_needdestroy(p, "received 603 response"); 21378 if (p->owner) { 21379 ast_queue_control_data(p->owner, AST_CONTROL_TRANSFER, &message, sizeof(message)); 21380 } 21381 break; 21382 default: 21383 /* We should treat unrecognized 9xx as 900. 400 is actually 21384 specified as a possible response, but any 4-6xx is 21385 theoretically possible. */ 21386 21387 if (resp < 299) { /* 1xx cases don't get here */ 21388 ast_log(LOG_WARNING, "SIP transfer to %s had unxpected 2xx response (%d), confusion is possible. \n", p->refer->refer_to, resp); 21389 } else { 21390 ast_log(LOG_WARNING, "SIP transfer to %s with response (%d). \n", p->refer->refer_to, resp); 21391 } 21392 21393 p->refer->status = REFER_FAILED; 21394 pvt_set_needdestroy(p, "received failure response"); 21395 if (p->owner) { 21396 ast_queue_control_data(p->owner, AST_CONTROL_TRANSFER, &message, sizeof(message)); 21397 } 21398 break; 21399 } 21400 }
| static int handle_response_register | ( | struct sip_pvt * | p, | |
| int | resp, | |||
| const char * | rest, | |||
| struct sip_request * | req, | |||
| uint32_t | seqno | |||
| ) | [static] |
Handle responses on REGISTER to services.
Definition at line 21403 of file chan_sip.c.
References __get_header(), ast_debug, ast_log(), AST_SCHED_DEL_UNREF, AST_SCHED_REPLACE_UNREF, ast_strlen_zero(), ast_tvnow(), do_register_auth(), EVENT_FLAG_SYSTEM, LOG_NOTICE, LOG_WARNING, manager_event, MAX, pvt_set_needdestroy(), REG_STATE_NOAUTH, REG_STATE_REGISTERED, REG_STATE_REJECTED, REG_STATE_UNREGISTERED, registry_addref(), registry_unref(), regstate2str(), S_OR, sip_get_header(), sip_reregister(), sip_scheddestroy(), strcasestr(), and transmit_register().
Referenced by handle_response().
21404 { 21405 int expires, expires_ms; 21406 struct sip_registry *r; 21407 r=p->registry; 21408 21409 switch (resp) { 21410 case 401: /* Unauthorized */ 21411 if (p->authtries == MAX_AUTHTRIES || do_register_auth(p, req, resp)) { 21412 ast_log(LOG_NOTICE, "Failed to authenticate on REGISTER to '%s@%s' (Tries %d)\n", p->registry->username, p->registry->hostname, p->authtries); 21413 pvt_set_needdestroy(p, "failed to authenticate REGISTER"); 21414 } 21415 break; 21416 case 403: /* Forbidden */ 21417 ast_log(LOG_WARNING, "Forbidden - wrong password on authentication for REGISTER for '%s' to '%s'\n", p->registry->username, p->registry->hostname); 21418 AST_SCHED_DEL_UNREF(sched, r->timeout, registry_unref(r, "reg ptr unref from handle_response_register 403")); 21419 r->regstate = REG_STATE_NOAUTH; 21420 pvt_set_needdestroy(p, "received 403 response"); 21421 break; 21422 case 404: /* Not found */ 21423 ast_log(LOG_WARNING, "Got 404 Not found on SIP register to service %s@%s, giving up\n", p->registry->username, p->registry->hostname); 21424 pvt_set_needdestroy(p, "received 404 response"); 21425 if (r->call) 21426 r->call = dialog_unref(r->call, "unsetting registry->call pointer-- case 404"); 21427 r->regstate = REG_STATE_REJECTED; 21428 AST_SCHED_DEL_UNREF(sched, r->timeout, registry_unref(r, "reg ptr unref from handle_response_register 404")); 21429 break; 21430 case 407: /* Proxy auth */ 21431 if (p->authtries == MAX_AUTHTRIES || do_register_auth(p, req, resp)) { 21432 ast_log(LOG_NOTICE, "Failed to authenticate on REGISTER to '%s' (tries '%d')\n", sip_get_header(&p->initreq, "From"), p->authtries); 21433 pvt_set_needdestroy(p, "failed to authenticate REGISTER"); 21434 } 21435 break; 21436 case 408: /* Request timeout */ 21437 /* Got a timeout response, so reset the counter of failed responses */ 21438 if (r) { 21439 r->regattempts = 0; 21440 } else { 21441 ast_log(LOG_WARNING, "Got a 408 response to our REGISTER on call %s after we had destroyed the registry object\n", p->callid); 21442 } 21443 break; 21444 case 423: /* Interval too brief */ 21445 r->expiry = atoi(sip_get_header(req, "Min-Expires")); 21446 ast_log(LOG_WARNING, "Got 423 Interval too brief for service %s@%s, minimum is %d seconds\n", p->registry->username, p->registry->hostname, r->expiry); 21447 AST_SCHED_DEL_UNREF(sched, r->timeout, registry_unref(r, "reg ptr unref from handle_response_register 423")); 21448 if (r->call) { 21449 r->call = dialog_unref(r->call, "unsetting registry->call pointer-- case 423"); 21450 pvt_set_needdestroy(p, "received 423 response"); 21451 } 21452 if (r->expiry > max_expiry) { 21453 ast_log(LOG_WARNING, "Required expiration time from %s@%s is too high, giving up\n", p->registry->username, p->registry->hostname); 21454 r->expiry = r->configured_expiry; 21455 r->regstate = REG_STATE_REJECTED; 21456 } else { 21457 r->regstate = REG_STATE_UNREGISTERED; 21458 transmit_register(r, SIP_REGISTER, NULL, NULL); 21459 } 21460 manager_event(EVENT_FLAG_SYSTEM, "Registry", "ChannelType: SIP\r\nUsername: %s\r\nDomain: %s\r\nStatus: %s\r\n", r->username, r->hostname, regstate2str(r->regstate)); 21461 break; 21462 case 479: /* SER: Not able to process the URI - address is wrong in register*/ 21463 ast_log(LOG_WARNING, "Got error 479 on register to %s@%s, giving up (check config)\n", p->registry->username, p->registry->hostname); 21464 pvt_set_needdestroy(p, "received 479 response"); 21465 if (r->call) 21466 r->call = dialog_unref(r->call, "unsetting registry->call pointer-- case 479"); 21467 r->regstate = REG_STATE_REJECTED; 21468 AST_SCHED_DEL_UNREF(sched, r->timeout, registry_unref(r, "reg ptr unref from handle_response_register 479")); 21469 break; 21470 case 200: /* 200 OK */ 21471 if (!r) { 21472 ast_log(LOG_WARNING, "Got 200 OK on REGISTER, but there isn't a registry entry for '%s' (we probably already got the OK)\n", S_OR(p->peername, p->username)); 21473 pvt_set_needdestroy(p, "received erroneous 200 response"); 21474 return 0; 21475 } 21476 21477 r->regstate = REG_STATE_REGISTERED; 21478 r->regtime = ast_tvnow(); /* Reset time of last successful registration */ 21479 manager_event(EVENT_FLAG_SYSTEM, "Registry", "ChannelType: SIP\r\nDomain: %s\r\nStatus: %s\r\n", r->hostname, regstate2str(r->regstate)); 21480 r->regattempts = 0; 21481 ast_debug(1, "Registration successful\n"); 21482 if (r->timeout > -1) { 21483 ast_debug(1, "Cancelling timeout %d\n", r->timeout); 21484 } 21485 AST_SCHED_DEL_UNREF(sched, r->timeout, registry_unref(r, "reg ptr unref from handle_response_register 200")); 21486 if (r->call) 21487 r->call = dialog_unref(r->call, "unsetting registry->call pointer-- case 200"); 21488 p->registry = registry_unref(p->registry, "unref registry entry p->registry"); 21489 /* Let this one hang around until we have all the responses */ 21490 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 21491 /* p->needdestroy = 1; */ 21492 21493 /* set us up for re-registering 21494 * figure out how long we got registered for 21495 * according to section 6.13 of RFC, contact headers override 21496 * expires headers, so check those first */ 21497 expires = 0; 21498 21499 /* XXX todo: try to save the extra call */ 21500 if (!ast_strlen_zero(sip_get_header(req, "Contact"))) { 21501 const char *contact = NULL; 21502 const char *tmptmp = NULL; 21503 int start = 0; 21504 for(;;) { 21505 contact = __get_header(req, "Contact", &start); 21506 /* this loop ensures we get a contact header about our register request */ 21507 if(!ast_strlen_zero(contact)) { 21508 if( (tmptmp=strstr(contact, p->our_contact))) { 21509 contact=tmptmp; 21510 break; 21511 } 21512 } else 21513 break; 21514 } 21515 tmptmp = strcasestr(contact, "expires="); 21516 if (tmptmp) { 21517 if (sscanf(tmptmp + 8, "%30d;", &expires) != 1) 21518 expires = 0; 21519 } 21520 21521 } 21522 if (!expires) 21523 expires=atoi(sip_get_header(req, "expires")); 21524 if (!expires) 21525 expires=default_expiry; 21526 21527 expires_ms = expires * 1000; 21528 if (expires <= EXPIRY_GUARD_LIMIT) 21529 expires_ms -= MAX((expires_ms * EXPIRY_GUARD_PCT), EXPIRY_GUARD_MIN); 21530 else 21531 expires_ms -= EXPIRY_GUARD_SECS * 1000; 21532 if (sipdebug) 21533 ast_log(LOG_NOTICE, "Outbound Registration: Expiry for %s is %d sec (Scheduling reregistration in %d s)\n", r->hostname, expires, expires_ms/1000); 21534 21535 r->refresh= (int) expires_ms / 1000; 21536 21537 /* Schedule re-registration before we expire */ 21538 AST_SCHED_REPLACE_UNREF(r->expire, sched, expires_ms, sip_reregister, r, 21539 registry_unref(_data,"unref in REPLACE del fail"), 21540 registry_unref(r,"unref in REPLACE add fail"), 21541 registry_addref(r,"The Addition side of REPLACE")); 21542 } 21543 return 1; 21544 }
| static void handle_response_subscribe | ( | struct sip_pvt * | p, | |
| int | resp, | |||
| const char * | rest, | |||
| struct sip_request * | req, | |||
| uint32_t | seqno | |||
| ) | [static] |
Definition at line 21220 of file chan_sip.c.
References ao2_callback, ast_cc_monitor_failed(), ast_debug, ast_free, ast_log(), ast_sched_add(), ast_string_field_set, ASTOBJ_REF, ASTOBJ_UNREF, do_proxy_auth(), find_sip_monitor_instance_by_subscription_pvt(), LOG_NOTICE, LOG_WARNING, pvt_set_needdestroy(), set_pvt_allowed_methods(), sip_alreadygone(), sip_get_header(), sip_subscribe_mwi_destroy(), sip_subscribe_mwi_do(), and transmit_response_with_date().
Referenced by handle_response().
21221 { 21222 if (p->subscribed == CALL_COMPLETION) { 21223 struct sip_monitor_instance *monitor_instance; 21224 21225 if (resp < 300) { 21226 return; 21227 } 21228 21229 /* Final failure response received. */ 21230 monitor_instance = ao2_callback(sip_monitor_instances, 0, 21231 find_sip_monitor_instance_by_subscription_pvt, p); 21232 if (monitor_instance) { 21233 ast_cc_monitor_failed(monitor_instance->core_id, 21234 monitor_instance->device_name, 21235 "Received error response to our SUBSCRIBE"); 21236 } 21237 return; 21238 } 21239 21240 if (p->subscribed != MWI_NOTIFICATION) { 21241 return; 21242 } 21243 if (!p->mwi) { 21244 return; 21245 } 21246 21247 switch (resp) { 21248 case 200: /* Subscription accepted */ 21249 ast_debug(3, "Got 200 OK on subscription for MWI\n"); 21250 set_pvt_allowed_methods(p, req); 21251 if (p->options) { 21252 ast_free(p->options); 21253 p->options = NULL; 21254 } 21255 p->mwi->subscribed = 1; 21256 if ((p->mwi->resub = ast_sched_add(sched, mwi_expiry * 1000, sip_subscribe_mwi_do, ASTOBJ_REF(p->mwi))) < 0) { 21257 ASTOBJ_UNREF(p->mwi, sip_subscribe_mwi_destroy); 21258 } 21259 break; 21260 case 401: 21261 case 407: 21262 ast_string_field_set(p, theirtag, NULL); 21263 if (p->authtries > 1 || do_proxy_auth(p, req, resp, SIP_SUBSCRIBE, 0)) { 21264 ast_log(LOG_NOTICE, "Failed to authenticate on SUBSCRIBE to '%s'\n", sip_get_header(&p->initreq, "From")); 21265 p->mwi->call = NULL; 21266 ASTOBJ_UNREF(p->mwi, sip_subscribe_mwi_destroy); 21267 pvt_set_needdestroy(p, "failed to authenticate SUBSCRIBE"); 21268 } 21269 break; 21270 case 403: 21271 transmit_response_with_date(p, "200 OK", req); 21272 ast_log(LOG_WARNING, "Authentication failed while trying to subscribe for MWI.\n"); 21273 p->mwi->call = NULL; 21274 ASTOBJ_UNREF(p->mwi, sip_subscribe_mwi_destroy); 21275 pvt_set_needdestroy(p, "received 403 response"); 21276 sip_alreadygone(p); 21277 break; 21278 case 404: 21279 ast_log(LOG_WARNING, "Subscription failed for MWI. The remote side said that a mailbox may not have been configured.\n"); 21280 p->mwi->call = NULL; 21281 ASTOBJ_UNREF(p->mwi, sip_subscribe_mwi_destroy); 21282 pvt_set_needdestroy(p, "received 404 response"); 21283 break; 21284 case 481: 21285 ast_log(LOG_WARNING, "Subscription failed for MWI. The remote side said that our dialog did not exist.\n"); 21286 p->mwi->call = NULL; 21287 ASTOBJ_UNREF(p->mwi, sip_subscribe_mwi_destroy); 21288 pvt_set_needdestroy(p, "received 481 response"); 21289 break; 21290 case 500: 21291 case 501: 21292 ast_log(LOG_WARNING, "Subscription failed for MWI. The remote side may have suffered a heart attack.\n"); 21293 p->mwi->call = NULL; 21294 ASTOBJ_UNREF(p->mwi, sip_subscribe_mwi_destroy); 21295 pvt_set_needdestroy(p, "received 500/501 response"); 21296 break; 21297 } 21298 }
| static void handle_response_update | ( | struct sip_pvt * | p, | |
| int | resp, | |||
| const char * | rest, | |||
| struct sip_request * | req, | |||
| uint32_t | seqno | |||
| ) | [static] |
Handle authentication challenge for SIP UPDATE.
This function is only called upon the receipt of a 401/407 response to an UPDATE.
Definition at line 20588 of file chan_sip.c.
References ast_log(), do_proxy_auth(), LOG_NOTICE, and sip_get_header().
Referenced by handle_response().
20589 { 20590 if (p->options) { 20591 p->options->auth_type = (resp == 401 ? WWW_AUTH : PROXY_AUTH); 20592 } 20593 if ((p->authtries == MAX_AUTHTRIES) || do_proxy_auth(p, req, resp, SIP_UPDATE, 1)) { 20594 ast_log(LOG_NOTICE, "Failed to authenticate on UPDATE to '%s'\n", sip_get_header(&p->initreq, "From")); 20595 } 20596 }
| static int handle_sip_publish_initial | ( | struct sip_pvt * | p, | |
| struct sip_request * | req, | |||
| struct event_state_compositor * | esc, | |||
| const int | expires | |||
| ) | [static] |
Definition at line 25239 of file chan_sip.c.
References ao2_ref, event_state_compositor::callbacks, create_esc_entry(), transmit_response(), and transmit_response_with_sip_etag().
Referenced by handle_request_publish().
25240 { 25241 struct sip_esc_entry *esc_entry = create_esc_entry(esc, req, expires); 25242 int res = 0; 25243 25244 if (!esc_entry) { 25245 transmit_response(p, "503 Internal Server Failure", req); 25246 return -1; 25247 } 25248 25249 if (esc->callbacks->initial_handler) { 25250 res = esc->callbacks->initial_handler(p, req, esc, esc_entry); 25251 } 25252 25253 if (!res) { 25254 transmit_response_with_sip_etag(p, "200 OK", req, esc_entry, 0); 25255 } 25256 25257 ao2_ref(esc_entry, -1); 25258 return res; 25259 }
| static int handle_sip_publish_modify | ( | struct sip_pvt * | p, | |
| struct sip_request * | req, | |||
| struct event_state_compositor * | esc, | |||
| const char *const | etag, | |||
| const int | expires | |||
| ) | [static] |
Definition at line 25289 of file chan_sip.c.
References ao2_ref, AST_SCHED_REPLACE_UNREF, event_state_compositor::callbacks, get_esc_entry(), publish_expire(), transmit_response(), and transmit_response_with_sip_etag().
Referenced by handle_request_publish().
25290 { 25291 struct sip_esc_entry *esc_entry = get_esc_entry(etag, esc); 25292 int expires_ms = expires * 1000; 25293 int res = 0; 25294 25295 if (!esc_entry) { 25296 transmit_response(p, "412 Conditional Request Failed", req); 25297 return -1; 25298 } 25299 25300 AST_SCHED_REPLACE_UNREF(esc_entry->sched_id, sched, expires_ms, publish_expire, esc_entry, 25301 ao2_ref(_data, -1), 25302 ao2_ref(esc_entry, -1), 25303 ao2_ref(esc_entry, +1)); 25304 25305 if (esc->callbacks->modify_handler) { 25306 res = esc->callbacks->modify_handler(p, req, esc, esc_entry); 25307 } 25308 25309 if (!res) { 25310 transmit_response_with_sip_etag(p, "200 OK", req, esc_entry, 1); 25311 } 25312 25313 ao2_ref(esc_entry, -1); 25314 return res; 25315 }
| static int handle_sip_publish_refresh | ( | struct sip_pvt * | p, | |
| struct sip_request * | req, | |||
| struct event_state_compositor * | esc, | |||
| const char *const | etag, | |||
| const int | expires | |||
| ) | [static] |
Definition at line 25261 of file chan_sip.c.
References ao2_ref, AST_SCHED_REPLACE_UNREF, event_state_compositor::callbacks, get_esc_entry(), publish_expire(), transmit_response(), and transmit_response_with_sip_etag().
Referenced by handle_request_publish().
25262 { 25263 struct sip_esc_entry *esc_entry = get_esc_entry(etag, esc); 25264 int expires_ms = expires * 1000; 25265 int res = 0; 25266 25267 if (!esc_entry) { 25268 transmit_response(p, "412 Conditional Request Failed", req); 25269 return -1; 25270 } 25271 25272 AST_SCHED_REPLACE_UNREF(esc_entry->sched_id, sched, expires_ms, publish_expire, esc_entry, 25273 ao2_ref(_data, -1), 25274 ao2_ref(esc_entry, -1), 25275 ao2_ref(esc_entry, +1)); 25276 25277 if (esc->callbacks->refresh_handler) { 25278 res = esc->callbacks->refresh_handler(p, req, esc, esc_entry); 25279 } 25280 25281 if (!res) { 25282 transmit_response_with_sip_etag(p, "200 OK", req, esc_entry, 1); 25283 } 25284 25285 ao2_ref(esc_entry, -1); 25286 return res; 25287 }
| static int handle_sip_publish_remove | ( | struct sip_pvt * | p, | |
| struct sip_request * | req, | |||
| struct event_state_compositor * | esc, | |||
| const char *const | etag | |||
| ) | [static] |
Definition at line 25317 of file chan_sip.c.
References ao2_ref, ao2_unlink, AST_SCHED_DEL, event_state_compositor::callbacks, event_state_compositor::compositor, get_esc_entry(), transmit_response(), and transmit_response_with_sip_etag().
Referenced by handle_request_publish().
25318 { 25319 struct sip_esc_entry *esc_entry = get_esc_entry(etag, esc); 25320 int res = 0; 25321 25322 if (!esc_entry) { 25323 transmit_response(p, "412 Conditional Request Failed", req); 25324 return -1; 25325 } 25326 25327 AST_SCHED_DEL(sched, esc_entry->sched_id); 25328 /* Scheduler's ref of the esc_entry */ 25329 ao2_ref(esc_entry, -1); 25330 25331 if (esc->callbacks->remove_handler) { 25332 res = esc->callbacks->remove_handler(p, req, esc, esc_entry); 25333 } 25334 25335 if (!res) { 25336 transmit_response_with_sip_etag(p, "200 OK", req, esc_entry, 1); 25337 } 25338 25339 /* Ref from finding the esc_entry earlier in function */ 25340 ao2_unlink(esc->compositor, esc_entry); 25341 ao2_ref(esc_entry, -1); 25342 return res; 25343 }
| static int handle_t38_options | ( | struct ast_flags * | flags, | |
| struct ast_flags * | mask, | |||
| struct ast_variable * | v, | |||
| int * | maxdatagram | |||
| ) | [static] |
Handle T.38 configuration options common to users and peers.
Definition at line 27709 of file chan_sip.c.
References ast_clear_flag, ast_log(), ast_set2_flag, ast_set_flag, ast_strdupa, ast_true(), ast_variable::lineno, LOG_WARNING, ast_variable::name, strsep(), ast_variable::value, and word.
Referenced by build_peer(), and reload_config().
27711 { 27712 int res = 1; 27713 27714 if (!strcasecmp(v->name, "t38pt_udptl")) { 27715 char *buf = ast_strdupa(v->value); 27716 char *word, *next = buf; 27717 27718 ast_set_flag(&mask[1], SIP_PAGE2_T38SUPPORT); 27719 27720 while ((word = strsep(&next, ","))) { 27721 if (ast_true(word) || !strcasecmp(word, "fec")) { 27722 ast_clear_flag(&flags[1], SIP_PAGE2_T38SUPPORT); 27723 ast_set_flag(&flags[1], SIP_PAGE2_T38SUPPORT_UDPTL_FEC); 27724 } else if (!strcasecmp(word, "redundancy")) { 27725 ast_clear_flag(&flags[1], SIP_PAGE2_T38SUPPORT); 27726 ast_set_flag(&flags[1], SIP_PAGE2_T38SUPPORT_UDPTL_REDUNDANCY); 27727 } else if (!strcasecmp(word, "none")) { 27728 ast_clear_flag(&flags[1], SIP_PAGE2_T38SUPPORT); 27729 ast_set_flag(&flags[1], SIP_PAGE2_T38SUPPORT_UDPTL); 27730 } else if (!strncasecmp(word, "maxdatagram=", 12)) { 27731 if (sscanf(&word[12], "%30u", maxdatagram) != 1) { 27732 ast_log(LOG_WARNING, "Invalid maxdatagram '%s' at line %d of %s\n", v->value, v->lineno, config); 27733 *maxdatagram = global_t38_maxdatagram; 27734 } 27735 } 27736 } 27737 } else if (!strcasecmp(v->name, "t38pt_usertpsource")) { 27738 ast_set_flag(&mask[1], SIP_PAGE2_UDPTL_DESTINATION); 27739 ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_UDPTL_DESTINATION); 27740 } else { 27741 res = 0; 27742 } 27743 27744 return res; 27745 }
| const char* hangup_cause2sip | ( | int | cause | ) |
Convert Asterisk hangup causes to SIP codes.
Possible values from causes.h
AST_CAUSE_NOTDEFINED AST_CAUSE_NORMAL AST_CAUSE_BUSY
AST_CAUSE_FAILURE AST_CAUSE_CONGESTION AST_CAUSE_UNALLOCATED
In addition to these, a lot of PRI codes is defined in causes.h
...should we take care of them too ?
Quote RFC 3398
ISUP Cause value SIP response
---------------- ------------
1 unallocated number 404 Not Found
2 no route to network 404 Not found
3 no route to destination 404 Not found
16 normal call clearing --- (*)
17 user busy 486 Busy here
18 no user responding 408 Request Timeout
19 no answer from the user 480 Temporarily unavailable
20 subscriber absent 480 Temporarily unavailable
21 call rejected 403 Forbidden (+)
22 number changed (w/o diagnostic) 410 Gone
22 number changed (w/ diagnostic) 301 Moved Permanently
23 redirection to new destination 410 Gone
26 non-selected user clearing 404 Not Found (=)
27 destination out of order 502 Bad Gateway
28 address incomplete 484 Address incomplete
29 facility rejected 501 Not implemented
31 normal unspecified 480 Temporarily unavailable
Definition at line 6269 of file chan_sip.c.
References AST_CAUSE_BEARERCAPABILITY_NOTAVAIL, AST_CAUSE_CALL_REJECTED, AST_CAUSE_CHAN_NOT_IMPLEMENTED, AST_CAUSE_CONGESTION, AST_CAUSE_DESTINATION_OUT_OF_ORDER, AST_CAUSE_FACILITY_REJECTED, AST_CAUSE_FAILURE, AST_CAUSE_INTERWORKING, AST_CAUSE_INVALID_NUMBER_FORMAT, AST_CAUSE_NO_ANSWER, AST_CAUSE_NO_ROUTE_DESTINATION, AST_CAUSE_NO_ROUTE_TRANSIT_NET, AST_CAUSE_NO_USER_RESPONSE, AST_CAUSE_NORMAL_UNSPECIFIED, AST_CAUSE_NOTDEFINED, AST_CAUSE_NUMBER_CHANGED, AST_CAUSE_SWITCH_CONGESTION, AST_CAUSE_UNALLOCATED, AST_CAUSE_UNREGISTERED, AST_CAUSE_USER_BUSY, and ast_debug.
Referenced by sip_hangup().
06270 { 06271 switch (cause) { 06272 case AST_CAUSE_UNALLOCATED: /* 1 */ 06273 case AST_CAUSE_NO_ROUTE_DESTINATION: /* 3 IAX2: Can't find extension in context */ 06274 case AST_CAUSE_NO_ROUTE_TRANSIT_NET: /* 2 */ 06275 return "404 Not Found"; 06276 case AST_CAUSE_CONGESTION: /* 34 */ 06277 case AST_CAUSE_SWITCH_CONGESTION: /* 42 */ 06278 return "503 Service Unavailable"; 06279 case AST_CAUSE_NO_USER_RESPONSE: /* 18 */ 06280 return "408 Request Timeout"; 06281 case AST_CAUSE_NO_ANSWER: /* 19 */ 06282 case AST_CAUSE_UNREGISTERED: /* 20 */ 06283 return "480 Temporarily unavailable"; 06284 case AST_CAUSE_CALL_REJECTED: /* 21 */ 06285 return "403 Forbidden"; 06286 case AST_CAUSE_NUMBER_CHANGED: /* 22 */ 06287 return "410 Gone"; 06288 case AST_CAUSE_NORMAL_UNSPECIFIED: /* 31 */ 06289 return "480 Temporarily unavailable"; 06290 case AST_CAUSE_INVALID_NUMBER_FORMAT: 06291 return "484 Address incomplete"; 06292 case AST_CAUSE_USER_BUSY: 06293 return "486 Busy here"; 06294 case AST_CAUSE_FAILURE: 06295 return "500 Server internal failure"; 06296 case AST_CAUSE_FACILITY_REJECTED: /* 29 */ 06297 return "501 Not Implemented"; 06298 case AST_CAUSE_CHAN_NOT_IMPLEMENTED: 06299 return "503 Service Unavailable"; 06300 /* Used in chan_iax2 */ 06301 case AST_CAUSE_DESTINATION_OUT_OF_ORDER: 06302 return "502 Bad Gateway"; 06303 case AST_CAUSE_BEARERCAPABILITY_NOTAVAIL: /* Can't find codec to connect to host */ 06304 return "488 Not Acceptable Here"; 06305 case AST_CAUSE_INTERWORKING: /* Unspecified Interworking issues */ 06306 return "500 Network error"; 06307 06308 case AST_CAUSE_NOTDEFINED: 06309 default: 06310 ast_debug(1, "AST hangup cause %d (no match found in SIP)\n", cause); 06311 return NULL; 06312 } 06313 06314 /* Never reached */ 06315 return 0; 06316 }
| int hangup_sip2cause | ( | int | cause | ) |
Convert SIP hangup causes to Asterisk hangup causes.
Definition at line 6147 of file chan_sip.c.
References AST_CAUSE_BEARERCAPABILITY_NOTAVAIL, AST_CAUSE_BUSY, AST_CAUSE_CALL_REJECTED, AST_CAUSE_CONGESTION, AST_CAUSE_DESTINATION_OUT_OF_ORDER, AST_CAUSE_FACILITY_REJECTED, AST_CAUSE_FAILURE, AST_CAUSE_INTERWORKING, AST_CAUSE_INVALID_NUMBER_FORMAT, AST_CAUSE_NO_ANSWER, AST_CAUSE_NO_ROUTE_DESTINATION, AST_CAUSE_NO_USER_RESPONSE, AST_CAUSE_NORMAL, AST_CAUSE_NORMAL_TEMPORARY_FAILURE, AST_CAUSE_NUMBER_CHANGED, AST_CAUSE_RECOVERY_ON_TIMER_EXPIRE, AST_CAUSE_UNALLOCATED, and AST_CAUSE_USER_BUSY.
Referenced by __transmit_response(), and handle_response().
06148 { 06149 /* Possible values taken from causes.h */ 06150 06151 switch(cause) { 06152 case 401: /* Unauthorized */ 06153 return AST_CAUSE_CALL_REJECTED; 06154 case 403: /* Not found */ 06155 return AST_CAUSE_CALL_REJECTED; 06156 case 404: /* Not found */ 06157 return AST_CAUSE_UNALLOCATED; 06158 case 405: /* Method not allowed */ 06159 return AST_CAUSE_INTERWORKING; 06160 case 407: /* Proxy authentication required */ 06161 return AST_CAUSE_CALL_REJECTED; 06162 case 408: /* No reaction */ 06163 return AST_CAUSE_NO_USER_RESPONSE; 06164 case 409: /* Conflict */ 06165 return AST_CAUSE_NORMAL_TEMPORARY_FAILURE; 06166 case 410: /* Gone */ 06167 return AST_CAUSE_NUMBER_CHANGED; 06168 case 411: /* Length required */ 06169 return AST_CAUSE_INTERWORKING; 06170 case 413: /* Request entity too large */ 06171 return AST_CAUSE_INTERWORKING; 06172 case 414: /* Request URI too large */ 06173 return AST_CAUSE_INTERWORKING; 06174 case 415: /* Unsupported media type */ 06175 return AST_CAUSE_INTERWORKING; 06176 case 420: /* Bad extension */ 06177 return AST_CAUSE_NO_ROUTE_DESTINATION; 06178 case 480: /* No answer */ 06179 return AST_CAUSE_NO_ANSWER; 06180 case 481: /* No answer */ 06181 return AST_CAUSE_INTERWORKING; 06182 case 482: /* Loop detected */ 06183 return AST_CAUSE_INTERWORKING; 06184 case 483: /* Too many hops */ 06185 return AST_CAUSE_NO_ANSWER; 06186 case 484: /* Address incomplete */ 06187 return AST_CAUSE_INVALID_NUMBER_FORMAT; 06188 case 485: /* Ambiguous */ 06189 return AST_CAUSE_UNALLOCATED; 06190 case 486: /* Busy everywhere */ 06191 return AST_CAUSE_BUSY; 06192 case 487: /* Request terminated */ 06193 return AST_CAUSE_INTERWORKING; 06194 case 488: /* No codecs approved */ 06195 return AST_CAUSE_BEARERCAPABILITY_NOTAVAIL; 06196 case 491: /* Request pending */ 06197 return AST_CAUSE_INTERWORKING; 06198 case 493: /* Undecipherable */ 06199 return AST_CAUSE_INTERWORKING; 06200 case 500: /* Server internal failure */ 06201 return AST_CAUSE_FAILURE; 06202 case 501: /* Call rejected */ 06203 return AST_CAUSE_FACILITY_REJECTED; 06204 case 502: 06205 return AST_CAUSE_DESTINATION_OUT_OF_ORDER; 06206 case 503: /* Service unavailable */ 06207 return AST_CAUSE_CONGESTION; 06208 case 504: /* Gateway timeout */ 06209 return AST_CAUSE_RECOVERY_ON_TIMER_EXPIRE; 06210 case 505: /* SIP version not supported */ 06211 return AST_CAUSE_INTERWORKING; 06212 case 600: /* Busy everywhere */ 06213 return AST_CAUSE_USER_BUSY; 06214 case 603: /* Decline */ 06215 return AST_CAUSE_CALL_REJECTED; 06216 case 604: /* Does not exist anywhere */ 06217 return AST_CAUSE_UNALLOCATED; 06218 case 606: /* Not acceptable */ 06219 return AST_CAUSE_BEARERCAPABILITY_NOTAVAIL; 06220 default: 06221 if (cause < 500 && cause >= 400) { 06222 /* 4xx class error that is unknown - someting wrong with our request */ 06223 return AST_CAUSE_INTERWORKING; 06224 } else if (cause < 600 && cause >= 500) { 06225 /* 5xx class error - problem in the remote end */ 06226 return AST_CAUSE_CONGESTION; 06227 } else if (cause < 700 && cause >= 600) { 06228 /* 6xx - global errors in the 4xx class */ 06229 return AST_CAUSE_INTERWORKING; 06230 } 06231 return AST_CAUSE_NORMAL; 06232 } 06233 /* Never reached */ 06234 return 0; 06235 }
| static int init_req | ( | struct sip_request * | req, | |
| int | sipmethod, | |||
| const char * | recip | |||
| ) | [static] |
Initialize SIP request.
Definition at line 10427 of file chan_sip.c.
References ast_free, ast_str_create(), ast_str_set(), sip_methods, and cfsip_methods::text.
10428 { 10429 /* Initialize a request */ 10430 memset(req, 0, sizeof(*req)); 10431 if (!(req->data = ast_str_create(SIP_MIN_PACKET))) 10432 goto e_return; 10433 if (!(req->content = ast_str_create(SIP_MIN_PACKET))) 10434 goto e_free_data; 10435 req->method = sipmethod; 10436 req->header[0] = 0; 10437 ast_str_set(&req->data, 0, "%s %s SIP/2.0\r\n", sip_methods[sipmethod].text, recip); 10438 req->headers++; 10439 return 0; 10440 10441 e_free_data: 10442 ast_free(req->data); 10443 req->data = NULL; 10444 e_return: 10445 return -1; 10446 }
| static int init_resp | ( | struct sip_request * | resp, | |
| const char * | msg | |||
| ) | [static] |
Initialize SIP response, based on SIP request.
Definition at line 10405 of file chan_sip.c.
References ast_free, ast_str_create(), and ast_str_set().
10406 { 10407 /* Initialize a response */ 10408 memset(resp, 0, sizeof(*resp)); 10409 resp->method = SIP_RESPONSE; 10410 if (!(resp->data = ast_str_create(SIP_MIN_PACKET))) 10411 goto e_return; 10412 if (!(resp->content = ast_str_create(SIP_MIN_PACKET))) 10413 goto e_free_data; 10414 resp->header[0] = 0; 10415 ast_str_set(&resp->data, 0, "SIP/2.0 %s\r\n", msg); 10416 resp->headers++; 10417 return 0; 10418 10419 e_free_data: 10420 ast_free(resp->data); 10421 resp->data = NULL; 10422 e_return: 10423 return -1; 10424 }
| static int initialize_escs | ( | void | ) | [static] |
Definition at line 1072 of file chan_sip.c.
References ao2_container_alloc, ARRAY_LEN, esc_cmp_fn(), esc_hash_fn(), and event_state_compositors.
Referenced by load_module().
01073 { 01074 int i, res = 0; 01075 for (i = 0; i < ARRAY_LEN(event_state_compositors); i++) { 01076 if (!((event_state_compositors[i].compositor) = 01077 ao2_container_alloc(ESC_MAX_BUCKETS, esc_hash_fn, esc_cmp_fn))) { 01078 res = -1; 01079 } 01080 } 01081 return res; 01082 }
| static void initialize_initreq | ( | struct sip_pvt * | p, | |
| struct sip_request * | req | |||
| ) | [static] |
Initialize the initital request packet in the pvt structure. This packet is used for creating replies and future requests in a dialog.
Definition at line 3093 of file chan_sip.c.
References ast_debug, ast_verbose, copy_request(), parse_request(), sip_methods, and cfsip_methods::text.
Referenced by transmit_invite(), transmit_message(), transmit_notify_with_mwi(), transmit_notify_with_sipfrag(), transmit_register(), transmit_reinvite_with_sdp(), and update_connectedline().
03094 { 03095 if (p->initreq.headers) { 03096 ast_debug(1, "Initializing already initialized SIP dialog %s (presumably reinvite)\n", p->callid); 03097 } else { 03098 ast_debug(1, "Initializing initreq for method %s - callid %s\n", sip_methods[req->method].text, p->callid); 03099 } 03100 /* Use this as the basis */ 03101 copy_request(&p->initreq, req); 03102 parse_request(&p->initreq); 03103 if (req->debug) { 03104 ast_verbose("Initreq: %d headers, %d lines\n", p->initreq.headers, p->initreq.lines); 03105 } 03106 }
| static int initialize_udptl | ( | struct sip_pvt * | p | ) | [static] |
Definition at line 6887 of file chan_sip.c.
References ast_channel_set_fd(), ast_clear_flag, ast_debug, ast_log(), AST_LOG_WARNING, ast_test_flag, ast_udptl_fd(), ast_udptl_new_with_bindaddr(), ast_udptl_setnat(), ast_udptl_setqos(), bindaddr, and set_t38_capabilities().
Referenced by process_sdp(), process_sdp_a_image(), and sip_indicate().
06888 { 06889 int natflags = ast_test_flag(&p->flags[1], SIP_PAGE2_SYMMETRICRTP); 06890 06891 if (!ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT)) { 06892 return 1; 06893 } 06894 06895 /* If we've already initialized T38, don't take any further action */ 06896 if (p->udptl) { 06897 return 0; 06898 } 06899 06900 /* T38 can be supported by this dialog, create it and set the derived properties */ 06901 if ((p->udptl = ast_udptl_new_with_bindaddr(sched, io, 0, &bindaddr))) { 06902 if (p->owner) { 06903 ast_channel_set_fd(p->owner, 5, ast_udptl_fd(p->udptl)); 06904 } 06905 06906 ast_udptl_setqos(p->udptl, global_tos_audio, global_cos_audio); 06907 p->t38_maxdatagram = p->relatedpeer ? p->relatedpeer->t38_maxdatagram : global_t38_maxdatagram; 06908 set_t38_capabilities(p); 06909 06910 ast_debug(1, "Setting NAT on UDPTL to %s\n", natflags ? "On" : "Off"); 06911 ast_udptl_setnat(p->udptl, natflags); 06912 } else { 06913 ast_log(AST_LOG_WARNING, "UDPTL creation failed - disabling T38 for this dialog\n"); 06914 ast_clear_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT); 06915 return 1; 06916 } 06917 06918 return 0; 06919 }
| static void initreqprep | ( | struct sip_request * | req, | |
| struct sip_pvt * | p, | |||
| int | sipmethod, | |||
| const char *const | explicit_uri | |||
| ) | [static] |
Initiate new SIP request to peer/user.
Definition at line 12335 of file chan_sip.c.
References add_header(), add_header_max_forwards(), add_route(), AST_DIGIT_ANYNUM, ast_escape_quoted(), ast_party_id_presentation(), AST_PRES_ALLOWED, AST_PRES_RESTRICTION, ast_sockaddr_port, ast_sockaddr_stringify_host_remote(), ast_str_alloca, ast_str_append(), ast_str_set(), ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_uri_encode(), ast_uri_sip_user, build_contact(), exten, init_req(), ourport, S_OR, sip_cfg, sip_methods, sip_standard_port(), and cfsip_methods::text.
Referenced by transmit_invite(), transmit_message(), and transmit_notify_with_mwi().
12336 { 12337 struct ast_str *invite = ast_str_alloca(256); 12338 char from[256]; 12339 char to[256]; 12340 char tmp_n[SIPBUFSIZE/2]; /* build a local copy of 'n' if needed */ 12341 char tmp_l[SIPBUFSIZE/2]; /* build a local copy of 'l' if needed */ 12342 const char *l = NULL; /* XXX what is this, exactly ? */ 12343 const char *n = NULL; /* XXX what is this, exactly ? */ 12344 const char *d = NULL; /* domain in from header */ 12345 const char *urioptions = ""; 12346 int ourport; 12347 int cid_has_name = 1; 12348 int cid_has_num = 1; 12349 12350 if (ast_test_flag(&p->flags[0], SIP_USEREQPHONE)) { 12351 const char *s = p->username; /* being a string field, cannot be NULL */ 12352 12353 /* Test p->username against allowed characters in AST_DIGIT_ANY 12354 If it matches the allowed characters list, then sipuser = ";user=phone" 12355 If not, then sipuser = "" 12356 */ 12357 /* + is allowed in first position in a tel: uri */ 12358 if (*s == '+') 12359 s++; 12360 for (; *s; s++) { 12361 if (!strchr(AST_DIGIT_ANYNUM, *s) ) 12362 break; 12363 } 12364 /* If we have only digits, add ;user=phone to the uri */ 12365 if (!*s) 12366 urioptions = ";user=phone"; 12367 } 12368 12369 12370 snprintf(p->lastmsg, sizeof(p->lastmsg), "Init: %s", sip_methods[sipmethod].text); 12371 12372 d = S_OR(p->fromdomain, ast_sockaddr_stringify_host_remote(&p->ourip)); 12373 if (p->owner) { 12374 if ((ast_party_id_presentation(&p->owner->connected.id) & AST_PRES_RESTRICTION) == AST_PRES_ALLOWED) { 12375 l = p->owner->connected.id.number.valid ? p->owner->connected.id.number.str : NULL; 12376 n = p->owner->connected.id.name.valid ? p->owner->connected.id.name.str : NULL; 12377 } else { 12378 /* Even if we are using RPID, we shouldn't leak information in the From if the user wants 12379 * their callerid restricted */ 12380 l = CALLERID_UNKNOWN; 12381 n = l; 12382 d = FROMDOMAIN_INVALID; 12383 } 12384 } 12385 12386 /* Hey, it's a NOTIFY! See if they've configured a mwi_from. 12387 * XXX Right now, this logic works because the only place that mwi_from 12388 * is set on the sip_pvt is in sip_send_mwi_to_peer. If things changed, then 12389 * we might end up putting the mwi_from setting into other types of NOTIFY 12390 * messages as well. 12391 */ 12392 if (sipmethod == SIP_NOTIFY && !ast_strlen_zero(p->mwi_from)) { 12393 l = p->mwi_from; 12394 } 12395 12396 if (ast_strlen_zero(l)) { 12397 cid_has_num = 0; 12398 l = default_callerid; 12399 } 12400 if (ast_strlen_zero(n)) { 12401 cid_has_name = 0; 12402 n = l; 12403 } 12404 12405 /* Allow user to be overridden */ 12406 if (!ast_strlen_zero(p->fromuser)) 12407 l = p->fromuser; 12408 else /* Save for any further attempts */ 12409 ast_string_field_set(p, fromuser, l); 12410 12411 /* Allow user to be overridden */ 12412 if (!ast_strlen_zero(p->fromname)) 12413 n = p->fromname; 12414 else /* Save for any further attempts */ 12415 ast_string_field_set(p, fromname, n); 12416 12417 if (sip_cfg.pedanticsipchecking) { 12418 ast_escape_quoted(n, tmp_n, sizeof(tmp_n)); 12419 n = tmp_n; 12420 ast_uri_encode(l, tmp_l, sizeof(tmp_l), ast_uri_sip_user); 12421 l = tmp_l; 12422 } 12423 12424 ourport = (p->fromdomainport) ? p->fromdomainport : ast_sockaddr_port(&p->ourip); 12425 12426 /* If a caller id name was specified, add a display name. */ 12427 if (cid_has_name || !cid_has_num) { 12428 snprintf(from, sizeof(from), "\"%s\" ", n); 12429 } else { 12430 from[0] = '\0'; 12431 } 12432 12433 if (!sip_standard_port(p->socket.type, ourport)) { 12434 size_t offset = strlen(from); 12435 snprintf(&from[offset], sizeof(from) - offset, "<sip:%s@%s:%d>;tag=%s", l, d, ourport, p->tag); 12436 } else { 12437 size_t offset = strlen(from); 12438 snprintf(&from[offset], sizeof(from) - offset, "<sip:%s@%s>;tag=%s", l, d, p->tag); 12439 } 12440 12441 if (!ast_strlen_zero(explicit_uri)) { 12442 ast_str_set(&invite, 0, "%s", explicit_uri); 12443 } else { 12444 /* If we're calling a registered SIP peer, use the fullcontact to dial to the peer */ 12445 if (!ast_strlen_zero(p->fullcontact)) { 12446 /* If we have full contact, trust it */ 12447 ast_str_append(&invite, 0, "%s", p->fullcontact); 12448 } else { 12449 /* Otherwise, use the username while waiting for registration */ 12450 ast_str_append(&invite, 0, "sip:"); 12451 if (!ast_strlen_zero(p->username)) { 12452 n = p->username; 12453 if (sip_cfg.pedanticsipchecking) { 12454 ast_uri_encode(n, tmp_n, sizeof(tmp_n), ast_uri_sip_user); 12455 n = tmp_n; 12456 } 12457 ast_str_append(&invite, 0, "%s@", n); 12458 } 12459 ast_str_append(&invite, 0, "%s", p->tohost); 12460 if (p->portinuri) { 12461 ast_str_append(&invite, 0, ":%d", ast_sockaddr_port(&p->sa)); 12462 } 12463 ast_str_append(&invite, 0, "%s", urioptions); 12464 } 12465 } 12466 12467 /* If custom URI options have been provided, append them */ 12468 if (p->options && !ast_strlen_zero(p->options->uri_options)) 12469 ast_str_append(&invite, 0, ";%s", p->options->uri_options); 12470 12471 /* This is the request URI, which is the next hop of the call 12472 which may or may not be the destination of the call 12473 */ 12474 ast_string_field_set(p, uri, invite->str); 12475 12476 if (!ast_strlen_zero(p->todnid)) { 12477 /*! \todo Need to add back the VXML URL here at some point, possibly use build_string for all this junk */ 12478 if (!strchr(p->todnid, '@')) { 12479 /* We have no domain in the dnid */ 12480 snprintf(to, sizeof(to), "<sip:%s@%s>%s%s", p->todnid, p->tohost, ast_strlen_zero(p->theirtag) ? "" : ";tag=", p->theirtag); 12481 } else { 12482 snprintf(to, sizeof(to), "<sip:%s>%s%s", p->todnid, ast_strlen_zero(p->theirtag) ? "" : ";tag=", p->theirtag); 12483 } 12484 } else { 12485 if (sipmethod == SIP_NOTIFY && !ast_strlen_zero(p->theirtag)) { 12486 /* If this is a NOTIFY, use the From: tag in the subscribe (RFC 3265) */ 12487 snprintf(to, sizeof(to), "<%s%s>;tag=%s", (strncasecmp(p->uri, "sip:", 4) ? "sip:" : ""), p->uri, p->theirtag); 12488 } else if (p->options && p->options->vxml_url) { 12489 /* If there is a VXML URL append it to the SIP URL */ 12490 snprintf(to, sizeof(to), "<%s>;%s", p->uri, p->options->vxml_url); 12491 } else { 12492 snprintf(to, sizeof(to), "<%s>", p->uri); 12493 } 12494 } 12495 12496 init_req(req, sipmethod, p->uri); 12497 /* now tmp_n is available so reuse it to build the CSeq */ 12498 snprintf(tmp_n, sizeof(tmp_n), "%u %s", ++p->ocseq, sip_methods[sipmethod].text); 12499 12500 add_header(req, "Via", p->via); 12501 add_header_max_forwards(p, req); 12502 /* This will be a no-op most of the time. However, under certain circumstances, 12503 * NOTIFY messages will use this function for preparing the request and should 12504 * have Route headers present. 12505 */ 12506 add_route(req, p->route); 12507 12508 add_header(req, "From", from); 12509 add_header(req, "To", to); 12510 ast_string_field_set(p, exten, l); 12511 build_contact(p); 12512 add_header(req, "Contact", p->our_contact); 12513 add_header(req, "Call-ID", p->callid); 12514 add_header(req, "CSeq", tmp_n); 12515 if (!ast_strlen_zero(global_useragent)) { 12516 add_header(req, "User-Agent", global_useragent); 12517 } 12518 }
| static const char * insecure2str | ( | int | mode | ) | [static] |
Convert Insecure setting to printable string.
Definition at line 17642 of file chan_sip.c.
References map_x_s().
Referenced by _sip_show_peer().
17643 { 17644 return map_x_s(insecurestr, mode, "<error>"); 17645 }
| static int interpret_t38_parameters | ( | struct sip_pvt * | p, | |
| const struct ast_control_t38_parameters * | parameters | |||
| ) | [static] |
Helper function which updates T.38 capability information and triggers a reinvite.
Definition at line 6795 of file chan_sip.c.
References AST_CONTROL_T38_PARAMETERS, ast_queue_control_data(), AST_SCHED_DEL_UNREF, ast_set_flag, AST_T38_NEGOTIATED, AST_T38_REFUSED, AST_T38_REQUEST_NEGOTIATE, AST_T38_REQUEST_PARMS, AST_T38_REQUEST_TERMINATE, AST_T38_TERMINATED, ast_test_flag, ast_udptl_get_far_max_ifp(), ast_udptl_set_local_max_ifp(), change_t38_state(), FALSE, ast_control_t38_parameters::fill_bit_removal, ast_control_t38_parameters::max_ifp, MIN, ast_control_t38_parameters::request_response, transmit_reinvite_with_sdp(), transmit_response_reliable(), transmit_response_with_t38_sdp(), and TRUE.
Referenced by sip_indicate().
06796 { 06797 int res = 0; 06798 06799 if (!ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT) || !p->udptl) { 06800 return -1; 06801 } 06802 switch (parameters->request_response) { 06803 case AST_T38_NEGOTIATED: 06804 case AST_T38_REQUEST_NEGOTIATE: /* Request T38 */ 06805 /* Negotiation can not take place without a valid max_ifp value. */ 06806 if (!parameters->max_ifp) { 06807 if (p->t38.state == T38_PEER_REINVITE) { 06808 AST_SCHED_DEL_UNREF(sched, p->t38id, dialog_unref(p, "when you delete the t38id sched, you should dec the refcount for the stored dialog ptr")); 06809 transmit_response_reliable(p, "488 Not acceptable here", &p->initreq); 06810 } 06811 change_t38_state(p, T38_REJECTED); 06812 break; 06813 } else if (p->t38.state == T38_PEER_REINVITE) { 06814 AST_SCHED_DEL_UNREF(sched, p->t38id, dialog_unref(p, "when you delete the t38id sched, you should dec the refcount for the stored dialog ptr")); 06815 p->t38.our_parms = *parameters; 06816 /* modify our parameters to conform to the peer's parameters, 06817 * based on the rules in the ITU T.38 recommendation 06818 */ 06819 if (!p->t38.their_parms.fill_bit_removal) { 06820 p->t38.our_parms.fill_bit_removal = FALSE; 06821 } 06822 if (!p->t38.their_parms.transcoding_mmr) { 06823 p->t38.our_parms.transcoding_mmr = FALSE; 06824 } 06825 if (!p->t38.their_parms.transcoding_jbig) { 06826 p->t38.our_parms.transcoding_jbig = FALSE; 06827 } 06828 p->t38.our_parms.version = MIN(p->t38.our_parms.version, p->t38.their_parms.version); 06829 p->t38.our_parms.rate_management = p->t38.their_parms.rate_management; 06830 ast_udptl_set_local_max_ifp(p->udptl, p->t38.our_parms.max_ifp); 06831 change_t38_state(p, T38_ENABLED); 06832 transmit_response_with_t38_sdp(p, "200 OK", &p->initreq, XMIT_CRITICAL); 06833 } else if (p->t38.state != T38_ENABLED) { 06834 p->t38.our_parms = *parameters; 06835 ast_udptl_set_local_max_ifp(p->udptl, p->t38.our_parms.max_ifp); 06836 change_t38_state(p, T38_LOCAL_REINVITE); 06837 if (!p->pendinginvite) { 06838 transmit_reinvite_with_sdp(p, TRUE, FALSE); 06839 } else if (!ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) { 06840 ast_set_flag(&p->flags[0], SIP_NEEDREINVITE); 06841 } 06842 } 06843 break; 06844 case AST_T38_TERMINATED: 06845 case AST_T38_REFUSED: 06846 case AST_T38_REQUEST_TERMINATE: /* Shutdown T38 */ 06847 if (p->t38.state == T38_PEER_REINVITE) { 06848 AST_SCHED_DEL_UNREF(sched, p->t38id, dialog_unref(p, "when you delete the t38id sched, you should dec the refcount for the stored dialog ptr")); 06849 change_t38_state(p, T38_REJECTED); 06850 transmit_response_reliable(p, "488 Not acceptable here", &p->initreq); 06851 } else if (p->t38.state == T38_ENABLED) 06852 transmit_reinvite_with_sdp(p, FALSE, FALSE); 06853 break; 06854 case AST_T38_REQUEST_PARMS: { /* Application wants remote's parameters re-sent */ 06855 struct ast_control_t38_parameters parameters = p->t38.their_parms; 06856 06857 if (p->t38.state == T38_PEER_REINVITE) { 06858 AST_SCHED_DEL_UNREF(sched, p->t38id, dialog_unref(p, "when you delete the t38id sched, you should dec the refcount for the stored dialog ptr")); 06859 parameters.max_ifp = ast_udptl_get_far_max_ifp(p->udptl); 06860 parameters.request_response = AST_T38_REQUEST_NEGOTIATE; 06861 ast_queue_control_data(p->owner, AST_CONTROL_T38_PARAMETERS, ¶meters, sizeof(parameters)); 06862 /* we need to return a positive value here, so that applications that 06863 * send this request can determine conclusively whether it was accepted or not... 06864 * older versions of chan_sip would just silently accept it and return zero. 06865 */ 06866 res = AST_T38_REQUEST_PARMS; 06867 } 06868 break; 06869 } 06870 default: 06871 res = -1; 06872 break; 06873 } 06874 06875 return res; 06876 }
| static int is_method_allowed | ( | unsigned int * | allowed_methods, | |
| enum sipmethod | method | |||
| ) | [static] |
Check if method is allowed for a device or a dialog.
Definition at line 8577 of file chan_sip.c.
Referenced by sip_sendtext(), and update_connectedline().
| static void list_route | ( | struct sip_route * | route | ) | [static] |
List all routes - mostly for debugging.
Definition at line 14625 of file chan_sip.c.
References ast_verbose.
Referenced by build_route().
14626 { 14627 if (!route) { 14628 ast_verbose("list_route: no route\n"); 14629 } else { 14630 for (;route; route = route->next) 14631 ast_verbose("list_route: hop: <%s>\n", route->hop); 14632 } 14633 }
| static int load_module | ( | void | ) | [static] |
PBX load module - initialization.
Definition at line 31394 of file chan_sip.c.
References ao2_container_alloc, ao2_t_container_alloc, ARRAY_LEN, ast_cc_agent_register(), ast_cc_monitor_register(), ast_channel_register(), ast_check_realtime(), ast_cli_register_multiple(), ast_custom_function_register, ast_data_register_multiple, ast_format_cap_add_all_by_type(), ast_format_cap_alloc(), AST_FORMAT_TYPE_AUDIO, ast_log(), ast_manager_register_xml, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, ast_msg_tech_register(), ast_realtime_require_field(), ast_register_application_xml, ast_rtp_glue_register, ast_sched_context_create(), ast_sched_context_destroy(), AST_TEST_REGISTER, ast_udptl_proto_register(), ast_verbose, ASTOBJ_CONTAINER_INIT, ast_channel_tech::capabilities, CHANNEL_MODULE_LOAD, dialog_cmp_cb(), dialog_hash_cb(), EVENT_FLAG_REPORTING, EVENT_FLAG_SYSTEM, initialize_escs(), io_context_create(), io_context_destroy(), LOG_ERROR, manager_show_registry(), manager_sip_qualify_peer(), manager_sip_show_peer(), manager_sip_show_peers(), manager_sipnotify(), network_change_event_subscribe(), peer_cmp_cb(), peer_hash_cb(), peer_ipcmp_cb(), peer_iphash_cb(), regl, reload_config(), restart_monitor(), RQ_CHAR, RQ_INTEGER4, RQ_UINTEGER2, ast_channel_tech::send_digit_begin, SENTINEL, sip_addheader(), sip_cfg, sip_dtmfmode(), sip_epa_register(), sip_is_xml_parsable(), sip_monitor_instance_cmp_fn(), sip_monitor_instance_hash_fn(), sip_poke_all_peers(), sip_register_tests(), sip_removeheader(), sip_reqresp_parser_init(), sip_send_all_mwi_subscriptions(), sip_send_all_registers(), sip_tech_info, submwil, threadt_cmp_cb(), and threadt_hash_cb().
31395 { 31396 ast_verbose("SIP channel loading...\n"); 31397 31398 if (!(sip_tech.capabilities = ast_format_cap_alloc())) { 31399 return AST_MODULE_LOAD_FAILURE; 31400 } 31401 31402 /* the fact that ao2_containers can't resize automatically is a major worry! */ 31403 /* if the number of objects gets above MAX_XXX_BUCKETS, things will slow down */ 31404 peers = ao2_t_container_alloc(HASH_PEER_SIZE, peer_hash_cb, peer_cmp_cb, "allocate peers"); 31405 peers_by_ip = ao2_t_container_alloc(HASH_PEER_SIZE, peer_iphash_cb, peer_ipcmp_cb, "allocate peers_by_ip"); 31406 dialogs = ao2_t_container_alloc(HASH_DIALOG_SIZE, dialog_hash_cb, dialog_cmp_cb, "allocate dialogs"); 31407 dialogs_needdestroy = ao2_t_container_alloc(1, NULL, NULL, "allocate dialogs_needdestroy"); 31408 dialogs_rtpcheck = ao2_t_container_alloc(HASH_DIALOG_SIZE, dialog_hash_cb, dialog_cmp_cb, "allocate dialogs for rtpchecks"); 31409 threadt = ao2_t_container_alloc(HASH_DIALOG_SIZE, threadt_hash_cb, threadt_cmp_cb, "allocate threadt table"); 31410 if (!peers || !peers_by_ip || !dialogs || !dialogs_needdestroy || !dialogs_rtpcheck 31411 || !threadt) { 31412 ast_log(LOG_ERROR, "Unable to create primary SIP container(s)\n"); 31413 return AST_MODULE_LOAD_FAILURE; 31414 } 31415 31416 if (!(sip_cfg.caps = ast_format_cap_alloc())) { 31417 return AST_MODULE_LOAD_FAILURE; 31418 } 31419 ast_format_cap_add_all_by_type(sip_tech.capabilities, AST_FORMAT_TYPE_AUDIO); 31420 31421 ASTOBJ_CONTAINER_INIT(®l); /* Registry object list -- not searched for anything */ 31422 ASTOBJ_CONTAINER_INIT(&submwil); /* MWI subscription object list */ 31423 31424 if (!(sched = ast_sched_context_create())) { 31425 ast_log(LOG_ERROR, "Unable to create scheduler context\n"); 31426 return AST_MODULE_LOAD_FAILURE; 31427 } 31428 31429 if (!(io = io_context_create())) { 31430 ast_log(LOG_ERROR, "Unable to create I/O context\n"); 31431 ast_sched_context_destroy(sched); 31432 return AST_MODULE_LOAD_FAILURE; 31433 } 31434 31435 sip_reloadreason = CHANNEL_MODULE_LOAD; 31436 31437 can_parse_xml = sip_is_xml_parsable(); 31438 if (reload_config(sip_reloadreason)) { /* Load the configuration from sip.conf */ 31439 return AST_MODULE_LOAD_DECLINE; 31440 } 31441 31442 /* Prepare the version that does not require DTMF BEGIN frames. 31443 * We need to use tricks such as memcpy and casts because the variable 31444 * has const fields. 31445 */ 31446 memcpy(&sip_tech_info, &sip_tech, sizeof(sip_tech)); 31447 memset((void *) &sip_tech_info.send_digit_begin, 0, sizeof(sip_tech_info.send_digit_begin)); 31448 31449 if (ast_msg_tech_register(&sip_msg_tech)) { 31450 /* LOAD_FAILURE stops Asterisk, so cleanup is a moot point. */ 31451 return AST_MODULE_LOAD_FAILURE; 31452 } 31453 31454 /* Make sure we can register our sip channel type */ 31455 if (ast_channel_register(&sip_tech)) { 31456 ast_log(LOG_ERROR, "Unable to register channel type 'SIP'\n"); 31457 io_context_destroy(io); 31458 ast_sched_context_destroy(sched); 31459 return AST_MODULE_LOAD_FAILURE; 31460 } 31461 31462 #ifdef TEST_FRAMEWORK 31463 AST_TEST_REGISTER(test_sip_peers_get); 31464 AST_TEST_REGISTER(test_sip_mwi_subscribe_parse); 31465 #endif 31466 31467 /* Register AstData providers */ 31468 ast_data_register_multiple(sip_data_providers, ARRAY_LEN(sip_data_providers)); 31469 31470 /* Register all CLI functions for SIP */ 31471 ast_cli_register_multiple(cli_sip, ARRAY_LEN(cli_sip)); 31472 31473 /* Tell the UDPTL subdriver that we're here */ 31474 ast_udptl_proto_register(&sip_udptl); 31475 31476 /* Tell the RTP engine about our RTP glue */ 31477 ast_rtp_glue_register(&sip_rtp_glue); 31478 31479 /* Register dialplan applications */ 31480 ast_register_application_xml(app_dtmfmode, sip_dtmfmode); 31481 ast_register_application_xml(app_sipaddheader, sip_addheader); 31482 ast_register_application_xml(app_sipremoveheader, sip_removeheader); 31483 31484 /* Register dialplan functions */ 31485 ast_custom_function_register(&sip_header_function); 31486 ast_custom_function_register(&sippeer_function); 31487 ast_custom_function_register(&sipchaninfo_function); 31488 ast_custom_function_register(&checksipdomain_function); 31489 31490 /* Register manager commands */ 31491 ast_manager_register_xml("SIPpeers", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_sip_show_peers); 31492 ast_manager_register_xml("SIPshowpeer", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_sip_show_peer); 31493 ast_manager_register_xml("SIPqualifypeer", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_sip_qualify_peer); 31494 ast_manager_register_xml("SIPshowregistry", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_show_registry); 31495 ast_manager_register_xml("SIPnotify", EVENT_FLAG_SYSTEM, manager_sipnotify); 31496 sip_poke_all_peers(); 31497 sip_send_all_registers(); 31498 sip_send_all_mwi_subscriptions(); 31499 initialize_escs(); 31500 31501 if (sip_epa_register(&cc_epa_static_data)) { 31502 return AST_MODULE_LOAD_DECLINE; 31503 } 31504 31505 if (sip_reqresp_parser_init() == -1) { 31506 ast_log(LOG_ERROR, "Unable to initialize the SIP request and response parser\n"); 31507 return AST_MODULE_LOAD_DECLINE; 31508 } 31509 31510 if (can_parse_xml) { 31511 /* SIP CC agents require the ability to parse XML PIDF bodies 31512 * in incoming PUBLISH requests 31513 */ 31514 if (ast_cc_agent_register(&sip_cc_agent_callbacks)) { 31515 return AST_MODULE_LOAD_DECLINE; 31516 } 31517 } 31518 if (ast_cc_monitor_register(&sip_cc_monitor_callbacks)) { 31519 return AST_MODULE_LOAD_DECLINE; 31520 } 31521 if (!(sip_monitor_instances = ao2_container_alloc(37, sip_monitor_instance_hash_fn, sip_monitor_instance_cmp_fn))) { 31522 return AST_MODULE_LOAD_DECLINE; 31523 } 31524 31525 /* And start the monitor for the first time */ 31526 restart_monitor(); 31527 31528 ast_realtime_require_field(ast_check_realtime("sipregs") ? "sipregs" : "sippeers", 31529 "name", RQ_CHAR, 10, 31530 "ipaddr", RQ_CHAR, INET6_ADDRSTRLEN - 1, 31531 "port", RQ_UINTEGER2, 5, 31532 "regseconds", RQ_INTEGER4, 11, 31533 "defaultuser", RQ_CHAR, 10, 31534 "fullcontact", RQ_CHAR, 35, 31535 "regserver", RQ_CHAR, 20, 31536 "useragent", RQ_CHAR, 20, 31537 "lastms", RQ_INTEGER4, 11, 31538 SENTINEL); 31539 31540 31541 sip_register_tests(); 31542 network_change_event_subscribe(); 31543 31544 return AST_MODULE_LOAD_SUCCESS; 31545 }
| static int local_attended_transfer | ( | struct sip_pvt * | transferer, | |
| struct sip_dual * | current, | |||
| struct sip_request * | req, | |||
| uint32_t | seqno, | |||
| int * | nounlock | |||
| ) | [static] |
Find all call legs and bridge transferee with target called from handle_request_refer.
Definition at line 23895 of file chan_sip.c.
References ao2_t_ref, append_history, ast_bridged_channel(), AST_CEL_ATTENDEDTRANSFER, ast_cel_report_event(), ast_channel_language(), ast_channel_linkedid(), ast_channel_name(), ast_channel_queue_connected_line_update(), ast_channel_ref, ast_channel_uniqueid(), ast_channel_unlock, ast_channel_unref, ast_clear_flag, ast_connected_line_build_data(), AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER, AST_CONTROL_READ_ACTION, AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, ast_copy_string(), ast_debug, ast_do_masquerade(), AST_FRAME_READ_ACTION_CONNECTED_LINE_MACRO, ast_indicate(), ast_manager_event_multichan, ast_party_connected_line_copy(), ast_party_connected_line_free(), ast_party_connected_line_init(), ast_queue_control_data(), ast_set_flag, ast_state2str(), AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, ast_streamfile(), ast_strlen_zero(), ast_waitstream(), attempt_transfer(), EVENT_FLAG_CALL, frame_size, get_sip_pvt_byid_locked(), pbx_builtin_getvar_helper(), sip_pvt_lock, sip_pvt_unlock, ast_party_connected_line::source, transmit_notify_with_sipfrag(), TRUE, and xfersound.
Referenced by handle_request_refer().
23896 { 23897 struct sip_dual target; /* Chan 1: Call from tranferer to Asterisk */ 23898 /* Chan 2: Call from Asterisk to target */ 23899 int res = 0; 23900 struct sip_pvt *targetcall_pvt; 23901 struct ast_party_connected_line connected_to_transferee; 23902 struct ast_party_connected_line connected_to_target; 23903 char transferer_linkedid[32]; 23904 struct ast_channel *chans[2]; 23905 23906 /* Check if the call ID of the replaces header does exist locally */ 23907 if (!(targetcall_pvt = get_sip_pvt_byid_locked(transferer->refer->replaces_callid, transferer->refer->replaces_callid_totag, 23908 transferer->refer->replaces_callid_fromtag))) { 23909 if (transferer->refer->localtransfer) { 23910 /* We did not find the refered call. Sorry, can't accept then */ 23911 /* Let's fake a response from someone else in order 23912 to follow the standard */ 23913 transmit_notify_with_sipfrag(transferer, seqno, "481 Call leg/transaction does not exist", TRUE); 23914 append_history(transferer, "Xfer", "Refer failed"); 23915 ast_clear_flag(&transferer->flags[0], SIP_GOTREFER); 23916 transferer->refer->status = REFER_FAILED; 23917 return -1; 23918 } 23919 /* Fall through for remote transfers that we did not find locally */ 23920 ast_debug(3, "SIP attended transfer: Not our call - generating INVITE with replaces\n"); 23921 return 0; 23922 } 23923 23924 /* Ok, we can accept this transfer */ 23925 append_history(transferer, "Xfer", "Refer accepted"); 23926 if (!targetcall_pvt->owner) { /* No active channel */ 23927 ast_debug(4, "SIP attended transfer: Error: No owner of target call\n"); 23928 /* Cancel transfer */ 23929 transmit_notify_with_sipfrag(transferer, seqno, "503 Service Unavailable", TRUE); 23930 append_history(transferer, "Xfer", "Refer failed"); 23931 ast_clear_flag(&transferer->flags[0], SIP_GOTREFER); 23932 transferer->refer->status = REFER_FAILED; 23933 sip_pvt_unlock(targetcall_pvt); 23934 if (targetcall_pvt) 23935 ao2_t_ref(targetcall_pvt, -1, "Drop targetcall_pvt pointer"); 23936 return -1; 23937 } 23938 23939 /* We have a channel, find the bridge */ 23940 target.chan1 = targetcall_pvt->owner; /* Transferer to Asterisk */ 23941 target.chan2 = ast_bridged_channel(targetcall_pvt->owner); /* Asterisk to target */ 23942 23943 if (!target.chan2 || !(target.chan2->_state == AST_STATE_UP || target.chan2->_state == AST_STATE_RINGING) ) { 23944 /* Wrong state of new channel */ 23945 if (target.chan2) 23946 ast_debug(4, "SIP attended transfer: Error: Wrong state of target call: %s\n", ast_state2str(target.chan2->_state)); 23947 else if (target.chan1->_state != AST_STATE_RING) 23948 ast_debug(4, "SIP attended transfer: Error: No target channel\n"); 23949 else 23950 ast_debug(4, "SIP attended transfer: Attempting transfer in ringing state\n"); 23951 } 23952 23953 /* Transfer */ 23954 if (sipdebug) { 23955 if (current->chan2) /* We have two bridges */ 23956 ast_debug(4, "SIP attended transfer: trying to bridge %s and %s\n", ast_channel_name(target.chan1), ast_channel_name(current->chan2)); 23957 else /* One bridge, propably transfer of IVR/voicemail etc */ 23958 ast_debug(4, "SIP attended transfer: trying to make %s take over (masq) %s\n", ast_channel_name(target.chan1), ast_channel_name(current->chan1)); 23959 } 23960 23961 ast_set_flag(&transferer->flags[0], SIP_DEFER_BYE_ON_TRANSFER); /* Delay hangup */ 23962 23963 ast_copy_string(transferer_linkedid, ast_channel_linkedid(transferer->owner), sizeof(transferer_linkedid)); 23964 23965 /* Perform the transfer */ 23966 chans[0] = transferer->owner; 23967 chans[1] = target.chan1; 23968 ast_manager_event_multichan(EVENT_FLAG_CALL, "Transfer", 2, chans, 23969 "TransferMethod: SIP\r\n" 23970 "TransferType: Attended\r\n" 23971 "Channel: %s\r\n" 23972 "Uniqueid: %s\r\n" 23973 "SIP-Callid: %s\r\n" 23974 "TargetChannel: %s\r\n" 23975 "TargetUniqueid: %s\r\n", 23976 ast_channel_name(transferer->owner), 23977 ast_channel_uniqueid(transferer->owner), 23978 transferer->callid, 23979 ast_channel_name(target.chan1), 23980 ast_channel_uniqueid(target.chan1)); 23981 ast_party_connected_line_init(&connected_to_transferee); 23982 ast_party_connected_line_init(&connected_to_target); 23983 /* No need to lock current->chan1 here since it was locked in sipsock_read */ 23984 ast_party_connected_line_copy(&connected_to_transferee, ¤t->chan1->connected); 23985 /* No need to lock target.chan1 here since it was locked in get_sip_pvt_byid_locked */ 23986 ast_party_connected_line_copy(&connected_to_target, &target.chan1->connected); 23987 connected_to_target.source = connected_to_transferee.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER; 23988 res = attempt_transfer(current, &target); 23989 if (res) { 23990 /* Failed transfer */ 23991 transmit_notify_with_sipfrag(transferer, seqno, "486 Busy Here", TRUE); 23992 append_history(transferer, "Xfer", "Refer failed"); 23993 ast_clear_flag(&transferer->flags[0], SIP_DEFER_BYE_ON_TRANSFER); 23994 /* if transfer failed, go ahead and unlock targetcall_pvt and it's owner channel */ 23995 sip_pvt_unlock(targetcall_pvt); 23996 ast_channel_unlock(target.chan1); 23997 } else { 23998 /* Transfer succeeded! */ 23999 const char *xfersound = pbx_builtin_getvar_helper(target.chan1, "ATTENDED_TRANSFER_COMPLETE_SOUND"); 24000 24001 /* target.chan1 was locked in get_sip_pvt_byid_locked, do not unlock target.chan1 before this */ 24002 ast_cel_report_event(target.chan1, AST_CEL_ATTENDEDTRANSFER, NULL, transferer_linkedid, target.chan2); 24003 24004 /* Tell transferer that we're done. */ 24005 transmit_notify_with_sipfrag(transferer, seqno, "200 OK", TRUE); 24006 append_history(transferer, "Xfer", "Refer succeeded"); 24007 transferer->refer->status = REFER_200OK; 24008 if (target.chan2 && !ast_strlen_zero(xfersound) && ast_streamfile(target.chan2, xfersound, ast_channel_language(target.chan2)) >= 0) { 24009 ast_waitstream(target.chan2, ""); 24010 } 24011 24012 /* By forcing the masquerade, we know that target.chan1 and target.chan2 are bridged. We then 24013 * can queue connected line updates where they need to go. 24014 * 24015 * before a masquerade, all channel and pvt locks must be unlocked. Any recursive 24016 * channel locks held before this function invalidates channel container locking order. 24017 * Since we are unlocking both the pvt (transferer) and its owner channel (current.chan1) 24018 * it is possible for current.chan1 to be destroyed in the pbx thread. To prevent this 24019 * we must give c a reference before any unlocking takes place. 24020 */ 24021 24022 ast_channel_ref(current->chan1); 24023 ast_channel_unlock(current->chan1); /* current.chan1 is p->owner before the masq, it was locked by socket_read()*/ 24024 ast_channel_unlock(target.chan1); 24025 *nounlock = 1; /* we just unlocked the dialog's channel and have no plans of locking it again. */ 24026 sip_pvt_unlock(targetcall_pvt); 24027 sip_pvt_unlock(transferer); 24028 24029 ast_do_masquerade(target.chan1); 24030 24031 ast_indicate(target.chan1, AST_CONTROL_UNHOLD); 24032 if (target.chan2) { 24033 ast_indicate(target.chan2, AST_CONTROL_UNHOLD); 24034 } 24035 24036 if (current->chan2 && current->chan2->_state == AST_STATE_RING) { 24037 ast_indicate(target.chan1, AST_CONTROL_RINGING); 24038 } 24039 24040 if (target.chan2) { 24041 ast_channel_queue_connected_line_update(target.chan1, &connected_to_transferee, NULL); 24042 ast_channel_queue_connected_line_update(target.chan2, &connected_to_target, NULL); 24043 } else { 24044 /* Since target.chan1 isn't actually connected to another channel, there is no way for us 24045 * to queue a frame so that its connected line status will be updated. 24046 * 24047 * Instead, we use the somewhat hackish approach of using a special control frame type that 24048 * instructs ast_read to perform a specific action. In this case, the frame we queue tells 24049 * ast_read to call the connected line interception macro configured for target.chan1. 24050 */ 24051 struct ast_control_read_action_payload *frame_payload; 24052 int payload_size; 24053 int frame_size; 24054 unsigned char connected_line_data[1024]; 24055 payload_size = ast_connected_line_build_data(connected_line_data, 24056 sizeof(connected_line_data), &connected_to_target, NULL); 24057 frame_size = payload_size + sizeof(*frame_payload); 24058 if (payload_size != -1 && (frame_payload = alloca(frame_size))) { 24059 frame_payload->payload_size = payload_size; 24060 memcpy(frame_payload->payload, connected_line_data, payload_size); 24061 frame_payload->action = AST_FRAME_READ_ACTION_CONNECTED_LINE_MACRO; 24062 ast_queue_control_data(target.chan1, AST_CONTROL_READ_ACTION, frame_payload, frame_size); 24063 } 24064 /* In addition to queueing the read action frame so that target.chan1's connected line info 24065 * will be updated, we also are going to queue a plain old connected line update on target.chan1. This 24066 * way, either Dial or Queue can apply this connected line update to the outgoing ringing channel. 24067 */ 24068 ast_channel_queue_connected_line_update(target.chan1, &connected_to_transferee, NULL); 24069 24070 } 24071 sip_pvt_lock(transferer); /* the transferer pvt is expected to remain locked on return */ 24072 24073 ast_channel_unref(current->chan1); 24074 } 24075 24076 /* at this point if the transfer is successful only the transferer pvt should be locked. */ 24077 ast_party_connected_line_free(&connected_to_target); 24078 ast_party_connected_line_free(&connected_to_transferee); 24079 if (targetcall_pvt) 24080 ao2_t_ref(targetcall_pvt, -1, "drop targetcall_pvt"); 24081 return 1; 24082 }
| static void lws2sws | ( | struct ast_str * | msgbuf | ) | [static] |
Parse multiline SIP headers into one header This is enabled if pedanticsipchecking is enabled.
Definition at line 8665 of file chan_sip.c.
References ast_str_strlen(), and len().
Referenced by handle_request_do().
08666 { 08667 char *msgbuf = data->str; 08668 int len = ast_str_strlen(data); 08669 int h = 0, t = 0; 08670 int lws = 0; 08671 08672 for (; h < len;) { 08673 /* Eliminate all CRs */ 08674 if (msgbuf[h] == '\r') { 08675 h++; 08676 continue; 08677 } 08678 /* Check for end-of-line */ 08679 if (msgbuf[h] == '\n') { 08680 /* Check for end-of-message */ 08681 if (h + 1 == len) 08682 break; 08683 /* Check for a continuation line */ 08684 if (msgbuf[h + 1] == ' ' || msgbuf[h + 1] == '\t') { 08685 /* Merge continuation line */ 08686 h++; 08687 continue; 08688 } 08689 /* Propagate LF and start new line */ 08690 msgbuf[t++] = msgbuf[h++]; 08691 lws = 0; 08692 continue; 08693 } 08694 if (msgbuf[h] == ' ' || msgbuf[h] == '\t') { 08695 if (lws) { 08696 h++; 08697 continue; 08698 } 08699 msgbuf[t++] = msgbuf[h++]; 08700 lws = 1; 08701 continue; 08702 } 08703 msgbuf[t++] = msgbuf[h++]; 08704 if (lws) 08705 lws = 0; 08706 } 08707 msgbuf[t] = '\0'; 08708 data->used = t; 08709 }
| static void make_our_tag | ( | char * | tagbuf, | |
| size_t | len | |||
| ) | [static] |
Make our SIP dialog tag.
Definition at line 7758 of file chan_sip.c.
References ast_random().
Referenced by handle_request_invite(), handle_request_subscribe(), sip_alloc(), transmit_register(), and transmit_response_using_temp().
07759 { 07760 snprintf(tagbuf, len, "as%08lx", ast_random()); 07761 }
| static int manager_show_registry | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Show SIP registrations in the manager API.
Definition at line 17253 of file chan_sip.c.
References ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_listack(), ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_RDLOCK, ASTOBJ_UNLOCK, regl, regstate2str(), S_OR, and total.
Referenced by load_module().
17254 { 17255 const char *id = astman_get_header(m, "ActionID"); 17256 char idtext[256] = ""; 17257 int total = 0; 17258 17259 if (!ast_strlen_zero(id)) 17260 snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id); 17261 17262 astman_send_listack(s, m, "Registrations will follow", "start"); 17263 17264 ASTOBJ_CONTAINER_TRAVERSE(®l, 1, do { 17265 ASTOBJ_RDLOCK(iterator); 17266 astman_append(s, 17267 "Event: RegistryEntry\r\n" 17268 "%s" 17269 "Host: %s\r\n" 17270 "Port: %d\r\n" 17271 "Username: %s\r\n" 17272 "Domain: %s\r\n" 17273 "DomainPort: %d\r\n" 17274 "Refresh: %d\r\n" 17275 "State: %s\r\n" 17276 "RegistrationTime: %ld\r\n" 17277 "\r\n", 17278 idtext, 17279 iterator->hostname, 17280 iterator->portno ? iterator->portno : STANDARD_SIP_PORT, 17281 iterator->username, 17282 S_OR(iterator->regdomain,iterator->hostname), 17283 iterator->regdomainport ? iterator->regdomainport : STANDARD_SIP_PORT, 17284 iterator->refresh, 17285 regstate2str(iterator->regstate), 17286 (long) iterator->regtime.tv_sec); 17287 ASTOBJ_UNLOCK(iterator); 17288 total++; 17289 } while(0)); 17290 17291 astman_append(s, 17292 "Event: RegistrationsComplete\r\n" 17293 "EventList: Complete\r\n" 17294 "ListItems: %d\r\n" 17295 "%s" 17296 "\r\n", total, idtext); 17297 17298 return 0; 17299 }
| static int manager_sip_qualify_peer | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Qualify SIP peers in the manager API.
Definition at line 18030 of file chan_sip.c.
References _sip_qualify_peer(), ast_strlen_zero(), astman_append(), astman_get_header(), and astman_send_error().
Referenced by load_module().
18031 { 18032 const char *a[4]; 18033 const char *peer; 18034 18035 peer = astman_get_header(m, "Peer"); 18036 if (ast_strlen_zero(peer)) { 18037 astman_send_error(s, m, "Peer: <name> missing."); 18038 return 0; 18039 } 18040 a[0] = "sip"; 18041 a[1] = "qualify"; 18042 a[2] = "peer"; 18043 a[3] = peer; 18044 18045 _sip_qualify_peer(1, -1, s, m, 4, a); 18046 astman_append(s, "\r\n\r\n" ); 18047 return 0; 18048 }
| static int manager_sip_show_peer | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Show SIP peers in the manager API.
Definition at line 17971 of file chan_sip.c.
References _sip_show_peer(), ast_strlen_zero(), astman_append(), astman_get_header(), and astman_send_error().
Referenced by load_module().
17972 { 17973 const char *a[4]; 17974 const char *peer; 17975 17976 peer = astman_get_header(m, "Peer"); 17977 if (ast_strlen_zero(peer)) { 17978 astman_send_error(s, m, "Peer: <name> missing."); 17979 return 0; 17980 } 17981 a[0] = "sip"; 17982 a[1] = "show"; 17983 a[2] = "peer"; 17984 a[3] = peer; 17985 17986 _sip_show_peer(1, -1, s, m, 4, a); 17987 astman_append(s, "\r\n" ); 17988 return 0; 17989 }
| static int manager_sip_show_peers | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Show SIP peers in the manager API.
Definition at line 17303 of file chan_sip.c.
References _sip_show_peers(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_listack(), and total.
Referenced by load_module().
17304 { 17305 const char *id = astman_get_header(m, "ActionID"); 17306 const char *a[] = {"sip", "show", "peers"}; 17307 char idtext[256] = ""; 17308 int total = 0; 17309 17310 if (!ast_strlen_zero(id)) 17311 snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id); 17312 17313 astman_send_listack(s, m, "Peer status list will follow", "start"); 17314 /* List the peers in separate manager events */ 17315 _sip_show_peers(-1, &total, s, m, 3, a); 17316 /* Send final confirmation */ 17317 astman_append(s, 17318 "Event: PeerlistComplete\r\n" 17319 "EventList: Complete\r\n" 17320 "ListItems: %d\r\n" 17321 "%s" 17322 "\r\n", total, idtext); 17323 return 0; 17324 }
| static int manager_sipnotify | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 13329 of file chan_sip.c.
References ast_log(), ast_set_flag, ast_str_append(), ast_str_strlen(), ast_strlen_zero(), ast_variable_new(), ast_variables_destroy(), astman_get_header(), astman_get_variables(), astman_send_ack(), astman_send_error(), create_addr(), dialog_unlink_all(), LOG_WARNING, ast_variable::name, ast_variable::next, sip_alloc(), sip_notify_allocate(), sip_scheddestroy(), transmit_invite(), ast_variable::value, and var.
Referenced by load_module().
13330 { 13331 const char *channame = astman_get_header(m, "Channel"); 13332 struct ast_variable *vars = astman_get_variables(m); 13333 struct sip_pvt *p; 13334 struct ast_variable *header, *var; 13335 13336 if (ast_strlen_zero(channame)) { 13337 astman_send_error(s, m, "SIPNotify requires a channel name"); 13338 return 0; 13339 } 13340 13341 if (!strncasecmp(channame, "sip/", 4)) { 13342 channame += 4; 13343 } 13344 13345 if (!(p = sip_alloc(NULL, NULL, 0, SIP_NOTIFY, NULL))) { 13346 astman_send_error(s, m, "Unable to build sip pvt data for notify (memory/socket error)"); 13347 return 0; 13348 } 13349 13350 if (create_addr(p, channame, NULL, 0, NULL)) { 13351 /* Maybe they're not registered, etc. */ 13352 dialog_unlink_all(p); 13353 dialog_unref(p, "unref dialog inside for loop" ); 13354 /* sip_destroy(p); */ 13355 astman_send_error(s, m, "Could not create address"); 13356 return 0; 13357 } 13358 13359 /* Notify is outgoing call */ 13360 ast_set_flag(&p->flags[0], SIP_OUTGOING); 13361 sip_notify_allocate(p); 13362 13363 p->notify->headers = header = ast_variable_new("Subscription-State", "terminated", ""); 13364 13365 for (var = vars; var; var = var->next) { 13366 if (!strcasecmp(var->name, "Content")) { 13367 if (ast_str_strlen(p->notify->content)) 13368 ast_str_append(&p->notify->content, 0, "\r\n"); 13369 ast_str_append(&p->notify->content, 0, "%s", var->value); 13370 } else if (!strcasecmp(var->name, "Content-Length")) { 13371 ast_log(LOG_WARNING, "it is not necessary to specify Content-Length, ignoring"); 13372 } else { 13373 header->next = ast_variable_new(var->name, var->value, ""); 13374 header = header->next; 13375 } 13376 } 13377 13378 sip_scheddestroy(p, SIP_TRANS_TIMEOUT); 13379 transmit_invite(p, SIP_NOTIFY, 0, 2, NULL); 13380 dialog_unref(p, "bump down the count of p since we're done with it."); 13381 13382 astman_send_ack(s, m, "Notify Sent"); 13383 ast_variables_destroy(vars); 13384 return 0; 13385 }
| static int map_s_x | ( | const struct _map_x_s * | table, | |
| const char * | s, | |||
| int | errorvalue | |||
| ) | [static] |
map from a string to an integer value, case insensitive. If no match is found, return errorvalue.
Definition at line 2278 of file chan_sip.c.
Referenced by str2dtmfmode(), str2stmode(), and str2strefresher().
02279 { 02280 const struct _map_x_s *cur; 02281 02282 for (cur = table; cur->s; cur++) { 02283 if (!strcasecmp(cur->s, s)) { 02284 return cur->x; 02285 } 02286 } 02287 return errorvalue; 02288 }
| static const char* map_x_s | ( | const struct _map_x_s * | table, | |
| int | x, | |||
| const char * | errorstring | |||
| ) | [static] |
map from an integer value to a string. If no match is found, return errorstring
Definition at line 2263 of file chan_sip.c.
Referenced by allowoverlap2str(), autocreatepeer2str(), dtmfmode2str(), faxec2str(), insecure2str(), referstatus2str(), regstate2str(), stmode2str(), and strefresher2str().
02264 { 02265 const struct _map_x_s *cur; 02266 02267 for (cur = table; cur->s; cur++) { 02268 if (cur->x == x) { 02269 return cur->s; 02270 } 02271 } 02272 return errorstring; 02273 }
| static void mark_method_allowed | ( | unsigned int * | allowed_methods, | |
| enum sipmethod | method | |||
| ) | [static] |
Definition at line 8566 of file chan_sip.c.
Referenced by handle_response(), handle_response_info(), handle_response_message(), mark_parsed_methods(), and set_pvt_allowed_methods().
| static void mark_method_unallowed | ( | unsigned int * | allowed_methods, | |
| enum sipmethod | method | |||
| ) | [static] |
Definition at line 8571 of file chan_sip.c.
Referenced by handle_response(), handle_response_info(), handle_response_message(), and handle_response_publish().
| static void mark_parsed_methods | ( | unsigned int * | methods, | |
| char * | methods_str | |||
| ) | [static] |
Definition at line 8582 of file chan_sip.c.
References ast_skip_blanks(), ast_strlen_zero(), find_sip_method(), mark_method_allowed(), and strsep().
Referenced by build_peer(), parse_allowed_methods(), and reload_config().
08583 { 08584 char *method; 08585 for (method = strsep(&methods_str, ","); !ast_strlen_zero(method); method = strsep(&methods_str, ",")) { 08586 int id = find_sip_method(ast_skip_blanks(method)); 08587 if (id == SIP_UNKNOWN) { 08588 continue; 08589 } 08590 mark_method_allowed(methods, id); 08591 } 08592 }
| static int match_and_cleanup_peer_sched | ( | void * | peerobj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 2893 of file chan_sip.c.
References ast_dnsmgr_release(), CMP_MATCH, peer_sched_cleanup(), SIP_PEERS_ALL, and sip_unref_peer().
Referenced by unlink_peers_from_tables().
02894 { 02895 struct sip_peer *peer = peerobj; 02896 peer_unlink_flag_t which = *(peer_unlink_flag_t *)arg; 02897 02898 if (which == SIP_PEERS_ALL || peer->the_mark) { 02899 peer_sched_cleanup(peer); 02900 if (peer->dnsmgr) { 02901 ast_dnsmgr_release(peer->dnsmgr); 02902 peer->dnsmgr = NULL; 02903 sip_unref_peer(peer, "Release peer from dnsmgr"); 02904 } 02905 return CMP_MATCH; 02906 } 02907 return 0; 02908 }
| static enum match_req_res match_req_to_dialog | ( | struct sip_pvt * | sip_pvt_ptr, | |
| struct match_req_args * | arg | |||
| ) | [static] |
Definition at line 8012 of file chan_sip.c.
References ast_strlen_zero(), ast_test_flag, match_req_args::authentication_present, match_req_args::callid, match_req_args::fromtag, match_req_args::method, match_req_args::respid, match_req_args::ruri, match_req_args::seqno, SIP_REQ_FORKED, SIP_REQ_LOOP_DETECTED, SIP_REQ_MATCH, SIP_REQ_NOT_MATCH, sip_uri_cmp(), match_req_args::totag, match_req_args::viabranch, and match_req_args::viasentby.
Referenced by find_call().
08013 { 08014 const char *init_ruri = NULL; 08015 if (sip_pvt_ptr->initreq.headers) { 08016 init_ruri = REQ_OFFSET_TO_STR(&sip_pvt_ptr->initreq, rlPart2); 08017 } 08018 08019 /* 08020 * Match Tags and call-id to Dialog 08021 */ 08022 if (!ast_strlen_zero(arg->callid) && strcmp(sip_pvt_ptr->callid, arg->callid)) { 08023 /* call-id does not match. */ 08024 return SIP_REQ_NOT_MATCH; 08025 } 08026 if (arg->method == SIP_RESPONSE) { 08027 /* Verify fromtag of response matches the tag we gave them. */ 08028 if (strcmp(arg->fromtag, sip_pvt_ptr->tag)) { 08029 /* fromtag from response does not match our tag */ 08030 return SIP_REQ_NOT_MATCH; 08031 } 08032 08033 /* Verify totag if we have one stored for this dialog, but never be strict about this for 08034 * a response until the dialog is established */ 08035 if (!ast_strlen_zero(sip_pvt_ptr->theirtag) && ast_test_flag(&sip_pvt_ptr->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED)) { 08036 if (ast_strlen_zero(arg->totag)) { 08037 /* missing totag when they already gave us one earlier */ 08038 return SIP_REQ_NOT_MATCH; 08039 } 08040 /* compare the totag of response with the tag we have stored for them */ 08041 if (strcmp(arg->totag, sip_pvt_ptr->theirtag)) { 08042 /* totag did not match what we had stored for them. */ 08043 char invite_branch[32] = { 0, }; 08044 if (sip_pvt_ptr->invite_branch) { 08045 snprintf(invite_branch, sizeof(invite_branch), "z9hG4bK%08x", (int) sip_pvt_ptr->invite_branch); 08046 } 08047 /* Forked Request Detection 08048 * 08049 * If this is a 200ok response and the totags do not match, this 08050 * might be a forked response to an outgoing Request. Detection of 08051 * a forked response must meet the criteria below. 08052 * 08053 * 1. must be a 2xx Response 08054 * 2. call-d equal to call-id of Request. this is done earlier 08055 * 3. from-tag equal to from-tag of Request. this is done earlier 08056 * 4. branch parameter equal to branch of inital Request 08057 * 5. to-tag _NOT_ equal to previous 2xx response that already established the dialog. 08058 */ 08059 if ((arg->respid == 200) && 08060 !ast_strlen_zero(invite_branch) && 08061 !ast_strlen_zero(arg->viabranch) && 08062 !strcmp(invite_branch, arg->viabranch)) { 08063 return SIP_REQ_FORKED; 08064 } 08065 08066 /* The totag did not match the one we had stored, and this is not a Forked Request. */ 08067 return SIP_REQ_NOT_MATCH; 08068 } 08069 } 08070 } else { 08071 /* Verify the fromtag of Request matches the tag they provided earlier. 08072 * If this is a Request with authentication credentials, forget their old 08073 * tag as it is not valid after the 401 or 407 response. */ 08074 if (!arg->authentication_present && strcmp(arg->fromtag, sip_pvt_ptr->theirtag)) { 08075 /* their tag does not match the one was have stored for them */ 08076 return SIP_REQ_NOT_MATCH; 08077 } 08078 /* Verify if totag is present in Request, that it matches what we gave them as our tag earlier */ 08079 if (!ast_strlen_zero(arg->totag) && (strcmp(arg->totag, sip_pvt_ptr->tag))) { 08080 /* totag from Request does not match our tag */ 08081 return SIP_REQ_NOT_MATCH; 08082 } 08083 } 08084 08085 /* 08086 * Compare incoming request against initial transaction. 08087 * 08088 * This is a best effort attempt at distinguishing forked requests from 08089 * our initial transaction. If all the elements are NOT in place to evaluate 08090 * this, this block is ignored and the dialog match is made regardless. 08091 * Once the totag is established after the dialog is confirmed, this is not necessary. 08092 * 08093 * CRITERIA required for initial transaction matching. 08094 * 08095 * 1. Is a Request 08096 * 2. Callid and theirtag match (this is done in the dialog matching block) 08097 * 3. totag is NOT present 08098 * 4. CSeq matchs our initial transaction's cseq number 08099 * 5. pvt has init via branch parameter stored 08100 */ 08101 if ((arg->method != SIP_RESPONSE) && /* must be a Request */ 08102 ast_strlen_zero(arg->totag) && /* must not have a totag */ 08103 (sip_pvt_ptr->init_icseq == arg->seqno) && /* the cseq must be the same as this dialogs initial cseq */ 08104 !ast_strlen_zero(sip_pvt_ptr->initviabranch) && /* The dialog must have started with a RFC3261 compliant branch tag */ 08105 init_ruri) { /* the dialog must have an initial request uri associated with it */ 08106 /* This Request matches all the criteria required for Loop/Merge detection. 08107 * Now we must go down the path of comparing VIA's and RURIs. */ 08108 if (ast_strlen_zero(arg->viabranch) || 08109 strcmp(arg->viabranch, sip_pvt_ptr->initviabranch) || 08110 ast_strlen_zero(arg->viasentby) || 08111 strcmp(arg->viasentby, sip_pvt_ptr->initviasentby)) { 08112 /* At this point, this request does not match this Dialog.*/ 08113 08114 /* if methods are different this is just a mismatch */ 08115 if ((sip_pvt_ptr->method != arg->method)) { 08116 return SIP_REQ_NOT_MATCH; 08117 } 08118 08119 /* If RUIs are different, this is a forked request to a separate URI. 08120 * Returning a mismatch allows this Request to be processed separately. */ 08121 if (sip_uri_cmp(init_ruri, arg->ruri)) { 08122 /* not a match, request uris are different */ 08123 return SIP_REQ_NOT_MATCH; 08124 } 08125 08126 /* Loop/Merge Detected 08127 * 08128 * ---Current Matches to Initial Request--- 08129 * request uri 08130 * Call-id 08131 * their-tag 08132 * no totag present 08133 * method 08134 * cseq 08135 * 08136 * --- Does not Match Initial Request --- 08137 * Top Via 08138 * 08139 * Without the same Via, this can not match our initial transaction for this dialog, 08140 * but given that this Request matches everything else associated with that initial 08141 * Request this is most certainly a Forked request in which we have already received 08142 * part of the fork. 08143 */ 08144 return SIP_REQ_LOOP_DETECTED; 08145 } 08146 } /* end of Request Via check */ 08147 08148 /* Match Authentication Request. 08149 * 08150 * A Request with an Authentication header must come back with the 08151 * same Request URI. Otherwise it is not a match. 08152 */ 08153 if ((arg->method != SIP_RESPONSE) && /* Must be a Request type to even begin checking this */ 08154 ast_strlen_zero(arg->totag) && /* no totag is present to match */ 08155 arg->authentication_present && /* Authentication header is present in Request */ 08156 sip_uri_cmp(init_ruri, arg->ruri)) { /* Compare the Request URI of both the last Request and this new one */ 08157 08158 /* Authentication was provided, but the Request URI did not match the last one on this dialog. */ 08159 return SIP_REQ_NOT_MATCH; 08160 } 08161 08162 return SIP_REQ_MATCH; 08163 }
| static int method_match | ( | enum sipmethod | id, | |
| const char * | name | |||
| ) | [static] |
returns true if 'name' (with optional trailing whitespace) matches the sip method 'id'. Strictly speaking, SIP methods are case SENSITIVE, but we do a case-insensitive comparison to be more tolerant. following Jon Postel's rule: Be gentle in what you accept, strict with what you send
Definition at line 3180 of file chan_sip.c.
References len(), sip_methods, and text.
Referenced by __sip_autodestruct(), __sip_semi_ack(), and find_sip_method().
03181 { 03182 int len = strlen(sip_methods[id].text); 03183 int l_name = name ? strlen(name) : 0; 03184 /* true if the string is long enough, and ends with whitespace, and matches */ 03185 return (l_name >= len && name[len] < 33 && 03186 !strncasecmp(sip_methods[id].text, name, len)); 03187 }
| static void mwi_event_cb | ( | const struct ast_event * | event, | |
| void * | userdata | |||
| ) | [static] |
Receive MWI events that we have subscribed to.
Definition at line 14965 of file chan_sip.c.
References sip_send_mwi_to_peer().
14966 { 14967 struct sip_peer *peer = userdata; 14968 14969 sip_send_mwi_to_peer(peer, 0); 14970 }
| static void network_change_event_cb | ( | const struct ast_event * | event, | |
| void * | userdata | |||
| ) | [static] |
Definition at line 14995 of file chan_sip.c.
References ast_debug, ast_sched_add(), and network_change_event_sched_cb().
14996 { 14997 ast_debug(1, "SIP, got a network change event, renewing all SIP registrations.\n"); 14998 if (network_change_event_sched_id == -1) { 14999 network_change_event_sched_id = ast_sched_add(sched, 1000, network_change_event_sched_cb, NULL); 15000 } 15001 }
| static int network_change_event_sched_cb | ( | const void * | data | ) | [static] |
Definition at line 14987 of file chan_sip.c.
References sip_send_all_mwi_subscriptions(), and sip_send_all_registers().
14988 { 14989 network_change_event_sched_id = -1; 14990 sip_send_all_registers(); 14991 sip_send_all_mwi_subscriptions(); 14992 return 0; 14993 }
| static void network_change_event_subscribe | ( | void | ) | [static] |
Definition at line 14972 of file chan_sip.c.
References AST_EVENT_IE_END, AST_EVENT_NETWORK_CHANGE, ast_event_subscribe(), and network_change_event_cb().
14973 { 14974 if (!network_change_event_subscription) { 14975 network_change_event_subscription = ast_event_subscribe(AST_EVENT_NETWORK_CHANGE, 14976 network_change_event_cb, "SIP Network Change", NULL, AST_EVENT_IE_END); 14977 } 14978 }
| static void network_change_event_unsubscribe | ( | void | ) | [static] |
Definition at line 14980 of file chan_sip.c.
References ast_event_unsubscribe().
14981 { 14982 if (network_change_event_subscription) { 14983 network_change_event_subscription = ast_event_unsubscribe(network_change_event_subscription); 14984 } 14985 }
| static struct sip_proxy* obproxy_get | ( | struct sip_pvt * | dialog, | |
| struct sip_peer * | peer | |||
| ) | [static, read] |
Get default outbound proxy or global proxy.
Definition at line 3152 of file chan_sip.c.
References append_history, ast_debug, and sip_cfg.
Referenced by __sip_subscribe_mwi_do(), create_addr(), create_addr_from_peer(), and transmit_register().
03153 { 03154 if (peer && peer->outboundproxy) { 03155 if (sipdebug) { 03156 ast_debug(1, "OBPROXY: Applying peer OBproxy to this call\n"); 03157 } 03158 append_history(dialog, "OBproxy", "Using peer obproxy %s", peer->outboundproxy->name); 03159 return peer->outboundproxy; 03160 } 03161 if (sip_cfg.outboundproxy.name[0]) { 03162 if (sipdebug) { 03163 ast_debug(1, "OBPROXY: Applying global OBproxy to this call\n"); 03164 } 03165 append_history(dialog, "OBproxy", "Using global obproxy %s", sip_cfg.outboundproxy.name); 03166 return &sip_cfg.outboundproxy; 03167 } 03168 if (sipdebug) { 03169 ast_debug(1, "OBPROXY: Not applying OBproxy to this call\n"); 03170 } 03171 return NULL; 03172 }
| static void on_dns_update_mwi | ( | struct ast_sockaddr * | old, | |
| struct ast_sockaddr * | new, | |||
| void * | data | |||
| ) | [static] |
Definition at line 12838 of file chan_sip.c.
References ast_debug, ast_sockaddr_copy(), ast_sockaddr_isnull(), ast_sockaddr_stringify(), and ast_strdupa.
Referenced by __sip_subscribe_mwi_do().
12839 { 12840 struct sip_subscription_mwi *mwi = data; 12841 const char *old_str; 12842 12843 /* This shouldn't happen, but just in case */ 12844 if (ast_sockaddr_isnull(new)) { 12845 ast_debug(1, "Empty sockaddr change...ignoring!\n"); 12846 return; 12847 } 12848 12849 old_str = ast_strdupa(ast_sockaddr_stringify(old)); 12850 ast_debug(1, "Changing mwi %s from %s to %s\n", mwi->hostname, old_str, ast_sockaddr_stringify(new)); 12851 ast_sockaddr_copy(&mwi->us, new); 12852 }
| static void on_dns_update_peer | ( | struct ast_sockaddr * | old, | |
| struct ast_sockaddr * | new, | |||
| void * | data | |||
| ) | [static] |
Definition at line 12809 of file chan_sip.c.
References ao2_link, ao2_lock, ao2_unlink, ao2_unlock, ast_debug, ast_sockaddr_copy(), ast_sockaddr_isnull(), ast_sockaddr_port, ast_sockaddr_set_port, ast_sockaddr_stringify(), ast_strdupa, and default_sip_port().
Referenced by build_peer(), and transmit_register().
12810 { 12811 struct sip_peer *peer = data; 12812 const char *old_str; 12813 12814 /* This shouldn't happen, but just in case */ 12815 if (ast_sockaddr_isnull(new)) { 12816 ast_debug(1, "Empty sockaddr change...ignoring!\n"); 12817 return; 12818 } 12819 12820 if (!ast_sockaddr_isnull(&peer->addr)) { 12821 ao2_unlink(peers_by_ip, peer); 12822 } 12823 12824 if (!ast_sockaddr_port(new)) { 12825 ast_sockaddr_set_port(new, default_sip_port(peer->socket.type)); 12826 } 12827 12828 old_str = ast_strdupa(ast_sockaddr_stringify(old)); 12829 ast_debug(1, "Changing peer %s address from %s to %s\n", peer->name, old_str, ast_sockaddr_stringify(new)); 12830 12831 ao2_lock(peer); 12832 ast_sockaddr_copy(&peer->addr, new); 12833 ao2_unlock(peer); 12834 12835 ao2_link(peers_by_ip, peer); 12836 }
| static void on_dns_update_registry | ( | struct ast_sockaddr * | old, | |
| struct ast_sockaddr * | new, | |||
| void * | data | |||
| ) | [static] |
Definition at line 12788 of file chan_sip.c.
References ast_debug, ast_sockaddr_copy(), ast_sockaddr_isnull(), ast_sockaddr_port, ast_sockaddr_set_port, ast_sockaddr_stringify(), ast_strdupa, and S_OR.
Referenced by transmit_register().
12789 { 12790 struct sip_registry *reg = data; 12791 const char *old_str; 12792 12793 /* This shouldn't happen, but just in case */ 12794 if (ast_sockaddr_isnull(new)) { 12795 ast_debug(1, "Empty sockaddr change...ignoring!\n"); 12796 return; 12797 } 12798 12799 if (!ast_sockaddr_port(new)) { 12800 ast_sockaddr_set_port(new, reg->portno); 12801 } 12802 12803 old_str = ast_strdupa(ast_sockaddr_stringify(old)); 12804 12805 ast_debug(1, "Changing registry %s from %s to %s\n", S_OR(reg->peername, reg->hostname), old_str, ast_sockaddr_stringify(new)); 12806 ast_sockaddr_copy(®->us, new); 12807 }
| static unsigned int parse_allowed_methods | ( | struct sip_request * | req | ) | [static] |
parse the Allow header to see what methods the endpoint we are communicating with allows.
We parse the allow header on incoming Registrations and save the result to the SIP peer that is registering. When the registration expires, we clear what we know about the peer's allowed methods. When the peer re-registers, we once again parse to see if the list of allowed methods has changed.
For peers that do not register, we parse the first message we receive during a call to see what is allowed, and save the information for the duration of the call.
| req | The SIP request we are parsing |
| The | methods allowed |
Definition at line 8609 of file chan_sip.c.
References ast_strdupa, ast_strip_quoted(), ast_strlen_zero(), mark_parsed_methods(), and sip_get_header().
Referenced by set_pvt_allowed_methods().
08610 { 08611 char *allow = ast_strdupa(sip_get_header(req, "Allow")); 08612 unsigned int allowed_methods = SIP_UNKNOWN; 08613 08614 if (ast_strlen_zero(allow)) { 08615 /* I have witnessed that REGISTER requests from Polycom phones do not 08616 * place the phone's allowed methods in an Allow header. Instead, they place the 08617 * allowed methods in a methods= parameter in the Contact header. 08618 */ 08619 char *contact = ast_strdupa(sip_get_header(req, "Contact")); 08620 char *methods = strstr(contact, ";methods="); 08621 08622 if (ast_strlen_zero(methods)) { 08623 /* RFC 3261 states: 08624 * 08625 * "The absence of an Allow header field MUST NOT be 08626 * interpreted to mean that the UA sending the message supports no 08627 * methods. Rather, it implies that the UA is not providing any 08628 * information on what methods it supports." 08629 * 08630 * For simplicity, we'll assume that the peer allows all known 08631 * SIP methods if they have no Allow header. We can then clear out the necessary 08632 * bits if the peer lets us know that we have sent an unsupported method. 08633 */ 08634 return UINT_MAX; 08635 } 08636 allow = ast_strip_quoted(methods + 9, "\"", "\""); 08637 } 08638 mark_parsed_methods(&allowed_methods, allow); 08639 return allowed_methods; 08640 }
| static void parse_copy | ( | struct sip_request * | dst, | |
| const struct sip_request * | src | |||
| ) | [static] |
Copy SIP request, parse it.
Definition at line 4101 of file chan_sip.c.
References copy_request(), and parse_request().
Referenced by send_request(), and send_response().
04102 { 04103 copy_request(dst, src); 04104 parse_request(dst); 04105 }
| int parse_minse | ( | const char * | p_hdrval, | |
| int *const | p_interval | |||
| ) | [static] |
Session-Timers: Function for parsing Min-SE header.
Definition at line 27063 of file chan_sip.c.
References ast_debug, ast_log(), ast_skip_blanks(), ast_strlen_zero(), and LOG_WARNING.
Referenced by handle_request_invite(), and proc_422_rsp().
27064 { 27065 if (ast_strlen_zero(p_hdrval)) { 27066 ast_log(LOG_WARNING, "Null Min-SE header\n"); 27067 return -1; 27068 } 27069 27070 *p_interval = 0; 27071 p_hdrval = ast_skip_blanks(p_hdrval); 27072 if (!sscanf(p_hdrval, "%30d", p_interval)) { 27073 ast_log(LOG_WARNING, "Parsing of Min-SE header failed %s\n", p_hdrval); 27074 return -1; 27075 } 27076 27077 ast_debug(2, "Received Min-SE: %d\n", *p_interval); 27078 return 0; 27079 }
| static void parse_moved_contact | ( | struct sip_pvt * | p, | |
| struct sip_request * | req, | |||
| char ** | name, | |||
| char ** | number, | |||
| int | set_call_forward | |||
| ) | [static] |
Parse 302 Moved temporalily response.
Definition at line 20409 of file chan_sip.c.
References ao2_ref, ast_copy_string(), ast_debug, ast_log(), ast_strdup, ast_strlen_zero(), ast_test_flag, ast_uri_decode(), ast_uri_sip_user, find_closing_quote(), get_in_brackets(), LOG_NOTICE, pbx_builtin_setvar_helper(), remove_uri_parameters(), set_socket_transport(), sip_get_header(), sip_get_transport(), and strcasestr().
Referenced by change_redirecting_information().
20410 { 20411 char contact[SIPBUFSIZE]; 20412 char *contact_name = NULL; 20413 char *contact_number = NULL; 20414 char *separator, *trans; 20415 char *domain; 20416 enum sip_transport transport = SIP_TRANSPORT_UDP; 20417 20418 ast_copy_string(contact, sip_get_header(req, "Contact"), sizeof(contact)); 20419 if ((separator = strchr(contact, ','))) 20420 *separator = '\0'; 20421 20422 contact_number = get_in_brackets(contact); 20423 if ((trans = strcasestr(contact_number, ";transport="))) { 20424 trans += 11; 20425 20426 if ((separator = strchr(trans, ';'))) 20427 *separator = '\0'; 20428 20429 if (!strncasecmp(trans, "tcp", 3)) 20430 transport = SIP_TRANSPORT_TCP; 20431 else if (!strncasecmp(trans, "tls", 3)) 20432 transport = SIP_TRANSPORT_TLS; 20433 else { 20434 if (strncasecmp(trans, "udp", 3)) 20435 ast_debug(1, "received contact with an invalid transport, '%s'\n", contact_number); 20436 /* This will assume UDP for all unknown transports */ 20437 transport = SIP_TRANSPORT_UDP; 20438 } 20439 } 20440 contact_number = remove_uri_parameters(contact_number); 20441 20442 if (p->socket.tcptls_session) { 20443 ao2_ref(p->socket.tcptls_session, -1); 20444 p->socket.tcptls_session = NULL; 20445 } 20446 20447 set_socket_transport(&p->socket, transport); 20448 20449 if (set_call_forward && ast_test_flag(&p->flags[0], SIP_PROMISCREDIR)) { 20450 char *host = NULL; 20451 if (!strncasecmp(contact_number, "sip:", 4)) 20452 contact_number += 4; 20453 else if (!strncasecmp(contact_number, "sips:", 5)) 20454 contact_number += 5; 20455 separator = strchr(contact_number, '/'); 20456 if (separator) 20457 *separator = '\0'; 20458 if ((host = strchr(contact_number, '@'))) { 20459 *host++ = '\0'; 20460 ast_debug(2, "Found promiscuous redirection to 'SIP/%s::::%s@%s'\n", contact_number, sip_get_transport(transport), host); 20461 if (p->owner) 20462 ast_channel_call_forward_build(p->owner, "SIP/%s::::%s@%s", contact_number, sip_get_transport(transport), host); 20463 } else { 20464 ast_debug(2, "Found promiscuous redirection to 'SIP/::::%s@%s'\n", sip_get_transport(transport), contact_number); 20465 if (p->owner) 20466 ast_channel_call_forward_build(p->owner, "SIP/::::%s@%s", sip_get_transport(transport), contact_number); 20467 } 20468 } else { 20469 separator = strchr(contact, '@'); 20470 if (separator) { 20471 *separator++ = '\0'; 20472 domain = separator; 20473 } else { 20474 /* No username part */ 20475 domain = contact; 20476 } 20477 separator = strchr(contact, '/'); /* WHEN do we hae a forward slash in the URI? */ 20478 if (separator) 20479 *separator = '\0'; 20480 20481 if (!strncasecmp(contact_number, "sip:", 4)) 20482 contact_number += 4; 20483 else if (!strncasecmp(contact_number, "sips:", 5)) 20484 contact_number += 5; 20485 separator = strchr(contact_number, ';'); /* And username ; parameters? */ 20486 if (separator) 20487 *separator = '\0'; 20488 ast_uri_decode(contact_number, ast_uri_sip_user); 20489 if (set_call_forward) { 20490 ast_debug(2, "Received 302 Redirect to extension '%s' (domain %s)\n", contact_number, domain); 20491 if (p->owner) { 20492 pbx_builtin_setvar_helper(p->owner, "SIPDOMAIN", domain); 20493 ast_channel_call_forward_set(p->owner, contact_number); 20494 } 20495 } 20496 } 20497 20498 /* We've gotten the number for the contact, now get the name */ 20499 20500 if (*contact == '\"') { 20501 contact_name = contact + 1; 20502 if (!(separator = (char *)find_closing_quote(contact_name, NULL))) { 20503 ast_log(LOG_NOTICE, "No closing quote on name in Contact header? %s\n", contact); 20504 } 20505 *separator = '\0'; 20506 } 20507 20508 if (name && !ast_strlen_zero(contact_name)) { 20509 *name = ast_strdup(contact_name); 20510 } 20511 if (number) { 20512 *number = ast_strdup(contact_number); 20513 } 20514 }
| static int parse_ok_contact | ( | struct sip_pvt * | pvt, | |
| struct sip_request * | req | |||
| ) | [static] |
Save contact header for 200 OK on INVITE.
Definition at line 14297 of file chan_sip.c.
References ast_copy_string(), ast_string_field_set, get_in_brackets(), sip_get_header(), and TRUE.
Referenced by forked_invite_init(), handle_request_invite(), handle_request_subscribe(), and handle_response_invite().
14298 { 14299 char contact[SIPBUFSIZE]; 14300 char *c; 14301 14302 /* Look for brackets */ 14303 ast_copy_string(contact, sip_get_header(req, "Contact"), sizeof(contact)); 14304 c = get_in_brackets(contact); 14305 14306 /* Save full contact to call pvt for later bye or re-invite */ 14307 ast_string_field_set(pvt, fullcontact, c); 14308 14309 /* Save URI for later ACKs, BYE or RE-invites */ 14310 ast_string_field_set(pvt, okcontacturi, c); 14311 14312 /* We should return false for URI:s we can't handle, 14313 like tel:, mailto:,ldap: etc */ 14314 return TRUE; 14315 }
| static enum parse_register_result parse_register_contact | ( | struct sip_pvt * | pvt, | |
| struct sip_peer * | p, | |||
| struct sip_request * | req | |||
| ) | [static] |
Parse contact header and save registration (peer registration).
Definition at line 14404 of file chan_sip.c.
References __get_header(), ao2_t_link, ao2_t_unlink, ast_apply_ha(), ast_copy_string(), ast_db_put(), ast_debug, ast_log(), ast_sched_add(), AST_SCHED_DEL_UNREF, ast_sched_when(), AST_SENSE_ALLOW, ast_sockaddr_cmp(), ast_sockaddr_copy(), ast_sockaddr_isnull(), ast_sockaddr_port, ast_sockaddr_resolve_first(), ast_sockaddr_set_port, ast_sockaddr_stringify(), ast_sockaddr_stringify_addr(), ast_strdupa, ast_string_field_build, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_verb, copy_socket_data(), default_sip_port(), EVENT_FLAG_SYSTEM, expire_register(), FALSE, get_in_brackets(), get_transport_str2enum(), LOG_NOTICE, LOG_WARNING, manager_event, parse_uri_legacy_check(), register_peer_exten(), set_socket_transport(), sip_cfg, sip_get_header(), sip_poke_peer(), sip_ref_peer(), sip_unref_peer(), strcasestr(), strsep(), and TRUE.
Referenced by register_verify().
14405 { 14406 char contact[SIPBUFSIZE]; 14407 char data[SIPBUFSIZE]; 14408 const char *expires = sip_get_header(req, "Expires"); 14409 int expire = atoi(expires); 14410 char *curi = NULL, *hostport = NULL, *transport = NULL; 14411 int transport_type; 14412 const char *useragent; 14413 struct ast_sockaddr oldsin, testsa; 14414 char *firstcuri = NULL; 14415 int start = 0; 14416 int wildcard_found = 0; 14417 int single_binding_found = 0; 14418 14419 ast_copy_string(contact, __get_header(req, "Contact", &start), sizeof(contact)); 14420 14421 if (ast_strlen_zero(expires)) { /* No expires header, try look in Contact: */ 14422 char *s = strcasestr(contact, ";expires="); 14423 if (s) { 14424 expires = strsep(&s, ";"); /* trim ; and beyond */ 14425 if (sscanf(expires + 9, "%30d", &expire) != 1) { 14426 expire = default_expiry; 14427 } 14428 } else { 14429 /* Nothing has been specified */ 14430 expire = default_expiry; 14431 } 14432 } 14433 14434 copy_socket_data(&pvt->socket, &req->socket); 14435 14436 do { 14437 /* Look for brackets */ 14438 curi = contact; 14439 if (strchr(contact, '<') == NULL) /* No <, check for ; and strip it */ 14440 strsep(&curi, ";"); /* This is Header options, not URI options */ 14441 curi = get_in_brackets(contact); 14442 if (!firstcuri) { 14443 firstcuri = ast_strdupa(curi); 14444 } 14445 14446 if (!strcasecmp(curi, "*")) { 14447 wildcard_found = 1; 14448 } else { 14449 single_binding_found = 1; 14450 } 14451 14452 if (wildcard_found && (ast_strlen_zero(expires) || expire != 0 || single_binding_found)) { 14453 /* Contact header parameter "*" detected, so punt if: Expires header is missing, 14454 * Expires value is not zero, or another Contact header is present. */ 14455 return PARSE_REGISTER_FAILED; 14456 } 14457 14458 ast_copy_string(contact, __get_header(req, "Contact", &start), sizeof(contact)); 14459 } while (!ast_strlen_zero(contact)); 14460 curi = firstcuri; 14461 14462 /* if they did not specify Contact: or Expires:, they are querying 14463 what we currently have stored as their contact address, so return 14464 it 14465 */ 14466 if (ast_strlen_zero(curi) && ast_strlen_zero(expires)) { 14467 /* If we have an active registration, tell them when the registration is going to expire */ 14468 if (peer->expire > -1 && !ast_strlen_zero(peer->fullcontact)) { 14469 pvt->expiry = ast_sched_when(sched, peer->expire); 14470 } 14471 return PARSE_REGISTER_QUERY; 14472 } else if (!strcasecmp(curi, "*") || !expire) { /* Unregister this peer */ 14473 /* This means remove all registrations and return OK */ 14474 AST_SCHED_DEL_UNREF(sched, peer->expire, 14475 sip_unref_peer(peer, "remove register expire ref")); 14476 ast_verb(3, "Unregistered SIP '%s'\n", peer->name); 14477 expire_register(sip_ref_peer(peer,"add ref for explicit expire_register")); 14478 return PARSE_REGISTER_UPDATE; 14479 } 14480 14481 /* Store whatever we got as a contact from the client */ 14482 ast_string_field_set(peer, fullcontact, curi); 14483 14484 /* For the 200 OK, we should use the received contact */ 14485 ast_string_field_build(pvt, our_contact, "<%s>", curi); 14486 14487 /* Make sure it's a SIP URL */ 14488 if (ast_strlen_zero(curi) || parse_uri_legacy_check(curi, "sip:,sips:", &curi, NULL, &hostport, &transport)) { 14489 ast_log(LOG_NOTICE, "Not a valid SIP contact (missing sip:/sips:) trying to use anyway\n"); 14490 } 14491 14492 /* handle the transport type specified in Contact header. */ 14493 if (!(transport_type = get_transport_str2enum(transport))) { 14494 transport_type = pvt->socket.type; 14495 } 14496 14497 /* if the peer's socket type is different than the Registration 14498 * transport type, change it. If it got this far, it is a 14499 * supported type, but check just in case */ 14500 if ((peer->socket.type != transport_type) && (peer->transports & transport_type)) { 14501 set_socket_transport(&peer->socket, transport_type); 14502 } 14503 14504 oldsin = peer->addr; 14505 14506 /* If we were already linked into the peers_by_ip container unlink ourselves so nobody can find us */ 14507 if (!ast_sockaddr_isnull(&peer->addr) && (!peer->is_realtime || ast_test_flag(&global_flags[1], SIP_PAGE2_RTCACHEFRIENDS))) { 14508 ao2_t_unlink(peers_by_ip, peer, "ao2_unlink of peer from peers_by_ip table"); 14509 } 14510 14511 if (!ast_test_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT) && !ast_test_flag(&peer->flags[0], SIP_NAT_RPORT_PRESENT)) { 14512 /* use the data provided in the Contact header for call routing */ 14513 ast_debug(1, "Store REGISTER's Contact header for call routing.\n"); 14514 /* XXX This could block for a long time XXX */ 14515 /*! \todo Check NAPTR/SRV if we have not got a port in the URI */ 14516 if (ast_sockaddr_resolve_first(&testsa, hostport, 0)) { 14517 ast_log(LOG_WARNING, "Invalid hostport '%s'\n", hostport); 14518 ast_string_field_set(peer, fullcontact, ""); 14519 ast_string_field_set(pvt, our_contact, ""); 14520 return PARSE_REGISTER_FAILED; 14521 } 14522 14523 /* If we have a port number in the given URI, make sure we do remember to not check for NAPTR/SRV records. 14524 The hostport part is actually a host. */ 14525 peer->portinuri = ast_sockaddr_port(&testsa) ? TRUE : FALSE; 14526 14527 if (!ast_sockaddr_port(&testsa)) { 14528 ast_sockaddr_set_port(&testsa, default_sip_port(transport_type)); 14529 } 14530 14531 ast_sockaddr_copy(&peer->addr, &testsa); 14532 } else { 14533 /* Don't trust the contact field. Just use what they came to us 14534 with */ 14535 ast_debug(1, "Store REGISTER's src-IP:port for call routing.\n"); 14536 peer->addr = pvt->recv; 14537 } 14538 14539 /* Check that they're allowed to register at this IP */ 14540 if (ast_apply_ha(sip_cfg.contact_ha, &peer->addr) != AST_SENSE_ALLOW || 14541 ast_apply_ha(peer->contactha, &peer->addr) != AST_SENSE_ALLOW) { 14542 ast_log(LOG_WARNING, "Domain '%s' disallowed by contact ACL (violating IP %s)\n", hostport, 14543 ast_sockaddr_stringify_addr(&testsa)); 14544 ast_string_field_set(peer, fullcontact, ""); 14545 ast_string_field_set(pvt, our_contact, ""); 14546 return PARSE_REGISTER_DENIED; 14547 } 14548 14549 /* if the Contact header information copied into peer->addr matches the 14550 * received address, and the transport types are the same, then copy socket 14551 * data into the peer struct */ 14552 if ((peer->socket.type == pvt->socket.type) && 14553 !ast_sockaddr_cmp(&peer->addr, &pvt->recv)) { 14554 copy_socket_data(&peer->socket, &pvt->socket); 14555 } 14556 14557 /* Now that our address has been updated put ourselves back into the container for lookups */ 14558 if (!peer->is_realtime || ast_test_flag(&peer->flags[1], SIP_PAGE2_RTCACHEFRIENDS)) { 14559 ao2_t_link(peers_by_ip, peer, "ao2_link into peers_by_ip table"); 14560 } 14561 14562 /* Save SIP options profile */ 14563 peer->sipoptions = pvt->sipoptions; 14564 14565 if (!ast_strlen_zero(curi) && ast_strlen_zero(peer->username)) { 14566 ast_string_field_set(peer, username, curi); 14567 } 14568 14569 AST_SCHED_DEL_UNREF(sched, peer->expire, 14570 sip_unref_peer(peer, "remove register expire ref")); 14571 14572 if (expire > max_expiry) { 14573 expire = max_expiry; 14574 } 14575 if (expire < min_expiry) { 14576 expire = min_expiry; 14577 } 14578 if (peer->is_realtime && !ast_test_flag(&peer->flags[1], SIP_PAGE2_RTCACHEFRIENDS)) { 14579 peer->expire = -1; 14580 } else { 14581 peer->expire = ast_sched_add(sched, (expire + 10) * 1000, expire_register, 14582 sip_ref_peer(peer, "add registration ref")); 14583 if (peer->expire == -1) { 14584 sip_unref_peer(peer, "remote registration ref"); 14585 } 14586 } 14587 pvt->expiry = expire; 14588 snprintf(data, sizeof(data), "%s:%d:%s:%s", ast_sockaddr_stringify(&peer->addr), 14589 expire, peer->username, peer->fullcontact); 14590 /* We might not immediately be able to reconnect via TCP, but try caching it anyhow */ 14591 if (!peer->rt_fromcontact || !sip_cfg.peer_rtupdate) 14592 ast_db_put("SIP/Registry", peer->name, data); 14593 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: SIP\r\nPeer: SIP/%s\r\nPeerStatus: Registered\r\nAddress: %s\r\n", peer->name, ast_sockaddr_stringify(&peer->addr)); 14594 14595 /* Is this a new IP address for us? */ 14596 if (ast_sockaddr_cmp(&peer->addr, &oldsin)) { 14597 ast_verb(3, "Registered SIP '%s' at %s\n", peer->name, 14598 ast_sockaddr_stringify(&peer->addr)); 14599 } 14600 sip_poke_peer(peer, 0); 14601 register_peer_exten(peer, 1); 14602 14603 /* Save User agent */ 14604 useragent = sip_get_header(req, "User-Agent"); 14605 if (strcasecmp(useragent, peer->useragent)) { 14606 ast_string_field_set(peer, useragent, useragent); 14607 ast_verb(4, "Saved useragent \"%s\" for peer %s\n", peer->useragent, peer->name); 14608 } 14609 return PARSE_REGISTER_UPDATE; 14610 }
| static int parse_request | ( | struct sip_request * | req | ) | [static] |
Parse a SIP message.
Definition at line 8714 of file chan_sip.c.
References ast_debug, ast_log(), ast_str_strlen(), ast_strlen_zero(), determine_firstline_parts(), and LOG_WARNING.
Referenced by _sip_tcp_helper_thread(), handle_request_do(), initialize_initreq(), and parse_copy().
08715 { 08716 char *c = req->data->str; 08717 ptrdiff_t *dst = req->header; 08718 int i = 0, lim = SIP_MAX_HEADERS - 1; 08719 unsigned int skipping_headers = 0; 08720 ptrdiff_t current_header_offset = 0; 08721 char *previous_header = ""; 08722 08723 req->header[0] = 0; 08724 req->headers = -1; /* mark that we are working on the header */ 08725 for (; *c; c++) { 08726 if (*c == '\r') { /* remove \r */ 08727 *c = '\0'; 08728 } else if (*c == '\n') { /* end of this line */ 08729 *c = '\0'; 08730 current_header_offset = (c + 1) - req->data->str; 08731 previous_header = req->data->str + dst[i]; 08732 if (skipping_headers) { 08733 /* check to see if this line is blank; if so, turn off 08734 the skipping flag, so the next line will be processed 08735 as a body line */ 08736 if (ast_strlen_zero(previous_header)) { 08737 skipping_headers = 0; 08738 } 08739 dst[i] = current_header_offset; /* record start of next line */ 08740 continue; 08741 } 08742 if (sipdebug) { 08743 ast_debug(4, "%7s %2d [%3d]: %s\n", 08744 req->headers < 0 ? "Header" : "Body", 08745 i, (int) strlen(previous_header), previous_header); 08746 } 08747 if (ast_strlen_zero(previous_header) && req->headers < 0) { 08748 req->headers = i; /* record number of header lines */ 08749 dst = req->line; /* start working on the body */ 08750 i = 0; 08751 lim = SIP_MAX_LINES - 1; 08752 } else { /* move to next line, check for overflows */ 08753 if (i++ == lim) { 08754 /* if we're processing headers, then skip any remaining 08755 headers and move on to processing the body, otherwise 08756 we're done */ 08757 if (req->headers != -1) { 08758 break; 08759 } else { 08760 req->headers = i; 08761 dst = req->line; 08762 i = 0; 08763 lim = SIP_MAX_LINES - 1; 08764 skipping_headers = 1; 08765 } 08766 } 08767 } 08768 dst[i] = current_header_offset; /* record start of next line */ 08769 } 08770 } 08771 08772 /* Check for last header or body line without CRLF. The RFC for SDP requires CRLF, 08773 but since some devices send without, we'll be generous in what we accept. However, 08774 if we've already reached the maximum number of lines for portion of the message 08775 we were parsing, we can't accept any more, so just ignore it. 08776 */ 08777 previous_header = req->data->str + dst[i]; 08778 if ((i < lim) && !ast_strlen_zero(previous_header)) { 08779 if (sipdebug) { 08780 ast_debug(4, "%7s %2d [%3d]: %s\n", 08781 req->headers < 0 ? "Header" : "Body", 08782 i, (int) strlen(previous_header), previous_header ); 08783 } 08784 i++; 08785 } 08786 08787 /* update count of header or body lines */ 08788 if (req->headers >= 0) { /* we are in the body */ 08789 req->lines = i; 08790 } else { /* no body */ 08791 req->headers = i; 08792 req->lines = 0; 08793 /* req->data->used will be a NULL byte */ 08794 req->line[0] = ast_str_strlen(req->data); 08795 } 08796 08797 if (*c) { 08798 ast_log(LOG_WARNING, "Too many lines, skipping <%s>\n", c); 08799 } 08800 08801 /* Split up the first line parts */ 08802 return determine_firstline_parts(req); 08803 }
| int parse_session_expires | ( | const char * | p_hdrval, | |
| int *const | p_interval, | |||
| enum st_refresher *const | p_ref | |||
| ) | [static] |
Session-Timers: Function for parsing Session-Expires header.
Definition at line 27083 of file chan_sip.c.
References ast_debug, ast_log(), ast_skip_blanks(), ast_strdupa, ast_strlen_zero(), LOG_WARNING, and strsep().
Referenced by handle_request_invite(), and handle_response_invite().
27084 { 27085 char *p_token; 27086 int ref_idx; 27087 char *p_se_hdr; 27088 27089 if (ast_strlen_zero(p_hdrval)) { 27090 ast_log(LOG_WARNING, "Null Session-Expires header\n"); 27091 return -1; 27092 } 27093 27094 *p_ref = SESSION_TIMER_REFRESHER_AUTO; 27095 *p_interval = 0; 27096 27097 p_se_hdr = ast_strdupa(p_hdrval); 27098 p_se_hdr = ast_skip_blanks(p_se_hdr); 27099 27100 while ((p_token = strsep(&p_se_hdr, ";"))) { 27101 p_token = ast_skip_blanks(p_token); 27102 if (!sscanf(p_token, "%30d", p_interval)) { 27103 ast_log(LOG_WARNING, "Parsing of Session-Expires failed\n"); 27104 return -1; 27105 } 27106 27107 ast_debug(2, "Session-Expires: %d\n", *p_interval); 27108 27109 if (!p_se_hdr) 27110 continue; 27111 27112 p_se_hdr = ast_skip_blanks(p_se_hdr); 27113 ref_idx = strlen("refresher="); 27114 if (!strncasecmp(p_se_hdr, "refresher=", ref_idx)) { 27115 p_se_hdr += ref_idx; 27116 p_se_hdr = ast_skip_blanks(p_se_hdr); 27117 27118 if (!strncasecmp(p_se_hdr, "uac", strlen("uac"))) { 27119 *p_ref = SESSION_TIMER_REFRESHER_UAC; 27120 ast_debug(2, "Refresher: UAC\n"); 27121 } else if (!strncasecmp(p_se_hdr, "uas", strlen("uas"))) { 27122 *p_ref = SESSION_TIMER_REFRESHER_UAS; 27123 ast_debug(2, "Refresher: UAS\n"); 27124 } else { 27125 ast_log(LOG_WARNING, "Invalid refresher value %s\n", p_se_hdr); 27126 return -1; 27127 } 27128 break; 27129 } 27130 } 27131 return 0; 27132 }
| static int parse_uri_legacy_check | ( | char * | uri, | |
| const char * | scheme, | |||
| char ** | user, | |||
| char ** | pass, | |||
| char ** | hostport, | |||
| char ** | transport | |||
| ) | [static] |
parse uri in a way that allows semicolon stripping if legacy mode is enabled
Definition at line 14323 of file chan_sip.c.
References parse_uri(), and sip_cfg.
Referenced by __set_address_from_contact(), check_user_full(), get_also_info(), get_destination(), parse_register_contact(), and register_verify().
14324 { 14325 int ret = parse_uri(uri, scheme, user, pass, hostport, transport); 14326 if (sip_cfg.legacy_useroption_parsing) { /* if legacy mode is active, strip semis from the user field */ 14327 char *p; 14328 if ((p = strchr(uri, (int)';'))) { 14329 *p = '\0'; 14330 } 14331 } 14332 return ret; 14333 }
| static int peer_cmp_cb | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
| static int peer_dump_func | ( | void * | userobj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 17553 of file chan_sip.c.
References ao2_t_ref, ast_cli(), and ast_cli_args::fd.
Referenced by sip_show_objects().
17554 { 17555 struct sip_peer *peer = userobj; 17556 int refc = ao2_t_ref(userobj, 0, ""); 17557 struct ast_cli_args *a = (struct ast_cli_args *) arg; 17558 17559 ast_cli(a->fd, "name: %s\ntype: peer\nobjflags: %d\nrefcount: %d\n\n", 17560 peer->name, 0, refc); 17561 return 0; 17562 }
| static int peer_hash_cb | ( | const void * | obj, | |
| const int | flags | |||
| ) | [static] |
Definition at line 30822 of file chan_sip.c.
References ast_str_case_hash().
30823 { 30824 const struct sip_peer *peer = obj; 30825 30826 return ast_str_case_hash(peer->name); 30827 }