#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 "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"
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 | 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_AUTH_BUF_INITLEN 256 |
| #define | check_request_transport(peer, tmpl) |
| generic function for determining if a correct transport is being used to contact a peer | |
| #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 %-39.39s %-3.3s %-3.3s %-3.3s %-8d %-10s %s\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 %-10s %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 } |
| 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 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 * | authl = NULL |
| Authentication list for realm authentication. | |
| struct ast_sockaddr | bindaddr |
| static struct epa_static_data | cc_epa_static_data |
| static struct ast_threadstorage | check_auth_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_check_auth_buf , .custom_init = NULL , } |
| 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 |
| Here we implement the container for dialogs (sip_pvt), defining generic wrapper functions to ease the transition from the current implementation (a single linked list) to a different container. In addition to a reference to the container, we need functions to lock/unlock the container and individual items, and functions to add/remove references to the individual items. | |
| 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 = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, PTHREAD_MUTEX_INITIALIZER } , 1, PTHREAD_MUTEX_INITIALIZER } |
| 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 = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, PTHREAD_MUTEX_INITIALIZER } , 1, PTHREAD_MUTEX_INITIALIZER } |
| 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 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 ast_mutex_t | sip_reload_lock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, PTHREAD_MUTEX_INITIALIZER } , 1, PTHREAD_MUTEX_INITIALIZER } |
| 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_check_auth_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, int 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, int seqno, int resp, struct ast_str *data, int len, int fatal, int sipmethod) |
| Transmit packet with retransmits. | |
| int | __sip_semi_ack (struct sip_pvt *p, int 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, int len) |
| Transmit SIP message Sends a SIP request or response on a given socket (in the pvt) Called by retrans_pkt, send_request, send_response and __sip_reliable_xmit. | |
| 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, format_t codec, 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_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 struct sip_auth * | add_realm_authentication (struct sip_auth *authlist, const char *configuration, int lineno) |
| Add realm authentication in list. | |
| 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, int codec, 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, const char *text) |
| 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, format_t codec, 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 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 void | auth_headers (enum sip_auth_type code, char **header, char **respheader) |
| return the request and response heade for a 401 or 407 code | |
| static int | auto_congest (const void *arg) |
| Scheduled congestion on a call. Only called by the scheduler, must return the reference when done. | |
| 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 (char *context, char *exten, int state, void *data) |
| Callback for the devicestate notification (SUBSCRIBE) support subsystem. | |
| 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_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 void | 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_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 int | clear_realm_authentication (struct sip_auth *authlist) |
| Clear realm authentication list (at reload). | |
| 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 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 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_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, char *tag, char *file, int line, const char *func) |
| void * | dialog_unlink_all (struct sip_pvt *dialog, int lockowner, int lockdialoglist) |
| 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, char *tag, char *file, int line, const char *func) |
| static void | disable_dsp_detect (struct sip_pvt *p) |
| static int | do_magic_pickup (struct ast_channel *channel, const char *extension, const char *context) |
| 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_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_incoming(), sipsock_read | |
| 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 struct sip_peer * | 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_auth * | find_realm_authentication (struct sip_auth *authlist, const char *realm) |
| Find authentication for a specific 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 | 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_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. 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. | |
| 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 const char * | get_header (const struct sip_request *req, const char *name) |
| Get header from SIP request. | |
| static struct ast_variable * | get_insecure_variable_from_config (struct ast_config *config) |
| 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, int addnewline) |
| Get text out of a SIP MESSAGE packet. | |
| static const char * | get_name_from_variable (struct ast_variable *var, const char *newpeername) |
| 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 (enum sip_transport t) |
| Return transport as string. | |
| 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, int 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, int 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) |
| Handle incoming MESSAGE request. | |
| static int | handle_request_notify (struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, int 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 int seqno, const char *uri) |
| static int | handle_request_refer (struct sip_pvt *p, struct sip_request *req, int debug, int 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, int 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, int seqno) |
| Handle SIP response in dialogue. | |
| static void | handle_response_invite (struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, int seqno) |
| Handle SIP response to INVITE dialogue. | |
| static void | handle_response_notify (struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, int 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, int seqno) |
| static void | handle_response_refer (struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, int seqno) |
| static int | handle_response_register (struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, int 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, int seqno) |
| static void | handle_response_update (struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, int 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 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, int seqno, int *nounlock) |
| Find all call legs and bridge transferee with target called from handle_request_refer. | |
| static int | lws2sws (char *msgbuf, int len) |
| 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 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 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 | 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_iphash_cb (const void *obj, const int flags) |
| static int | peer_is_marked (void *peerobj, void *arg, 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 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 void | process_request_queue (struct sip_pvt *p, int *recount, int *nounlock) |
| 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 | 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 int | queue_request (struct sip_pvt *p, const struct sip_request *req) |
| static struct sip_peer * | realtime_peer (const char *newpeername, struct ast_sockaddr *addr, int devstate_only) |
| 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 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) |
| Receive SIP MESSAGE method messages. | |
| static struct sip_peer * | ref_peer (struct sip_peer *peer, char *tag) |
| 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 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, int 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 | scheduler_process_request_queue (const void *data) |
| 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, int seqno) |
| Send SIP Request to the other part of the dialogue. | |
| static int | send_response (struct sip_pvt *p, struct sip_request *req, enum xmittype reliable, int 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 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 | |
| static int | sip_call (struct ast_channel *ast, 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_ack (struct ast_cc_agent *agent) |
| 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 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 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 (void *data) |
| Part of PBX channel interface. | |
| 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 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 format_t | sip_get_codec (struct ast_channel *chan) |
| static enum ast_rtp_glue_result | sip_get_rtp_peer (struct ast_channel *chan, struct ast_rtp_instance **instance) |
| 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 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 called from sip_request_call (calls from the pbx ) for outbound channels and from handle_request_invite for inbound channels. | |
| 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, int seqno) |
| Park a call using the subsystem in res_features.c This is executed in a separate thread. | |
| 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 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 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) |
| 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, format_t format, const struct ast_channel *requestor, void *data, 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. | |
| 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, const struct ast_event *event, 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) |
| Send SIP MESSAGE text within a call Called from PBX core sendtext() application. | |
| 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, format_t codecs, 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. | |
| 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 enum st_mode | st_get_mode (struct sip_pvt *p) |
| 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_with_text (struct sip_pvt *p, const char *text) |
| Transmit text 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, int 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, int 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_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_marked_peers_from_tables (void) |
| static void | unlink_peer_from_tables (struct sip_peer *peer) |
| static int | unload_module (void) |
| PBX unload module API. | |
| static void * | unref_peer (struct sip_peer *peer, char *tag) |
| 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 | 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_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
| |
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] |
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 2170 of file chan_sip.c.
Referenced by __sip_autodestruct(), __sip_reliable_xmit(), auto_congest(), build_reply_digest(), cb_extensionstate(), check_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(), process_sdp(), 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_AUTH_BUF_INITLEN 256 |
Definition at line 13245 of file chan_sip.c.
Referenced by check_auth(), and transmit_fake_auth_response().
| #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 2253 of file chan_sip.c.
Referenced by create_addr_from_peer(), and register_verify().
| #define DATA_EXPORT_SIP_PEER | ( | MEMBER | ) |
Definition at line 28207 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 17056 of file chan_sip.c.
| #define FORMAT "%-30.30s %-12.12s %-10.10s %-10.10s\n" |
Definition at line 17056 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 17056 of file chan_sip.c.
| #define FORMAT "%-39.39s %-6.6s %-12.12s %8d %-20.20s %-25.25s\n" |
Definition at line 17056 of file chan_sip.c.
| #define FORMAT "%-40.40s %-20.20s %-16.16s\n" |
Definition at line 17056 of file chan_sip.c.
| #define FORMAT "%-25.25s %-39.39s %-3.3s %-3.3s %-3.3s %-8d %-10s %s\n" |
Definition at line 17056 of file chan_sip.c.
| #define FORMAT "%-25.25s %-15.15s %-15.15s %-15.15s %-5.5s%-10.10s\n" |
Definition at line 17056 of file chan_sip.c.
| #define FORMAT "%-47.47s %-9.9s %-6.6s\n" |
Definition at line 17056 of file chan_sip.c.
| #define FORMAT "%-25.25s %-15.15s %-15.15s \n" |
Definition at line 17056 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 17055 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 17055 of file chan_sip.c.
| #define FORMAT2 "%-39.39s %-6.6s %-12.12s %8.8s %-20.20s %-25.25s\n" |
Definition at line 17055 of file chan_sip.c.
| #define FORMAT2 "%-25.25s %-39.39s %-3.3s %-10.10s %-3.3s %-8s %-10s %s\n" |
Definition at line 17055 of file chan_sip.c.
| #define FORMAT2 "%-47.47s %9.9s %6.6s\n" |
Definition at line 17055 of file chan_sip.c.
| #define FORMAT2 "%-25.25s %-15.15s %-15.15s \n" |
Definition at line 17055 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); \ } \
Definition at line 696 of file chan_sip.c.
Referenced by check_user_full(), get_also_info(), get_destination(), get_refer_info(), and register_verify().
| #define sip_pvt_lock | ( | x | ) | ao2_lock(x) |
Definition at line 1077 of file chan_sip.c.
Referenced by __sip_ack(), add_header_max_forwards(), auto_congest(), cb_extensionstate(), check_rtp_timeout(), complete_sipch(), find_call(), get_sip_pvt_byid_locked(), handle_incoming(), handle_invite_replaces(), handle_request_bye(), handle_request_invite(), handle_request_refer(), handle_request_subscribe(), local_attended_transfer(), proc_session_timer(), retrans_pkt(), scheduler_process_request_queue(), sip_answer(), sip_call(), sip_cc_agent_ack(), sip_cc_agent_destructor(), sip_cc_agent_init(), sip_cc_agent_recall(), 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_new(), sip_park(), sip_queryoption(), sip_read(), sip_reg_timeout(), sip_reinvite_retry(), sip_request_call(), sip_senddigit_begin(), sip_senddigit_end(), sip_set_rtp_peer(), sip_set_udptl_peer(), 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) |
| #define sip_pvt_unlock | ( | x | ) | ao2_unlock(x) |
Definition at line 1079 of file chan_sip.c.
Referenced by __sip_ack(), add_header_max_forwards(), auto_congest(), cb_extensionstate(), check_rtp_timeout(), complete_sipch(), dialog_needdestroy(), get_sip_pvt_byid_locked(), handle_incoming(), handle_invite_replaces(), handle_request_bye(), handle_request_do(), handle_request_invite(), handle_request_refer(), handle_request_subscribe(), local_attended_transfer(), proc_session_timer(), retrans_pkt(), scheduler_process_request_queue(), sip_answer(), sip_call(), sip_cc_agent_ack(), sip_cc_agent_destructor(), sip_cc_agent_init(), sip_cc_agent_recall(), 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_new(), sip_park(), sip_queryoption(), sip_read(), sip_reg_timeout(), sip_reinvite_retry(), sip_request_call(), sip_senddigit_begin(), sip_senddigit_end(), sip_set_rtp_peer(), sip_set_udptl_peer(), 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 1176 of file chan_sip.c.
Referenced by __sip_ack(), handle_request_cancel(), and retrans_pkt().
| enum match_req_res |
Definition at line 7193 of file chan_sip.c.
07193 { 07194 SIP_REQ_MATCH, 07195 SIP_REQ_NOT_MATCH, 07196 SIP_REQ_LOOP_DETECTED, 07197 };
| static const char * __get_header | ( | const struct sip_request * | req, | |
| const char * | name, | |||
| int * | start | |||
| ) | [static] |
Definition at line 6778 of file chan_sip.c.
References ast_skip_blanks(), find_alias(), len(), pass, and sip_cfg.
06779 { 06780 int pass; 06781 06782 /* 06783 * Technically you can place arbitrary whitespace both before and after the ':' in 06784 * a header, although RFC3261 clearly says you shouldn't before, and place just 06785 * one afterwards. If you shouldn't do it, what absolute idiot decided it was 06786 * a good idea to say you can do it, and if you can do it, why in the hell would. 06787 * you say you shouldn't. 06788 * Anyways, pedanticsipchecking controls whether we allow spaces before ':', 06789 * and we always allow spaces after that for compatibility. 06790 */ 06791 for (pass = 0; name && pass < 2;pass++) { 06792 int x, len = strlen(name); 06793 for (x = *start; x < req->headers; x++) { 06794 const char *header = REQ_OFFSET_TO_STR(req, header[x]); 06795 if (!strncasecmp(header, name, len)) { 06796 const char *r = header + len; /* skip name */ 06797 if (sip_cfg.pedanticsipchecking) 06798 r = ast_skip_blanks(r); 06799 06800 if (*r == ':') { 06801 *start = x+1; 06802 return ast_skip_blanks(r+1); 06803 } 06804 } 06805 } 06806 if (pass == 0) /* Try aliases */ 06807 name = find_alias(name, NULL); 06808 } 06809 06810 /* Don't return NULL, so get_header is always a valid pointer */ 06811 return ""; 06812 }
| static void __init_check_auth_buf | ( | void | ) | [static] |
| static void __init_ts_temp_pvt | ( | void | ) | [static] |
| static void __reg_module | ( | void | ) | [static] |
Definition at line 28645 of file chan_sip.c.
| static int __set_address_from_contact | ( | const char * | fullcontact, | |
| struct ast_sockaddr * | addr, | |||
| int | tcp | |||
| ) | [static] |
Definition at line 12835 of file chan_sip.c.
References ast_copy_string(), ast_log(), ast_sockaddr_port, ast_sockaddr_resolve_first(), ast_sockaddr_set_port, get_transport_str2enum(), and LOG_WARNING.
Referenced by build_peer(), and set_address_from_contact().
12836 { 12837 char *domain, *transport; 12838 char contact_buf[256]; 12839 char *contact; 12840 12841 /* Work on a copy */ 12842 ast_copy_string(contact_buf, fullcontact, sizeof(contact_buf)); 12843 contact = contact_buf; 12844 12845 /* 12846 * We have only the part in <brackets> here so we just need to parse a SIP URI. 12847 * 12848 * Note: The outbound proxy could be using UDP between the proxy and Asterisk. 12849 * We still need to be able to send to the remote agent through the proxy. 12850 */ 12851 12852 if (parse_uri(contact, "sip:,sips:", &contact, NULL, &domain, 12853 &transport)) { 12854 ast_log(LOG_WARNING, "Invalid contact uri %s (missing sip: or sips:), attempting to use anyway\n", fullcontact); 12855 } 12856 12857 /* XXX This could block for a long time XXX */ 12858 /* We should only do this if it's a name, not an IP */ 12859 /* \todo - if there's no PORT number in contact - we are required to check NAPTR/SRV records 12860 to find transport, port address and hostname. If there's a port number, we have to 12861 assume that the domain part is a host name and only look for an A/AAAA record in DNS. 12862 */ 12863 12864 if (ast_sockaddr_resolve_first(addr, domain, 0)) { 12865 ast_log(LOG_WARNING, "Invalid host name in Contact: (can't " 12866 "resolve in DNS) : '%s'\n", domain); 12867 return -1; 12868 } 12869 12870 /* set port */ 12871 if (!ast_sockaddr_port(addr)) { 12872 ast_sockaddr_set_port(addr, 12873 (get_transport_str2enum(transport) == 12874 SIP_TRANSPORT_TLS || 12875 !strncasecmp(fullcontact, "sips", 4)) ? 12876 STANDARD_TLS_PORT : STANDARD_SIP_PORT); 12877 } 12878 12879 return 0; 12880 }
| int __sip_ack | ( | struct sip_pvt * | p, | |
| int | seqno, | |||
| int | resp, | |||
| int | sipmethod | |||
| ) |
Acknowledges receipt of a packet and stops retransmission called with p locked.
Definition at line 3700 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().
03701 { 03702 struct sip_pkt *cur, *prev = NULL; 03703 const char *msg = "Not Found"; /* used only for debugging */ 03704 int res = FALSE; 03705 03706 /* If we have an outbound proxy for this dialog, then delete it now since 03707 the rest of the requests in this dialog needs to follow the routing. 03708 If obforcing is set, we will keep the outbound proxy during the whole 03709 dialog, regardless of what the SIP rfc says 03710 */ 03711 if (p->outboundproxy && !p->outboundproxy->force){ 03712 ref_proxy(p, NULL); 03713 } 03714 03715 for (cur = p->packets; cur; prev = cur, cur = cur->next) { 03716 if (cur->seqno != seqno || cur->is_resp != resp) { 03717 continue; 03718 } 03719 if (cur->is_resp || cur->method == sipmethod) { 03720 res = TRUE; 03721 msg = "Found"; 03722 if (!resp && (seqno == p->pendinginvite)) { 03723 ast_debug(1, "Acked pending invite %d\n", p->pendinginvite); 03724 p->pendinginvite = 0; 03725 } 03726 if (cur->retransid > -1) { 03727 if (sipdebug) 03728 ast_debug(4, "** SIP TIMER: Cancelling retransmit of packet (reply received) Retransid #%d\n", cur->retransid); 03729 } 03730 /* This odd section is designed to thwart a 03731 * race condition in the packet scheduler. There are 03732 * two conditions under which deleting the packet from the 03733 * scheduler can fail. 03734 * 03735 * 1. The packet has been removed from the scheduler because retransmission 03736 * is being attempted. The problem is that if the packet is currently attempting 03737 * retransmission and we are at this point in the code, then that MUST mean 03738 * that retrans_pkt is waiting on p's lock. Therefore we will relinquish the 03739 * lock temporarily to allow retransmission. 03740 * 03741 * 2. The packet has reached its maximum number of retransmissions and has 03742 * been permanently removed from the packet scheduler. If this is the case, then 03743 * the packet's retransid will be set to -1. The atomicity of the setting and checking 03744 * of the retransid to -1 is ensured since in both cases p's lock is held. 03745 */ 03746 while (cur->retransid > -1 && ast_sched_del(sched, cur->retransid)) { 03747 sip_pvt_unlock(p); 03748 usleep(1); 03749 sip_pvt_lock(p); 03750 } 03751 UNLINK(cur, p->packets, prev); 03752 dialog_unref(cur->owner, "unref pkt cur->owner dialog from sip ack before freeing pkt"); 03753 if (cur->data) { 03754 ast_free(cur->data); 03755 } 03756 ast_free(cur); 03757 break; 03758 } 03759 } 03760 ast_debug(1, "Stopping retransmission on '%s' of %s %d: Match %s\n", 03761 p->callid, resp ? "Response" : "Request", seqno, msg); 03762 return res; 03763 }
| 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 3572 of file chan_sip.c.
References __sip_pretend_ack(), append_history, AST_CAUSE_PROTOCOL_ERROR, 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_scheddestroy(), cfsip_methods::text, transmit_request_with_auth(), transmit_state_notify(), and TRUE.
Referenced by sip_scheddestroy(), and sip_show_sched().
03573 { 03574 struct sip_pvt *p = (struct sip_pvt *)data; 03575 03576 /* If this is a subscription, tell the phone that we got a timeout */ 03577 if (p->subscribed && p->subscribed != MWI_NOTIFICATION && p->subscribed != CALL_COMPLETION) { 03578 transmit_state_notify(p, AST_EXTENSION_DEACTIVATED, 1, TRUE); /* Send last notification */ 03579 p->subscribed = NONE; 03580 append_history(p, "Subscribestatus", "timeout"); 03581 ast_debug(3, "Re-scheduled destruction of SIP subscription %s\n", p->callid ? p->callid : "<unknown>"); 03582 return 10000; /* Reschedule this destruction so that we know that it's gone */ 03583 } 03584 03585 /* If there are packets still waiting for delivery, delay the destruction */ 03586 if (p->packets) { 03587 if (!p->needdestroy) { 03588 char method_str[31]; 03589 ast_debug(3, "Re-scheduled destruction of SIP call %s\n", p->callid ? p->callid : "<unknown>"); 03590 append_history(p, "ReliableXmit", "timeout"); 03591 if (sscanf(p->lastmsg, "Tx: %30s", method_str) == 1 || sscanf(p->lastmsg, "Rx: %30s", method_str) == 1) { 03592 if (method_match(SIP_CANCEL, method_str) || method_match(SIP_BYE, method_str)) { 03593 pvt_set_needdestroy(p, "autodestruct"); 03594 } 03595 } 03596 return 10000; 03597 } else { 03598 /* They've had their chance to respond. Time to bail */ 03599 __sip_pretend_ack(p); 03600 } 03601 } 03602 03603 /* Reset schedule ID */ 03604 p->autokillid = -1; 03605 03606 if (p->owner) { 03607 ast_log(LOG_WARNING, "Autodestruct on dialog '%s' with owner in place (Method: %s)\n", p->callid, sip_methods[p->method].text); 03608 ast_queue_hangup_with_cause(p->owner, AST_CAUSE_PROTOCOL_ERROR); 03609 } else if (p->refer && !p->alreadygone) { 03610 ast_debug(3, "Finally hanging up channel after transfer: %s\n", p->callid); 03611 transmit_request_with_auth(p, SIP_BYE, 0, XMIT_RELIABLE, 1); 03612 append_history(p, "ReferBYE", "Sending BYE on transferer call leg %s", p->callid); 03613 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 03614 } else { 03615 append_history(p, "AutoDestroy", "%s", p->callid); 03616 ast_debug(3, "Auto destroying SIP dialog '%s'\n", p->callid); 03617 dialog_unlink_all(p, TRUE, TRUE); /* once it's unlinked and unrefd everywhere, it'll be freed automagically */ 03618 /* dialog_unref(p, "unref dialog-- no other matching conditions"); -- unlink all now should finish off the dialog's references and free it. */ 03619 /* sip_destroy(p); */ /* Go ahead and destroy dialog. All attempts to recover is done */ 03620 /* sip_destroy also absorbs the reference */ 03621 } 03622 dialog_unref(p, "The ref to a dialog passed to this sched callback is going out of scope; unref it."); 03623 return 0; 03624 }
| void __sip_destroy | ( | struct sip_pvt * | p, | |
| int | lockowner, | |||
| int | lockdialoglist | |||
| ) |
Execute destruction of SIP dialog structure, release memory.
Definition at line 5249 of file chan_sip.c.
References ao2_ref, ast_cc_config_params_destroy(), ast_channel_lock, ast_channel_unlock, ast_debug, ast_free, ast_free_ha(), AST_LIST_REMOVE_HEAD, ast_rtp_instance_destroy(), AST_SCHED_DEL_UNREF, AST_SOFTHANGUP_DEV, ast_string_field_free_memory, ast_test_flag, ast_udptl_destroy(), ast_variables_destroy(), ast_verbose, deinit_req(), free_old_route(), registry_unref(), sip_debug_test_pvt(), sip_dump_history(), sip_methods, cfsip_methods::text, TRUE, unref_peer(), and update_call_counter().
Referenced by sip_destroy().
05250 { 05251 struct sip_request *req; 05252 05253 if (p->stimer) { 05254 ast_free(p->stimer); 05255 p->stimer = NULL; 05256 } 05257 05258 if (sip_debug_test_pvt(p)) 05259 ast_verbose("Really destroying SIP dialog '%s' Method: %s\n", p->callid, sip_methods[p->method].text); 05260 05261 if (ast_test_flag(&p->flags[0], SIP_INC_COUNT) || ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD)) { 05262 update_call_counter(p, DEC_CALL_LIMIT); 05263 ast_debug(2, "This call did not properly clean up call limits. Call ID %s\n", p->callid); 05264 } 05265 05266 /* Unlink us from the owner if we have one */ 05267 if (p->owner) { 05268 if (lockowner) 05269 ast_channel_lock(p->owner); 05270 ast_debug(1, "Detaching from %s\n", p->owner->name); 05271 p->owner->tech_pvt = NULL; 05272 /* Make sure that the channel knows its backend is going away */ 05273 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 05274 if (lockowner) 05275 ast_channel_unlock(p->owner); 05276 /* Give the channel a chance to react before deallocation */ 05277 usleep(1); 05278 } 05279 05280 /* Remove link from peer to subscription of MWI */ 05281 if (p->relatedpeer && p->relatedpeer->mwipvt) 05282 p->relatedpeer->mwipvt = dialog_unref(p->relatedpeer->mwipvt, "delete ->relatedpeer->mwipvt"); 05283 if (p->relatedpeer && p->relatedpeer->call == p) 05284 p->relatedpeer->call = dialog_unref(p->relatedpeer->call, "unset the relatedpeer->call field in tandem with relatedpeer field itself"); 05285 05286 if (p->relatedpeer) 05287 p->relatedpeer = unref_peer(p->relatedpeer,"unsetting a dialog relatedpeer field in sip_destroy"); 05288 05289 if (p->registry) { 05290 if (p->registry->call == p) 05291 p->registry->call = dialog_unref(p->registry->call, "nulling out the registry's call dialog field in unlink_all"); 05292 p->registry = registry_unref(p->registry, "delete p->registry"); 05293 } 05294 05295 if (p->mwi) { 05296 p->mwi->call = NULL; 05297 } 05298 05299 if (dumphistory) 05300 sip_dump_history(p); 05301 05302 if (p->options) 05303 ast_free(p->options); 05304 05305 if (p->notify) { 05306 ast_variables_destroy(p->notify->headers); 05307 ast_free(p->notify->content); 05308 ast_free(p->notify); 05309 } 05310 if (p->rtp) { 05311 ast_rtp_instance_destroy(p->rtp); 05312 } 05313 if (p->vrtp) { 05314 ast_rtp_instance_destroy(p->vrtp); 05315 } 05316 if (p->trtp) { 05317 ast_rtp_instance_destroy(p->trtp); 05318 } 05319 if (p->udptl) 05320 ast_udptl_destroy(p->udptl); 05321 if (p->refer) 05322 ast_free(p->refer); 05323 if (p->route) { 05324 free_old_route(p->route); 05325 p->route = NULL; 05326 } 05327 deinit_req(&p->initreq); 05328 05329 /* Destroy Session-Timers if allocated */ 05330 if (p->stimer) { 05331 p->stimer->quit_flag = 1; 05332 if (p->stimer->st_active == TRUE && p->stimer->st_schedid > -1) { 05333 AST_SCHED_DEL_UNREF(sched, p->stimer->st_schedid, 05334 dialog_unref(p, "removing session timer ref")); 05335 } 05336 ast_free(p->stimer); 05337 p->stimer = NULL; 05338 } 05339 05340 /* Clear history */ 05341 if (p->history) { 05342 struct sip_history *hist; 05343 while ( (hist = AST_LIST_REMOVE_HEAD(p->history, list)) ) { 05344 ast_free(hist); 05345 p->history_entries--; 05346 } 05347 ast_free(p->history); 05348 p->history = NULL; 05349 } 05350 05351 while ((req = AST_LIST_REMOVE_HEAD(&p->request_queue, next))) { 05352 ast_free(req); 05353 } 05354 05355 if (p->chanvars) { 05356 ast_variables_destroy(p->chanvars); 05357 p->chanvars = NULL; 05358 } 05359 05360 if (p->srtp) { 05361 sip_srtp_destroy(p->srtp); 05362 p->srtp = NULL; 05363 } 05364 05365 if (p->vsrtp) { 05366 sip_srtp_destroy(p->vsrtp); 05367 p->vsrtp = NULL; 05368 } 05369 05370 if (p->tsrtp) { 05371 sip_srtp_destroy(p->tsrtp); 05372 p->tsrtp = NULL; 05373 } 05374 05375 if (p->directmediaha) { 05376 ast_free_ha(p->directmediaha); 05377 p->directmediaha = NULL; 05378 } 05379 05380 ast_string_field_free_memory(p); 05381 05382 ast_cc_config_params_destroy(p->cc_params); 05383 05384 if (p->epa_entry) { 05385 ao2_ref(p->epa_entry, -1); 05386 p->epa_entry = NULL; 05387 } 05388 05389 if (p->socket.tcptls_session) { 05390 ao2_ref(p->socket.tcptls_session, -1); 05391 p->socket.tcptls_session = NULL; 05392 } 05393 }
| static int __sip_do_register | ( | struct sip_registry * | r | ) | [static] |
Register with SIP proxy.
Definition at line 12111 of file chan_sip.c.
References transmit_register().
Referenced by sip_reregister().
12112 { 12113 int res; 12114 12115 res = transmit_register(r, SIP_REGISTER, NULL, NULL); 12116 return res; 12117 }
| void __sip_pretend_ack | ( | struct sip_pvt * | p | ) |
Pretend to ack all packets called with p locked.
Definition at line 3767 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().
03768 { 03769 struct sip_pkt *cur = NULL; 03770 03771 while (p->packets) { 03772 int method; 03773 if (cur == p->packets) { 03774 ast_log(LOG_WARNING, "Have a packet that doesn't want to give up! %s\n", sip_methods[cur->method].text); 03775 return; 03776 } 03777 cur = p->packets; 03778 method = (cur->method) ? cur->method : find_sip_method(cur->data->str); 03779 __sip_ack(p, cur->seqno, cur->is_resp, method); 03780 } 03781 }
| static enum sip_result __sip_reliable_xmit | ( | struct sip_pvt * | p, | |
| int | seqno, | |||
| int | resp, | |||
| struct ast_str * | data, | |||
| int | len, | |||
| int | fatal, | |||
| int | sipmethod | |||
| ) | [static] |
Transmit packet with retransmits.
Definition at line 3480 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_tvnow(), DEFAULT_RETRANS, LOG_ERROR, and retrans_pkt().
Referenced by send_request(), and send_response().
03481 { 03482 struct sip_pkt *pkt = NULL; 03483 int siptimer_a = DEFAULT_RETRANS; 03484 int xmitres = 0; 03485 int respid; 03486 03487 if (sipmethod == SIP_INVITE) { 03488 /* Note this is a pending invite */ 03489 p->pendinginvite = seqno; 03490 } 03491 03492 /* If the transport is something reliable (TCP or TLS) then don't really send this reliably */ 03493 /* I removed the code from retrans_pkt that does the same thing so it doesn't get loaded into the scheduler */ 03494 /*! \todo According to the RFC some packets need to be retransmitted even if its TCP, so this needs to get revisited */ 03495 if (!(p->socket.type & SIP_TRANSPORT_UDP)) { 03496 xmitres = __sip_xmit(p, data, len); /* Send packet */ 03497 if (xmitres == XMIT_ERROR) { /* Serious network trouble, no need to try again */ 03498 append_history(p, "XmitErr", "%s", fatal ? "(Critical)" : "(Non-critical)"); 03499 return AST_FAILURE; 03500 } else { 03501 return AST_SUCCESS; 03502 } 03503 } 03504 03505 if (!(pkt = ast_calloc(1, sizeof(*pkt) + len + 1))) { 03506 return AST_FAILURE; 03507 } 03508 /* copy data, add a terminator and save length */ 03509 if (!(pkt->data = ast_str_create(len))) { 03510 ast_free(pkt); 03511 return AST_FAILURE; 03512 } 03513 ast_str_set(&pkt->data, 0, "%s%s", data->str, "\0"); 03514 pkt->packetlen = len; 03515 /* copy other parameters from the caller */ 03516 pkt->method = sipmethod; 03517 pkt->seqno = seqno; 03518 pkt->is_resp = resp; 03519 pkt->is_fatal = fatal; 03520 pkt->owner = dialog_ref(p, "__sip_reliable_xmit: setting pkt->owner"); 03521 pkt->next = p->packets; 03522 p->packets = pkt; /* Add it to the queue */ 03523 if (resp) { 03524 /* Parse out the response code */ 03525 if (sscanf(ast_str_buffer(pkt->data), "SIP/2.0 %30u", &respid) == 1) { 03526 pkt->response_code = respid; 03527 } 03528 } 03529 pkt->timer_t1 = p->timer_t1; /* Set SIP timer T1 */ 03530 pkt->retransid = -1; 03531 if (pkt->timer_t1) { 03532 siptimer_a = pkt->timer_t1; 03533 } 03534 03535 pkt->time_sent = ast_tvnow(); /* time packet was sent */ 03536 pkt->retrans_stop_time = 64 * (pkt->timer_t1 ? pkt->timer_t1 : DEFAULT_TIMER_T1); /* time in ms after pkt->time_sent to stop retransmission */ 03537 03538 /* Schedule retransmission */ 03539 AST_SCHED_REPLACE_VARIABLE(pkt->retransid, sched, siptimer_a, retrans_pkt, pkt, 1); 03540 if (sipdebug) { 03541 ast_debug(4, "*** SIP TIMER: Initializing retransmit timer on packet: Id #%d\n", pkt->retransid); 03542 } 03543 03544 xmitres = __sip_xmit(pkt->owner, pkt->data, pkt->packetlen); /* Send packet */ 03545 03546 if (xmitres == XMIT_ERROR) { /* Serious network trouble, no need to try again */ 03547 append_history(pkt->owner, "XmitErr", "%s", pkt->is_fatal ? "(Critical)" : "(Non-critical)"); 03548 ast_log(LOG_ERROR, "Serious Network Trouble; __sip_xmit returns error for pkt data\n"); 03549 AST_SCHED_DEL(sched, pkt->retransid); 03550 p->packets = pkt->next; 03551 pkt->owner = dialog_unref(pkt->owner,"pkt is being freed, its dialog ref is dead now"); 03552 ast_free(pkt->data); 03553 ast_free(pkt); 03554 return AST_FAILURE; 03555 } else { 03556 /* This is odd, but since the retrans timer starts at 500ms and the do_monitor thread 03557 * only wakes up every 1000ms by default, we have to poke the thread here to make 03558 * sure it successfully detects this must be retransmitted in less time than 03559 * it usually sleeps for. Otherwise it might not retransmit this packet for 1000ms. */ 03560 if (monitor_thread != AST_PTHREADT_NULL) { 03561 pthread_kill(monitor_thread, SIGURG); 03562 } 03563 return AST_SUCCESS; 03564 } 03565 }
| int __sip_semi_ack | ( | struct sip_pvt * | p, | |
| int | seqno, | |||
| int | resp, | |||
| int | sipmethod | |||
| ) |
Acks receipt of packet, keep it around (used for provisional responses).
Definition at line 3784 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().
03785 { 03786 struct sip_pkt *cur; 03787 int res = FALSE; 03788 03789 for (cur = p->packets; cur; cur = cur->next) { 03790 if (cur->seqno == seqno && cur->is_resp == resp && 03791 (cur->is_resp || method_match(sipmethod, cur->data->str))) { 03792 /* this is our baby */ 03793 if (cur->retransid > -1) { 03794 if (sipdebug) 03795 ast_debug(4, "*** SIP TIMER: Cancelling retransmission #%d - %s (got response)\n", cur->retransid, sip_methods[sipmethod].text); 03796 } 03797 AST_SCHED_DEL(sched, cur->retransid); 03798 res = TRUE; 03799 break; 03800 } 03801 } 03802 ast_debug(1, "(Provisional) Stopping retransmission (but retaining packet) on '%s' %s %d: %s\n", p->callid, resp ? "Response" : "Request", seqno, res == -1 ? "Not Found" : "Found"); 03803 return res; 03804 }
| static int __sip_subscribe_mwi_do | ( | struct sip_subscription_mwi * | mwi | ) | [static] |
Actually setup an MWI subscription or resubscribe.
Definition at line 11460 of file chan_sip.c.
References ast_dnsmgr_lookup(), ast_set_flag, ast_sip_ouraddrfor(), ast_sockaddr_port, ast_sockaddr_set_port, ast_string_field_set, ast_strlen_zero(), ASTOBJ_REF, bindaddr, build_callid_pvt(), build_contact(), build_via(), create_addr(), dialog_unlink_all(), get_address_family_filter(), get_srv_protocol(), get_srv_service(), MAXHOSTNAMELEN, obproxy_get(), ref_proxy(), set_socket_transport(), sip_alloc(), sip_cfg, transmit_invite(), and TRUE.
Referenced by sip_subscribe_mwi_do().
11461 { 11462 /* If we have no DNS manager let's do a lookup */ 11463 if (!mwi->dnsmgr) { 11464 char transport[MAXHOSTNAMELEN]; 11465 snprintf(transport, sizeof(transport), "_%s._%s", get_srv_service(mwi->transport), get_srv_protocol(mwi->transport)); 11466 11467 mwi->us.ss.ss_family = get_address_family_filter(&bindaddr); /* Filter address family */ 11468 ast_dnsmgr_lookup(mwi->hostname, &mwi->us, &mwi->dnsmgr, sip_cfg.srvlookup ? transport : NULL); 11469 } 11470 11471 /* If we already have a subscription up simply send a resubscription */ 11472 if (mwi->call) { 11473 transmit_invite(mwi->call, SIP_SUBSCRIBE, 0, 0, NULL); 11474 return 0; 11475 } 11476 11477 /* Create a dialog that we will use for the subscription */ 11478 if (!(mwi->call = sip_alloc(NULL, NULL, 0, SIP_SUBSCRIBE, NULL))) { 11479 return -1; 11480 } 11481 11482 ref_proxy(mwi->call, obproxy_get(mwi->call, NULL)); 11483 11484 if (!ast_sockaddr_port(&mwi->us) && mwi->portno) { 11485 ast_sockaddr_set_port(&mwi->us, mwi->portno); 11486 } 11487 11488 /* Setup the destination of our subscription */ 11489 if (create_addr(mwi->call, mwi->hostname, &mwi->us, 0, NULL)) { 11490 dialog_unlink_all(mwi->call, TRUE, TRUE); 11491 mwi->call = dialog_unref(mwi->call, "unref dialog after unlink_all"); 11492 return 0; 11493 } 11494 11495 mwi->call->expiry = mwi_expiry; 11496 11497 if (!mwi->dnsmgr && mwi->portno) { 11498 ast_sockaddr_set_port(&mwi->call->sa, mwi->portno); 11499 ast_sockaddr_set_port(&mwi->call->recv, mwi->portno); 11500 } else { 11501 mwi->portno = ast_sockaddr_port(&mwi->call->sa); 11502 } 11503 11504 /* Set various other information */ 11505 if (!ast_strlen_zero(mwi->authuser)) { 11506 ast_string_field_set(mwi->call, peername, mwi->authuser); 11507 ast_string_field_set(mwi->call, authname, mwi->authuser); 11508 ast_string_field_set(mwi->call, fromuser, mwi->authuser); 11509 } else { 11510 ast_string_field_set(mwi->call, peername, mwi->username); 11511 ast_string_field_set(mwi->call, authname, mwi->username); 11512 ast_string_field_set(mwi->call, fromuser, mwi->username); 11513 } 11514 ast_string_field_set(mwi->call, username, mwi->username); 11515 if (!ast_strlen_zero(mwi->secret)) { 11516 ast_string_field_set(mwi->call, peersecret, mwi->secret); 11517 } 11518 set_socket_transport(&mwi->call->socket, mwi->transport); 11519 mwi->call->socket.port = htons(mwi->portno); 11520 ast_sip_ouraddrfor(&mwi->call->sa, &mwi->call->ourip, mwi->call); 11521 build_contact(mwi->call); 11522 build_via(mwi->call); 11523 build_callid_pvt(mwi->call); 11524 ast_set_flag(&mwi->call->flags[0], SIP_OUTGOING); 11525 11526 /* Associate the call with us */ 11527 mwi->call->mwi = ASTOBJ_REF(mwi); 11528 11529 /* Actually send the packet */ 11530 transmit_invite(mwi->call, SIP_SUBSCRIBE, 0, 2, NULL); 11531 11532 return 0; 11533 }
| static int __sip_xmit | ( | struct sip_pvt * | p, | |
| struct ast_str * | data, | |||
| int | len | |||
| ) | [static] |
Transmit SIP message Sends a SIP request or response on a given socket (in the pvt) Called by retrans_pkt, send_request, send_response and __sip_reliable_xmit.
Definition at line 3081 of file chan_sip.c.
References ast_debug, ast_log(), ast_sendto(), ast_sockaddr_stringify(), 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().
03082 { 03083 int res = 0; 03084 const struct ast_sockaddr *dst = sip_real_dst(p); 03085 03086 ast_debug(2, "Trying to put '%.11s' onto %s socket destined for %s\n", data->str, get_transport_pvt(p), ast_sockaddr_stringify(dst)); 03087 03088 if (sip_prepare_socket(p) < 0) { 03089 return XMIT_ERROR; 03090 } 03091 03092 if (p->socket.type == SIP_TRANSPORT_UDP) { 03093 res = ast_sendto(p->socket.fd, data->str, len, 0, dst); 03094 } else if (p->socket.tcptls_session) { 03095 res = sip_tcptls_write(p->socket.tcptls_session, data->str, len); 03096 } else { 03097 ast_debug(2, "Socket type is TCP but no tcptls_session is present to write to\n"); 03098 return XMIT_ERROR; 03099 } 03100 03101 if (res == -1) { 03102 switch (errno) { 03103 case EBADF: /* Bad file descriptor - seems like this is generated when the host exist, but doesn't accept the UDP packet */ 03104 case EHOSTUNREACH: /* Host can't be reached */ 03105 case ENETDOWN: /* Interface down */ 03106 case ENETUNREACH: /* Network failure */ 03107 case ECONNREFUSED: /* ICMP port unreachable */ 03108 res = XMIT_ERROR; /* Don't bother with trying to transmit again */ 03109 } 03110 } 03111 if (res != len) { 03112 ast_log(LOG_WARNING, "sip_xmit of %p (len %d) to %s returned %d: %s\n", data, len, ast_sockaddr_stringify(dst), res, strerror(errno)); 03113 } 03114 03115 return res; 03116 }
| 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 9642 of file chan_sip.c.
References add_cc_call_info_to_response(), add_header(), add_rpid(), ast_cause2str(), ast_clear_flag, ast_log(), ast_test_flag, get_header(), hangup_sip2cause(), LOG_WARNING, respprep(), and send_response().
Referenced by transmit_response(), transmit_response_reliable(), and transmit_response_using_temp().
09643 { 09644 struct sip_request resp; 09645 int seqno = 0; 09646 09647 if (reliable && (sscanf(get_header(req, "CSeq"), "%30d ", &seqno) != 1)) { 09648 ast_log(LOG_WARNING, "Unable to determine sequence number from '%s'\n", get_header(req, "CSeq")); 09649 return -1; 09650 } 09651 respprep(&resp, p, msg, req); 09652 09653 if (ast_test_flag(&p->flags[0], SIP_SENDRPID) 09654 && ast_test_flag(&p->flags[1], SIP_PAGE2_CONNECTLINEUPDATE_PEND) 09655 && (!strncmp(msg, "180", 3) || !strncmp(msg, "183", 3))) { 09656 ast_clear_flag(&p->flags[1], SIP_PAGE2_CONNECTLINEUPDATE_PEND); 09657 add_rpid(&resp, p); 09658 } 09659 if (ast_test_flag(&p->flags[0], SIP_OFFER_CC)) { 09660 add_cc_call_info_to_response(p, &resp); 09661 } 09662 09663 /* If we are cancelling an incoming invite for some reason, add information 09664 about the reason why we are doing this in clear text */ 09665 if (p->method == SIP_INVITE && msg[0] != '1') { 09666 char buf[20]; 09667 09668 if (ast_test_flag(&p->flags[1], SIP_PAGE2_Q850_REASON)) { 09669 int hangupcause = 0; 09670 09671 if (p->owner && p->owner->hangupcause) { 09672 hangupcause = p->owner->hangupcause; 09673 } else if (p->hangupcause) { 09674 hangupcause = p->hangupcause; 09675 } else { 09676 int respcode; 09677 if (sscanf(msg, "%30d ", &respcode)) 09678 hangupcause = hangup_sip2cause(respcode); 09679 } 09680 09681 if (hangupcause) { 09682 sprintf(buf, "Q.850;cause=%i", hangupcause & 0x7f); 09683 add_header(&resp, "Reason", buf); 09684 } 09685 } 09686 09687 if (p->owner && p->owner->hangupcause) { 09688 add_header(&resp, "X-Asterisk-HangupCause", ast_cause2str(p->owner->hangupcause)); 09689 snprintf(buf, sizeof(buf), "%d", p->owner->hangupcause); 09690 add_header(&resp, "X-Asterisk-HangupCauseCode", buf); 09691 } 09692 } 09693 return send_response(p, &resp, reliable, seqno); 09694 }
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 28645 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 16112 of file chan_sip.c.
References ast_cli(), astman_send_error(), CLI_SHOWUSAGE, CLI_SUCCESS, FALSE, find_peer(), sip_poke_peer(), TRUE, and unref_peer().
Referenced by manager_sip_qualify_peer(), and sip_qualify_peer().
16113 { 16114 struct sip_peer *peer; 16115 int load_realtime; 16116 16117 if (argc < 4) 16118 return CLI_SHOWUSAGE; 16119 16120 load_realtime = (argc == 5 && !strcmp(argv[4], "load")) ? TRUE : FALSE; 16121 if ((peer = find_peer(argv[3], NULL, load_realtime, FINDPEERS, FALSE, 0))) { 16122 sip_poke_peer(peer, 1); 16123 unref_peer(peer, "qualify: done with peer"); 16124 } else if (type == 0) { 16125 ast_cli(fd, "Peer '%s' not found\n", argv[3]); 16126 } else { 16127 astman_send_error(s, m, "Peer not found"); 16128 } 16129 return CLI_SUCCESS; 16130 }
| 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 16197 of file chan_sip.c.
References ARRAY_LEN, ast_callerid_merge(), ast_cdr_flags2str(), ast_check_realtime(), ast_cli(), AST_CLI_YESNO, ast_codec_pref_index(), ast_describe_caller_presentation(), ast_getformatname(), ast_getformatname_multiple(), 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, dtmfmode2str(), FALSE, faxec2str(), find_peer(), get_transport(), 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, status, stmode2str(), strefresher2str(), text, transfermode2str(), TRUE, unref_peer(), and ast_variable::value.
Referenced by manager_sip_show_peer(), and sip_show_peer().
16198 { 16199 char status[30] = ""; 16200 char cbuf[256]; 16201 struct sip_peer *peer; 16202 char codec_buf[512]; 16203 struct ast_codec_pref *pref; 16204 struct ast_variable *v; 16205 struct sip_auth *auth; 16206 int x = 0, load_realtime; 16207 format_t codec = 0; 16208 int realtimepeers; 16209 16210 realtimepeers = ast_check_realtime("sippeers"); 16211 16212 if (argc < 4) 16213 return CLI_SHOWUSAGE; 16214 16215 load_realtime = (argc == 5 && !strcmp(argv[4], "load")) ? TRUE : FALSE; 16216 peer = find_peer(argv[3], NULL, load_realtime, FINDPEERS, FALSE, 0); 16217 16218 if (s) { /* Manager */ 16219 if (peer) { 16220 const char *id = astman_get_header(m, "ActionID"); 16221 16222 astman_append(s, "Response: Success\r\n"); 16223 if (!ast_strlen_zero(id)) 16224 astman_append(s, "ActionID: %s\r\n", id); 16225 } else { 16226 snprintf (cbuf, sizeof(cbuf), "Peer %s not found.", argv[3]); 16227 astman_send_error(s, m, cbuf); 16228 return CLI_SUCCESS; 16229 } 16230 } 16231 if (peer && type==0 ) { /* Normal listing */ 16232 struct ast_str *mailbox_str = ast_str_alloca(512); 16233 ast_cli(fd, "\n\n"); 16234 ast_cli(fd, " * Name : %s\n", peer->name); 16235 if (realtimepeers) { /* Realtime is enabled */ 16236 ast_cli(fd, " Realtime peer: %s\n", peer->is_realtime ? "Yes, cached" : "No"); 16237 } 16238 ast_cli(fd, " Secret : %s\n", ast_strlen_zero(peer->secret)?"<Not set>":"<Set>"); 16239 ast_cli(fd, " MD5Secret : %s\n", ast_strlen_zero(peer->md5secret)?"<Not set>":"<Set>"); 16240 ast_cli(fd, " Remote Secret: %s\n", ast_strlen_zero(peer->remotesecret)?"<Not set>":"<Set>"); 16241 for (auth = peer->auth; auth; auth = auth->next) { 16242 ast_cli(fd, " Realm-auth : Realm %-15.15s User %-10.20s ", auth->realm, auth->username); 16243 ast_cli(fd, "%s\n", !ast_strlen_zero(auth->secret)?"<Secret set>":(!ast_strlen_zero(auth->md5secret)?"<MD5secret set>" : "<Not set>")); 16244 } 16245 ast_cli(fd, " Context : %s\n", peer->context); 16246 ast_cli(fd, " Subscr.Cont. : %s\n", S_OR(peer->subscribecontext, "<Not set>") ); 16247 ast_cli(fd, " Language : %s\n", peer->language); 16248 if (!ast_strlen_zero(peer->accountcode)) 16249 ast_cli(fd, " Accountcode : %s\n", peer->accountcode); 16250 ast_cli(fd, " AMA flags : %s\n", ast_cdr_flags2str(peer->amaflags)); 16251 ast_cli(fd, " Transfer mode: %s\n", transfermode2str(peer->allowtransfer)); 16252 ast_cli(fd, " CallingPres : %s\n", ast_describe_caller_presentation(peer->callingpres)); 16253 if (!ast_strlen_zero(peer->fromuser)) 16254 ast_cli(fd, " FromUser : %s\n", peer->fromuser); 16255 if (!ast_strlen_zero(peer->fromdomain)) 16256 ast_cli(fd, " FromDomain : %s Port %d\n", peer->fromdomain, (peer->fromdomainport) ? peer->fromdomainport : STANDARD_SIP_PORT); 16257 ast_cli(fd, " Callgroup : "); 16258 print_group(fd, peer->callgroup, 0); 16259 ast_cli(fd, " Pickupgroup : "); 16260 print_group(fd, peer->pickupgroup, 0); 16261 peer_mailboxes_to_str(&mailbox_str, peer); 16262 ast_cli(fd, " MOH Suggest : %s\n", peer->mohsuggest); 16263 ast_cli(fd, " Mailbox : %s\n", mailbox_str->str); 16264 ast_cli(fd, " VM Extension : %s\n", peer->vmexten); 16265 ast_cli(fd, " LastMsgsSent : %d/%d\n", (peer->lastmsgssent & 0x7fff0000) >> 16, peer->lastmsgssent & 0xffff); 16266 ast_cli(fd, " Call limit : %d\n", peer->call_limit); 16267 ast_cli(fd, " Max forwards : %d\n", peer->maxforwards); 16268 if (peer->busy_level) 16269 ast_cli(fd, " Busy level : %d\n", peer->busy_level); 16270 ast_cli(fd, " Dynamic : %s\n", AST_CLI_YESNO(peer->host_dynamic)); 16271 ast_cli(fd, " Callerid : %s\n", ast_callerid_merge(cbuf, sizeof(cbuf), peer->cid_name, peer->cid_num, "<unspecified>")); 16272 ast_cli(fd, " MaxCallBR : %d kbps\n", peer->maxcallbitrate); 16273 ast_cli(fd, " Expire : %ld\n", ast_sched_when(sched, peer->expire)); 16274 ast_cli(fd, " Insecure : %s\n", insecure2str(ast_test_flag(&peer->flags[0], SIP_INSECURE))); 16275 ast_cli(fd, " Force rport : %s\n", AST_CLI_YESNO(ast_test_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT))); 16276 ast_cli(fd, " ACL : %s\n", AST_CLI_YESNO(peer->ha != NULL)); 16277 ast_cli(fd, " DirectMedACL : %s\n", AST_CLI_YESNO(peer->directmediaha != NULL)); 16278 ast_cli(fd, " T.38 support : %s\n", AST_CLI_YESNO(ast_test_flag(&peer->flags[1], SIP_PAGE2_T38SUPPORT))); 16279 ast_cli(fd, " T.38 EC mode : %s\n", faxec2str(ast_test_flag(&peer->flags[1], SIP_PAGE2_T38SUPPORT))); 16280 ast_cli(fd, " T.38 MaxDtgrm: %d\n", peer->t38_maxdatagram); 16281 ast_cli(fd, " DirectMedia : %s\n", AST_CLI_YESNO(ast_test_flag(&peer->flags[0], SIP_DIRECT_MEDIA))); 16282 ast_cli(fd, " PromiscRedir : %s\n", AST_CLI_YESNO(ast_test_flag(&peer->flags[0], SIP_PROMISCREDIR))); 16283 ast_cli(fd, " User=Phone : %s\n", AST_CLI_YESNO(ast_test_flag(&peer->flags[0], SIP_USEREQPHONE))); 16284 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))); 16285 ast_cli(fd, " Text Support : %s\n", AST_CLI_YESNO(ast_test_flag(&peer->flags[1], SIP_PAGE2_TEXTSUPPORT))); 16286 ast_cli(fd, " Ign SDP ver : %s\n", AST_CLI_YESNO(ast_test_flag(&peer->flags[1], SIP_PAGE2_IGNORESDPVERSION))); 16287 ast_cli(fd, " Trust RPID : %s\n", AST_CLI_YESNO(ast_test_flag(&peer->flags[0], SIP_TRUSTRPID))); 16288 ast_cli(fd, " Send RPID : %s\n", AST_CLI_YESNO(ast_test_flag(&peer->flags[0], SIP_SENDRPID))); 16289 ast_cli(fd, " Subscriptions: %s\n", AST_CLI_YESNO(ast_test_flag(&peer->flags[1], SIP_PAGE2_ALLOWSUBSCRIBE))); 16290 ast_cli(fd, " Overlap dial : %s\n", AST_CLI_YESNO(ast_test_flag(&peer->flags[1], SIP_PAGE2_ALLOWOVERLAP))); 16291 if (peer->outboundproxy) 16292 ast_cli(fd, " Outb. proxy : %s %s\n", ast_strlen_zero(peer->outboundproxy->name) ? "<not set>" : peer->outboundproxy->name, 16293 peer->outboundproxy->force ? "(forced)" : ""); 16294 16295 /* - is enumerated */ 16296 ast_cli(fd, " DTMFmode : %s\n", dtmfmode2str(ast_test_flag(&peer->flags[0], SIP_DTMF))); 16297 ast_cli(fd, " Timer T1 : %d\n", peer->timer_t1); 16298 ast_cli(fd, " Timer B : %d\n", peer->timer_b); 16299 ast_cli(fd, " ToHost : %s\n", peer->tohost); 16300 ast_cli(fd, " Addr->IP : %s\n", ast_sockaddr_stringify(&peer->addr)); 16301 ast_cli(fd, " Defaddr->IP : %s\n", ast_sockaddr_stringify(&peer->defaddr)); 16302 ast_cli(fd, " Prim.Transp. : %s\n", get_transport(peer->socket.type)); 16303 ast_cli(fd, " Allowed.Trsp : %s\n", get_transport_list(peer->transports)); 16304 if (!ast_strlen_zero(sip_cfg.regcontext)) 16305 ast_cli(fd, " Reg. exten : %s\n", peer->regexten); 16306 ast_cli(fd, " Def. Username: %s\n", peer->username); 16307 ast_cli(fd, " SIP Options : "); 16308 if (peer->sipoptions) { 16309 int lastoption = -1; 16310 for (x = 0 ; x < ARRAY_LEN(sip_options); x++) { 16311 if (sip_options[x].id != lastoption) { 16312 if (peer->sipoptions & sip_options[x].id) 16313 ast_cli(fd, "%s ", sip_options[x].text); 16314 lastoption = x; 16315 } 16316 } 16317 } else 16318 ast_cli(fd, "(none)"); 16319 16320 ast_cli(fd, "\n"); 16321 ast_cli(fd, " Codecs : "); 16322 ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, peer->capability); 16323 ast_cli(fd, "%s\n", codec_buf); 16324 ast_cli(fd, " Codec Order : ("); 16325 print_codec_to_cli(fd, &peer->prefs); 16326 ast_cli(fd, ")\n"); 16327 16328 ast_cli(fd, " Auto-Framing : %s \n", AST_CLI_YESNO(peer->autoframing)); 16329 ast_cli(fd, " 100 on REG : %s\n", AST_CLI_YESNO(ast_test_flag(&peer->flags[1], SIP_PAGE2_REGISTERTRYING))); 16330 ast_cli(fd, " Status : "); 16331 peer_status(peer, status, sizeof(status)); 16332 ast_cli(fd, "%s\n", status); 16333 ast_cli(fd, " Useragent : %s\n", peer->useragent); 16334 ast_cli(fd, " Reg. Contact : %s\n", peer->fullcontact); 16335 ast_cli(fd, " Qualify Freq : %d ms\n", peer->qualifyfreq); 16336 if (peer->chanvars) { 16337 ast_cli(fd, " Variables :\n"); 16338 for (v = peer->chanvars ; v ; v = v->next) 16339 ast_cli(fd, " %s = %s\n", v->name, v->value); 16340 } 16341 16342 ast_cli(fd, " Sess-Timers : %s\n", stmode2str(peer->stimer.st_mode_oper)); 16343 ast_cli(fd, " Sess-Refresh : %s\n", strefresher2str(peer->stimer.st_ref)); 16344 ast_cli(fd, " Sess-Expires : %d secs\n", peer->stimer.st_max_se); 16345 ast_cli(fd, " Min-Sess : %d secs\n", peer->stimer.st_min_se); 16346 ast_cli(fd, " RTP Engine : %s\n", peer->engine); 16347 ast_cli(fd, " Parkinglot : %s\n", peer->parkinglot); 16348 ast_cli(fd, " Use Reason : %s\n", AST_CLI_YESNO(ast_test_flag(&peer->flags[1], SIP_PAGE2_Q850_REASON))); 16349 ast_cli(fd, "\n"); 16350 peer = unref_peer(peer, "sip_show_peer: unref_peer: done with peer ptr"); 16351 } else if (peer && type == 1) { /* manager listing */ 16352 char buffer[256]; 16353 struct ast_str *mailbox_str = ast_str_alloca(512); 16354 astman_append(s, "Channeltype: SIP\r\n"); 16355 astman_append(s, "ObjectName: %s\r\n", peer->name); 16356 astman_append(s, "ChanObjectType: peer\r\n"); 16357 astman_append(s, "SecretExist: %s\r\n", ast_strlen_zero(peer->secret)?"N":"Y"); 16358 astman_append(s, "RemoteSecretExist: %s\r\n", ast_strlen_zero(peer->remotesecret)?"N":"Y"); 16359 astman_append(s, "MD5SecretExist: %s\r\n", ast_strlen_zero(peer->md5secret)?"N":"Y"); 16360 astman_append(s, "Context: %s\r\n", peer->context); 16361 astman_append(s, "Language: %s\r\n", peer->language); 16362 if (!ast_strlen_zero(peer->accountcode)) 16363 astman_append(s, "Accountcode: %s\r\n", peer->accountcode); 16364 astman_append(s, "AMAflags: %s\r\n", ast_cdr_flags2str(peer->amaflags)); 16365 astman_append(s, "CID-CallingPres: %s\r\n", ast_describe_caller_presentation(peer->callingpres)); 16366 if (!ast_strlen_zero(peer->fromuser)) 16367 astman_append(s, "SIP-FromUser: %s\r\n", peer->fromuser); 16368 if (!ast_strlen_zero(peer->fromdomain)) 16369 astman_append(s, "SIP-FromDomain: %s\r\nSip-FromDomain-Port: %d\r\n", peer->fromdomain, (peer->fromdomainport) ? peer->fromdomainport : STANDARD_SIP_PORT); 16370 astman_append(s, "Callgroup: "); 16371 astman_append(s, "%s\r\n", ast_print_group(buffer, sizeof(buffer), peer->callgroup)); 16372 astman_append(s, "Pickupgroup: "); 16373 astman_append(s, "%s\r\n", ast_print_group(buffer, sizeof(buffer), peer->pickupgroup)); 16374 astman_append(s, "MOHSuggest: %s\r\n", peer->mohsuggest); 16375 peer_mailboxes_to_str(&mailbox_str, peer); 16376 astman_append(s, "VoiceMailbox: %s\r\n", mailbox_str->str); 16377 astman_append(s, "TransferMode: %s\r\n", transfermode2str(peer->allowtransfer)); 16378 astman_append(s, "Maxforwards: %d\r\n", peer->maxforwards); 16379 astman_append(s, "LastMsgsSent: %d\r\n", peer->lastmsgssent); 16380 astman_append(s, "Maxforwards: %d\r\n", peer->maxforwards); 16381 astman_append(s, "Call-limit: %d\r\n", peer->call_limit); 16382 astman_append(s, "Busy-level: %d\r\n", peer->busy_level); 16383 astman_append(s, "MaxCallBR: %d kbps\r\n", peer->maxcallbitrate); 16384 astman_append(s, "Dynamic: %s\r\n", peer->host_dynamic?"Y":"N"); 16385 astman_append(s, "Callerid: %s\r\n", ast_callerid_merge(cbuf, sizeof(cbuf), peer->cid_name, peer->cid_num, "")); 16386 astman_append(s, "RegExpire: %ld seconds\r\n", ast_sched_when(sched, peer->expire)); 16387 astman_append(s, "SIP-AuthInsecure: %s\r\n", insecure2str(ast_test_flag(&peer->flags[0], SIP_INSECURE))); 16388 astman_append(s, "SIP-Forcerport: %s\r\n", (ast_test_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT)?"Y":"N")); 16389 astman_append(s, "ACL: %s\r\n", (peer->ha?"Y":"N")); 16390 astman_append(s, "SIP-CanReinvite: %s\r\n", (ast_test_flag(&peer->flags[0], SIP_DIRECT_MEDIA)?"Y":"N")); 16391 astman_append(s, "SIP-DirectMedia: %s\r\n", (ast_test_flag(&peer->flags[0], SIP_DIRECT_MEDIA)?"Y":"N")); 16392 astman_append(s, "SIP-PromiscRedir: %s\r\n", (ast_test_flag(&peer->flags[0], SIP_PROMISCREDIR)?"Y":"N")); 16393 astman_append(s, "SIP-UserPhone: %s\r\n", (ast_test_flag(&peer->flags[0], SIP_USEREQPHONE)?"Y":"N")); 16394 astman_append(s, "SIP-VideoSupport: %s\r\n", (ast_test_flag(&peer->flags[1], SIP_PAGE2_VIDEOSUPPORT)?"Y":"N")); 16395 astman_append(s, "SIP-TextSupport: %s\r\n", (ast_test_flag(&peer->flags[1], SIP_PAGE2_TEXTSUPPORT)?"Y":"N")); 16396 astman_append(s, "SIP-T.38Support: %s\r\n", (ast_test_flag(&peer->flags[1], SIP_PAGE2_T38SUPPORT)?"Y":"N")); 16397 astman_append(s, "SIP-T.38EC: %s\r\n", faxec2str(ast_test_flag(&peer->flags[1], SIP_PAGE2_T38SUPPORT))); 16398 astman_append(s, "SIP-T.38MaxDtgrm: %d\r\n", peer->t38_maxdatagram); 16399 astman_append(s, "SIP-Sess-Timers: %s\r\n", stmode2str(peer->stimer.st_mode_oper)); 16400 astman_append(s, "SIP-Sess-Refresh: %s\r\n", strefresher2str(peer->stimer.st_ref)); 16401 astman_append(s, "SIP-Sess-Expires: %d\r\n", peer->stimer.st_max_se); 16402 astman_append(s, "SIP-Sess-Min: %d\r\n", peer->stimer.st_min_se); 16403 astman_append(s, "SIP-RTP-Engine: %s\r\n", peer->engine); 16404 16405 /* - is enumerated */ 16406 astman_append(s, "SIP-DTMFmode: %s\r\n", dtmfmode2str(ast_test_flag(&peer->flags[0], SIP_DTMF))); 16407 astman_append(s, "ToHost: %s\r\n", peer->tohost); 16408 astman_append(s, "Address-IP: %s\r\nAddress-Port: %d\r\n", ast_sockaddr_stringify_addr(&peer->addr), ast_sockaddr_port(&peer->addr)); 16409 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)); 16410 astman_append(s, "Default-Username: %s\r\n", peer->username); 16411 if (!ast_strlen_zero(sip_cfg.regcontext)) 16412 astman_append(s, "RegExtension: %s\r\n", peer->regexten); 16413 astman_append(s, "Codecs: "); 16414 ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, peer->capability); 16415 astman_append(s, "%s\r\n", codec_buf); 16416 astman_append(s, "CodecOrder: "); 16417 pref = &peer->prefs; 16418 for(x = 0; x < 64 ; x++) { 16419 codec = ast_codec_pref_index(pref, x); 16420 if (!codec) 16421 break; 16422 astman_append(s, "%s", ast_getformatname(codec)); 16423 if (x < 63 && ast_codec_pref_index(pref, x+1)) 16424 astman_append(s, ","); 16425 } 16426 16427 astman_append(s, "\r\n"); 16428 astman_append(s, "Status: "); 16429 peer_status(peer, status, sizeof(status)); 16430 astman_append(s, "%s\r\n", status); 16431 astman_append(s, "SIP-Useragent: %s\r\n", peer->useragent); 16432 astman_append(s, "Reg-Contact: %s\r\n", peer->fullcontact); 16433 astman_append(s, "QualifyFreq: %d ms\r\n", peer->qualifyfreq); 16434 astman_append(s, "Parkinglot: %s\r\n", peer->parkinglot); 16435 if (peer->chanvars) { 16436 for (v = peer->chanvars ; v ; v = v->next) { 16437 astman_append(s, "ChanVariable: %s=%s\r\n", v->name, v->value); 16438 } 16439 } 16440 astman_append(s, "SIP-Use-Reason-Header : %s\n", (ast_test_flag(&peer->flags[1], SIP_PAGE2_Q850_REASON)) ? "Y" : "N"); 16441 16442 peer = unref_peer(peer, "sip_show_peer: unref_peer: done with peer"); 16443 16444 } else { 16445 ast_cli(fd, "Peer %s not found.\n", argv[3]); 16446 ast_cli(fd, "\n"); 16447 } 16448 16449 return CLI_SUCCESS; 16450 }
| 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 15515 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(), ast_sockaddr_stringify_addr(), ast_strlen_zero(), ast_test_flag, astman_append(), astman_get_header(), CLI_SHOWUSAGE, CLI_SUCCESS, FALSE, FORMAT, FORMAT2, id, name, peer_status(), peercomparefunc(), status, TRUE, and unref_peer().
Referenced by manager_sip_show_peers(), and sip_show_peers().
15516 { 15517 regex_t regexbuf; 15518 int havepattern = FALSE; 15519 struct sip_peer *peer; 15520 struct ao2_iterator i; 15521 15522 /* the last argument is left-aligned, so we don't need a size anyways */ 15523 #define FORMAT2 "%-25.25s %-39.39s %-3.3s %-10.10s %-3.3s %-8s %-10s %s\n" 15524 #define FORMAT "%-25.25s %-39.39s %-3.3s %-3.3s %-3.3s %-8d %-10s %s\n" 15525 15526 char name[256]; 15527 int total_peers = 0; 15528 int peers_mon_online = 0; 15529 int peers_mon_offline = 0; 15530 int peers_unmon_offline = 0; 15531 int peers_unmon_online = 0; 15532 const char *id; 15533 char idtext[256] = ""; 15534 int realtimepeers; 15535 int objcount = ao2_container_count(peers); 15536 struct sip_peer **peerarray; 15537 int k; 15538 15539 15540 realtimepeers = ast_check_realtime("sippeers"); 15541 peerarray = ast_calloc(sizeof(struct sip_peer *), objcount); 15542 15543 if (s) { /* Manager - get ActionID */ 15544 id = astman_get_header(m, "ActionID"); 15545 if (!ast_strlen_zero(id)) 15546 snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id); 15547 } 15548 15549 switch (argc) { 15550 case 5: 15551 if (!strcasecmp(argv[3], "like")) { 15552 if (regcomp(®exbuf, argv[4], REG_EXTENDED | REG_NOSUB)) 15553 return CLI_SHOWUSAGE; 15554 havepattern = TRUE; 15555 } else 15556 return CLI_SHOWUSAGE; 15557 case 3: 15558 break; 15559 default: 15560 return CLI_SHOWUSAGE; 15561 } 15562 15563 if (!s) /* Normal list */ 15564 ast_cli(fd, FORMAT2, "Name/username", "Host", "Dyn", "Forcerport", "ACL", "Port", "Status", (realtimepeers ? "Realtime" : "")); 15565 15566 15567 i = ao2_iterator_init(peers, 0); 15568 while ((peer = ao2_t_iterator_next(&i, "iterate thru peers table"))) { 15569 ao2_lock(peer); 15570 15571 if (!(peer->type & SIP_TYPE_PEER)) { 15572 ao2_unlock(peer); 15573 unref_peer(peer, "unref peer because it's actually a user"); 15574 continue; 15575 } 15576 15577 if (havepattern && regexec(®exbuf, peer->name, 0, NULL, 0)) { 15578 objcount--; 15579 ao2_unlock(peer); 15580 unref_peer(peer, "toss iterator peer ptr before continue"); 15581 continue; 15582 } 15583 15584 peerarray[total_peers++] = peer; 15585 ao2_unlock(peer); 15586 } 15587 ao2_iterator_destroy(&i); 15588 15589 qsort(peerarray, total_peers, sizeof(struct sip_peer *), peercomparefunc); 15590 15591 for(k=0; k < total_peers; k++) { 15592 char status[20] = ""; 15593 char srch[2000]; 15594 char pstatus; 15595 peer = peerarray[k]; 15596 15597 ao2_lock(peer); 15598 if (havepattern && regexec(®exbuf, peer->name, 0, NULL, 0)) { 15599 ao2_unlock(peer); 15600 unref_peer(peer, "toss iterator peer ptr before continue"); 15601 continue; 15602 } 15603 15604 if (!ast_strlen_zero(peer->username) && !s) 15605 snprintf(name, sizeof(name), "%s/%s", peer->name, peer->username); 15606 else 15607 ast_copy_string(name, peer->name, sizeof(name)); 15608 15609 pstatus = peer_status(peer, status, sizeof(status)); 15610 if (pstatus == 1) 15611 peers_mon_online++; 15612 else if (pstatus == 0) 15613 peers_mon_offline++; 15614 else { 15615 if (ast_sockaddr_isnull(&peer->addr) || 15616 !ast_sockaddr_port(&peer->addr)) { 15617 peers_unmon_offline++; 15618 } else { 15619 peers_unmon_online++; 15620 } 15621 } 15622 15623 snprintf(srch, sizeof(srch), FORMAT, name, 15624 ast_sockaddr_isnull(&peer->addr) ? "(Unspecified)" : ast_sockaddr_stringify_addr(&peer->addr), 15625 peer->host_dynamic ? " D " : " ", /* Dynamic or not? */ 15626 ast_test_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT) ? " N " : " ", /* NAT=yes? */ 15627 peer->ha ? " A " : " ", /* permit/deny */ 15628 ast_sockaddr_isnull(&peer->addr) ? 0 : ast_sockaddr_port(&peer->addr), status, 15629 realtimepeers ? (peer->is_realtime ? "Cached RT":"") : ""); 15630 15631 if (!s) {/* Normal CLI list */ 15632 ast_cli(fd, FORMAT, name, 15633 ast_sockaddr_isnull(&peer->addr) ? "(Unspecified)" : ast_sockaddr_stringify_addr(&peer->addr), 15634 peer->host_dynamic ? " D " : " ", /* Dynamic or not? */ 15635 ast_test_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT) ? " N " : " ", /* NAT=yes? */ 15636 peer->ha ? " A " : " ", /* permit/deny */ 15637 ast_sockaddr_isnull(&peer->addr) ? 0 : ast_sockaddr_port(&peer->addr), status, 15638 realtimepeers ? (peer->is_realtime ? "Cached RT":"") : ""); 15639 } else { /* Manager format */ 15640 /* The names here need to be the same as other channels */ 15641 astman_append(s, 15642 "Event: PeerEntry\r\n%s" 15643 "Channeltype: SIP\r\n" 15644 "ObjectName: %s\r\n" 15645 "ChanObjectType: peer\r\n" /* "peer" or "user" */ 15646 "IPaddress: %s\r\n" 15647 "IPport: %d\r\n" 15648 "Dynamic: %s\r\n" 15649 "Forcerport: %s\r\n" 15650 "VideoSupport: %s\r\n" 15651 "TextSupport: %s\r\n" 15652 "ACL: %s\r\n" 15653 "Status: %s\r\n" 15654 "RealtimeDevice: %s\r\n\r\n", 15655 idtext, 15656 peer->name, 15657 ast_sockaddr_isnull(&peer->addr) ? "-none-" : ast_sockaddr_stringify(&peer->addr), 15658 ast_sockaddr_isnull(&peer->addr) ? 0 : ast_sockaddr_port(&peer->addr), 15659 peer->host_dynamic ? "yes" : "no", /* Dynamic or not? */ 15660 ast_test_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT) ? "yes" : "no", /* NAT=yes? */ 15661 ast_test_flag(&peer->flags[1], SIP_PAGE2_VIDEOSUPPORT) ? "yes" : "no", /* VIDEOSUPPORT=yes? */ 15662 ast_test_flag(&peer->flags[1], SIP_PAGE2_TEXTSUPPORT) ? "yes" : "no", /* TEXTSUPPORT=yes? */ 15663 peer->ha ? "yes" : "no", /* permit/deny */ 15664 status, 15665 realtimepeers ? (peer->is_realtime ? "yes":"no") : "no"); 15666 } 15667 ao2_unlock(peer); 15668 unref_peer(peer, "toss iterator peer ptr"); 15669 } 15670 15671 if (!s) 15672 ast_cli(fd, "%d sip peers [Monitored: %d online, %d offline Unmonitored: %d online, %d offline]\n", 15673 total_peers, peers_mon_online, peers_mon_offline, peers_unmon_online, peers_unmon_offline); 15674 15675 if (havepattern) 15676 regfree(®exbuf); 15677 15678 if (total) 15679 *total = total_peers; 15680 15681 ast_free(peerarray); 15682 15683 return CLI_SUCCESS; 15684 #undef FORMAT 15685 #undef FORMAT2 15686 }
| 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 2428 of file chan_sip.c.
References ao2_lock, ao2_ref, ao2_t_find, ao2_t_ref, ao2_t_unlink, ao2_unlock, 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_tcptls_client_start(), ast_tcptls_server_write(), cleanup(), ast_tcptls_session_instance::client, copy_request(), deinit_req(), errno, ast_tcptls_session_instance::f, ast_tcptls_session_instance::fd, get_header(), handle_request_do(), len(), 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_threadinfo_create(), and ast_tcptls_session_instance::ssl.
Referenced by sip_tcp_worker_fn().
02429 { 02430 int res, cl; 02431 struct sip_request req = { 0, } , reqcpy = { 0, }; 02432 struct sip_threadinfo *me = NULL; 02433 char buf[1024] = ""; 02434 struct pollfd fds[2] = { { 0 }, { 0 }, }; 02435 struct ast_tcptls_session_args *ca = NULL; 02436 02437 /* If this is a server session, then the connection has already been setup, 02438 * simply create the threadinfo object so we can access this thread for writing. 02439 * 02440 * if this is a client connection more work must be done. 02441 * 1. We own the parent session args for a client connection. This pointer needs 02442 * to be held on to so we can decrement it's ref count on thread destruction. 02443 * 2. The threadinfo object was created before this thread was launched, however 02444 * it must be found within the threadt table. 02445 * 3. Last, the tcptls_session must be started. 02446 */ 02447 if (!tcptls_session->client) { 02448 if (!(me = sip_threadinfo_create(tcptls_session, tcptls_session->ssl ? SIP_TRANSPORT_TLS : SIP_TRANSPORT_TCP))) { 02449 goto cleanup; 02450 } 02451 ao2_t_ref(me, +1, "Adding threadinfo ref for tcp_helper_thread"); 02452 } else { 02453 struct sip_threadinfo tmp = { 02454 .tcptls_session = tcptls_session, 02455 }; 02456 02457 if ((!(ca = tcptls_session->parent)) || 02458 (!(me = ao2_t_find(threadt, &tmp, OBJ_POINTER, "ao2_find, getting sip_threadinfo in tcp helper thread"))) || 02459 (!(tcptls_session = ast_tcptls_client_start(tcptls_session)))) { 02460 goto cleanup; 02461 } 02462 } 02463 02464 me->threadid = pthread_self(); 02465 ast_debug(2, "Starting thread for %s server\n", tcptls_session->ssl ? "SSL" : "TCP"); 02466 02467 /* set up pollfd to watch for reads on both the socket and the alert_pipe */ 02468 fds[0].fd = tcptls_session->fd; 02469 fds[1].fd = me->alert_pipe[0]; 02470 fds[0].events = fds[1].events = POLLIN | POLLPRI; 02471 02472 if (!(req.data = ast_str_create(SIP_MIN_PACKET))) { 02473 goto cleanup; 02474 } 02475 if (!(reqcpy.data = ast_str_create(SIP_MIN_PACKET))) { 02476 goto cleanup; 02477 } 02478 02479 for (;;) { 02480 struct ast_str *str_save; 02481 02482 res = ast_poll(fds, 2, -1); /* polls for both socket and alert_pipe */ 02483 if (res < 0) { 02484 ast_debug(2, "SIP %s server :: ast_wait_for_input returned %d\n", tcptls_session->ssl ? "SSL": "TCP", res); 02485 goto cleanup; 02486 } 02487 02488 /* handle the socket event, check for both reads from the socket fd, 02489 * and writes from alert_pipe fd */ 02490 if (fds[0].revents) { /* there is data on the socket to be read */ 02491 02492 fds[0].revents = 0; 02493 02494 /* clear request structure */ 02495 str_save = req.data; 02496 memset(&req, 0, sizeof(req)); 02497 req.data = str_save; 02498 ast_str_reset(req.data); 02499 02500 str_save = reqcpy.data; 02501 memset(&reqcpy, 0, sizeof(reqcpy)); 02502 reqcpy.data = str_save; 02503 ast_str_reset(reqcpy.data); 02504 02505 memset(buf, 0, sizeof(buf)); 02506 02507 if (tcptls_session->ssl) { 02508 set_socket_transport(&req.socket, SIP_TRANSPORT_TLS); 02509 req.socket.port = htons(ourport_tls); 02510 } else { 02511 set_socket_transport(&req.socket, SIP_TRANSPORT_TCP); 02512 req.socket.port = htons(ourport_tcp); 02513 } 02514 req.socket.fd = tcptls_session->fd; 02515 02516 /* Read in headers one line at a time */ 02517 while (req.len < 4 || strncmp(REQ_OFFSET_TO_STR(&req, len - 4), "\r\n\r\n", 4)) { 02518 ast_mutex_lock(&tcptls_session->lock); 02519 if (!fgets(buf, sizeof(buf), tcptls_session->f)) { 02520 ast_mutex_unlock(&tcptls_session->lock); 02521 goto cleanup; 02522 } 02523 ast_mutex_unlock(&tcptls_session->lock); 02524 if (me->stop) { 02525 goto cleanup; 02526 } 02527 ast_str_append(&req.data, 0, "%s", buf); 02528 req.len = req.data->used; 02529 } 02530 copy_request(&reqcpy, &req); 02531 parse_request(&reqcpy); 02532 /* In order to know how much to read, we need the content-length header */ 02533 if (sscanf(get_header(&reqcpy, "Content-Length"), "%30d", &cl)) { 02534 while (cl > 0) { 02535 size_t bytes_read; 02536 ast_mutex_lock(&tcptls_session->lock); 02537 if (!(bytes_read = fread(buf, 1, MIN(sizeof(buf) - 1, cl), tcptls_session->f))) { 02538 ast_mutex_unlock(&tcptls_session->lock); 02539 goto cleanup; 02540 } 02541 buf[bytes_read] = '\0'; 02542 ast_mutex_unlock(&tcptls_session->lock); 02543 if (me->stop) { 02544 goto cleanup; 02545 } 02546 cl -= strlen(buf); 02547 ast_str_append(&req.data, 0, "%s", buf); 02548 req.len = req.data->used; 02549 } 02550 } 02551 /*! \todo XXX If there's no Content-Length or if the content-length and what 02552 we receive is not the same - we should generate an error */ 02553 02554 req.socket.tcptls_session = tcptls_session; 02555 handle_request_do(&req, &tcptls_session->remote_address); 02556 } 02557 02558 if (fds[1].revents) { /* alert_pipe indicates there is data in the send queue to be sent */ 02559 enum sip_tcptls_alert alert; 02560 struct tcptls_packet *packet; 02561 02562 fds[1].revents = 0; 02563 02564 if (read(me->alert_pipe[0], &alert, sizeof(alert)) == -1) { 02565 ast_log(LOG_ERROR, "read() failed: %s\n", strerror(errno)); 02566 continue; 02567 } 02568 02569 switch (alert) { 02570 case TCPTLS_ALERT_STOP: 02571 goto cleanup; 02572 case TCPTLS_ALERT_DATA: 02573 ao2_lock(me); 02574 if (!(packet = AST_LIST_REMOVE_HEAD(&me->packet_q, entry))) { 02575 ast_log(LOG_WARNING, "TCPTLS thread alert_pipe indicated packet should be sent, but frame_q is empty"); 02576 } else if (ast_tcptls_server_write(tcptls_session, ast_str_buffer(packet->data), packet->len) == -1) { 02577 ast_log(LOG_WARNING, "Failure to write to tcp/tls socket\n"); 02578 } 02579 02580 if (packet) { 02581 ao2_t_ref(packet, -1, "tcptls packet sent, this is no longer needed"); 02582 } 02583 ao2_unlock(me); 02584 break; 02585 default: 02586 ast_log(LOG_ERROR, "Unknown tcptls thread alert '%d'\n", alert); 02587 } 02588 } 02589 } 02590 02591 ast_debug(2, "Shutting down thread for %s server\n", tcptls_session->ssl ? "SSL" : "TCP"); 02592 02593 cleanup: 02594 if (me) { 02595 ao2_t_unlink(threadt, me, "Removing tcptls helper thread, thread is closing"); 02596 ao2_t_ref(me, -1, "Removing tcp_helper_threads threadinfo ref"); 02597 } 02598 deinit_req(&reqcpy); 02599 deinit_req(&req); 02600 02601 /* if client, we own the parent session arguments and must decrement ref */ 02602 if (ca) { 02603 ao2_t_ref(ca, -1, "closing tcptls thread, getting rid of client tcptls_session arguments"); 02604 } 02605 02606 if (tcptls_session) { 02607 ast_mutex_lock(&tcptls_session->lock); 02608 if (tcptls_session->f) { 02609 fclose(tcptls_session->f); 02610 tcptls_session->f = NULL; 02611 } 02612 if (tcptls_session->fd != -1) { 02613 close(tcptls_session->fd); 02614 tcptls_session->fd = -1; 02615 } 02616 tcptls_session->parent = NULL; 02617 ast_mutex_unlock(&tcptls_session->lock); 02618 02619 ao2_ref(tcptls_session, -1); 02620 tcptls_session = NULL; 02621 } 02622 return NULL; 02623 }
| static void add_blank | ( | struct sip_request * | req | ) | [static] |
add a blank line if no body
Definition at line 3815 of file chan_sip.c.
References ast_str_append(), and ast_str_strlen().
Referenced by send_request(), and send_response().
03816 { 03817 if (!req->lines) { 03818 /* Add extra empty return. add_header() reserves 4 bytes so cannot be truncated */ 03819 ast_str_append(&req->data, 0, "\r\n"); 03820 req->len = ast_str_strlen(req->data); 03821 } 03822 }
| static void add_cc_call_info_to_response | ( | struct sip_pvt * | p, | |
| struct sip_request * | resp | |||
| ) | [static] |
Definition at line 10819 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().
10820 { 10821 char uri[SIPBUFSIZE]; 10822 struct ast_str *header = ast_str_alloca(SIPBUFSIZE); 10823 struct ast_cc_agent *agent = find_sip_cc_agent_by_original_callid(p); 10824 struct sip_cc_agent_pvt *agent_pvt; 10825 10826 if (!agent) { 10827 /* Um, what? How could the SIP_OFFER_CC flag be set but there not be an 10828 * agent? Oh well, we'll just warn and return without adding the header. 10829 */ 10830 ast_log(LOG_WARNING, "Can't find SIP CC agent for call '%s' even though OFFER_CC flag was set?\n", p->callid); 10831 return; 10832 } 10833 10834 agent_pvt = agent->private_data; 10835 10836 if (!ast_strlen_zero(agent_pvt->subscribe_uri)) { 10837 ast_copy_string(uri, agent_pvt->subscribe_uri, sizeof(uri)); 10838 } else { 10839 generate_uri(p, uri, sizeof(uri)); 10840 ast_copy_string(agent_pvt->subscribe_uri, uri, sizeof(agent_pvt->subscribe_uri)); 10841 } 10842 /* XXX Hardcode "NR" as the m reason for now. This should perhaps be changed 10843 * to be more accurate. This parameter has no bearing on the actual operation 10844 * of the feature; it's just there for informational purposes. 10845 */ 10846 ast_str_set(&header, 0, "<%s>;purpose=call-completion;m=%s", uri, "NR"); 10847 add_header(resp, "Call-Info", ast_str_buffer(header)); 10848 ao2_ref(agent, -1); 10849 }
| static void add_codec_to_sdp | ( | const struct sip_pvt * | p, | |
| format_t | 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 10129 of file chan_sip.c.
References ast_codec_pref_getsize(), AST_FORMAT_G719, AST_FORMAT_G723_1, AST_FORMAT_G729A, AST_FORMAT_ILBC, 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, ast_format_list::cur_ms, and ast_rtp_codecs::pref.
Referenced by add_sdp().
10132 { 10133 int rtp_code; 10134 struct ast_format_list fmt; 10135 10136 10137 if (debug) 10138 ast_verbose("Adding codec 0x%" PRIx64 " (%s) to SDP\n", codec, ast_getformatname(codec)); 10139 if ((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->rtp), 1, codec)) == -1) 10140 return; 10141 10142 if (p->rtp) { 10143 struct ast_codec_pref *pref = &ast_rtp_instance_get_codecs(p->rtp)->pref; 10144 fmt = ast_codec_pref_getsize(pref, codec); 10145 } 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 */ 10146 return; 10147 ast_str_append(m_buf, 0, " %d", rtp_code); 10148 ast_str_append(a_buf, 0, "a=rtpmap:%d %s/%d\r\n", rtp_code, 10149 ast_rtp_lookup_mime_subtype2(1, codec, 10150 ast_test_flag(&p->flags[0], SIP_G726_NONSTANDARD) ? AST_RTP_OPT_G726_NONSTANDARD : 0), 10151 ast_rtp_lookup_sample_rate2(1, codec)); 10152 10153 switch (codec) { 10154 case AST_FORMAT_G729A: 10155 /* Indicate that we don't support VAD (G.729 annex B) */ 10156 ast_str_append(a_buf, 0, "a=fmtp:%d annexb=no\r\n", rtp_code); 10157 break; 10158 case AST_FORMAT_G723_1: 10159 /* Indicate that we don't support VAD (G.723.1 annex A) */ 10160 ast_str_append(a_buf, 0, "a=fmtp:%d annexa=no\r\n", rtp_code); 10161 break; 10162 case AST_FORMAT_ILBC: 10163 /* Add information about us using only 20/30 ms packetization */ 10164 ast_str_append(a_buf, 0, "a=fmtp:%d mode=%d\r\n", rtp_code, fmt.cur_ms); 10165 break; 10166 case AST_FORMAT_SIREN7: 10167 /* Indicate that we only expect 32Kbps */ 10168 ast_str_append(a_buf, 0, "a=fmtp:%d bitrate=32000\r\n", rtp_code); 10169 break; 10170 case AST_FORMAT_SIREN14: 10171 /* Indicate that we only expect 48Kbps */ 10172 ast_str_append(a_buf, 0, "a=fmtp:%d bitrate=48000\r\n", rtp_code); 10173 break; 10174 case AST_FORMAT_G719: 10175 /* Indicate that we only expect 64Kbps */ 10176 ast_str_append(a_buf, 0, "a=fmtp:%d bitrate=64000\r\n", rtp_code); 10177 break; 10178 } 10179 10180 if (fmt.cur_ms && (fmt.cur_ms < *min_packet_size)) 10181 *min_packet_size = fmt.cur_ms; 10182 10183 /* Our first codec packetization processed cannot be zero */ 10184 if ((*min_packet_size)==0 && fmt.cur_ms) 10185 *min_packet_size = fmt.cur_ms; 10186 }
| static int add_content | ( | struct sip_request * | req, | |
| const char * | line | |||
| ) | [static] |
Add content (not header) to SIP message.
Definition at line 9104 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().
09105 { 09106 if (req->lines) { 09107 ast_log(LOG_WARNING, "Can't add more content when the content has been finalized\n"); 09108 return -1; 09109 } 09110 09111 ast_str_append(&req->content, 0, "%s", line); 09112 return 0; 09113 }
| 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 9993 of file chan_sip.c.
References add_content(), and add_header().
Referenced by transmit_info_with_digit().
09994 { 09995 char tmp[256]; 09996 int event; 09997 if (mode) { 09998 /* Application/dtmf short version used by some implementations */ 09999 if (digit == '*') 10000 event = 10; 10001 else if (digit == '#') 10002 event = 11; 10003 else if ((digit >= 'A') && (digit <= 'D')) 10004 event = 12 + digit - 'A'; 10005 else 10006 event = atoi(&digit); 10007 snprintf(tmp, sizeof(tmp), "%d\r\n", event); 10008 add_header(req, "Content-Type", "application/dtmf"); 10009 add_content(req, tmp); 10010 } else { 10011 /* Application/dtmf-relay as documented by Cisco */ 10012 snprintf(tmp, sizeof(tmp), "Signal=%c\r\nDuration=%u\r\n", digit, duration); 10013 add_header(req, "Content-Type", "application/dtmf-relay"); 10014 add_content(req, tmp); 10015 } 10016 return 0; 10017 }
| 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 11201 of file chan_sip.c.
References add_header(), ast_sockaddr_stringify_host(), ast_strlen_zero(), and sip_reason_code_to_str().
Referenced by transmit_invite(), and update_redirecting().
11202 { 11203 const char *diverting_number; 11204 const char *diverting_name; 11205 const char *reason; 11206 char header_text[256]; 11207 11208 if (!pvt->owner) { 11209 return; 11210 } 11211 11212 diverting_number = pvt->owner->redirecting.from.number.str; 11213 if (!pvt->owner->redirecting.from.number.valid 11214 || ast_strlen_zero(diverting_number)) { 11215 return; 11216 } 11217 11218 reason = sip_reason_code_to_str(pvt->owner->redirecting.reason); 11219 11220 /* We at least have a number to place in the Diversion header, which is enough */ 11221 diverting_name = pvt->owner->redirecting.from.name.str; 11222 if (!pvt->owner->redirecting.from.name.valid 11223 || ast_strlen_zero(diverting_name)) { 11224 snprintf(header_text, sizeof(header_text), "<sip:%s@%s>;reason=%s", diverting_number, 11225 ast_sockaddr_stringify_host(&pvt->ourip), reason); 11226 } else { 11227 snprintf(header_text, sizeof(header_text), "\"%s\" <sip:%s@%s>;reason=%s", 11228 diverting_name, diverting_number, 11229 ast_sockaddr_stringify_host(&pvt->ourip), reason); 11230 } 11231 11232 add_header(req, "Diversion", header_text); 11233 }
| static int add_header | ( | struct sip_request * | req, | |
| const char * | var, | |||
| const char * | value | |||
| ) | [static] |
Add header to SIP message.
Definition at line 9032 of file chan_sip.c.
References ast_log(), ast_str_append(), ast_str_strlen(), find_alias(), LOG_WARNING, and sip_cfg.
09033 { 09034 if (req->headers == SIP_MAX_HEADERS) { 09035 ast_log(LOG_WARNING, "Out of SIP header space\n"); 09036 return -1; 09037 } 09038 09039 if (req->lines) { 09040 ast_log(LOG_WARNING, "Can't add more headers when lines have been added\n"); 09041 return -1; 09042 } 09043 09044 if (sip_cfg.compactheaders) { 09045 var = find_alias(var, var); 09046 } 09047 09048 ast_str_append(&req->data, 0, "%s: %s\r\n", var, value); 09049 req->header[req->headers] = req->len; 09050 09051 req->len = ast_str_strlen(req->data); 09052 req->headers++; 09053 09054 return 0; 09055 }
| 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 9058 of file chan_sip.c.
References add_header(), ast_channel_trylock, ast_channel_unlock, pbx_builtin_getvar_helper(), sip_pvt_lock, and sip_pvt_unlock.
Referenced by initreqprep(), reqprep(), and transmit_register().
09059 { 09060 char clen[10]; 09061 const char *max = NULL; 09062 09063 /* deadlock avoidance */ 09064 while (dialog->owner && ast_channel_trylock(dialog->owner)) { 09065 sip_pvt_unlock(dialog); 09066 usleep(1); 09067 sip_pvt_lock(dialog); 09068 } 09069 09070 if (dialog->owner) { 09071 max = pbx_builtin_getvar_helper(dialog->owner, "SIP_MAX_FORWARDS"); 09072 ast_channel_unlock(dialog->owner); 09073 } 09074 09075 /* The channel variable overrides the peer/channel value */ 09076 if (max == NULL) { 09077 snprintf(clen, sizeof(clen), "%d", dialog->maxforwards); 09078 } 09079 return add_header(req, "Max-Forwards", max != NULL ? max : clen); 09080 }
| 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 10267 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().
10270 { 10271 int rtp_code; 10272 10273 if (debug) 10274 ast_verbose("Adding non-codec 0x%x (%s) to SDP\n", format, ast_rtp_lookup_mime_subtype2(0, format, 0)); 10275 if ((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->rtp), 0, format)) == -1) 10276 return; 10277 10278 ast_str_append(m_buf, 0, " %d", rtp_code); 10279 ast_str_append(a_buf, 0, "a=rtpmap:%d %s/%d\r\n", rtp_code, 10280 ast_rtp_lookup_mime_subtype2(0, format, 0), 10281 ast_rtp_lookup_sample_rate2(0, format)); 10282 if (format == AST_RTP_DTMF) /* Indicate we support DTMF and FLASH... */ 10283 ast_str_append(a_buf, 0, "a=fmtp:%d 0-16\r\n", rtp_code); 10284 }
| static void add_peer_mailboxes | ( | struct sip_peer * | peer, | |
| const char * | value | |||
| ) | [static] |
Definition at line 25536 of file chan_sip.c.
References ast_calloc, AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_strdupa, ast_strlen_zero(), context, mailbox, mbox(), S_OR, and strsep().
Referenced by build_peer().
25537 { 25538 char *next, *mbox, *context; 25539 25540 next = ast_strdupa(value); 25541 25542 while ((mbox = context = strsep(&next, ","))) { 25543 struct sip_mailbox *mailbox; 25544 int duplicate = 0; 25545 25546 strsep(&context, "@"); 25547 25548 if (ast_strlen_zero(mbox)) { 25549 continue; 25550 } 25551 25552 /* Check whether the mailbox is already in the list */ 25553 AST_LIST_TRAVERSE(&peer->mailboxes, mailbox, entry) { 25554 if (!strcmp(mailbox->mailbox, mbox) && !strcmp(S_OR(mailbox->context, ""), S_OR(context, ""))) { 25555 duplicate = 1; 25556 mailbox->delme = 0; 25557 break; 25558 } 25559 } 25560 if (duplicate) { 25561 continue; 25562 } 25563 25564 if (!(mailbox = ast_calloc(1, sizeof(*mailbox) + strlen(mbox) + strlen(S_OR(context, ""))))) { 25565 continue; 25566 } 25567 25568 if (!ast_strlen_zero(context)) { 25569 mailbox->context = mailbox->mailbox + strlen(mbox) + 1; 25570 strcpy(mailbox->context, context); /* SAFE */ 25571 } 25572 strcpy(mailbox->mailbox, mbox); /* SAFE */ 25573 25574 AST_LIST_INSERT_TAIL(&peer->mailboxes, mailbox, entry); 25575 } 25576 }
| static void add_peer_mwi_subs | ( | struct sip_peer * | peer | ) | [static] |
Definition at line 22883 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_LIST_TRAVERSE, mailbox, mwi_event_cb(), and S_OR.
Referenced by build_peer(), and handle_request_subscribe().
22884 { 22885 struct sip_mailbox *mailbox; 22886 22887 AST_LIST_TRAVERSE(&peer->mailboxes, mailbox, entry) { 22888 mailbox->event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "SIP mbox event", peer, 22889 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox->mailbox, 22890 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, S_OR(mailbox->context, "default"), 22891 AST_EVENT_IE_END); 22892 } 22893 }
| static struct sip_auth * add_realm_authentication | ( | struct sip_auth * | authlist, | |
| const char * | configuration, | |||
| int | lineno | |||
| ) | [static, read] |
Add realm authentication in list.
Definition at line 25349 of file chan_sip.c.
References ast_calloc, ast_copy_string(), ast_debug, ast_log(), ast_strlen_zero(), ast_verb, LOG_WARNING, and secret.
Referenced by build_peer(), and reload_config().
25350 { 25351 char authcopy[256]; 25352 char *username=NULL, *realm=NULL, *secret=NULL, *md5secret=NULL; 25353 struct sip_auth *a, *b, *auth; 25354 25355 if (ast_strlen_zero(configuration)) 25356 return authlist; 25357 25358 ast_debug(1, "Auth config :: %s\n", configuration); 25359 25360 ast_copy_string(authcopy, configuration, sizeof(authcopy)); 25361 username = authcopy; 25362 25363 /* split user[:secret] and relm */ 25364 realm = strrchr(username, '@'); 25365 if (realm) 25366 *realm++ = '\0'; 25367 if (ast_strlen_zero(username) || ast_strlen_zero(realm)) { 25368 ast_log(LOG_WARNING, "Format for authentication entry is user[:secret]@realm at line %d\n", lineno); 25369 return authlist; 25370 } 25371 25372 /* parse username at ':' for secret, or '#" for md5secret */ 25373 if ((secret = strchr(username, ':'))) { 25374 *secret++ = '\0'; 25375 } else if ((md5secret = strchr(username, '#'))) { 25376 *md5secret++ = '\0'; 25377 } 25378 25379 if (!(auth = ast_calloc(1, sizeof(*auth)))) 25380 return authlist; 25381 25382 ast_copy_string(auth->realm, realm, sizeof(auth->realm)); 25383 ast_copy_string(auth->username, username, sizeof(auth->username)); 25384 if (secret) 25385 ast_copy_string(auth->secret, secret, sizeof(auth->secret)); 25386 if (md5secret) 25387 ast_copy_string(auth->md5secret, md5secret, sizeof(auth->md5secret)); 25388 25389 /* find the end of the list */ 25390 for (b = NULL, a = authlist; a ; b = a, a = a->next) 25391 ; 25392 if (b) 25393 b->next = auth; /* Add structure add end of list */ 25394 else 25395 authlist = auth; 25396 25397 ast_verb(3, "Added authentication for realm %s\n", realm); 25398 25399 return authlist; 25400 25401 }
| static void add_route | ( | struct sip_request * | req, | |
| struct sip_route * | route | |||
| ) | [static] |
Add route header into request per learned route.
Definition at line 9215 of file chan_sip.c.
References add_header(), and ast_copy_string().
Referenced by initreqprep(), and reqprep().
09216 { 09217 char r[SIPBUFSIZE*2], *p; 09218 int n, rem = sizeof(r); 09219 09220 if (!route) 09221 return; 09222 09223 p = r; 09224 for (;route ; route = route->next) { 09225 n = strlen(route->hop); 09226 if (rem < n+3) /* we need room for ",<route>" */ 09227 break; 09228 if (p != r) { /* add a separator after fist route */ 09229 *p++ = ','; 09230 --rem; 09231 } 09232 *p++ = '<'; 09233 ast_copy_string(p, route->hop, rem); /* cannot fail */ 09234 p += n; 09235 *p++ = '>'; 09236 rem -= (n+2); 09237 } 09238 *p = '\0'; 09239 add_header(req, "Route", r); 09240 }
| static int add_rpid | ( | struct sip_request * | req, | |
| struct sip_pvt * | p | |||
| ) | [static] |
Add Remote-Party-ID header to SIP message.
Definition at line 10023 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(), ast_str_alloca, ast_str_append(), ast_str_buffer(), ast_str_set(), ast_strlen_zero(), ast_test_flag, ast_uri_encode(), and S_OR.
Referenced by __transmit_response(), transmit_invite(), transmit_reinvite_with_sdp(), transmit_response_with_sdp(), and update_connectedline().
10024 { 10025 struct ast_str *tmp = ast_str_alloca(256); 10026 char tmp2[256]; 10027 char *lid_num = NULL; 10028 char *lid_name = NULL; 10029 int lid_pres; 10030 const char *fromdomain; 10031 const char *privacy = NULL; 10032 const char *screen = NULL; 10033 const char *anonymous_string = "\"Anonymous\" <anonymous@anonymous.invalid>"; 10034 10035 if (!ast_test_flag(&p->flags[0], SIP_SENDRPID)) { 10036 return 0; 10037 } 10038 10039 if (p->owner && p->owner->connected.id.number.valid 10040 && p->owner->connected.id.number.str) { 10041 lid_num = p->owner->connected.id.number.str; 10042 } 10043 if (p->owner && p->owner->connected.id.name.valid 10044 && p->owner->connected.id.name.str) { 10045 lid_name = p->owner->connected.id.name.str; 10046 } 10047 lid_pres = (p->owner) ? ast_party_id_presentation(&p->owner->connected.id) : AST_PRES_NUMBER_NOT_AVAILABLE; 10048 10049 if (ast_strlen_zero(lid_num)) 10050 return 0; 10051 if (ast_strlen_zero(lid_name)) 10052 lid_name = lid_num; 10053 fromdomain = S_OR(p->fromdomain, ast_sockaddr_stringify_host(&p->ourip)); 10054 10055 lid_num = ast_uri_encode(lid_num, tmp2, sizeof(tmp2), 1); 10056 10057 if (ast_test_flag(&p->flags[0], SIP_SENDRPID_PAI)) { 10058 if ((lid_pres & AST_PRES_RESTRICTION) != AST_PRES_ALLOWED) { 10059 ast_str_set(&tmp, -1, "%s", anonymous_string); 10060 } else { 10061 ast_str_set(&tmp, -1, "\"%s\" <sip:%s@%s>", lid_name, lid_num, fromdomain); 10062 } 10063 add_header(req, "P-Asserted-Identity", ast_str_buffer(tmp)); 10064 } else { 10065 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"); 10066 10067 switch (lid_pres) { 10068 case AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED: 10069 case AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN: 10070 privacy = "off"; 10071 screen = "no"; 10072 break; 10073 case AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN: 10074 case AST_PRES_ALLOWED_NETWORK_NUMBER: 10075 privacy = "off"; 10076 screen = "yes"; 10077 break; 10078 case AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED: 10079 case AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN: 10080 privacy = "full"; 10081 screen = "no"; 10082 break; 10083 case AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN: 10084 case AST_PRES_PROHIB_NETWORK_NUMBER: 10085 privacy = "full"; 10086 screen = "yes"; 10087 break; 10088 case AST_PRES_NUMBER_NOT_AVAILABLE: 10089 break; 10090 default: 10091 if ((lid_pres & AST_PRES_RESTRICTION) != AST_PRES_ALLOWED) { 10092 privacy = "full"; 10093 } 10094 else 10095 privacy = "off"; 10096 screen = "no"; 10097 break; 10098 } 10099 10100 if (!ast_strlen_zero(privacy) && !ast_strlen_zero(screen)) { 10101 ast_str_append(&tmp, -1, ";privacy=%s;screen=%s", privacy, screen); 10102 } 10103 10104 add_header(req, "Remote-Party-ID", ast_str_buffer(tmp)); 10105 } 10106 return 0; 10107 }
| 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 10405 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(), ast_codec_pref_index(), ast_debug, AST_FORMAT_AUDIO_MASK, AST_FORMAT_TEXT_MASK, AST_FORMAT_VIDEO_MASK, 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_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, capability, debug, FALSE, get_crypto_attrib(), get_our_media_address(), LOG_WARNING, sip_debug_test_pvt(), t38_get_rate(), TRUE, UDPTL_ERROR_CORRECTION_FEC, UDPTL_ERROR_CORRECTION_NONE, UDPTL_ERROR_CORRECTION_REDUNDANCY, and version.
10406 { 10407 format_t alreadysent = 0; 10408 10409 struct ast_sockaddr addr = { {0,} }; 10410 struct ast_sockaddr vaddr = { {0,} }; 10411 struct ast_sockaddr taddr = { {0,} }; 10412 struct ast_sockaddr udptladdr = { {0,} }; 10413 struct ast_sockaddr dest = { {0,} }; 10414 struct ast_sockaddr vdest = { {0,} }; 10415 struct ast_sockaddr tdest = { {0,} }; 10416 struct ast_sockaddr udptldest = { {0,} }; 10417 10418 /* SDP fields */ 10419 char *version = "v=0\r\n"; /* Protocol version */ 10420 char subject[256]; /* Subject of the session */ 10421 char owner[256]; /* Session owner/creator */ 10422 char connection[256]; /* Connection data */ 10423 char *session_time = "t=0 0\r\n"; /* Time the session is active */ 10424 char bandwidth[256] = ""; /* Max bitrate */ 10425 char *hold = ""; 10426 struct ast_str *m_audio = ast_str_alloca(256); /* Media declaration line for audio */ 10427 struct ast_str *m_video = ast_str_alloca(256); /* Media declaration line for video */ 10428 struct ast_str *m_text = ast_str_alloca(256); /* Media declaration line for text */ 10429 struct ast_str *m_modem = ast_str_alloca(256); /* Media declaration line for modem */ 10430 struct ast_str *a_audio = ast_str_alloca(1024); /* Attributes for audio */ 10431 struct ast_str *a_video = ast_str_alloca(1024); /* Attributes for video */ 10432 struct ast_str *a_text = ast_str_alloca(1024); /* Attributes for text */ 10433 struct ast_str *a_modem = ast_str_alloca(1024); /* Attributes for modem */ 10434 const char *a_crypto = NULL; 10435 const char *v_a_crypto = NULL; 10436 const char *t_a_crypto = NULL; 10437 10438 format_t x; 10439 format_t capability = 0; 10440 int needaudio = FALSE; 10441 int needvideo = FALSE; 10442 int needtext = FALSE; 10443 int debug = sip_debug_test_pvt(p); 10444 int min_audio_packet_size = 0; 10445 int min_video_packet_size = 0; 10446 int min_text_packet_size = 0; 10447 10448 char codecbuf[SIPBUFSIZE]; 10449 char buf[SIPBUFSIZE]; 10450 char dummy_answer[256]; 10451 10452 /* Set the SDP session name */ 10453 snprintf(subject, sizeof(subject), "s=%s\r\n", ast_strlen_zero(global_sdpsession) ? "-" : global_sdpsession); 10454 10455 if (!p->rtp) { 10456 ast_log(LOG_WARNING, "No way to add SDP without an RTP structure\n"); 10457 return AST_FAILURE; 10458 } 10459 /* XXX We should not change properties in the SIP dialog until 10460 we have acceptance of the offer if this is a re-invite */ 10461 10462 /* Set RTP Session ID and version */ 10463 if (!p->sessionid) { 10464 p->sessionid = (int)ast_random(); 10465 p->sessionversion = p->sessionid; 10466 } else { 10467 if (oldsdp == FALSE) 10468 p->sessionversion++; 10469 } 10470 10471 if (add_audio) { 10472 /* Check if we need video in this call */ 10473 if ((p->jointcapability & AST_FORMAT_VIDEO_MASK) && !p->novideo) { 10474 if (p->vrtp) { 10475 needvideo = TRUE; 10476 ast_debug(2, "This call needs video offers!\n"); 10477 } else 10478 ast_debug(2, "This call needs video offers, but there's no video support enabled!\n"); 10479 } 10480 /* Check if we need text in this call */ 10481 if ((p->jointcapability & AST_FORMAT_TEXT_MASK) && !p->notext) { 10482 if (sipdebug_text) 10483 ast_verbose("We think we can do text\n"); 10484 if (p->trtp) { 10485 if (sipdebug_text) { 10486 ast_verbose("And we have a text rtp object\n"); 10487 } 10488 needtext = TRUE; 10489 ast_debug(2, "This call needs text offers! \n"); 10490 } else { 10491 ast_debug(2, "This call needs text offers, but there's no text support enabled ! \n"); 10492 } 10493 } 10494 } 10495 10496 get_our_media_address(p, needvideo, needtext, &addr, &vaddr, &taddr, &dest, &vdest, &tdest); 10497 10498 snprintf(owner, sizeof(owner), "o=%s %d %d IN %s %s\r\n", 10499 ast_strlen_zero(global_sdpowner) ? "-" : global_sdpowner, 10500 p->sessionid, p->sessionversion, 10501 (ast_sockaddr_is_ipv6(&dest) && !ast_sockaddr_is_ipv4_mapped(&dest)) ? 10502 "IP6" : "IP4", 10503 ast_sockaddr_stringify_addr(&dest)); 10504 10505 snprintf(connection, sizeof(connection), "c=IN %s %s\r\n", 10506 (ast_sockaddr_is_ipv6(&dest) && !ast_sockaddr_is_ipv4_mapped(&dest)) ? 10507 "IP6" : "IP4", 10508 ast_sockaddr_stringify_addr(&dest)); 10509 10510 if (add_audio) { 10511 capability = p->jointcapability; 10512 10513 /* XXX note, Video and Text are negated - 'true' means 'no' */ 10514 ast_debug(1, "** Our capability: %s Video flag: %s Text flag: %s\n", ast_getformatname_multiple(codecbuf, sizeof(codecbuf), capability), 10515 p->novideo ? "True" : "False", p->notext ? "True" : "False"); 10516 ast_debug(1, "** Our prefcodec: %s \n", ast_getformatname_multiple(codecbuf, sizeof(codecbuf), p->prefcodec)); 10517 10518 /* Check if we need audio */ 10519 if (capability & AST_FORMAT_AUDIO_MASK) 10520 needaudio = TRUE; 10521 10522 if (debug) { 10523 ast_verbose("Audio is at %s\n", ast_sockaddr_stringify_port(&p->ourip)); 10524 } 10525 10526 /* Ok, we need video. Let's add what we need for video and set codecs. 10527 Video is handled differently than audio since we can not transcode. */ 10528 if (needvideo) { 10529 get_crypto_attrib(p->vsrtp, &v_a_crypto); 10530 ast_str_append(&m_video, 0, "m=video %d RTP/%s", ast_sockaddr_port(&vdest), 10531 v_a_crypto ? "SAVP" : "AVP"); 10532 10533 /* Build max bitrate string */ 10534 if (p->maxcallbitrate) 10535 snprintf(bandwidth, sizeof(bandwidth), "b=CT:%d\r\n", p->maxcallbitrate); 10536 if (debug) { 10537 ast_verbose("Video is at %s\n", ast_sockaddr_stringify(&p->ourip)); 10538 } 10539 } 10540 10541 /* Ok, we need text. Let's add what we need for text and set codecs. 10542 Text is handled differently than audio since we can not transcode. */ 10543 if (needtext) { 10544 if (sipdebug_text) 10545 ast_verbose("Lets set up the text sdp\n"); 10546 get_crypto_attrib(p->tsrtp, &t_a_crypto); 10547 ast_str_append(&m_text, 0, "m=text %d RTP/%s", ast_sockaddr_port(&tdest), 10548 t_a_crypto ? "SAVP" : "AVP"); 10549 if (debug) { /* XXX should I use tdest below ? */ 10550 ast_verbose("Text is at %s\n", ast_sockaddr_stringify(&p->ourip)); 10551 } 10552 } 10553 10554 /* Start building generic SDP headers */ 10555 10556 /* We break with the "recommendation" and send our IP, in order that our 10557 peer doesn't have to ast_gethostbyname() us */ 10558 10559 get_crypto_attrib(p->srtp, &a_crypto); 10560 ast_str_append(&m_audio, 0, "m=audio %d RTP/%s", ast_sockaddr_port(&dest), 10561 a_crypto ? "SAVP" : "AVP"); 10562 10563 if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD) == SIP_PAGE2_CALL_ONHOLD_ONEDIR) 10564 hold = "a=recvonly\r\n"; 10565 else if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD) == SIP_PAGE2_CALL_ONHOLD_INACTIVE) 10566 hold = "a=inactive\r\n"; 10567 else 10568 hold = "a=sendrecv\r\n"; 10569 10570 /* Now, start adding audio codecs. These are added in this order: 10571 - First what was requested by the calling channel 10572 - Then preferences in order from sip.conf device config for this peer/user 10573 - Then other codecs in capabilities, including video 10574 */ 10575 10576 /* Prefer the audio codec we were requested to use, first, no matter what 10577 Note that p->prefcodec can include video codecs, so mask them out 10578 */ 10579 if (capability & p->prefcodec) { 10580 format_t codec = p->prefcodec & AST_FORMAT_AUDIO_MASK; 10581 10582 add_codec_to_sdp(p, codec, &m_audio, &a_audio, debug, &min_audio_packet_size); 10583 alreadysent |= codec; 10584 } 10585 10586 /* Start by sending our preferred audio/video codecs */ 10587 for (x = 0; x < 64; x++) { 10588 format_t codec; 10589 10590 if (!(codec = ast_codec_pref_index(&p->prefs, x))) 10591 break; 10592 10593 if (!(capability & codec)) 10594 continue; 10595 10596 if (alreadysent & codec) 10597 continue; 10598 10599 add_codec_to_sdp(p, codec, &m_audio, &a_audio, debug, &min_audio_packet_size); 10600 alreadysent |= codec; 10601 } 10602 10603 /* Now send any other common audio and video codecs, and non-codec formats: */ 10604 for (x = 1ULL; x <= (needtext ? AST_FORMAT_TEXT_MASK : (needvideo ? AST_FORMAT_VIDEO_MASK : AST_FORMAT_AUDIO_MASK)); x <<= 1) { 10605 if (!(capability & x)) /* Codec not requested */ 10606 continue; 10607 10608 if (alreadysent & x) /* Already added to SDP */ 10609 continue; 10610 10611 if (x & AST_FORMAT_AUDIO_MASK) 10612 add_codec_to_sdp(p, x, &m_audio, &a_audio, debug, &min_audio_packet_size); 10613 else if (x & AST_FORMAT_VIDEO_MASK) 10614 add_vcodec_to_sdp(p, x, &m_video, &a_video, debug, &min_video_packet_size); 10615 else if (x & AST_FORMAT_TEXT_MASK) 10616 add_tcodec_to_sdp(p, x, &m_text, &a_text, debug, &min_text_packet_size); 10617 } 10618 10619 /* Now add DTMF RFC2833 telephony-event as a codec */ 10620 for (x = 1LL; x <= AST_RTP_MAX; x <<= 1) { 10621 if (!(p->jointnoncodeccapability & x)) 10622 continue; 10623 10624 add_noncodec_to_sdp(p, x, &m_audio, &a_audio, debug); 10625 } 10626 10627 ast_debug(3, "-- Done with adding codecs to SDP\n"); 10628 10629 if (!p->owner || !ast_internal_timing_enabled(p->owner)) 10630 ast_str_append(&a_audio, 0, "a=silenceSupp:off - - - -\r\n"); 10631 10632 if (min_audio_packet_size) 10633 ast_str_append(&a_audio, 0, "a=ptime:%d\r\n", min_audio_packet_size); 10634 10635 /* XXX don't think you can have ptime for video */ 10636 if (min_video_packet_size) 10637 ast_str_append(&a_video, 0, "a=ptime:%d\r\n", min_video_packet_size); 10638 10639 /* XXX don't think you can have ptime for text */ 10640 if (min_text_packet_size) 10641 ast_str_append(&a_text, 0, "a=ptime:%d\r\n", min_text_packet_size); 10642 10643 if (m_audio->len - m_audio->used < 2 || m_video->len - m_video->used < 2 || 10644 m_text->len - m_text->used < 2 || a_text->len - a_text->used < 2 || 10645 a_audio->len - a_audio->used < 2 || a_video->len - a_video->used < 2) 10646 ast_log(LOG_WARNING, "SIP SDP may be truncated due to undersized buffer!!\n"); 10647 } 10648 10649 if (add_t38) { 10650 /* Our T.38 end is */ 10651 ast_udptl_get_us(p->udptl, &udptladdr); 10652 10653 /* Determine T.38 UDPTL destination */ 10654 if (!ast_sockaddr_isnull(&p->udptlredirip)) { 10655 ast_sockaddr_copy(&udptldest, &p->udptlredirip); 10656 } else { 10657 ast_sockaddr_copy(&udptldest, &p->ourip); 10658 ast_sockaddr_set_port(&udptldest, ast_sockaddr_port(&udptladdr)); 10659 } 10660 10661 if (debug) { 10662 ast_debug(1, "T.38 UDPTL is at %s port %d\n", ast_sockaddr_stringify_addr(&p->ourip), ast_sockaddr_port(&udptladdr)); 10663 } 10664 10665 /* We break with the "recommendation" and send our IP, in order that our 10666 peer doesn't have to ast_gethostbyname() us */ 10667 10668 ast_str_append(&m_modem, 0, "m=image %d udptl t38\r\n", ast_sockaddr_port(&udptldest)); 10669 10670 if (!ast_sockaddr_cmp(&udptldest, &dest)) { 10671 ast_str_append(&m_modem, 0, "c=IN %s %s\r\n", 10672 (ast_sockaddr_is_ipv6(&dest) && !ast_sockaddr_is_ipv4_mapped(&dest)) ? 10673 "IP6" : "IP4", ast_sockaddr_stringify_addr(&udptldest)); 10674 } 10675 10676 ast_str_append(&a_modem, 0, "a=T38FaxVersion:%d\r\n", p->t38.our_parms.version); 10677 ast_str_append(&a_modem, 0, "a=T38MaxBitRate:%d\r\n", t38_get_rate(p->t38.our_parms.rate)); 10678 if (p->t38.our_parms.fill_bit_removal) { 10679 ast_str_append(&a_modem, 0, "a=T38FaxFillBitRemoval\r\n"); 10680 } 10681 if (p->t38.our_parms.transcoding_mmr) { 10682 ast_str_append(&a_modem, 0, "a=T38FaxTranscodingMMR\r\n"); 10683 } 10684 if (p->t38.our_parms.transcoding_jbig) { 10685 ast_str_append(&a_modem, 0, "a=T38FaxTranscodingJBIG\r\n"); 10686 } 10687 switch (p->t38.our_parms.rate_management) { 10688 case AST_T38_RATE_MANAGEMENT_TRANSFERRED_TCF: 10689 ast_str_append(&a_modem, 0, "a=T38FaxRateManagement:transferredTCF\r\n"); 10690 break; 10691 case AST_T38_RATE_MANAGEMENT_LOCAL_TCF: 10692 ast_str_append(&a_modem, 0, "a=T38FaxRateManagement:localTCF\r\n"); 10693 break; 10694 } 10695 ast_str_append(&a_modem, 0, "a=T38FaxMaxDatagram:%u\r\n", ast_udptl_get_local_max_datagram(p->udptl)); 10696 switch (ast_udptl_get_error_correction_scheme(p->udptl)) { 10697 case UDPTL_ERROR_CORRECTION_NONE: 10698 break; 10699 case UDPTL_ERROR_CORRECTION_FEC: 10700 ast_str_append(&a_modem, 0, "a=T38FaxUdpEC:t38UDPFEC\r\n"); 10701 break; 10702 case UDPTL_ERROR_CORRECTION_REDUNDANCY: 10703 ast_str_append(&a_modem, 0, "a=T38FaxUdpEC:t38UDPRedundancy\r\n"); 10704 break; 10705 } 10706 } 10707 10708 if (needaudio) 10709 ast_str_append(&m_audio, 0, "\r\n"); 10710 if (needvideo) 10711 ast_str_append(&m_video, 0, "\r\n"); 10712 if (needtext) 10713 ast_str_append(&m_text, 0, "\r\n"); 10714 10715 add_header(resp, "Content-Type", "application/sdp"); 10716 add_content(resp, version); 10717 add_content(resp, owner); 10718 add_content(resp, subject); 10719 add_content(resp, connection); 10720 if (needvideo) /* only if video response is appropriate */ 10721 add_content(resp, bandwidth); 10722 add_content(resp, session_time); 10723 if (needaudio) { 10724 add_content(resp, m_audio->str); 10725 add_content(resp, a_audio->str); 10726 add_content(resp, hold); 10727 if (a_crypto) { 10728 add_content(resp, a_crypto); 10729 } 10730 } else if (p->offered_media[SDP_AUDIO].offered) { 10731 snprintf(dummy_answer, sizeof(dummy_answer), "m=audio 0 RTP/AVP %s\r\n", p->offered_media[SDP_AUDIO].codecs); 10732 add_content(resp, dummy_answer); 10733 } 10734 if (needvideo) { /* only if video response is appropriate */ 10735 add_content(resp, m_video->str); 10736 add_content(resp, a_video->str); 10737 add_content(resp, hold); /* Repeat hold for the video stream */ 10738 if (v_a_crypto) { 10739 add_content(resp, v_a_crypto); 10740 } 10741 } else if (p->offered_media[SDP_VIDEO].offered) { 10742 snprintf(dummy_answer, sizeof(dummy_answer), "m=video 0 RTP/AVP %s\r\n", p->offered_media[SDP_VIDEO].codecs); 10743 add_content(resp, dummy_answer); 10744 } 10745 if (needtext) { /* only if text response is appropriate */ 10746 add_content(resp, m_text->str); 10747 add_content(resp, a_text->str); 10748 add_content(resp, hold); /* Repeat hold for the text stream */ 10749 if (t_a_crypto) { 10750 add_content(resp, t_a_crypto); 10751 } 10752 } else if (p->offered_media[SDP_TEXT].offered) { 10753 snprintf(dummy_answer, sizeof(dummy_answer), "m=text 0 RTP/AVP %s\r\n", p->offered_media[SDP_TEXT].codecs); 10754 add_content(resp, dummy_answer); 10755 } 10756 if (add_t38) { 10757 add_content(resp, m_modem->str); 10758 add_content(resp, a_modem->str); 10759 } else if (p->offered_media[SDP_IMAGE].offered) { 10760 add_content(resp, "m=image 0 udptl t38\r\n"); 10761 } 10762 10763 /* Update lastrtprx when we send our SDP */ 10764 p->lastrtprx = p->lastrtptx = time(NULL); /* XXX why both ? */ 10765 10766 ast_debug(3, "Done building SDP. Settling with this capability: %s\n", ast_getformatname_multiple(buf, SIPBUFSIZE, capability)); 10767 10768 return AST_SUCCESS; 10769 }
| 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 25285 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().
25286 { 25287 struct domain *d; 25288 25289 if (ast_strlen_zero(domain)) { 25290 ast_log(LOG_WARNING, "Zero length domain.\n"); 25291 return 1; 25292 } 25293 25294 if (!(d = ast_calloc(1, sizeof(*d)))) 25295 return 0; 25296 25297 ast_copy_string(d->domain, domain, sizeof(d->domain)); 25298 25299 if (!ast_strlen_zero(context)) 25300 ast_copy_string(d->context, context, sizeof(d->context)); 25301 25302 d->mode = mode; 25303 25304 AST_LIST_LOCK(&domain_list); 25305 AST_LIST_INSERT_TAIL(&domain_list, d, list); 25306 AST_LIST_UNLOCK(&domain_list); 25307 25308 if (sipdebug) 25309 ast_debug(1, "Added local SIP domain '%s'\n", domain); 25310 25311 return 1; 25312 }
| 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 9020 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().
09021 { 09022 int res; 09023 if (st_get_mode(pvt) != SESSION_TIMER_MODE_REFUSE) { 09024 res = add_header(req, "Supported", "replaces, timer"); 09025 } else { 09026 res = add_header(req, "Supported", "replaces"); 09027 } 09028 return res; 09029 }
| static void add_tcodec_to_sdp | ( | const struct sip_pvt * | p, | |
| int | codec, | |||
| 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 10213 of file chan_sip.c.
References 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(), and ast_verbose.
Referenced by add_sdp().
10216 { 10217 int rtp_code; 10218 10219 if (!p->trtp) 10220 return; 10221 10222 if (debug) 10223 ast_verbose("Adding text codec 0x%x (%s) to SDP\n", codec, ast_getformatname(codec)); 10224 10225 if ((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->trtp), 1, codec)) == -1) 10226 return; 10227 10228 ast_str_append(m_buf, 0, " %d", rtp_code); 10229 ast_str_append(a_buf, 0, "a=rtpmap:%d %s/%d\r\n", rtp_code, 10230 ast_rtp_lookup_mime_subtype2(1, codec, 0), 10231 ast_rtp_lookup_sample_rate2(1, codec)); 10232 /* Add fmtp code here */ 10233 10234 if (codec == AST_FORMAT_T140RED) { 10235 int t140code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->trtp), 1, AST_FORMAT_T140); 10236 ast_str_append(a_buf, 0, "a=fmtp:%d %d/%d/%d\r\n", rtp_code, 10237 t140code, 10238 t140code, 10239 t140code); 10240 10241 } 10242 }
| static int add_text | ( | struct sip_request * | req, | |
| const char * | text | |||
| ) | [static] |
Add text body to SIP message.
Definition at line 9981 of file chan_sip.c.
References add_content(), and add_header().
Referenced by transmit_message_with_text().
09982 { 09983 /* XXX Convert \n's to \r\n's XXX */ 09984 add_header(req, "Content-Type", "text/plain;charset=UTF-8"); 09985 add_content(req, text); 09986 return 0; 09987 }
| static struct ast_variable* add_var | ( | const char * | buf, | |
| struct ast_variable * | list | |||
| ) | [static, read] |
implement the setvar config line
Definition at line 25434 of file chan_sip.c.
References ast_strdupa, ast_variable_new(), and ast_variable::next.
25435 { 25436 struct ast_variable *tmpvar = NULL; 25437 char *varname = ast_strdupa(buf), *varval = NULL; 25438 25439 if ((varval = strchr(varname, '='))) { 25440 *varval++ = '\0'; 25441 if ((tmpvar = ast_variable_new(varname, varval, ""))) { 25442 tmpvar->next = list; 25443 list = tmpvar; 25444 } 25445 } 25446 return list; 25447 }
| static void add_vcodec_to_sdp | ( | const struct sip_pvt * | p, | |
| format_t | codec, | |||
| 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 10190 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(), and ast_verbose.
Referenced by add_sdp().
10193 { 10194 int rtp_code; 10195 10196 if (!p->vrtp) 10197 return; 10198 10199 if (debug) 10200 ast_verbose("Adding video codec 0x%" PRIx64 " (%s) to SDP\n", codec, ast_getformatname(codec)); 10201 10202 if ((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->vrtp), 1, codec)) == -1) 10203 return; 10204 10205 ast_str_append(m_buf, 0, " %d", rtp_code); 10206 ast_str_append(a_buf, 0, "a=rtpmap:%d %s/%d\r\n", rtp_code, 10207 ast_rtp_lookup_mime_subtype2(1, codec, 0), 10208 ast_rtp_lookup_sample_rate2(1, codec)); 10209 /* Add fmtp code here */ 10210 }
| static int add_vidupdate | ( | struct sip_request * | req | ) | [static] |
add XML encoded media control with update
Definition at line 10111 of file chan_sip.c.
References add_content(), and add_header().
Referenced by transmit_info_with_vidupdate().
10112 { 10113 const char *xml_is_a_huge_waste_of_space = 10114 "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\r\n" 10115 " <media_control>\r\n" 10116 " <vc_primitive>\r\n" 10117 " <to_encoder>\r\n" 10118 " <picture_fast_update>\r\n" 10119 " </picture_fast_update>\r\n" 10120 " </to_encoder>\r\n" 10121 " </vc_primitive>\r\n" 10122 " </media_control>\r\n"; 10123 add_header(req, "Content-Type", "application/media_control+xml"); 10124 add_content(req, xml_is_a_huge_waste_of_space); 10125 return 0; 10126 }
| static void append_date | ( | struct sip_request * | req | ) | [static] |
Append date to SIP message.
Definition at line 9819 of file chan_sip.c.
References add_header().
09820 { 09821 char tmpdat[256]; 09822 struct tm tm; 09823 time_t t = time(NULL); 09824 09825 gmtime_r(&t, &tm); 09826 strftime(tmpdat, sizeof(tmpdat), "%a, %d %b %Y %T GMT", &tm); 09827 add_header(req, "Date", tmpdat); 09828 }
| static void append_history_full | ( | struct sip_pvt * | p, | |
| const char * | fmt, | |||
| ... | ||||
| ) | [static] |
Append to SIP dialog history with arg list.
Definition at line 3272 of file chan_sip.c.
References append_history_va().
03273 { 03274 va_list ap; 03275 03276 if (!p) { 03277 return; 03278 } 03279 03280 if (!p->do_history && !recordhistory && !dumphistory) { 03281 return; 03282 } 03283 03284 va_start(ap, fmt); 03285 append_history_va(p, fmt, ap); 03286 va_end(ap); 03287 03288 return; 03289 }
| 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 3244 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().
03245 { 03246 char buf[80], *c = buf; /* max history length */ 03247 struct sip_history *hist; 03248 int l; 03249 03250 vsnprintf(buf, sizeof(buf), fmt, ap); 03251 strsep(&c, "\r\n"); /* Trim up everything after \r or \n */ 03252 l = strlen(buf) + 1; 03253 if (!(hist = ast_calloc(1, sizeof(*hist) + l))) { 03254 return; 03255 } 03256 if (!p->history && !(p->history = ast_calloc(1, sizeof(*p->history)))) { 03257 ast_free(hist); 03258 return; 03259 } 03260 memcpy(hist->event, buf, l); 03261 if (p->history_entries == MAX_HISTORY_ENTRIES) { 03262 struct sip_history *oldest; 03263 oldest = AST_LIST_REMOVE_HEAD(p->history, list); 03264 p->history_entries--; 03265 ast_free(oldest); 03266 } 03267 AST_LIST_INSERT_TAIL(p->history, hist, list); 03268 p->history_entries++; 03269 }
| static int apply_directmedia_ha | ( | struct sip_pvt * | p, | |
| const char * | op | |||
| ) | [static] |
Definition at line 27293 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().
27294 { 27295 struct ast_sockaddr us = { { 0, }, }, them = { { 0, }, }; 27296 int res = AST_SENSE_ALLOW; 27297 27298 ast_rtp_instance_get_remote_address(p->rtp, &them); 27299 ast_rtp_instance_get_local_address(p->rtp, &us); 27300 27301 if ((res = ast_apply_ha(p->directmediaha, &them)) == AST_SENSE_DENY) { 27302 ast_debug(3, "Reinvite %s to %s denied by directmedia ACL on %s\n", 27303 op, ast_strdupa(ast_sockaddr_stringify(&them)), ast_strdupa(ast_sockaddr_stringify(&us))); 27304 } 27305 27306 return res; 27307 }
| 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 20166 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().
20167 { 20168 if (chan && chan->_state == AST_STATE_UP) { 20169 if (ast_test_flag(chan, AST_FLAG_MOH)) 20170 ast_moh_stop(chan); 20171 else if (chan->generatordata) 20172 ast_deactivate_generator(chan); 20173 } 20174 }
| 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 3138 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, get_transport(), internip, ast_tcptls_session_args::local_address, LOG_NOTICE, LOG_WARNING, and sip_cfg.
Referenced by __sip_subscribe_mwi_do(), sip_alloc(), sip_cc_monitor_request_cc(), sip_poke_peer(), sip_request_call(), sip_send_mwi_to_peer(), transmit_publish(), transmit_register(), and transmit_response_using_temp().
03139 { 03140 struct ast_sockaddr theirs; 03141 03142 /* Set want_remap to non-zero if we want to remap 'us' to an externally 03143 * reachable IP address and port. This is done if: 03144 * 1. we have a localaddr list (containing 'internal' addresses marked 03145 * as 'deny', so ast_apply_ha() will return AST_SENSE_DENY on them, 03146 * and AST_SENSE_ALLOW on 'external' ones); 03147 * 2. externaddr is set, so we know what to use as the 03148 * externally visible address; 03149 * 3. the remote address, 'them', is external; 03150 * 4. the address returned by ast_ouraddrfor() is 'internal' (AST_SENSE_DENY 03151 * when passed to ast_apply_ha() so it does need to be remapped. 03152 * This fourth condition is checked later. 03153 */ 03154 int want_remap = 0; 03155 03156 ast_sockaddr_copy(us, &internip); /* starting guess for the internal address */ 03157 /* now ask the system what would it use to talk to 'them' */ 03158 ast_ouraddrfor(them, us); 03159 ast_sockaddr_copy(&theirs, them); 03160 03161 if (ast_sockaddr_is_ipv6(&theirs)) { 03162 if (localaddr && !ast_sockaddr_isnull(&externaddr)) { 03163 ast_log(LOG_WARNING, "Address remapping activated in sip.conf " 03164 "but we're using IPv6, which doesn't need it. Please " 03165 "remove \"localnet\" and/or \"externaddr\" settings.\n"); 03166 } 03167 } else { 03168 want_remap = localaddr && 03169 !ast_sockaddr_isnull(&externaddr) && 03170 ast_apply_ha(localaddr, &theirs) == AST_SENSE_ALLOW ; 03171 } 03172 03173 if (want_remap && 03174 (!sip_cfg.matchexternaddrlocally || !ast_apply_ha(localaddr, us)) ) { 03175 /* if we used externhost, see if it is time to refresh the info */ 03176 if (externexpire && time(NULL) >= externexpire) { 03177 if (ast_sockaddr_resolve_first(&externaddr, externhost, 0)) { 03178 ast_log(LOG_NOTICE, "Warning: Re-lookup of '%s' failed!\n", externhost); 03179 } 03180 externexpire = time(NULL) + externrefresh; 03181 } 03182 if (!ast_sockaddr_isnull(&externaddr)) { 03183 ast_sockaddr_copy(us, &externaddr); 03184 switch (p->socket.type) { 03185 case SIP_TRANSPORT_TCP: 03186 if (!externtcpport && ast_sockaddr_port(&externaddr)) { 03187 /* for consistency, default to the externaddr port */ 03188 externtcpport = ast_sockaddr_port(&externaddr); 03189 } 03190 ast_sockaddr_set_port(us, externtcpport); 03191 break; 03192 case SIP_TRANSPORT_TLS: 03193 ast_sockaddr_set_port(us, externtlsport); 03194 break; 03195 case SIP_TRANSPORT_UDP: 03196 if (!ast_sockaddr_port(&externaddr)) { 03197 ast_sockaddr_set_port(us, ast_sockaddr_port(&bindaddr)); 03198 } 03199 break; 03200 default: 03201 break; 03202 } 03203 } 03204 ast_debug(1, "Target address %s is not local, substituting externaddr\n", 03205 ast_sockaddr_stringify(them)); 03206 } else if (p) { 03207 /* no remapping, but we bind to a specific address, so use it. */ 03208 switch (p->socket.type) { 03209 case SIP_TRANSPORT_TCP: 03210 if (!ast_sockaddr_is_any(&sip_tcp_desc.local_address)) { 03211 ast_sockaddr_copy(us, 03212 &sip_tcp_desc.local_address); 03213 } else { 03214 ast_sockaddr_set_port(us, 03215 ast_sockaddr_port(&sip_tcp_desc.local_address)); 03216 } 03217 break; 03218 case SIP_TRANSPORT_TLS: 03219 if (!ast_sockaddr_is_any(&sip_tls_desc.local_address)) { 03220 ast_sockaddr_copy(us, 03221 &sip_tls_desc.local_address); 03222 } else { 03223 ast_sockaddr_set_port(us, 03224 ast_sockaddr_port(&sip_tls_desc.local_address)); 03225 } 03226 break; 03227 case SIP_TRANSPORT_UDP: 03228 /* fall through on purpose */ 03229 default: 03230 if (!ast_sockaddr_is_any(&bindaddr)) { 03231 ast_sockaddr_copy(us, &bindaddr); 03232 } 03233 if (!ast_sockaddr_port(us)) { 03234 ast_sockaddr_set_port(us, ast_sockaddr_port(&bindaddr)); 03235 } 03236 } 03237 } else if (!ast_sockaddr_is_any(&bindaddr)) { 03238 ast_sockaddr_copy(us, &bindaddr); 03239 } 03240 ast_debug(3, "Setting SIP_TRANSPORT_%s with address %s\n", get_transport(p->socket.type), ast_sockaddr_stringify(us)); 03241 }
| 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 27955 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(), reload_config(), set_destination(), sip_do_debug_ip(), and sip_request_call().
27957 { 27958 return ast_sockaddr_resolve_first_af(addr, name, flag, get_address_family_filter(&bindaddr)); 27959 }
| 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 27931 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().
27933 { 27934 struct ast_sockaddr *addrs; 27935 int addrs_cnt; 27936 27937 addrs_cnt = ast_sockaddr_resolve(&addrs, name, flag, family); 27938 if (addrs_cnt <= 0) { 27939 return 1; 27940 } 27941 if (addrs_cnt > 1) { 27942 ast_debug(1, "Multiple addresses, using the first one only\n"); 27943 } 27944 27945 ast_sockaddr_copy(addr, &addrs[0]); 27946 27947 ast_free(addrs); 27948 return 0; 27949 }
| 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 20178 of file chan_sip.c.
References ast_channel_masquerade(), ast_debug, ast_log(), ast_quiet_chan(), AST_SOFTHANGUP_DEV, ast_softhangup_nolock(), ast_state2str(), LOG_NOTICE, and LOG_WARNING.
20179 { 20180 int res = 0; 20181 struct ast_channel *peera = NULL, 20182 *peerb = NULL, 20183 *peerc = NULL, 20184 *peerd = NULL; 20185 20186 20187 /* We will try to connect the transferee with the target and hangup 20188 all channels to the transferer */ 20189 ast_debug(4, "Sip transfer:--------------------\n"); 20190 if (transferer->chan1) 20191 ast_debug(4, "-- Transferer to PBX channel: %s State %s\n", transferer->chan1->name, ast_state2str(transferer->chan1->_state)); 20192 else 20193 ast_debug(4, "-- No transferer first channel - odd??? \n"); 20194 if (target->chan1) 20195 ast_debug(4, "-- Transferer to PBX second channel (target): %s State %s\n", target->chan1->name, ast_state2str(target->chan1->_state)); 20196 else 20197 ast_debug(4, "-- No target first channel ---\n"); 20198 if (transferer->chan2) 20199 ast_debug(4, "-- Bridged call to transferee: %s State %s\n", transferer->chan2->name, ast_state2str(transferer->chan2->_state)); 20200 else 20201 ast_debug(4, "-- No bridged call to transferee\n"); 20202 if (target->chan2) 20203 ast_debug(4, "-- Bridged call to transfer target: %s State %s\n", target->chan2 ? target->chan2->name : "<none>", target->chan2 ? ast_state2str(target->chan2->_state) : "(none)"); 20204 else 20205 ast_debug(4, "-- No target second channel ---\n"); 20206 ast_debug(4, "-- END Sip transfer:--------------------\n"); 20207 if (transferer->chan2) { /* We have a bridge on the transferer's channel */ 20208 peera = transferer->chan1; /* Transferer - PBX -> transferee channel * the one we hangup */ 20209 peerb = target->chan1; /* Transferer - PBX -> target channel - This will get lost in masq */ 20210 peerc = transferer->chan2; /* Asterisk to Transferee */ 20211 peerd = target->chan2; /* Asterisk to Target */ 20212 ast_debug(3, "SIP transfer: Four channels to handle\n"); 20213 } else if (target->chan2) { /* Transferer has no bridge (IVR), but transferee */ 20214 peera = target->chan1; /* Transferer to PBX -> target channel */ 20215 peerb = transferer->chan1; /* Transferer to IVR*/ 20216 peerc = target->chan2; /* Asterisk to Target */ 20217 peerd = transferer->chan2; /* Nothing */ 20218 ast_debug(3, "SIP transfer: Three channels to handle\n"); 20219 } 20220 20221 if (peera && peerb && peerc && (peerb != peerc)) { 20222 ast_quiet_chan(peera); /* Stop generators */ 20223 ast_quiet_chan(peerb); 20224 ast_quiet_chan(peerc); 20225 if (peerd) 20226 ast_quiet_chan(peerd); 20227 20228 ast_debug(4, "SIP transfer: trying to masquerade %s into %s\n", peerc->name, peerb->name); 20229 if (ast_channel_masquerade(peerb, peerc)) { 20230 ast_log(LOG_WARNING, "Failed to masquerade %s into %s\n", peerb->name, peerc->name); 20231 res = -1; 20232 } else 20233 ast_debug(4, "SIP transfer: Succeeded to masquerade channels.\n"); 20234 return res; 20235 } else { 20236 ast_log(LOG_NOTICE, "SIP Transfer attempted with no appropriate bridged calls to transfer\n"); 20237 if (transferer->chan1) 20238 ast_softhangup_nolock(transferer->chan1, AST_SOFTHANGUP_DEV); 20239 if (target->chan1) 20240 ast_softhangup_nolock(target->chan1, AST_SOFTHANGUP_DEV); 20241 return -1; 20242 } 20243 return 0; 20244 }
| static void auth_headers | ( | enum sip_auth_type | code, | |
| char ** | header, | |||
| char ** | respheader | |||
| ) | [static] |
return the request and response heade for a 401 or 407 code
Definition at line 12612 of file chan_sip.c.
References ast_verbose.
Referenced by check_auth(), do_proxy_auth(), do_register_auth(), and transmit_request_with_auth().
12613 { 12614 if (code == WWW_AUTH) { /* 401 */ 12615 *header = "WWW-Authenticate"; 12616 *respheader = "Authorization"; 12617 } else if (code == PROXY_AUTH) { /* 407 */ 12618 *header = "Proxy-Authenticate"; 12619 *respheader = "Proxy-Authorization"; 12620 } else { 12621 ast_verbose("-- wrong response code %d\n", code); 12622 *header = *respheader = "Invalid"; 12623 } 12624 }
| 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 5049 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().
05050 { 05051 struct sip_pvt *p = (struct sip_pvt *)arg; 05052 05053 sip_pvt_lock(p); 05054 p->initid = -1; /* event gone, will not be rescheduled */ 05055 if (p->owner) { 05056 /* XXX fails on possible deadlock */ 05057 if (!ast_channel_trylock(p->owner)) { 05058 append_history(p, "Cong", "Auto-congesting (timer)"); 05059 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 05060 ast_channel_unlock(p->owner); 05061 } 05062 05063 /* Give the channel a chance to act before we proceed with destruction */ 05064 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 05065 } 05066 sip_pvt_unlock(p); 05067 dialog_unref(p, "unreffing arg passed into auto_congest callback (p->initid)"); 05068 return 0; 05069 }
| static void build_callid_pvt | ( | struct sip_pvt * | pvt | ) | [static] |
Build SIP Call-ID value for a non-REGISTER transaction.
Definition at line 6983 of file chan_sip.c.
References ast_sockaddr_stringify(), ast_string_field_build, generate_random_string(), and S_OR.
Referenced by __sip_subscribe_mwi_do(), sip_alloc(), sip_poke_peer(), sip_request_call(), and sip_send_mwi_to_peer().
06984 { 06985 char buf[33]; 06986 06987 const char *host = S_OR(pvt->fromdomain, ast_sockaddr_stringify(&pvt->ourip)); 06988 06989 ast_string_field_build(pvt, callid, "%s@%s", generate_random_string(buf, sizeof(buf)), host); 06990 06991 }
| 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 6994 of file chan_sip.c.
References ast_sockaddr_stringify_host(), ast_string_field_build, generate_random_string(), and S_OR.
Referenced by transmit_register().
06995 { 06996 char buf[33]; 06997 06998 const char *host = S_OR(fromdomain, ast_sockaddr_stringify_host(ourip)); 06999 07000 ast_string_field_build(reg, callid, "%s@%s", generate_random_string(buf, sizeof(buf)), host); 07001 }
| static void build_contact | ( | struct sip_pvt * | p | ) | [static] |
Build contact header - the contact header we send out.
Definition at line 11013 of file chan_sip.c.
References ast_sockaddr_stringify(), ast_string_field_build, ast_strlen_zero(), and 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().
11014 { 11015 if (p->socket.type == SIP_TRANSPORT_UDP) { 11016 ast_string_field_build(p, our_contact, "<sip:%s%s%s>", p->exten, 11017 ast_strlen_zero(p->exten) ? "" : "@", ast_sockaddr_stringify(&p->ourip)); 11018 } else { 11019 ast_string_field_build(p, our_contact, "<sip:%s%s%s;transport=%s>", p->exten, 11020 ast_strlen_zero(p->exten) ? "" : "@", ast_sockaddr_stringify(&p->ourip), 11021 get_transport(p->socket.type)); 11022 } 11023 }
| 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 25579 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_t_alloc, ao2_t_find, ao2_t_ref, 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(), ast_free, ast_free_ha(), ast_get_cc_agent_policy(), ast_get_group(), 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_sockaddr_stringify_host(), 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_true(), ast_variables_destroy(), bindaddr, cid_name, cid_num, clear_realm_authentication(), context, DEFAULT_MAXMS, destroy_association(), destroy_mailbox(), 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, parkinglot, PARSE_PORT_FORBID, port_str2int(), proxy_update(), ref_peer(), reg_source_db(), secret, set_peer_defaults(), set_socket_transport(), sip_cfg, sip_destroy_peer_fn(), sip_poke_peer(), sip_register(), sip_send_mwi_to_peer(), srvlookup, str2stmode(), str2strefresher(), strsep(), TRUE, unref_peer(), and ast_variable::value.
25580 { 25581 struct sip_peer *peer = NULL; 25582 struct ast_ha *oldha = NULL; 25583 struct ast_ha *olddirectmediaha = NULL; 25584 int found = 0; 25585 int firstpass = 1; 25586 uint16_t port = 0; 25587 int format = 0; /* Ama flags */ 25588 int timerb_set = 0, timert1_set = 0; 25589 time_t regseconds = 0; 25590 struct ast_flags peerflags[3] = {{(0)}}; 25591 struct ast_flags mask[3] = {{(0)}}; 25592 char callback[256] = ""; 25593 struct sip_peer tmp_peer; 25594 const char *srvlookup = NULL; 25595 static int deprecation_warning = 1; 25596 int alt_fullcontact = alt ? 1 : 0, headercount = 0; 25597 struct ast_str *fullcontact = ast_str_alloca(512); 25598 25599 if (!realtime || ast_test_flag(&global_flags[1], SIP_PAGE2_RTCACHEFRIENDS)) { 25600 /* Note we do NOT use find_peer here, to avoid realtime recursion */ 25601 /* We also use a case-sensitive comparison (unlike find_peer) so 25602 that case changes made to the peer name will be properly handled 25603 during reload 25604 */ 25605 ast_copy_string(tmp_peer.name, name, sizeof(tmp_peer.name)); 25606 peer = ao2_t_find(peers, &tmp_peer, OBJ_POINTER | OBJ_UNLINK, "find and unlink peer from peers table"); 25607 } 25608 25609 if (peer) { 25610 /* Already in the list, remove it and it will be added back (or FREE'd) */ 25611 found++; 25612 if (!(peer->the_mark)) 25613 firstpass = 0; 25614 } else { 25615 if (!(peer = ao2_t_alloc(sizeof(*peer), sip_destroy_peer_fn, "allocate a peer struct"))) 25616 return NULL; 25617 25618 if (ast_string_field_init(peer, 512)) { 25619 ao2_t_ref(peer, -1, "failed to string_field_init, drop peer"); 25620 return NULL; 25621 } 25622 25623 if (!(peer->cc_params = ast_cc_config_params_init())) { 25624 ao2_t_ref(peer, -1, "failed to allocate cc_params for peer"); 25625 return NULL; 25626 } 25627 25628 if (realtime && !ast_test_flag(&global_flags[1], SIP_PAGE2_RTCACHEFRIENDS)) { 25629 ast_atomic_fetchadd_int(&rpeerobjs, 1); 25630 ast_debug(3, "-REALTIME- peer built. Name: %s. Peer objects: %d\n", name, rpeerobjs); 25631 } else 25632 ast_atomic_fetchadd_int(&speerobjs, 1); 25633 } 25634 25635 /* Note that our peer HAS had its reference count increased */ 25636 if (firstpass) { 25637 peer->lastmsgssent = -1; 25638 oldha = peer->ha; 25639 peer->ha = NULL; 25640 olddirectmediaha = peer->directmediaha; 25641 peer->directmediaha = NULL; 25642 set_peer_defaults(peer); /* Set peer defaults */ 25643 peer->type = 0; 25644 } 25645 if (!found && name) 25646 ast_copy_string(peer->name, name, sizeof(peer->name)); 25647 25648 /* If we have channel variables, remove them (reload) */ 25649 if (peer->chanvars) { 25650 ast_variables_destroy(peer->chanvars); 25651 peer->chanvars = NULL; 25652 /* XXX should unregister ? */ 25653 } 25654 25655 if (found) 25656 peer->portinuri = 0; 25657 25658 /* If we have realm authentication information, remove them (reload) */ 25659 clear_realm_authentication(peer->auth); 25660 peer->auth = NULL; 25661 /* clear the transport information. We will detect if a default value is required after parsing the config */ 25662 peer->default_outbound_transport = 0; 25663 peer->transports = 0; 25664 25665 if (!devstate_only) { 25666 struct sip_mailbox *mailbox; 25667 AST_LIST_TRAVERSE(&peer->mailboxes, mailbox, entry) { 25668 mailbox->delme = 1; 25669 } 25670 } 25671 25672 for (; v || ((v = alt) && !(alt=NULL)); v = v->next) { 25673 if (!devstate_only) { 25674 if (handle_common_options(&peerflags[0], &mask[0], v)) { 25675 continue; 25676 } 25677 if (handle_t38_options(&peerflags[0], &mask[0], v, &peer->t38_maxdatagram)) { 25678 continue; 25679 } 25680 if (!strcasecmp(v->name, "transport") && !ast_strlen_zero(v->value)) { 25681 char *val = ast_strdupa(v->value); 25682 char *trans; 25683 25684 while ((trans = strsep(&val, ","))) { 25685 trans = ast_skip_blanks(trans); 25686 25687 if (!strncasecmp(trans, "udp", 3)) { 25688 peer->transports |= SIP_TRANSPORT_UDP; 25689 } else if (!strncasecmp(trans, "tcp", 3)) { 25690 peer->transports |= SIP_TRANSPORT_TCP; 25691 } else if (!strncasecmp(trans, "tls", 3)) { 25692 peer->transports |= SIP_TRANSPORT_TLS; 25693 } else { 25694 ast_log(LOG_NOTICE, "'%s' is not a valid transport type. if no other is specified, udp will be used.\n", trans); 25695 } 25696 25697 if (!peer->default_outbound_transport) { /*!< The first transport listed should be default outbound */ 25698 peer->default_outbound_transport = peer->transports; 25699 } 25700 } 25701 } else if (realtime && !strcasecmp(v->name, "regseconds")) { 25702 ast_get_time_t(v->value, ®seconds, 0, NULL); 25703 } else if (realtime && !strcasecmp(v->name, "name")) { 25704 ast_copy_string(peer->name, v->value, sizeof(peer->name)); 25705 } else if (realtime && !strcasecmp(v->name, "useragent")) { 25706 ast_string_field_set(peer, useragent, v->value); 25707 } else if (!strcasecmp(v->name, "type")) { 25708 if (!strcasecmp(v->value, "peer")) { 25709 peer->type |= SIP_TYPE_PEER; 25710 } else if (!strcasecmp(v->value, "user")) { 25711 peer->type |= SIP_TYPE_USER; 25712 } else if (!strcasecmp(v->value, "friend")) { 25713 peer->type = SIP_TYPE_USER | SIP_TYPE_PEER; 25714 } 25715 } else if (!strcasecmp(v->name, "remotesecret")) { 25716 ast_string_field_set(peer, remotesecret, v->value); 25717 } else if (!strcasecmp(v->name, "secret")) { 25718 ast_string_field_set(peer, secret, v->value); 25719 } else if (!strcasecmp(v->name, "md5secret")) { 25720 ast_string_field_set(peer, md5secret, v->value); 25721 } else if (!strcasecmp(v->name, "auth")) { 25722 peer->auth = add_realm_authentication(peer->auth, v->value, v->lineno); 25723 } else if (!strcasecmp(v->name, "callerid")) { 25724 char cid_name[80] = { '\0' }, cid_num[80] = { '\0' }; 25725 25726 ast_callerid_split(v->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num)); 25727 ast_string_field_set(peer, cid_name, cid_name); 25728 ast_string_field_set(peer, cid_num, cid_num); 25729 } else if (!strcasecmp(v->name, "mwi_from")) { 25730 ast_string_field_set(peer, mwi_from, v->value); 25731 } else if (!strcasecmp(v->name, "fullname")) { 25732 ast_string_field_set(peer, cid_name, v->value); 25733 } else if (!strcasecmp(v->name, "trunkname")) { 25734 /* This is actually for a trunk, so we don't want to override callerid */ 25735 ast_string_field_set(peer, cid_name, ""); 25736 } else if (!strcasecmp(v->name, "cid_number")) { 25737 ast_string_field_set(peer, cid_num, v->value); 25738 } else if (!strcasecmp(v->name, "cid_tag")) { 25739 ast_string_field_set(peer, cid_tag, v->value); 25740 } else if (!strcasecmp(v->name, "context")) { 25741 ast_string_field_set(peer, context, v->value); 25742 ast_set_flag(&peer->flags[1], SIP_PAGE2_HAVEPEERCONTEXT); 25743 } else if (!strcasecmp(v->name, "subscribecontext")) { 25744 ast_string_field_set(peer, subscribecontext, v->value); 25745 } else if (!strcasecmp(v->name, "fromdomain")) { 25746 char *fromdomainport; 25747 ast_string_field_set(peer, fromdomain, v->value); 25748 if ((fromdomainport = strchr(peer->fromdomain, ':'))) { 25749 *fromdomainport++ = '\0'; 25750 if (!(peer->fromdomainport = port_str2int(fromdomainport, 0))) { 25751 ast_log(LOG_NOTICE, "'%s' is not a valid port number for fromdomain.\n",fromdomainport); 25752 } 25753 } else { 25754 peer->fromdomainport = STANDARD_SIP_PORT; 25755 } 25756 } else if (!strcasecmp(v->name, "usereqphone")) { 25757 ast_set2_flag(&peer->flags[0], ast_true(v->value), SIP_USEREQPHONE); 25758 } else if (!strcasecmp(v->name, "fromuser")) { 25759 ast_string_field_set(peer, fromuser, v->value); 25760 } else if (!strcasecmp(v->name, "outboundproxy")) { 25761 char *tok, *proxyname; 25762 25763 if (ast_strlen_zero(v->value)) { 25764 ast_log(LOG_WARNING, "no value given for outbound proxy on line %d of sip.conf.", v->lineno); 25765 continue; 25766 } 25767 25768 peer->outboundproxy = 25769 ao2_alloc(sizeof(*peer->outboundproxy), NULL); 25770 25771 tok = ast_skip_blanks(strtok(ast_strdupa(v->value), ",")); 25772 25773 sip_parse_host(tok, v->lineno, &proxyname, 25774 &peer->outboundproxy->port, 25775 &peer->outboundproxy->transport); 25776 25777 tok = ast_skip_blanks(strtok(ast_strdupa(v->value), ",")); 25778 25779 if ((tok = strtok(NULL, ","))) { 25780 peer->outboundproxy->force = !strncasecmp(ast_skip_blanks(tok), "force", 5); 25781 } else { 25782 peer->outboundproxy->force = FALSE; 25783 } 25784 25785 if (ast_strlen_zero(proxyname)) { 25786 ast_log(LOG_WARNING, "you must specify a name for the outboundproxy on line %d of sip.conf.", v->lineno); 25787 sip_cfg.outboundproxy.name[0] = '\0'; 25788 continue; 25789 } 25790 25791 ast_copy_string(peer->outboundproxy->name, proxyname, sizeof(peer->outboundproxy->name)); 25792 25793 proxy_update(peer->outboundproxy); 25794 } else if (!strcasecmp(v->name, "host")) { 25795 if (!strcasecmp(v->value, "dynamic")) { 25796 /* They'll register with us */ 25797 if (!found || !peer->host_dynamic) { 25798 /* Initialize stuff if this is a new peer, or if it used to 25799 * not be dynamic before the reload. */ 25800 ast_sockaddr_setnull(&peer->addr); 25801 } 25802 peer->host_dynamic = TRUE; 25803 } else { 25804 /* Non-dynamic. Make sure we become that way if we're not */ 25805 AST_SCHED_DEL_UNREF(sched, peer->expire, 25806 unref_peer(peer, "removing register expire ref")); 25807 peer->host_dynamic = FALSE; 25808 srvlookup = v->value; 25809 } 25810 } else if (!strcasecmp(v->name, "defaultip")) { 25811 if (!ast_strlen_zero(v->value) && ast_get_ip(&peer->defaddr, v->value)) { 25812 unref_peer(peer, "unref_peer: from build_peer defaultip"); 25813 return NULL; 25814 } 25815 } else if (!strcasecmp(v->name, "permit") || !strcasecmp(v->name, "deny")) { 25816 int ha_error = 0; 25817 if (!ast_strlen_zero(v->value)) { 25818 peer->ha = ast_append_ha(v->name, v->value, peer->ha, &ha_error); 25819 } 25820 if (ha_error) { 25821 ast_log(LOG_ERROR, "Bad ACL entry in configuration line %d : %s\n", v->lineno, v->value); 25822 } 25823 } else if (!strcasecmp(v->name, "contactpermit") || !strcasecmp(v->name, "contactdeny")) { 25824 int ha_error = 0; 25825 if (!ast_strlen_zero(v->value)) { 25826 peer->contactha = ast_append_ha(v->name + 7, v->value, peer->contactha, &ha_error); 25827 } 25828 if (ha_error) { 25829 ast_log(LOG_ERROR, "Bad ACL entry in configuration line %d : %s\n", v->lineno, v->value); 25830 } 25831 } else if (!strcasecmp(v->name, "directmediapermit") || !strcasecmp(v->name, "directmediadeny")) { 25832 int ha_error = 0; 25833 peer->directmediaha = ast_append_ha(v->name + 11, v->value, peer->directmediaha, &ha_error); 25834 if (ha_error) { 25835 ast_log(LOG_ERROR, "Bad directmedia ACL entry in configuration line %d : %s\n", v->lineno, v->value); 25836 } 25837 } else if (!strcasecmp(v->name, "port")) { 25838 peer->portinuri = 1; 25839 if (!(port = port_str2int(v->value, 0))) { 25840 if (realtime) { 25841 /* If stored as integer, could be 0 for some DBs (notably MySQL) */ 25842 peer->portinuri = 0; 25843 } else { 25844 ast_log(LOG_WARNING, "Invalid peer port configuration at line %d : %s\n", v->lineno, v->value); 25845 } 25846 } 25847 } else if (!strcasecmp(v->name, "callingpres")) { 25848 peer->callingpres = ast_parse_caller_presentation(v->value); 25849 if (peer->callingpres == -1) { 25850 peer->callingpres = atoi(v->value); 25851 } 25852 } else if (!strcasecmp(v->name, "username") || !strcmp(v->name, "defaultuser")) { /* "username" is deprecated */ 25853 ast_string_field_set(peer, username, v->value); 25854 if (!strcasecmp(v->name, "username")) { 25855 if (deprecation_warning) { 25856 ast_log(LOG_NOTICE, "The 'username' field for sip peers has been deprecated in favor of the term 'defaultuser'\n"); 25857 deprecation_warning = 0; 25858 } 25859 peer->deprecated_username = 1; 25860 } 25861 } else if (!strcasecmp(v->name, "language")) { 25862 ast_string_field_set(peer, language, v->value); 25863 } else if (!strcasecmp(v->name, "regexten")) { 25864 ast_string_field_set(peer, regexten, v->value); 25865 } else if (!strcasecmp(v->name, "callbackextension")) { 25866 ast_copy_string(callback, v->value, sizeof(callback)); 25867 } else if (!strcasecmp(v->name, "amaflags")) { 25868 format = ast_cdr_amaflags2int(v->value); 25869 if (format < 0) { 25870 ast_log(LOG_WARNING, "Invalid AMA Flags for peer: %s at line %d\n", v->value, v->lineno); 25871 } else { 25872 peer->amaflags = format; 25873 } 25874 } else if (!strcasecmp(v->name, "maxforwards")) { 25875 if ((sscanf(v->value, "%30d", &peer->maxforwards) != 1) || (peer->maxforwards < 1)) { 25876 ast_log(LOG_WARNING, "'%s' is not a valid maxforwards value at line %d. Using default.\n", v->value, v->lineno); 25877 peer->maxforwards = sip_cfg.default_max_forwards; 25878 } 25879 } else if (!strcasecmp(v->name, "accountcode")) { 25880 ast_string_field_set(peer, accountcode, v->value); 25881 } else if (!strcasecmp(v->name, "mohinterpret")) { 25882 ast_string_field_set(peer, mohinterpret, v->value); 25883 } else if (!strcasecmp(v->name, "mohsuggest")) { 25884 ast_string_field_set(peer, mohsuggest, v->value); 25885 } else if (!strcasecmp(v->name, "parkinglot")) { 25886 ast_string_field_set(peer, parkinglot, v->value); 25887 } else if (!strcasecmp(v->name, "rtp_engine")) { 25888 ast_string_field_set(peer, engine, v->value); 25889 } else if (!strcasecmp(v->name, "mailbox")) { 25890 add_peer_mailboxes(peer, v->value); 25891 } else if (!strcasecmp(v->name, "hasvoicemail")) { 25892 /* People expect that if 'hasvoicemail' is set, that the mailbox will 25893 * be also set, even if not explicitly specified. */ 25894 if (ast_true(v->value) && AST_LIST_EMPTY(&peer->mailboxes)) { 25895 add_peer_mailboxes(peer, name); 25896 } 25897 } else if (!strcasecmp(v->name, "subscribemwi")) { 25898 ast_set2_flag(&peer->flags[1], ast_true(v->value), SIP_PAGE2_SUBSCRIBEMWIONLY); 25899 } else if (!strcasecmp(v->name, "vmexten")) { 25900 ast_string_field_set(peer, vmexten, v->value); 25901 } else if (!strcasecmp(v->name, "callgroup")) { 25902 peer->callgroup = ast_get_group(v->value); 25903 } else if (!strcasecmp(v->name, "allowtransfer")) { 25904 peer->allowtransfer = ast_true(v->value) ? TRANSFER_OPENFORALL : TRANSFER_CLOSED; 25905 } else if (!strcasecmp(v->name, "pickupgroup")) { 25906 peer->pickupgroup = ast_get_group(v->value); 25907 } else if (!strcasecmp(v->name, "allow")) { 25908 int error = ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, TRUE); 25909 if (error) { 25910 ast_log(LOG_WARNING, "Codec configuration errors found in line %d : %s = %s\n", v->lineno, v->name, v->value); 25911 } 25912 } else if (!strcasecmp(v->name, "disallow")) { 25913 int error = ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, FALSE); 25914 if (error) { 25915 ast_log(LOG_WARNING, "Codec configuration errors found in line %d : %s = %s\n", v->lineno, v->name, v->value); 25916 } 25917 } else if (!strcasecmp(v->name, "preferred_codec_only")) { 25918 ast_set2_flag(&peer->flags[1], ast_true(v->value), SIP_PAGE2_PREFERRED_CODEC); 25919 } else if (!strcasecmp(v->name, "registertrying")) { 25920 ast_set2_flag(&peer->flags[1], ast_true(v->value), SIP_PAGE2_REGISTERTRYING); 25921 } else if (!strcasecmp(v->name, "autoframing")) { 25922 peer->autoframing = ast_true(v->value); 25923 } else if (!strcasecmp(v->name, "rtptimeout")) { 25924 if ((sscanf(v->value, "%30d", &peer->rtptimeout) != 1) || (peer->rtptimeout < 0)) { 25925 ast_log(LOG_WARNING, "'%s' is not a valid RTP hold time at line %d. Using default.\n", v->value, v->lineno); 25926 peer->rtptimeout = global_rtptimeout; 25927 } 25928 } else if (!strcasecmp(v->name, "rtpholdtimeout")) { 25929 if ((sscanf(v->value, "%30d", &peer->rtpholdtimeout) != 1) || (peer->rtpholdtimeout < 0)) { 25930 ast_log(LOG_WARNING, "'%s' is not a valid RTP hold time at line %d. Using default.\n", v->value, v->lineno); 25931 peer->rtpholdtimeout = global_rtpholdtimeout; 25932 } 25933 } else if (!strcasecmp(v->name, "rtpkeepalive")) { 25934 if ((sscanf(v->value, "%30d", &peer->rtpkeepalive) != 1) || (peer->rtpkeepalive < 0)) { 25935 ast_log(LOG_WARNING, "'%s' is not a valid RTP keepalive time at line %d. Using default.\n", v->value, v->lineno); 25936 peer->rtpkeepalive = global_rtpkeepalive; 25937 } 25938 } else if (!strcasecmp(v->name, "timert1")) { 25939 if ((sscanf(v->value, "%30d", &peer->timer_t1) != 1) || (peer->timer_t1 < 200) || (peer->timer_t1 < global_t1min)) { 25940 ast_log(LOG_WARNING, "'%s' is not a valid T1 time at line %d. Using default.\n", v->value, v->lineno); 25941 peer->timer_t1 = global_t1min; 25942 } 25943 timert1_set = 1; 25944 } else if (!strcasecmp(v->name, "timerb")) { 25945 if ((sscanf(v->value, "%30d", &peer->timer_b) != 1) || (peer->timer_b < 200)) { 25946 ast_log(LOG_WARNING, "'%s' is not a valid Timer B time at line %d. Using default.\n", v->value, v->lineno); 25947 peer->timer_b = global_timer_b; 25948 } 25949 timerb_set = 1; 25950 } else if (!strcasecmp(v->name, "setvar")) { 25951 peer->chanvars = add_var(v->value, peer->chanvars); 25952 } else if (!strcasecmp(v->name, "header")) { 25953 char tmp[4096]; 25954 snprintf(tmp, sizeof(tmp), "__SIPADDHEADERpre%2d=%s", ++headercount, v->value); 25955 peer->chanvars = add_var(tmp, peer->chanvars); 25956 } else if (!strcasecmp(v->name, "qualifyfreq")) { 25957 int i; 25958 if (sscanf(v->value, "%30d", &i) == 1) { 25959 peer->qualifyfreq = i * 1000; 25960 } else { 25961 ast_log(LOG_WARNING, "Invalid qualifyfreq number '%s' at line %d of %s\n", v->value, v->lineno, config); 25962 peer->qualifyfreq = global_qualifyfreq; 25963 } 25964 } else if (!strcasecmp(v->name, "maxcallbitrate")) { 25965 peer->maxcallbitrate = atoi(v->value); 25966 if (peer->maxcallbitrate < 0) { 25967 peer->maxcallbitrate = default_maxcallbitrate; 25968 } 25969 } else if (!strcasecmp(v->name, "session-timers")) { 25970 int i = (int) str2stmode(v->value); 25971 if (i < 0) { 25972 ast_log(LOG_WARNING, "Invalid session-timers '%s' at line %d of %s\n", v->value, v->lineno, config); 25973 peer->stimer.st_mode_oper = global_st_mode; 25974 } else { 25975 peer->stimer.st_mode_oper = i; 25976 } 25977 } else if (!strcasecmp(v->name, "session-expires")) { 25978 if (sscanf(v->value, "%30d", &peer->stimer.st_max_se) != 1) { 25979 ast_log(LOG_WARNING, "Invalid session-expires '%s' at line %d of %s\n", v->value, v->lineno, config); 25980 peer->stimer.st_max_se = global_max_se; 25981 } 25982 } else if (!strcasecmp(v->name, "session-minse")) { 25983 if (sscanf(v->value, "%30d", &peer->stimer.st_min_se) != 1) { 25984 ast_log(LOG_WARNING, "Invalid session-minse '%s' at line %d of %s\n", v->value, v->lineno, config); 25985 peer->stimer.st_min_se = global_min_se; 25986 } 25987 if (peer->stimer.st_min_se < 90) { 25988 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); 25989 peer->stimer.st_min_se = global_min_se; 25990 } 25991 } else if (!strcasecmp(v->name, "session-refresher")) { 25992 int i = (int) str2strefresher(v->value); 25993 if (i < 0) { 25994 ast_log(LOG_WARNING, "Invalid session-refresher '%s' at line %d of %s\n", v->value, v->lineno, config); 25995 peer->stimer.st_ref = global_st_refresher; 25996 } else { 25997 peer->stimer.st_ref = i; 25998 } 25999 } else if (!strcasecmp(v->name, "disallowed_methods")) { 26000 char *disallow = ast_strdupa(v->value); 26001 mark_parsed_methods(&peer->disallowed_methods, disallow); 26002 } else if (!strcasecmp(v->name, "unsolicited_mailbox")) { 26003 ast_string_field_set(peer, unsolicited_mailbox, v->value); 26004 } else if (!strcasecmp(v->name, "use_q850_reason")) { 26005 ast_set2_flag(&peer->flags[1], ast_true(v->value), SIP_PAGE2_Q850_REASON); 26006 } else if (!strcasecmp(v->name, "encryption")) { 26007 ast_set2_flag(&peer->flags[1], ast_true(v->value), SIP_PAGE2_USE_SRTP); 26008 } else if (!strcasecmp(v->name, "snom_aoc_enabled")) { 26009 ast_set2_flag(&peer->flags[2], ast_true(v->value), SIP_PAGE3_SNOM_AOC); 26010 } 26011 } 26012 26013 /* These apply to devstate lookups */ 26014 if (realtime && !strcasecmp(v->name, "lastms")) { 26015 sscanf(v->value, "%30d", &peer->lastms); 26016 } else if (realtime && !strcasecmp(v->name, "ipaddr") && !ast_strlen_zero(v->value) ) { 26017 ast_sockaddr_parse(&peer->addr, v->value, PARSE_PORT_FORBID); 26018 } else if (realtime && !strcasecmp(v->name, "fullcontact")) { 26019 if (alt_fullcontact && !alt) { 26020 /* Reset, because the alternate also has a fullcontact and we 26021 * do NOT want the field value to be doubled. It might be 26022 * tempting to skip this, but the first table might not have 26023 * fullcontact and since we're here, we know that the alternate 26024 * absolutely does. */ 26025 alt_fullcontact = 0; 26026 ast_str_reset(fullcontact); 26027 } 26028 /* Reconstruct field, because realtime separates our value at the ';' */ 26029 if (fullcontact->used > 0) { 26030 ast_str_append(&fullcontact, 0, ";%s", v->value); 26031 } else { 26032 ast_str_set(&fullcontact, 0, "%s", v->value); 26033 } 26034 } else if (!strcasecmp(v->name, "qualify")) { 26035 if (!strcasecmp(v->value, "no")) { 26036 peer->maxms = 0; 26037 } else if (!strcasecmp(v->value, "yes")) { 26038 peer->maxms = default_qualify ? default_qualify : DEFAULT_MAXMS; 26039 } else if (sscanf(v->value, "%30d", &peer->maxms) != 1) { 26040 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); 26041 peer->maxms = 0; 26042 } 26043 if (realtime && !ast_test_flag(&global_flags[1], SIP_PAGE2_RTCACHEFRIENDS) && peer->maxms > 0) { 26044 /* This would otherwise cause a network storm, where the 26045 * qualify response refreshes the peer from the database, 26046 * which in turn causes another qualify to be sent, ad 26047 * infinitum. */ 26048 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); 26049 peer->maxms = 0; 26050 } 26051 } else if (!strcasecmp(v->name, "callcounter")) { 26052 peer->call_limit = ast_true(v->value) ? INT_MAX : 0; 26053 } else if (!strcasecmp(v->name, "call-limit")) { 26054 peer->call_limit = atoi(v->value); 26055 if (peer->call_limit < 0) { 26056 peer->call_limit = 0; 26057 } 26058 } else if (!strcasecmp(v->name, "busylevel")) { 26059 peer->busy_level = atoi(v->value); 26060 if (peer->busy_level < 0) { 26061 peer->busy_level = 0; 26062 } 26063 } else if (ast_cc_is_config_param(v->name)) { 26064 ast_cc_set_param(peer->cc_params, v->name, v->value); 26065 } 26066 } 26067 26068 if (!devstate_only) { 26069 struct sip_mailbox *mailbox; 26070 AST_LIST_TRAVERSE_SAFE_BEGIN(&peer->mailboxes, mailbox, entry) { 26071 if (mailbox->delme) { 26072 AST_LIST_REMOVE_CURRENT(entry); 26073 destroy_mailbox(mailbox); 26074 } 26075 } 26076 AST_LIST_TRAVERSE_SAFE_END; 26077 } 26078 26079 if (!can_parse_xml && (ast_get_cc_agent_policy(peer->cc_params) == AST_CC_AGENT_NATIVE)) { 26080 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); 26081 ast_set_cc_agent_policy(peer->cc_params, AST_CC_AGENT_NEVER); 26082 } 26083 26084 /* Note that Timer B is dependent upon T1 and MUST NOT be lower 26085 * than T1 * 64, according to RFC 3261, Section 17.1.1.2 */ 26086 if (peer->timer_b < peer->timer_t1 * 64) { 26087 if (timerb_set && timert1_set) { 26088 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); 26089 } else if (timerb_set) { 26090 if ((peer->timer_t1 = peer->timer_b / 64) < global_t1min) { 26091 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); 26092 peer->timer_t1 = global_t1min; 26093 peer->timer_b = peer->timer_t1 * 64; 26094 } 26095 peer->timer_t1 = peer->timer_b / 64; 26096 } else { 26097 peer->timer_b = peer->timer_t1 * 64; 26098 } 26099 } 26100 26101 if (!peer->default_outbound_transport) { 26102 /* Set default set of transports */ 26103 peer->transports = default_transports; 26104 /* Set default primary transport */ 26105 peer->default_outbound_transport = default_primary_transport; 26106 } 26107 26108 /* The default transport type set during build_peer should only replace the socket.type when... 26109 * 1. Registration is not present and the socket.type and default transport types are different. 26110 * 2. The socket.type is not an acceptable transport type after rebuilding peer. 26111 * 3. The socket.type is not set yet. */ 26112 if (((peer->socket.type != peer->default_outbound_transport) && (peer->expire == -1)) || 26113 !(peer->socket.type & peer->transports) || !(peer->socket.type)) { 26114 26115 set_socket_transport(&peer->socket, peer->default_outbound_transport); 26116 } 26117 26118 if (ast_str_strlen(fullcontact)) { 26119 ast_string_field_set(peer, fullcontact, ast_str_buffer(fullcontact)); 26120 peer->rt_fromcontact = TRUE; 26121 /* We have a hostname in the fullcontact, but if we don't have an 26122 * address listed on the entry (or if it's 'dynamic'), then we need to 26123 * parse the entry to obtain the IP address, so a dynamic host can be 26124 * contacted immediately after reload (as opposed to waiting for it to 26125 * register once again). But if we have an address for this peer and NAT was 26126 * specified, use that address instead. */ 26127 /* XXX May need to revisit the final argument; does the realtime DB store whether 26128 * the original contact was over TLS or not? XXX */ 26129 if (!ast_test_flag(&peer->flags[0], SIP_NAT_RPORT_PRESENT) || ast_sockaddr_isnull(&peer->addr)) { 26130 __set_address_from_contact(fullcontact->str, &peer->addr, 0); 26131 } 26132 } 26133 26134 if (srvlookup && peer->dnsmgr == NULL) { 26135 char transport[MAXHOSTNAMELEN]; 26136 char _srvlookup[MAXHOSTNAMELEN]; 26137 char *params; 26138 26139 ast_copy_string(_srvlookup, srvlookup, sizeof(_srvlookup)); 26140 if ((params = strchr(_srvlookup, ';'))) { 26141 *params++ = '\0'; 26142 } 26143 26144 snprintf(transport, sizeof(transport), "_%s._%s", get_srv_service(peer->socket.type), get_srv_protocol(peer->socket.type)); 26145 26146 peer->addr.ss.ss_family = get_address_family_filter(&bindaddr); /* Filter address family */ 26147 if (ast_dnsmgr_lookup(_srvlookup, &peer->addr, &peer->dnsmgr, sip_cfg.srvlookup && !peer->portinuri ? transport : NULL)) { 26148 ast_log(LOG_ERROR, "srvlookup failed for host: %s, on peer %s, removing peer\n", _srvlookup, peer->name); 26149 unref_peer(peer, "getting rid of a peer pointer"); 26150 return NULL; 26151 } 26152 26153 ast_string_field_set(peer, tohost, peer->dnsmgr ? srvlookup : 26154 ast_sockaddr_stringify_host(&peer->addr)); 26155 26156 if (global_dynamic_exclude_static) { 26157 int err = 0; 26158 sip_cfg.contact_ha = ast_append_ha("deny", ast_sockaddr_stringify_addr(&peer->addr), 26159 sip_cfg.contact_ha, &err); 26160 if (err) { 26161 ast_log(LOG_ERROR, "Bad ACL entry in configuration line %d : %s\n", v->lineno, v->value); 26162 } 26163 } 26164 } 26165 26166 if (port && !realtime && peer->host_dynamic) { 26167 ast_sockaddr_set_port(&peer->defaddr, port); 26168 } else if (port) { 26169 ast_sockaddr_set_port(&peer->addr, port); 26170 } 26171 26172 if (ast_sockaddr_port(&peer->addr) == 0) { 26173 ast_sockaddr_set_port(&peer->addr, 26174 (peer->socket.type & SIP_TRANSPORT_TLS) ? 26175 STANDARD_TLS_PORT : STANDARD_SIP_PORT); 26176 } 26177 if (ast_sockaddr_port(&peer->defaddr) == 0) { 26178 ast_sockaddr_set_port(&peer->defaddr, 26179 (peer->socket.type & SIP_TRANSPORT_TLS) ? 26180 STANDARD_TLS_PORT : STANDARD_SIP_PORT); 26181 } 26182 if (!peer->socket.port) { 26183 peer->socket.port = htons(((peer->socket.type & SIP_TRANSPORT_TLS) ? STANDARD_TLS_PORT : STANDARD_SIP_PORT)); 26184 } 26185 26186 if (!sip_cfg.ignore_regexpire && peer->host_dynamic && realtime) { 26187 time_t nowtime = time(NULL); 26188 26189 if ((nowtime - regseconds) > 0) { 26190 destroy_association(peer); 26191 memset(&peer->addr, 0, sizeof(peer->addr)); 26192 peer->lastms = -1; 26193 ast_debug(1, "Bah, we're expired (%d/%d/%d)!\n", (int)(nowtime - regseconds), (int)regseconds, (int)nowtime); 26194 } 26195 } 26196 26197 /* Startup regular pokes */ 26198 if (!devstate_only && realtime && peer->lastms > 0) { 26199 ref_peer(peer, "schedule qualify"); 26200 sip_poke_peer(peer, 0); 26201 } 26202 26203 ast_copy_flags(&peer->flags[0], &peerflags[0], mask[0].flags); 26204 ast_copy_flags(&peer->flags[1], &peerflags[1], mask[1].flags); 26205 ast_copy_flags(&peer->flags[2], &peerflags[2], mask[2].flags); 26206 if (ast_test_flag(&peer->flags[1], SIP_PAGE2_ALLOWSUBSCRIBE)) { 26207 sip_cfg.allowsubscribe = TRUE; /* No global ban any more */ 26208 } 26209 if (peer->host_dynamic && !peer->is_realtime) { 26210 reg_source_db(peer); 26211 } 26212 26213 /* If they didn't request that MWI is sent *only* on subscribe, go ahead and 26214 * subscribe to it now. */ 26215 if (!devstate_only && !ast_test_flag(&peer->flags[1], SIP_PAGE2_SUBSCRIBEMWIONLY) && 26216 !AST_LIST_EMPTY(&peer->mailboxes)) { 26217 add_peer_mwi_subs(peer); 26218 /* Send MWI from the event cache only. This is so we can send initial 26219 * MWI if app_voicemail got loaded before chan_sip. If it is the other 26220 * way, then we will get events when app_voicemail gets loaded. */ 26221 sip_send_mwi_to_peer(peer, NULL, 1); 26222 } 26223 26224 peer->the_mark = 0; 26225 26226 ast_free_ha(oldha); 26227 ast_free_ha(olddirectmediaha); 26228 if (!ast_strlen_zero(callback)) { /* build string from peer info */ 26229 char *reg_string; 26230 if (asprintf(®_string, "%s?%s:%s@%s/%s", peer->name, peer->username, !ast_strlen_zero(peer->remotesecret) ? peer->remotesecret : peer->secret, peer->tohost, callback) < 0) { 26231 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno)); 26232 } else if (reg_string) { 26233 sip_register(reg_string, 0); /* XXX TODO: count in registry_count */ 26234 ast_free(reg_string); 26235 } 26236 } 26237 return peer; 26238 }
| static int build_reply_digest | ( | struct sip_pvt * | p, | |
| int | method, | |||
| char * | digest, | |||
| int | digest_len | |||
| ) | [static] |
Build reply digest.
Definition at line 18017 of file chan_sip.c.
References append_history, ast_copy_string(), ast_debug, ast_md5_hash(), ast_random(), ast_sockaddr_stringify_host(), ast_strlen_zero(), find_realm_authentication(), secret, sip_methods, and text.
Referenced by reply_digest(), transmit_register(), and transmit_request_with_auth().
18018 { 18019 char a1[256]; 18020 char a2[256]; 18021 char a1_hash[256]; 18022 char a2_hash[256]; 18023 char resp[256]; 18024 char resp_hash[256]; 18025 char uri[256]; 18026 char opaque[256] = ""; 18027 char cnonce[80]; 18028 const char *username; 18029 const char *secret; 18030 const char *md5secret; 18031 struct sip_auth *auth = NULL; /* Realm authentication */ 18032 18033 if (!ast_strlen_zero(p->domain)) 18034 ast_copy_string(uri, p->domain, sizeof(uri)); 18035 else if (!ast_strlen_zero(p->uri)) 18036 ast_copy_string(uri, p->uri, sizeof(uri)); 18037 else 18038 snprintf(uri, sizeof(uri), "sip:%s@%s", p->username, ast_sockaddr_stringify_host(&p->sa)); 18039 18040 snprintf(cnonce, sizeof(cnonce), "%08lx", ast_random()); 18041 18042 /* Check if we have separate auth credentials */ 18043 if(!(auth = find_realm_authentication(p->peerauth, p->realm))) /* Start with peer list */ 18044 auth = find_realm_authentication(authl, p->realm); /* If not, global list */ 18045 18046 if (auth) { 18047 ast_debug(3, "use realm [%s] from peer [%s][%s]\n", auth->username, p->peername, p->username); 18048 username = auth->username; 18049 secret = auth->secret; 18050 md5secret = auth->md5secret; 18051 if (sipdebug) 18052 ast_debug(1, "Using realm %s authentication for call %s\n", p->realm, p->callid); 18053 } else { 18054 /* No authentication, use peer or register= config */ 18055 username = p->authname; 18056 secret = p->peersecret; 18057 md5secret = p->peermd5secret; 18058 } 18059 if (ast_strlen_zero(username)) /* We have no authentication */ 18060 return -1; 18061 18062 /* Calculate SIP digest response */ 18063 snprintf(a1, sizeof(a1), "%s:%s:%s", username, p->realm, secret); 18064 snprintf(a2, sizeof(a2), "%s:%s", sip_methods[method].text, uri); 18065 if (!ast_strlen_zero(md5secret)) 18066 ast_copy_string(a1_hash, md5secret, sizeof(a1_hash)); 18067 else 18068 ast_md5_hash(a1_hash, a1); 18069 ast_md5_hash(a2_hash, a2); 18070 18071 p->noncecount++; 18072 if (!ast_strlen_zero(p->qop)) 18073 snprintf(resp, sizeof(resp), "%s:%s:%08x:%s:%s:%s", a1_hash, p->nonce, p->noncecount, cnonce, "auth", a2_hash); 18074 else 18075 snprintf(resp, sizeof(resp), "%s:%s:%s", a1_hash, p->nonce, a2_hash); 18076 ast_md5_hash(resp_hash, resp); 18077 18078 /* only include the opaque string if it's set */ 18079 if (!ast_strlen_zero(p->opaque)) { 18080 snprintf(opaque, sizeof(opaque), ", opaque=\"%s\"", p->opaque); 18081 } 18082 18083 /* XXX We hard code our qop to "auth" for now. XXX */ 18084 if (!ast_strlen_zero(p->qop)) 18085 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); 18086 else 18087 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); 18088 18089 append_history(p, "AuthResp", "Auth response sent for %s in realm %s - nc %d", username, p->realm, p->noncecount); 18090 18091 return 0; 18092 }
| 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 13123 of file chan_sip.c.
References __get_header(), ast_copy_string(), ast_debug, ast_malloc, ast_strlen_zero(), free_old_route(), get_header(), len(), list_route(), and sip_debug_test_pvt().
Referenced by build_profile(), build_user_routes(), handle_request_invite(), handle_request_subscribe(), and handle_response_invite().
13124 { 13125 struct sip_route *thishop, *head, *tail; 13126 int start = 0; 13127 int len; 13128 const char *rr, *contact, *c; 13129 13130 /* Once a persistent route is set, don't fool with it */ 13131 if (p->route && p->route_persistent) { 13132 ast_debug(1, "build_route: Retaining previous route: <%s>\n", p->route->hop); 13133 return; 13134 } 13135 13136 if (p->route) { 13137 free_old_route(p->route); 13138 p->route = NULL; 13139 } 13140 13141 /* We only want to create the route set the first time this is called */ 13142 p->route_persistent = 1; 13143 13144 /* Build a tailq, then assign it to p->route when done. 13145 * If backwards, we add entries from the head so they end up 13146 * in reverse order. However, we do need to maintain a correct 13147 * tail pointer because the contact is always at the end. 13148 */ 13149 head = NULL; 13150 tail = head; 13151 /* 1st we pass through all the hops in any Record-Route headers */ 13152 for (;;) { 13153 /* Each Record-Route header */ 13154 rr = __get_header(req, "Record-Route", &start); 13155 if (*rr == '\0') { 13156 break; 13157 } 13158 for (; (rr = strchr(rr, '<')) ; rr += len) { /* Each route entry */ 13159 ++rr; 13160 len = strcspn(rr, ">") + 1; 13161 /* Make a struct route */ 13162 if ((thishop = ast_malloc(sizeof(*thishop) + len))) { 13163 /* ast_calloc is not needed because all fields are initialized in this block */ 13164 ast_copy_string(thishop->hop, rr, len); 13165 ast_debug(2, "build_route: Record-Route hop: <%s>\n", thishop->hop); 13166 /* Link in */ 13167 if (backwards) { 13168 /* Link in at head so they end up in reverse order */ 13169 thishop->next = head; 13170 head = thishop; 13171 /* If this was the first then it'll be the tail */ 13172 if (!tail) { 13173 tail = thishop; 13174 } 13175 } else { 13176 thishop->next = NULL; 13177 /* Link in at the end */ 13178 if (tail) { 13179 tail->next = thishop; 13180 } else { 13181 head = thishop; 13182 } 13183 tail = thishop; 13184 } 13185 } 13186 } 13187 } 13188 13189 /* Only append the contact if we are dealing with a strict router */ 13190 if (!head || (!ast_strlen_zero(head->hop) && strstr(head->hop, ";lr") == NULL) ) { 13191 /* 2nd append the Contact: if there is one */ 13192 /* Can be multiple Contact headers, comma separated values - we just take the first */ 13193 contact = get_header(req, "Contact"); 13194 if (!ast_strlen_zero(contact)) { 13195 ast_debug(2, "build_route: Contact hop: %s\n", contact); 13196 /* Look for <: delimited address */ 13197 c = strchr(contact, '<'); 13198 if (c) { 13199 /* Take to > */ 13200 ++c; 13201 len = strcspn(c, ">") + 1; 13202 } else { 13203 /* No <> - just take the lot */ 13204 c = contact; 13205 len = strlen(contact) + 1; 13206 } 13207 if ((thishop = ast_malloc(sizeof(*thishop) + len))) { 13208 /* ast_calloc is not needed because all fields are initialized in this block */ 13209 ast_copy_string(thishop->hop, c, len); 13210 thishop->next = NULL; 13211 /* Goes at the end */ 13212 if (tail) { 13213 tail->next = thishop; 13214 } else { 13215 head = thishop; 13216 } 13217 } 13218 } 13219 } 13220 13221 /* Store as new route */ 13222 p->route = head; 13223 13224 /* For debugging dump what we ended up with */ 13225 if (sip_debug_test_pvt(p)) { 13226 list_route(p->route); 13227 } 13228 }
| static void build_via | ( | struct sip_pvt * | p | ) | [static] |
Build a Via header for a request.
Definition at line 3119 of file chan_sip.c.
References ast_sockaddr_stringify(), 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().
03120 { 03121 /* Work around buggy UNIDEN UIP200 firmware */ 03122 const char *rport = (ast_test_flag(&p->flags[0], SIP_NAT_FORCE_RPORT) || ast_test_flag(&p->flags[0], SIP_NAT_RPORT_PRESENT)) ? ";rport" : ""; 03123 03124 /* z9hG4bK is a magic cookie. See RFC 3261 section 8.1.1.7 */ 03125 snprintf(p->via, sizeof(p->via), "SIP/2.0/%s %s;branch=z9hG4bK%08x%s", 03126 get_transport_pvt(p), 03127 ast_sockaddr_stringify(&p->ourip), 03128 (int) p->branch, rport); 03129 }
| static int cb_extensionstate | ( | char * | context, | |
| char * | exten, | |||
| int | state, | |||
| void * | data | |||
| ) | [static] |
Callback for the devicestate notification (SUBSCRIBE) support subsystem.
Definition at line 13498 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 handle_request_subscribe(), handle_response(), and handle_response_notify().
13499 { 13500 struct sip_pvt *p = data; 13501 13502 sip_pvt_lock(p); 13503 13504 switch(state) { 13505 case AST_EXTENSION_DEACTIVATED: /* Retry after a while */ 13506 case AST_EXTENSION_REMOVED: /* Extension is gone */ 13507 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); /* Delete subscription in 32 secs */ 13508 ast_verb(2, "Extension state: Watcher for hint %s %s. Notify User %s\n", exten, state == AST_EXTENSION_DEACTIVATED ? "deactivated" : "removed", p->username); 13509 p->stateid = -1; 13510 p->subscribed = NONE; 13511 append_history(p, "Subscribestatus", "%s", state == AST_EXTENSION_REMOVED ? "HintRemoved" : "Deactivated"); 13512 break; 13513 default: /* Tell user */ 13514 p->laststate = state; 13515 break; 13516 } 13517 if (p->subscribed != NONE) { /* Only send state NOTIFY if we know the format */ 13518 if (!p->pendinginvite) { 13519 transmit_state_notify(p, state, 1, FALSE); 13520 } else { 13521 /* We already have a NOTIFY sent that is not answered. Queue the state up. 13522 if many state changes happen meanwhile, we will only send a notification of the last one */ 13523 ast_set_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE); 13524 } 13525 } 13526 ast_verb(2, "Extension Changed %s[%s] new state %s for Notify User %s %s\n", exten, context, ast_extension_state2str(state), p->username, 13527 ast_test_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE) ? "(queued)" : ""); 13528 13529 sip_pvt_unlock(p); 13530 13531 return 0; 13532 }
| static void cc_epa_destructor | ( | void * | data | ) | [static] |
Definition at line 872 of file chan_sip.c.
References ast_free.
00873 { 00874 struct sip_epa_entry *epa_entry = data; 00875 struct cc_epa_entry *cc_entry = epa_entry->instance_data; 00876 ast_free(cc_entry); 00877 }
| 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 18602 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(), get_header(), LOG_WARNING, and transmit_invite().
18603 { 18604 struct cc_epa_entry *cc_entry = epa_entry->instance_data; 18605 struct sip_monitor_instance *monitor_instance = ao2_callback(sip_monitor_instances, 0, 18606 find_sip_monitor_instance_by_suspension_entry, epa_entry); 18607 const char *min_expires; 18608 18609 if (!monitor_instance) { 18610 ast_log(LOG_WARNING, "Can't find monitor_instance corresponding to epa_entry %p.\n", epa_entry); 18611 return; 18612 } 18613 18614 if (resp != 423) { 18615 ast_cc_monitor_failed(cc_entry->core_id, monitor_instance->device_name, 18616 "Received error response to our PUBLISH"); 18617 ao2_ref(monitor_instance, -1); 18618 return; 18619 } 18620 18621 /* Allrighty, the other end doesn't like our Expires value. They think it's 18622 * too small, so let's see if they've provided a more sensible value. If they 18623 * haven't, then we'll just double our Expires value and see if they like that 18624 * instead. 18625 * 18626 * XXX Ideally this logic could be placed into its own function so that SUBSCRIBE, 18627 * PUBLISH, and REGISTER could all benefit from the same shared code. 18628 */ 18629 min_expires = get_header(req, "Min-Expires"); 18630 if (ast_strlen_zero(min_expires)) { 18631 pvt->expiry *= 2; 18632 if (pvt->expiry < 0) { 18633 /* You dork! You overflowed! */ 18634 ast_cc_monitor_failed(cc_entry->core_id, monitor_instance->device_name, 18635 "PUBLISH expiry overflowed"); 18636 ao2_ref(monitor_instance, -1); 18637 return; 18638 } 18639 } else if (sscanf(min_expires, "%d", &pvt->expiry) != 1) { 18640 ast_cc_monitor_failed(cc_entry->core_id, monitor_instance->device_name, 18641 "Min-Expires has non-numeric value"); 18642 ao2_ref(monitor_instance, -1); 18643 return; 18644 } 18645 /* At this point, we have most certainly changed pvt->expiry, so try transmitting 18646 * again 18647 */ 18648 transmit_invite(pvt, SIP_PUBLISH, FALSE, 0, NULL); 18649 ao2_ref(monitor_instance, -1); 18650 }
| 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 18340 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_header(), 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, 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().
18343 { 18344 char *redirecting_from_name = NULL; 18345 char *redirecting_from_number = NULL; 18346 char *redirecting_to_name = NULL; 18347 char *redirecting_to_number = NULL; 18348 int reason = AST_REDIRECTING_REASON_UNCONDITIONAL; 18349 int is_response = req->method == SIP_RESPONSE; 18350 int res = 0; 18351 18352 res = get_rdnis(p, req, &redirecting_from_name, &redirecting_from_number, &reason); 18353 if (res == -1) { 18354 if (is_response) { 18355 get_name_and_number(get_header(req, "TO"), &redirecting_from_name, &redirecting_from_number); 18356 } else { 18357 return; 18358 } 18359 } 18360 18361 /* At this point, all redirecting "from" info should be filled in appropriately 18362 * on to the "to" info 18363 */ 18364 18365 if (is_response) { 18366 parse_moved_contact(p, req, &redirecting_to_name, &redirecting_to_number, set_call_forward); 18367 } else { 18368 get_name_and_number(get_header(req, "TO"), &redirecting_to_name, &redirecting_to_number); 18369 } 18370 18371 if (!ast_strlen_zero(redirecting_from_number)) { 18372 ast_debug(3, "Got redirecting from number %s\n", redirecting_from_number); 18373 update_redirecting->from.number = 1; 18374 redirecting->from.number.valid = 1; 18375 ast_free(redirecting->from.number.str); 18376 redirecting->from.number.str = redirecting_from_number; 18377 } 18378 if (!ast_strlen_zero(redirecting_from_name)) { 18379 ast_debug(3, "Got redirecting from name %s\n", redirecting_from_name); 18380 update_redirecting->from.name = 1; 18381 redirecting->from.name.valid = 1; 18382 ast_free(redirecting->from.name.str); 18383 redirecting->from.name.str = redirecting_from_name; 18384 } 18385 if (!ast_strlen_zero(p->cid_tag)) { 18386 ast_free(redirecting->from.tag); 18387 redirecting->from.tag = ast_strdup(p->cid_tag); 18388 ast_free(redirecting->to.tag); 18389 redirecting->to.tag = ast_strdup(p->cid_tag); 18390 } 18391 if (!ast_strlen_zero(redirecting_to_number)) { 18392 ast_debug(3, "Got redirecting to number %s\n", redirecting_to_number); 18393 update_redirecting->to.number = 1; 18394 redirecting->to.number.valid = 1; 18395 ast_free(redirecting->to.number.str); 18396 redirecting->to.number.str = redirecting_to_number; 18397 } 18398 if (!ast_strlen_zero(redirecting_to_name)) { 18399 ast_debug(3, "Got redirecting to name %s\n", redirecting_from_number); 18400 update_redirecting->to.name = 1; 18401 redirecting->to.name.valid = 1; 18402 ast_free(redirecting->to.name.str); 18403 redirecting->to.name.str = redirecting_to_name; 18404 } 18405 redirecting->reason = reason; 18406 }
| static void change_t38_state | ( | struct sip_pvt * | p, | |
| int | state | |||
| ) | [static] |
Change the T38 state on a SIP dialog.
Definition at line 4669 of file chan_sip.c.
References 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, ast_channel::name, and ast_control_t38_parameters::request_response.
Referenced by handle_response_invite(), interpret_t38_parameters(), process_sdp(), and sip_t38_abort().
04670 { 04671 int old = p->t38.state; 04672 struct ast_channel *chan = p->owner; 04673 struct ast_control_t38_parameters parameters = { .request_response = 0 }; 04674 04675 /* Don't bother changing if we are already in the state wanted */ 04676 if (old == state) 04677 return; 04678 04679 p->t38.state = state; 04680 ast_debug(2, "T38 state changed to %d on channel %s\n", p->t38.state, chan ? chan->name : "<none>"); 04681 04682 /* If no channel was provided we can't send off a control frame */ 04683 if (!chan) 04684 return; 04685 04686 /* Given the state requested and old state determine what control frame we want to queue up */ 04687 switch (state) { 04688 case T38_PEER_REINVITE: 04689 parameters = p->t38.their_parms; 04690 parameters.max_ifp = ast_udptl_get_far_max_ifp(p->udptl); 04691 parameters.request_response = AST_T38_REQUEST_NEGOTIATE; 04692 ast_udptl_set_tag(p->udptl, "SIP/%s", p->username); 04693 break; 04694 case T38_ENABLED: 04695 parameters = p->t38.their_parms; 04696 parameters.max_ifp = ast_udptl_get_far_max_ifp(p->udptl); 04697 parameters.request_response = AST_T38_NEGOTIATED; 04698 ast_udptl_set_tag(p->udptl, "SIP/%s", p->username); 04699 break; 04700 case T38_DISABLED: 04701 if (old == T38_ENABLED) { 04702 parameters.request_response = AST_T38_TERMINATED; 04703 } else if (old == T38_LOCAL_REINVITE) { 04704 parameters.request_response = AST_T38_REFUSED; 04705 } 04706 break; 04707 case T38_LOCAL_REINVITE: 04708 /* wait until we get a peer response before responding to local reinvite */ 04709 break; 04710 } 04711 04712 /* Woot we got a message, create a control frame and send it on! */ 04713 if (parameters.request_response) 04714 ast_queue_control_data(chan, AST_CONTROL_T38_PARAMETERS, ¶meters, sizeof(parameters)); 04715 }
| 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 13252 of file chan_sip.c.
References append_history, ast_copy_string(), AST_DYNSTR_BUILD_FAILED, ast_log(), ast_md5_hash(), ast_skip_blanks(), ast_str_set(), ast_str_thread_get(), ast_strlen_zero(), auth_headers(), check_auth_buf, CHECK_AUTH_BUF_INITLEN, FALSE, get_header(), LOG_NOTICE, LOG_WARNING, S_OR, set_nonce_randdata(), sip_methods, sip_scheddestroy(), strsep(), text, transmit_response_with_auth(), and TRUE.
Referenced by check_peer_ok(), and register_verify().
13255 { 13256 const char *response; 13257 char *reqheader, *respheader; 13258 const char *authtoken; 13259 char a1_hash[256]; 13260 char resp_hash[256]=""; 13261 char *c; 13262 int wrongnonce = FALSE; 13263 int good_response; 13264 const char *usednonce = p->randdata; 13265 struct ast_str *buf; 13266 int res; 13267 13268 /* table of recognised keywords, and their value in the digest */ 13269 enum keys { K_RESP, K_URI, K_USER, K_NONCE, K_LAST }; 13270 struct x { 13271 const char *key; 13272 const char *s; 13273 } *i, keys[] = { 13274 [K_RESP] = { "response=", "" }, 13275 [K_URI] = { "uri=", "" }, 13276 [K_USER] = { "username=", "" }, 13277 [K_NONCE] = { "nonce=", "" }, 13278 [K_LAST] = { NULL, NULL} 13279 }; 13280 13281 /* Always OK if no secret */ 13282 if (ast_strlen_zero(secret) && ast_strlen_zero(md5secret)) 13283 return AUTH_SUCCESSFUL; 13284 13285 /* Always auth with WWW-auth since we're NOT a proxy */ 13286 /* Using proxy-auth in a B2BUA may block proxy authorization in the same transaction */ 13287 response = "401 Unauthorized"; 13288 13289 /* 13290 * Note the apparent swap of arguments below, compared to other 13291 * usages of auth_headers(). 13292 */ 13293 auth_headers(WWW_AUTH, &respheader, &reqheader); 13294 13295 authtoken = get_header(req, reqheader); 13296 if (ignore && !ast_strlen_zero(p->randdata) && ast_strlen_zero(authtoken)) { 13297 /* This is a retransmitted invite/register/etc, don't reconstruct authentication 13298 information */ 13299 if (!reliable) { 13300 /* Resend message if this was NOT a reliable delivery. Otherwise the 13301 retransmission should get it */ 13302 transmit_response_with_auth(p, response, req, p->randdata, reliable, respheader, 0); 13303 /* Schedule auto destroy in 32 seconds (according to RFC 3261) */ 13304 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 13305 } 13306 return AUTH_CHALLENGE_SENT; 13307 } else if (ast_strlen_zero(p->randdata) || ast_strlen_zero(authtoken)) { 13308 /* We have no auth, so issue challenge and request authentication */ 13309 set_nonce_randdata(p, 1); /* Create nonce for challenge */ 13310 transmit_response_with_auth(p, response, req, p->randdata, reliable, respheader, 0); 13311 /* Schedule auto destroy in 32 seconds */ 13312 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 13313 return AUTH_CHALLENGE_SENT; 13314 } 13315 13316 /* --- We have auth, so check it */ 13317 13318 /* Whoever came up with the authentication section of SIP can suck my %&#$&* for not putting 13319 an example in the spec of just what it is you're doing a hash on. */ 13320 13321 if (!(buf = ast_str_thread_get(&check_auth_buf, CHECK_AUTH_BUF_INITLEN))) { 13322 return AUTH_SECRET_FAILED; /*! XXX \todo need a better return code here */ 13323 } 13324 13325 /* Make a copy of the response and parse it */ 13326 res = ast_str_set(&buf, 0, "%s", authtoken); 13327 13328 if (res == AST_DYNSTR_BUILD_FAILED) { 13329 return AUTH_SECRET_FAILED; /*! XXX \todo need a better return code here */ 13330 } 13331 13332 c = buf->str; 13333 13334 while(c && *(c = ast_skip_blanks(c)) ) { /* lookup for keys */ 13335 for (i = keys; i->key != NULL; i++) { 13336 const char *separator = ","; /* default */ 13337 13338 if (strncasecmp(c, i->key, strlen(i->key)) != 0) { 13339 continue; 13340 } 13341 /* Found. Skip keyword, take text in quotes or up to the separator. */ 13342 c += strlen(i->key); 13343 if (*c == '"') { /* in quotes. Skip first and look for last */ 13344 c++; 13345 separator = "\""; 13346 } 13347 i->s = c; 13348 strsep(&c, separator); 13349 break; 13350 } 13351 if (i->key == NULL) { /* not found, jump after space or comma */ 13352 strsep(&c, " ,"); 13353 } 13354 } 13355 13356 /* Verify that digest username matches the username we auth as */ 13357 if (strcmp(username, keys[K_USER].s)) { 13358 ast_log(LOG_WARNING, "username mismatch, have <%s>, digest has <%s>\n", 13359 username, keys[K_USER].s); 13360 /* Oops, we're trying something here */ 13361 return AUTH_USERNAME_MISMATCH; 13362 } 13363 13364 /* Verify nonce from request matches our nonce, and the nonce has not already been responded to. 13365 * If this check fails, send 401 with new nonce */ 13366 if (strcasecmp(p->randdata, keys[K_NONCE].s) || p->stalenonce) { /* XXX it was 'n'casecmp ? */ 13367 wrongnonce = TRUE; 13368 usednonce = keys[K_NONCE].s; 13369 } else { 13370 p->stalenonce = 1; /* now, since the nonce has a response, mark it as stale so it can't be sent or responded to again */ 13371 } 13372 13373 if (!ast_strlen_zero(md5secret)) { 13374 ast_copy_string(a1_hash, md5secret, sizeof(a1_hash)); 13375 } else { 13376 char a1[256]; 13377 13378 snprintf(a1, sizeof(a1), "%s:%s:%s", username, p->realm, secret); 13379 ast_md5_hash(a1_hash, a1); 13380 } 13381 13382 /* compute the expected response to compare with what we received */ 13383 { 13384 char a2[256]; 13385 char a2_hash[256]; 13386 char resp[256]; 13387 13388 snprintf(a2, sizeof(a2), "%s:%s", sip_methods[sipmethod].text, 13389 S_OR(keys[K_URI].s, uri)); 13390 ast_md5_hash(a2_hash, a2); 13391 snprintf(resp, sizeof(resp), "%s:%s:%s", a1_hash, usednonce, a2_hash); 13392 ast_md5_hash(resp_hash, resp); 13393 } 13394 13395 good_response = keys[K_RESP].s && 13396 !strncasecmp(keys[K_RESP].s, resp_hash, strlen(resp_hash)); 13397 if (wrongnonce) { 13398 if (good_response) { 13399 if (sipdebug) 13400 ast_log(LOG_NOTICE, "Correct auth, but based on stale nonce received from '%s'\n", get_header(req, "From")); 13401 /* We got working auth token, based on stale nonce . */ 13402 set_nonce_randdata(p, 0); 13403 transmit_response_with_auth(p, response, req, p->randdata, reliable, respheader, TRUE); 13404 } else { 13405 /* Everything was wrong, so give the device one more try with a new challenge */ 13406 if (!req->ignore) { 13407 if (sipdebug) { 13408 ast_log(LOG_NOTICE, "Bad authentication received from '%s'\n", get_header(req, "To")); 13409 } 13410 set_nonce_randdata(p, 1); 13411 } else { 13412 if (sipdebug) { 13413 ast_log(LOG_NOTICE, "Duplicate authentication received from '%s'\n", get_header(req, "To")); 13414 } 13415 } 13416 transmit_response_with_auth(p, response, req, p->randdata, reliable, respheader, FALSE); 13417 } 13418 13419 /* Schedule auto destroy in 32 seconds */ 13420 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 13421 return AUTH_CHALLENGE_SENT; 13422 } 13423 if (good_response) { 13424 append_history(p, "AuthOK", "Auth challenge successful for %s", username); 13425 return AUTH_SUCCESSFUL; 13426 } 13427 13428 /* Ok, we have a bad username/secret pair */ 13429 /* Tell the UAS not to re-send this authentication data, because 13430 it will continue to fail 13431 */ 13432 13433 return AUTH_SECRET_FAILED; 13434 }
| 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 14800 of file chan_sip.c.
References accountcode, ao2_t_ref, ast_apply_ha(), ast_cc_copy_config_params(), ast_copy_flags, ast_debug, 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_verbose, check_auth(), cid_name, cid_num, context, copy_vars(), debug, dialog_initialize_rtp(), do_setnat(), FALSE, find_peer(), get_rpid(), language, mohinterpret, mohsuggest, parkinglot, set_pvt_allowed_methods(), set_t38_capabilities(), sip_debug_test_addr(), TRUE, and unref_peer().
Referenced by check_user_full().
14804 { 14805 enum check_auth_result res; 14806 int debug = sip_debug_test_addr(addr); 14807 struct sip_peer *peer; 14808 14809 if (sipmethod == SIP_SUBSCRIBE) { 14810 /* For subscribes, match on device name only; for other methods, 14811 * match on IP address-port of the incoming request. 14812 */ 14813 peer = find_peer(of, NULL, TRUE, FINDALLDEVICES, FALSE, 0); 14814 } else { 14815 /* First find devices based on username (avoid all type=peer's) */ 14816 peer = find_peer(of, NULL, TRUE, FINDUSERS, FALSE, 0); 14817 14818 /* Then find devices based on IP */ 14819 if (!peer) { 14820 peer = find_peer(NULL, &p->recv, TRUE, FINDPEERS, FALSE, p->socket.type); 14821 } 14822 } 14823 14824 if (!peer) { 14825 if (debug) { 14826 ast_verbose("No matching peer for '%s' from '%s'\n", 14827 of, ast_sockaddr_stringify(&p->recv)); 14828 } 14829 return AUTH_DONT_KNOW; 14830 } 14831 14832 if (!ast_apply_ha(peer->ha, addr)) { 14833 ast_debug(2, "Found peer '%s' for '%s', but fails host access\n", peer->name, of); 14834 unref_peer(peer, "unref_peer: check_peer_ok: from find_peer call, early return of AUTH_ACL_FAILED"); 14835 return AUTH_ACL_FAILED; 14836 } 14837 if (debug) 14838 ast_verbose("Found peer '%s' for '%s' from %s\n", 14839 peer->name, of, ast_sockaddr_stringify(&p->recv)); 14840 14841 /* XXX what about p->prefs = peer->prefs; ? */ 14842 /* Set Frame packetization */ 14843 if (p->rtp) { 14844 ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(p->rtp), p->rtp, &peer->prefs); 14845 p->autoframing = peer->autoframing; 14846 } 14847 14848 /* Take the peer */ 14849 ast_copy_flags(&p->flags[0], &peer->flags[0], SIP_FLAGS_TO_COPY); 14850 ast_copy_flags(&p->flags[1], &peer->flags[1], SIP_PAGE2_FLAGS_TO_COPY); 14851 ast_copy_flags(&p->flags[2], &peer->flags[2], SIP_PAGE3_FLAGS_TO_COPY); 14852 14853 if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT) && p->udptl) { 14854 p->t38_maxdatagram = peer->t38_maxdatagram; 14855 set_t38_capabilities(p); 14856 } 14857 14858 /* Copy SIP extensions profile to peer */ 14859 /* XXX is this correct before a successful auth ? */ 14860 if (p->sipoptions) 14861 peer->sipoptions = p->sipoptions; 14862 14863 do_setnat(p); 14864 14865 ast_string_field_set(p, peersecret, peer->secret); 14866 ast_string_field_set(p, peermd5secret, peer->md5secret); 14867 ast_string_field_set(p, subscribecontext, peer->subscribecontext); 14868 ast_string_field_set(p, mohinterpret, peer->mohinterpret); 14869 ast_string_field_set(p, mohsuggest, peer->mohsuggest); 14870 ast_string_field_set(p, parkinglot, peer->parkinglot); 14871 ast_string_field_set(p, engine, peer->engine); 14872 p->disallowed_methods = peer->disallowed_methods; 14873 set_pvt_allowed_methods(p, req); 14874 ast_cc_copy_config_params(p->cc_params, peer->cc_params); 14875 if (peer->callingpres) /* Peer calling pres setting will override RPID */ 14876 p->callingpres = peer->callingpres; 14877 if (peer->maxms && peer->lastms) 14878 p->timer_t1 = peer->lastms < global_t1min ? global_t1min : peer->lastms; 14879 else 14880 p->timer_t1 = peer->timer_t1; 14881 14882 /* Set timer B to control transaction timeouts */ 14883 if (peer->timer_b) 14884 p->timer_b = peer->timer_b; 14885 else 14886 p->timer_b = 64 * p->timer_t1; 14887 14888 if (ast_test_flag(&peer->flags[0], SIP_INSECURE_INVITE)) { 14889 /* Pretend there is no required authentication */ 14890 ast_string_field_set(p, peersecret, NULL); 14891 ast_string_field_set(p, peermd5secret, NULL); 14892 } 14893 if (!(res = check_auth(p, req, peer->name, p->peersecret, p->peermd5secret, sipmethod, uri2, reliable, req->ignore))) { 14894 ast_copy_flags(&p->flags[0], &peer->flags[0], SIP_FLAGS_TO_COPY); 14895 ast_copy_flags(&p->flags[1], &peer->flags[1], SIP_PAGE2_FLAGS_TO_COPY); 14896 ast_copy_flags(&p->flags[2], &peer->flags[2], SIP_PAGE3_FLAGS_TO_COPY); 14897 /* If we have a call limit, set flag */ 14898 if (peer->call_limit) 14899 ast_set_flag(&p->flags[0], SIP_CALL_LIMIT); 14900 ast_string_field_set(p, peername, peer->name); 14901 ast_string_field_set(p, authname, peer->name); 14902 14903 if (sipmethod == SIP_INVITE) { 14904 /* copy channel vars */ 14905 p->chanvars = copy_vars(peer->chanvars); 14906 } 14907 14908 if (authpeer) { 14909 ao2_t_ref(peer, 1, "copy pointer into (*authpeer)"); 14910 (*authpeer) = peer; /* Add a ref to the object here, to keep it in memory a bit longer if it is realtime */ 14911 } 14912 14913 if (!ast_strlen_zero(peer->username)) { 14914 ast_string_field_set(p, username, peer->username); 14915 /* Use the default username for authentication on outbound calls */ 14916 /* XXX this takes the name from the caller... can we override ? */ 14917 ast_string_field_set(p, authname, peer->username); 14918 } 14919 if (!get_rpid(p, req)) { 14920 if (!ast_strlen_zero(peer->cid_num)) { 14921 char *tmp = ast_strdupa(peer->cid_num); 14922 if (global_shrinkcallerid && ast_is_shrinkable_phonenumber(tmp)) 14923 ast_shrink_phone_number(tmp); 14924 ast_string_field_set(p, cid_num, tmp); 14925 } 14926 if (!ast_strlen_zero(peer->cid_name)) 14927 ast_string_field_set(p, cid_name, peer->cid_name); 14928 if (!ast_strlen_zero(peer->cid_tag)) 14929 ast_string_field_set(p, cid_tag, peer->cid_tag); 14930 if (peer->callingpres) 14931 p->callingpres = peer->callingpres; 14932 } 14933 ast_string_field_set(p, fullcontact, peer->fullcontact); 14934 if (!ast_strlen_zero(peer->context)) 14935 ast_string_field_set(p, context, peer->context); 14936 ast_string_field_set(p, peersecret, peer->secret); 14937 ast_string_field_set(p, peermd5secret, peer->md5secret); 14938 ast_string_field_set(p, language, peer->language); 14939 ast_string_field_set(p, accountcode, peer->accountcode); 14940 p->amaflags = peer->amaflags; 14941 p->callgroup = peer->callgroup; 14942 p->pickupgroup = peer->pickupgroup; 14943 p->capability = peer->capability; 14944 p->prefs = peer->prefs; 14945 p->jointcapability = peer->capability; 14946 if (peer->maxforwards > 0) { 14947 p->maxforwards = peer->maxforwards; 14948 } 14949 if (p->peercapability) 14950 p->jointcapability &= p->peercapability; 14951 p->maxcallbitrate = peer->maxcallbitrate; 14952 if ((ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833) || 14953 (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO)) 14954 p->noncodeccapability |= AST_RTP_DTMF; 14955 else 14956 p->noncodeccapability &= ~AST_RTP_DTMF; 14957 p->jointnoncodeccapability = p->noncodeccapability; 14958 if (!dialog_initialize_rtp(p)) { 14959 if (p->rtp) { 14960 ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(p->rtp), p->rtp, &peer->prefs); 14961 p->autoframing = peer->autoframing; 14962 } 14963 } else { 14964 res = AUTH_RTP_FAILED; 14965 } 14966 } 14967 unref_peer(peer, "check_peer_ok: unref_peer: tossing temp ptr to peer from find_peer"); 14968 return res; 14969 }
| static void check_pendings | ( | struct sip_pvt * | p | ) | [static] |
Check pending actions on SIP call.
Definition at line 18526 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().
18527 { 18528 if (ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) { 18529 /* if we can't BYE, then this is really a pending CANCEL */ 18530 if (p->invitestate == INV_PROCEEDING || p->invitestate == INV_EARLY_MEDIA) 18531 transmit_request(p, SIP_CANCEL, p->lastinvite, XMIT_RELIABLE, FALSE); 18532 /* Actually don't destroy us yet, wait for the 487 on our original 18533 INVITE, but do set an autodestruct just in case we never get it. */ 18534 else { 18535 /* We have a pending outbound invite, don't send something 18536 new in-transaction */ 18537 if (p->pendinginvite) 18538 return; 18539 18540 if (p->owner) { 18541 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_DEV); 18542 } 18543 /* Perhaps there is an SD change INVITE outstanding */ 18544 transmit_request_with_auth(p, SIP_BYE, 0, XMIT_RELIABLE, TRUE); 18545 } 18546 ast_clear_flag(&p->flags[0], SIP_PENDINGBYE); 18547 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 18548 } else if (ast_test_flag(&p->flags[0], SIP_NEEDREINVITE)) { 18549 /* if we can't REINVITE, hold it for later */ 18550 if (p->pendinginvite || p->invitestate == INV_CALLING || p->invitestate == INV_PROCEEDING || p->invitestate == INV_EARLY_MEDIA || p->waitid > 0) { 18551 ast_debug(2, "NOT Sending pending reinvite (yet) on '%s'\n", p->callid); 18552 } else { 18553 ast_debug(2, "Sending pending reinvite on '%s'\n", p->callid); 18554 /* Didn't get to reinvite yet, so do it now */ 18555 transmit_reinvite_with_sdp(p, (p->t38.state == T38_LOCAL_REINVITE ? TRUE : FALSE), FALSE); 18556 ast_clear_flag(&p->flags[0], SIP_NEEDREINVITE); 18557 } 18558 } 18559 }
| static void 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 24169 of file chan_sip.c.
References ast_channel_trylock, ast_channel_unlock, ast_log(), ast_rtp_instance_get_hold_timeout(), ast_rtp_instance_get_timeout(), 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, LOG_NOTICE, sip_pvt_lock, and sip_pvt_unlock.
Referenced by dialog_needdestroy().
24170 { 24171 /* If we have no RTP or no active owner, no need to check timers */ 24172 if (!dialog->rtp || !dialog->owner) 24173 return; 24174 /* If the call is not in UP state or redirected outside Asterisk, no need to check timers */ 24175 24176 if (dialog->owner->_state != AST_STATE_UP || !ast_sockaddr_isnull(&dialog->redirip)) 24177 return; 24178 24179 /* If the call is involved in a T38 fax session do not check RTP timeout */ 24180 if (dialog->t38.state == T38_ENABLED) 24181 return; 24182 24183 /* If we have no timers set, return now */ 24184 if (!ast_rtp_instance_get_timeout(dialog->rtp) && !ast_rtp_instance_get_hold_timeout(dialog->rtp)) { 24185 return; 24186 } 24187 24188 /*! \todo Check video RTP keepalives 24189 24190 Do we need to move the lastrtptx to the RTP structure to have one for audio and one 24191 for video? It really does belong to the RTP structure. 24192 */ 24193 24194 /* Check AUDIO RTP timers */ 24195 if (dialog->lastrtprx && (ast_rtp_instance_get_timeout(dialog->rtp) || ast_rtp_instance_get_hold_timeout(dialog->rtp)) && (t > dialog->lastrtprx + ast_rtp_instance_get_timeout(dialog->rtp))) { 24196 if (!ast_test_flag(&dialog->flags[1], SIP_PAGE2_CALL_ONHOLD) || (ast_rtp_instance_get_hold_timeout(dialog->rtp) && (t > dialog->lastrtprx + ast_rtp_instance_get_hold_timeout(dialog->rtp)))) { 24197 /* Needs a hangup */ 24198 if (ast_rtp_instance_get_timeout(dialog->rtp)) { 24199 while (dialog->owner && ast_channel_trylock(dialog->owner)) { 24200 sip_pvt_unlock(dialog); 24201 usleep(1); 24202 sip_pvt_lock(dialog); 24203 } 24204 if (!dialog->owner) { 24205 return; /* channel hangup can occur during deadlock avoidance. */ 24206 } 24207 ast_log(LOG_NOTICE, "Disconnecting call '%s' for lack of RTP activity in %ld seconds\n", 24208 dialog->owner->name, (long) (t - dialog->lastrtprx)); 24209 /* Issue a softhangup */ 24210 ast_softhangup_nolock(dialog->owner, AST_SOFTHANGUP_DEV); 24211 ast_channel_unlock(dialog->owner); 24212 /* forget the timeouts for this call, since a hangup 24213 has already been requested and we don't want to 24214 repeatedly request hangups 24215 */ 24216 ast_rtp_instance_set_timeout(dialog->rtp, 0); 24217 ast_rtp_instance_set_hold_timeout(dialog->rtp, 0); 24218 if (dialog->vrtp) { 24219 ast_rtp_instance_set_timeout(dialog->vrtp, 0); 24220 ast_rtp_instance_set_hold_timeout(dialog->vrtp, 0); 24221 } 24222 } 24223 } 24224 } 24225 }
| 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 25315 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().
25316 { 25317 struct domain *d; 25318 int result = 0; 25319 25320 AST_LIST_LOCK(&domain_list); 25321 AST_LIST_TRAVERSE(&domain_list, d, list) { 25322 if (strcasecmp(d->domain, domain)) 25323 continue; 25324 25325 if (len && !ast_strlen_zero(d->context)) 25326 ast_copy_string(context, d->context, len); 25327 25328 result = 1; 25329 break; 25330 } 25331 AST_LIST_UNLOCK(&domain_list); 25332 25333 return result; 25334 }
| 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 15100 of file chan_sip.c.
References check_user_full().
Referenced by handle_request_options(), and handle_request_publish().
15101 { 15102 return check_user_full(p, req, sipmethod, uri, reliable, addr, NULL); 15103 }
| 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 14977 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(), dummy(), exten, get_header(), get_rpid(), LOG_ERROR, LOG_NOTICE, sip_cfg, SIP_PEDANTIC_DECODE, strsep(), and terminate_uri().
Referenced by check_user(), handle_request_invite(), and handle_request_subscribe().
14980 { 14981 char from[256] = { 0, }; 14982 char *dummy = NULL; /* dummy return value for parse_uri */ 14983 char *domain = NULL; /* dummy return value for parse_uri */ 14984 char *of; 14985 enum check_auth_result res = AUTH_DONT_KNOW; 14986 char calleridname[50]; 14987 char *uri2 = ast_strdupa(uri); 14988 14989 terminate_uri(uri2); /* trim extra stuff */ 14990 14991 ast_copy_string(from, get_header(req, "From"), sizeof(from)); 14992 /* XXX here tries to map the username for invite things */ 14993 memset(calleridname, 0, sizeof(calleridname)); 14994 14995 /* strip the display-name portion off the beginning of the FROM header. */ 14996 if (!(of = (char *) get_calleridname(from, calleridname, sizeof(calleridname)))) { 14997 ast_log(LOG_ERROR, "FROM header can not be parsed \n"); 14998 return res; 14999 } 15000 15001 if (calleridname[0]) 15002 ast_string_field_set(p, cid_name, calleridname); 15003 15004 if (ast_strlen_zero(p->exten)) { 15005 char *t = uri2; 15006 if (!strncasecmp(t, "sip:", 4)) 15007 t+= 4; 15008 else if (!strncasecmp(t, "sips:", 5)) 15009 t += 5; 15010 ast_string_field_set(p, exten, t); 15011 t = strchr(p->exten, '@'); 15012 if (t) 15013 *t = '\0'; 15014 15015 if (ast_strlen_zero(p->our_contact)) 15016 build_contact(p); 15017 } 15018 15019 of = get_in_brackets(of); 15020 15021 /* save the URI part of the From header */ 15022 ast_string_field_set(p, from, of); 15023 15024 /* ignore all fields but name */ 15025 if (parse_uri(of, "sip:,sips:", &of, &dummy, &domain, NULL)) { 15026 ast_log(LOG_NOTICE, "From address missing 'sip:', using it anyway\n"); 15027 } 15028 15029 SIP_PEDANTIC_DECODE(of); 15030 SIP_PEDANTIC_DECODE(domain); 15031 15032 if (ast_strlen_zero(of)) { 15033 /* XXX note: the original code considered a missing @host 15034 * as a username-only URI. The SIP RFC (19.1.1) says that 15035 * this is wrong, and it should be considered as a domain-only URI. 15036 * For backward compatibility, we keep this block, but it is 15037 * really a mistake and should go away. 15038 */ 15039 of = domain; 15040 } else { 15041 char *tmp = ast_strdupa(of); 15042 /* We need to be able to handle auth-headers looking like 15043 <sip:8164444422;phone-context=+1@1.2.3.4:5060;user=phone;tag=SDadkoa01-gK0c3bdb43> 15044 */ 15045 tmp = strsep(&tmp, ";"); 15046 if (global_shrinkcallerid && ast_is_shrinkable_phonenumber(tmp)) 15047 ast_shrink_phone_number(tmp); 15048 ast_string_field_set(p, cid_num, tmp); 15049 } 15050 15051 if (global_match_auth_username) { 15052 /* 15053 * XXX This is experimental code to grab the search key from the 15054 * Auth header's username instead of the 'From' name, if available. 15055 * Do not enable this block unless you understand the side effects (if any!) 15056 * Note, the search for "username" should be done in a more robust way. 15057 * Note2, at the moment we check both fields, though maybe we should 15058 * pick one or another depending on the request ? XXX 15059 */ 15060 const char *hdr = get_header(req, "Authorization"); 15061 if (ast_strlen_zero(hdr)) 15062 hdr = get_header(req, "Proxy-Authorization"); 15063 15064 if ( !ast_strlen_zero(hdr) && (hdr = strstr(hdr, "username=\"")) ) { 15065 ast_copy_string(from, hdr + strlen("username=\""), sizeof(from)); 15066 of = from; 15067 of = strsep(&of, "\""); 15068 } 15069 } 15070 15071 res = check_peer_ok(p, of, req, sipmethod, addr, 15072 authpeer, reliable, calleridname, uri2); 15073 if (res != AUTH_DONT_KNOW) 15074 return res; 15075 15076 /* Finally, apply the guest policy */ 15077 if (sip_cfg.allowguest) { 15078 get_rpid(p, req); 15079 if (!dialog_initialize_rtp(p)) { 15080 res = AUTH_SUCCESSFUL; 15081 } else { 15082 res = AUTH_RTP_FAILED; 15083 } 15084 } else if (sip_cfg.alwaysauthreject) 15085 res = AUTH_FAKE_AUTH; /* reject with fake authorization request */ 15086 else 15087 res = AUTH_SECRET_FAILED; /* we don't want any guests, authentication will fail */ 15088 15089 15090 if (ast_test_flag(&p->flags[1], SIP_PAGE2_RPORT_PRESENT)) { 15091 ast_set_flag(&p->flags[0], SIP_NAT_RPORT_PRESENT); 15092 } 15093 15094 return res; 15095 }
| 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 14739 of file chan_sip.c.
References ast_copy_string(), ast_log(), ast_set_flag, ast_skip_blanks(), ast_sockaddr_port, ast_sockaddr_resolve_first(), ast_sockaddr_set_port, ast_sockaddr_stringify(), ast_verbose, get_header(), LOG_WARNING, sip_debug_test_pvt(), 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().
14740 { 14741 char via[512]; 14742 char *c, *maddr; 14743 struct ast_sockaddr tmp; 14744 uint16_t port; 14745 14746 ast_copy_string(via, get_header(req, "Via"), sizeof(via)); 14747 14748 /* Work on the leftmost value of the topmost Via header */ 14749 c = strchr(via, ','); 14750 if (c) 14751 *c = '\0'; 14752 14753 /* Check for rport */ 14754 c = strstr(via, ";rport"); 14755 if (c && (c[6] != '=')) { /* rport query, not answer */ 14756 ast_set_flag(&p->flags[1], SIP_PAGE2_RPORT_PRESENT); 14757 ast_set_flag(&p->flags[0], SIP_NAT_RPORT_PRESENT); 14758 } 14759 14760 /* Check for maddr */ 14761 maddr = strstr(via, "maddr="); 14762 if (maddr) { 14763 maddr += 6; 14764 c = maddr + strspn(maddr, "abcdefghijklmnopqrstuvwxyz" 14765 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-.:[]"); 14766 *c = '\0'; 14767 } 14768 14769 c = strchr(via, ';'); 14770 if (c) 14771 *c = '\0'; 14772 14773 c = strchr(via, ' '); 14774 if (c) { 14775 *c = '\0'; 14776 c = ast_skip_blanks(c+1); 14777 if (strcasecmp(via, "SIP/2.0/UDP") && strcasecmp(via, "SIP/2.0/TCP") && strcasecmp(via, "SIP/2.0/TLS")) { 14778 ast_log(LOG_WARNING, "Don't know how to respond via '%s'\n", via); 14779 return; 14780 } 14781 14782 if (maddr && ast_sockaddr_resolve_first(&p->sa, maddr, 0)) { 14783 p->sa = p->recv; 14784 } 14785 14786 ast_sockaddr_resolve_first(&tmp, c, 0); 14787 port = ast_sockaddr_port(&tmp); 14788 ast_sockaddr_set_port(&p->sa, 14789 port != 0 ? port : STANDARD_SIP_PORT); 14790 14791 if (sip_debug_test_pvt(p)) { 14792 ast_verbose("Sending to %s (%s)\n", 14793 ast_sockaddr_stringify(sip_real_dst(p)), 14794 sip_nat_mode(p)); 14795 } 14796 } 14797 }
| 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 14709 of file chan_sip.c.
References ast_copy_string(), ast_parse_arg(), ast_sockaddr_set_port, get_header(), PARSE_ADDR, and strsep().
14710 { 14711 char via[256]; 14712 char *cur, *opts; 14713 14714 ast_copy_string(via, get_header(req, "Via"), sizeof(via)); 14715 14716 /* Work on the leftmost value of the topmost Via header */ 14717 opts = strchr(via, ','); 14718 if (opts) 14719 *opts = '\0'; 14720 14721 /* parse all relevant options */ 14722 opts = strchr(via, ';'); 14723 if (!opts) 14724 return; /* no options to parse */ 14725 *opts++ = '\0'; 14726 while ( (cur = strsep(&opts, ";")) ) { 14727 if (!strncmp(cur, "rport=", 6)) { 14728 int port = strtol(cur+6, NULL, 10); 14729 /* XXX add error checking */ 14730 ast_sockaddr_set_port(&p->ourip, port); 14731 } else if (!strncmp(cur, "received=", 9)) { 14732 if (ast_parse_arg(cur + 9, PARSE_ADDR, &p->ourip)) 14733 ; /* XXX add error checking */ 14734 } 14735 } 14736 }
| 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 15783 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().
15784 { 15785 char *oldcontext, *newcontext, *stalecontext, *stringp, newlist[AST_MAX_CONTEXT]; 15786 15787 while ((oldcontext = strsep(&old, "&"))) { 15788 stalecontext = '\0'; 15789 ast_copy_string(newlist, new, sizeof(newlist)); 15790 stringp = newlist; 15791 while ((newcontext = strsep(&stringp, "&"))) { 15792 if (!strcmp(newcontext, oldcontext)) { 15793 /* This is not the context you're looking for */ 15794 stalecontext = '\0'; 15795 break; 15796 } else if (strcmp(newcontext, oldcontext)) { 15797 stalecontext = oldcontext; 15798 } 15799 15800 } 15801 if (stalecontext) 15802 ast_context_destroy(ast_context_find(stalecontext), "SIP"); 15803 } 15804 }
| static void clear_peer_mailboxes | ( | struct sip_peer * | peer | ) | [static] |
Destroy all peer-related mailbox subscriptions
Definition at line 4267 of file chan_sip.c.
References AST_LIST_REMOVE_HEAD, destroy_mailbox(), and mailbox.
Referenced by set_peer_defaults(), and sip_destroy_peer().
04268 { 04269 struct sip_mailbox *mailbox; 04270 04271 while ((mailbox = AST_LIST_REMOVE_HEAD(&peer->mailboxes, entry))) 04272 destroy_mailbox(mailbox); 04273 }
| static int clear_realm_authentication | ( | struct sip_auth * | authlist | ) | [static] |
Clear realm authentication list (at reload).
Definition at line 25404 of file chan_sip.c.
References ast_free.
Referenced by build_peer(), reload_config(), sip_destroy_peer(), and unload_module().
25405 { 25406 struct sip_auth *a = authlist; 25407 struct sip_auth *b; 25408 25409 while (a) { 25410 b = a; 25411 a = a->next; 25412 ast_free(b); 25413 } 25414 25415 return 1; 25416 }
| static void clear_sip_domains | ( | void | ) | [static] |
Clear our domain list (at reload).
Definition at line 25337 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().
25338 { 25339 struct domain *d; 25340 25341 AST_LIST_LOCK(&domain_list); 25342 while ((d = AST_LIST_REMOVE_HEAD(&domain_list, list))) 25343 ast_free(d); 25344 AST_LIST_UNLOCK(&domain_list); 25345 }
| static char * complete_sip_peer | ( | const char * | word, | |
| int | state, | |||
| int | flags2 | |||
| ) | [static] |
Do completion on peer name.
Definition at line 17179 of file chan_sip.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_t_iterator_next, ast_strdup, ast_test_flag, and unref_peer().
Referenced by complete_sip_show_peer(), complete_sipnotify(), sip_do_debug(), and sip_prune_realtime().
17180 { 17181 char *result = NULL; 17182 int wordlen = strlen(word); 17183 int which = 0; 17184 struct ao2_iterator i = ao2_iterator_init(peers, 0); 17185 struct sip_peer *peer; 17186 17187 while ((peer = ao2_t_iterator_next(&i, "iterate thru peers table"))) { 17188 /* locking of the object is not required because only the name and flags are being compared */ 17189 if (!strncasecmp(word, peer->name, wordlen) && 17190 (!flags2 || ast_test_flag(&peer->flags[1], flags2)) && 17191 ++which > state) 17192 result = ast_strdup(peer->name); 17193 unref_peer(peer, "toss iterator peer ptr before break"); 17194 if (result) { 17195 break; 17196 } 17197 } 17198 ao2_iterator_destroy(&i); 17199 return result; 17200 }
| static char * complete_sip_registered_peer | ( | const char * | word, | |
| int | state, | |||
| int | flags2 | |||
| ) | [static] |
Do completion on registered peer name.
Definition at line 17203 of file chan_sip.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_t_iterator_next, ast_strdup, ast_test_flag, and unref_peer().
Referenced by complete_sip_unregister().
17204 { 17205 char *result = NULL; 17206 int wordlen = strlen(word); 17207 int which = 0; 17208 struct ao2_iterator i; 17209 struct sip_peer *peer; 17210 17211 i = ao2_iterator_init(peers, 0); 17212 while ((peer = ao2_t_iterator_next(&i, "iterate thru peers table"))) { 17213 if (!strncasecmp(word, peer->name, wordlen) && 17214 (!flags2 || ast_test_flag(&peer->flags[1], flags2)) && 17215 ++which > state && peer->expire > 0) 17216 result = ast_strdup(peer->name); 17217 if (result) { 17218 unref_peer(peer, "toss iterator peer ptr before break"); 17219 break; 17220 } 17221 unref_peer(peer, "toss iterator peer ptr"); 17222 } 17223 ao2_iterator_destroy(&i); 17224 return result; 17225 }
| 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 17228 of file chan_sip.c.
References complete_sipch().
Referenced by sip_show_history().
17229 { 17230 if (pos == 3) 17231 return complete_sipch(line, word, pos, state); 17232 17233 return NULL; 17234 }
| 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 17237 of file chan_sip.c.
References complete_sip_peer().
Referenced by sip_qualify_peer(), and sip_show_peer().
17238 { 17239 if (pos == 3) { 17240 return complete_sip_peer(word, state, 0); 17241 } 17242 17243 return NULL; 17244 }
| 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 16480 of file chan_sip.c.
References complete_sip_user().
Referenced by sip_show_user().
16481 { 16482 if (pos == 3) 16483 return complete_sip_user(word, state); 16484 16485 return NULL; 16486 }
| 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 17247 of file chan_sip.c.
References complete_sip_registered_peer().
Referenced by sip_unregister().
17248 { 17249 if (pos == 2) 17250 return complete_sip_registered_peer(word, state, 0); 17251 17252 return NULL; 17253 }
| static char* complete_sip_user | ( | const char * | word, | |
| int | state | |||
| ) | [static] |
Do completion on user name.
Definition at line 16453 of file chan_sip.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_unlock, ast_strdup, and unref_peer().
Referenced by complete_sip_show_user().
16454 { 16455 char *result = NULL; 16456 int wordlen = strlen(word); 16457 int which = 0; 16458 struct ao2_iterator user_iter; 16459 struct sip_peer *user; 16460 16461 user_iter = ao2_iterator_init(peers, 0); 16462 while ((user = ao2_iterator_next(&user_iter))) { 16463 ao2_lock(user); 16464 if (!(user->type & SIP_TYPE_USER)) { 16465 ao2_unlock(user); 16466 unref_peer(user, "complete sip user"); 16467 continue; 16468 } 16469 /* locking of the object is not required because only the name and flags are being compared */ 16470 if (!strncasecmp(word, user->name, wordlen) && ++which > state) { 16471 result = ast_strdup(user->name); 16472 } 16473 ao2_unlock(user); 16474 unref_peer(user, "complete sip user"); 16475 } 16476 ao2_iterator_destroy(&user_iter); 16477 return result; 16478 }
| 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 17149 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().
17150 { 17151 int which=0; 17152 struct sip_pvt *cur; 17153 char *c = NULL; 17154 int wordlen = strlen(word); 17155 struct ao2_iterator i; 17156 17157 if (pos != 3) { 17158 return NULL; 17159 } 17160 17161 i = ao2_iterator_init(dialogs, 0); 17162 while ((cur = ao2_t_iterator_next(&i, "iterate thru dialogs"))) { 17163 sip_pvt_lock(cur); 17164 if (!strncasecmp(word, cur->callid, wordlen) && ++which > state) { 17165 c = ast_strdup(cur->callid); 17166 sip_pvt_unlock(cur); 17167 dialog_unref(cur, "drop ref in iterator loop break"); 17168 break; 17169 } 17170 sip_pvt_unlock(cur); 17171 dialog_unref(cur, "drop ref in iterator loop"); 17172 } 17173 ao2_iterator_destroy(&i); 17174 return c; 17175 }
| static char * complete_sipnotify | ( | const char * | line, | |
| const char * | word, | |||
| int | pos, | |||
| int | state | |||
| ) | [static] |
Support routine for 'sip notify' CLI.
Definition at line 17256 of file chan_sip.c.
References ast_category_browse(), ast_strdup, and complete_sip_peer().
Referenced by sip_cli_notify().
17257 { 17258 char *c = NULL; 17259 17260 if (pos == 2) { 17261 int which = 0; 17262 char *cat = NULL; 17263 int wordlen = strlen(word); 17264 17265 /* do completion for notify type */ 17266 17267 if (!notify_types) 17268 return NULL; 17269 17270 while ( (cat = ast_category_browse(notify_types, cat)) ) { 17271 if (!strncasecmp(word, cat, wordlen) && ++which > state) { 17272 c = ast_strdup(cat); 17273 break; 17274 } 17275 } 17276 return c; 17277 } 17278 17279 if (pos > 2) 17280 return complete_sip_peer(word, state, 0); 17281 17282 return NULL; 17283 }
| static int construct_pidf_body | ( | enum sip_cc_publish_state | state, | |
| char * | pidf_body, | |||
| size_t | size, | |||
| const char * | presentity | |||
| ) | [static] |
Definition at line 1901 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().
01902 { 01903 struct ast_str *body = ast_str_alloca(size); 01904 char tuple_id[32]; 01905 01906 generate_random_string(tuple_id, sizeof(tuple_id)); 01907 01908 /* We'll make this a bare-bones pidf body. In state_notify_build_xml, the PIDF 01909 * body gets a lot more extra junk that isn't necessary, so we'll leave it out here. 01910 */ 01911 ast_str_append(&body, 0, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); 01912 /* XXX The entity attribute is currently set to the peer name associated with the 01913 * dialog. This is because we currently only call this function for call-completion 01914 * PUBLISH bodies. In such cases, the entity is completely disregarded. For other 01915 * event packages, it may be crucial to have a proper URI as the presentity so this 01916 * should be revisited as support is expanded. 01917 */ 01918 ast_str_append(&body, 0, "<presence xmlns=\"urn:ietf:params:xml:ns:pidf\" entity=\"%s\">\n", presentity); 01919 ast_str_append(&body, 0, "<tuple id=\"%s\">\n", tuple_id); 01920 ast_str_append(&body, 0, "<status><basic>%s</basic></status>\n", state == CC_OPEN ? "open" : "closed"); 01921 ast_str_append(&body, 0, "</tuple>\n"); 01922 ast_str_append(&body, 0, "</presence>\n"); 01923 ast_copy_string(pidf_body, ast_str_buffer(body), size); 01924 return 0; 01925 }
| 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 9127 of file chan_sip.c.
References __get_header(), add_header(), and ast_strlen_zero().
Referenced by respprep().
09128 { 09129 int start = 0; 09130 int copied = 0; 09131 for (;;) { 09132 const char *tmp = __get_header(orig, field, &start); 09133 09134 if (ast_strlen_zero(tmp)) 09135 break; 09136 /* Add what we're responding to */ 09137 add_header(req, field, tmp); 09138 copied++; 09139 } 09140 return copied ? 0 : -1; 09141 }
| 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 9116 of file chan_sip.c.
References add_header(), ast_log(), ast_strlen_zero(), get_header(), and LOG_NOTICE.
Referenced by reqprep(), and respprep().
09117 { 09118 const char *tmp = get_header(orig, field); 09119 09120 if (!ast_strlen_zero(tmp)) /* Add what we're responding to */ 09121 return add_header(req, field, tmp); 09122 ast_log(LOG_NOTICE, "No field '%s' present to copy\n", field); 09123 return -1; 09124 }
| 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 10792 of file chan_sip.c.
References ast_str_copy_string(), ast_str_create(), and ast_str_strlen().
Referenced by _sip_tcp_helper_thread(), handle_request_bye(), handle_request_invite(), handle_request_options(), handle_request_refer(), handle_request_register(), handle_request_subscribe(), initialize_initreq(), parse_copy(), queue_request(), sip_park(), and sip_park_thread().
10793 { 10794 /* XXX this function can encounter memory allocation errors, perhaps it 10795 * should return a value */ 10796 10797 struct ast_str *duplicate = dst->data; 10798 struct ast_str *duplicate_content = dst->content; 10799 10800 /* copy the entire request then restore the original data and content 10801 * members from the dst request */ 10802 memcpy(dst, src, sizeof(*dst)); 10803 dst->data = duplicate; 10804 dst->content = duplicate_content; 10805 10806 /* copy the data into the dst request */ 10807 if (!dst->data && !(dst->data = ast_str_create(ast_str_strlen(src->data) + 1))) 10808 return; 10809 ast_str_copy_string(&dst->data, src->data); 10810 10811 /* copy the content into the dst request (if it exists) */ 10812 if (src->content) { 10813 if (!dst->content && !(dst->content = ast_str_create(ast_str_strlen(src->content) + 1))) 10814 return; 10815 ast_str_copy_string(&dst->content, src->content); 10816 } 10817 }
| static void copy_socket_data | ( | struct sip_socket * | to_sock, | |
| const struct sip_socket * | from_sock | |||
| ) | [static] |
Definition at line 4731 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().
04732 { 04733 if (to_sock->tcptls_session) { 04734 ao2_ref(to_sock->tcptls_session, -1); 04735 to_sock->tcptls_session = NULL; 04736 } 04737 04738 if (from_sock->tcptls_session) { 04739 ao2_ref(from_sock->tcptls_session, +1); 04740 } 04741 04742 *to_sock = *from_sock; 04743 }
| static struct ast_variable * copy_vars | ( | struct ast_variable * | src | ) | [static, read] |
duplicate a list of channel variables,
Definition at line 2280 of file chan_sip.c.
References ast_variable_new(), and ast_variable::next.
02281 { 02282 struct ast_variable *res = NULL, *tmp, *v = NULL; 02283 02284 for (v = src ; v ; v = v->next) { 02285 if ((tmp = ast_variable_new(v->name, v->value, v->file))) { 02286 tmp->next = res; 02287 res = tmp; 02288 } 02289 } 02290 return res; 02291 }
| 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 9151 of file chan_sip.c.
References __get_header(), add_header(), ast_copy_string(), ast_log(), ast_sockaddr_port, ast_sockaddr_stringify_addr(), ast_strlen_zero(), ast_test_flag, and LOG_NOTICE.
Referenced by respprep().
09152 { 09153 int copied = 0; 09154 int start = 0; 09155 09156 for (;;) { 09157 char new[512]; 09158 const char *oh = __get_header(orig, field, &start); 09159 09160 if (ast_strlen_zero(oh)) 09161 break; 09162 09163 if (!copied) { /* Only check for empty rport in topmost via header */ 09164 char leftmost[512], *others, *rport; 09165 09166 /* Only work on leftmost value */ 09167 ast_copy_string(leftmost, oh, sizeof(leftmost)); 09168 others = strchr(leftmost, ','); 09169 if (others) 09170 *others++ = '\0'; 09171 09172 /* Find ;rport; (empty request) */ 09173 rport = strstr(leftmost, ";rport"); 09174 if (rport && *(rport+6) == '=') 09175 rport = NULL; /* We already have a parameter to rport */ 09176 09177 if (((ast_test_flag(&p->flags[0], SIP_NAT_FORCE_RPORT)) || (rport && ast_test_flag(&p->flags[0], SIP_NAT_RPORT_PRESENT)))) { 09178 /* We need to add received port - rport */ 09179 char *end; 09180 09181 rport = strstr(leftmost, ";rport"); 09182 09183 if (rport) { 09184 end = strchr(rport + 1, ';'); 09185 if (end) 09186 memmove(rport, end, strlen(end) + 1); 09187 else 09188 *rport = '\0'; 09189 } 09190 09191 /* Add rport to first VIA header if requested */ 09192 snprintf(new, sizeof(new), "%s;received=%s;rport=%d%s%s", 09193 leftmost, ast_sockaddr_stringify_addr(&p->recv), 09194 ast_sockaddr_port(&p->recv), 09195 others ? "," : "", others ? others : ""); 09196 } else { 09197 /* We should *always* add a received to the topmost via */ 09198 snprintf(new, sizeof(new), "%s;received=%s%s%s", 09199 leftmost, ast_sockaddr_stringify_addr(&p->recv), 09200 others ? "," : "", others ? others : ""); 09201 } 09202 oh = new; /* the header to copy */ 09203 } /* else add the following via headers untouched */ 09204 add_header(req, field, oh); 09205 copied++; 09206 } 09207 if (!copied) { 09208 ast_log(LOG_NOTICE, "No header field '%s' present to copy\n", field); 09209 return -1; 09210 } 09211 return 0; 09212 }
| 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 4949 of file chan_sip.c.
References AST_APP_ARG, 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(), dialog_initialize_rtp(), FALSE, find_peer(), get_srv_protocol(), get_srv_service(), LOG_WARNING, MAXHOSTNAMELEN, obproxy_get(), ref_peer(), ref_proxy(), service, set_socket_transport(), sip_cfg, TRUE, and unref_peer().
04950 { 04951 struct sip_peer *peer; 04952 char *peername, *peername2, *hostn; 04953 char host[MAXHOSTNAMELEN]; 04954 char service[MAXHOSTNAMELEN]; 04955 int srv_ret = 0; 04956 int tportno; 04957 04958 AST_DECLARE_APP_ARGS(hostport, 04959 AST_APP_ARG(host); 04960 AST_APP_ARG(port); 04961 ); 04962 04963 peername = ast_strdupa(opeer); 04964 peername2 = ast_strdupa(opeer); 04965 AST_NONSTANDARD_RAW_ARGS(hostport, peername2, ':'); 04966 04967 if (hostport.port) 04968 dialog->portinuri = 1; 04969 04970 dialog->timer_t1 = global_t1; /* Default SIP retransmission timer T1 (RFC 3261) */ 04971 dialog->timer_b = global_timer_b; /* Default SIP transaction timer B (RFC 3261) */ 04972 peer = find_peer(peername, NULL, TRUE, FINDPEERS, FALSE, 0); 04973 04974 if (peer) { 04975 int res; 04976 if (newdialog) { 04977 set_socket_transport(&dialog->socket, 0); 04978 } 04979 res = create_addr_from_peer(dialog, peer); 04980 if (!ast_sockaddr_isnull(remote_address)) { 04981 ast_sockaddr_copy(&dialog->sa, remote_address); 04982 } 04983 dialog->relatedpeer = ref_peer(peer, "create_addr: setting dialog's relatedpeer pointer"); 04984 unref_peer(peer, "create_addr: unref peer from find_peer hashtab lookup"); 04985 return res; 04986 } 04987 04988 if (dialog_initialize_rtp(dialog)) { 04989 return -1; 04990 } 04991 04992 ast_string_field_set(dialog, tohost, hostport.host); 04993 dialog->allowed_methods &= ~sip_cfg.disallowed_methods; 04994 04995 /* Get the outbound proxy information */ 04996 ref_proxy(dialog, obproxy_get(dialog, NULL)); 04997 04998 if (addr) { 04999 /* This address should be updated using dnsmgr */ 05000 ast_sockaddr_copy(&dialog->sa, addr); 05001 } else { 05002 05003 /* Let's see if we can find the host in DNS. First try DNS SRV records, 05004 then hostname lookup */ 05005 /*! \todo Fix this function. When we ask for SRV, we should check all transports 05006 In the future, we should first check NAPTR to find out transport preference 05007 */ 05008 hostn = peername; 05009 /* Section 4.2 of RFC 3263 specifies that if a port number is specified, then 05010 * an A record lookup should be used instead of SRV. 05011 */ 05012 if (!hostport.port && sip_cfg.srvlookup) { 05013 snprintf(service, sizeof(service), "_%s._%s.%s", 05014 get_srv_service(dialog->socket.type), 05015 get_srv_protocol(dialog->socket.type), peername); 05016 if ((srv_ret = ast_get_srv(NULL, host, sizeof(host), &tportno, 05017 service)) > 0) { 05018 hostn = host; 05019 } 05020 } 05021 05022 if (ast_sockaddr_resolve_first(&dialog->sa, hostn, 0)) { 05023 ast_log(LOG_WARNING, "No such host: %s\n", peername); 05024 } 05025 05026 if (srv_ret > 0) { 05027 ast_sockaddr_set_port(&dialog->sa, tportno); 05028 } 05029 } 05030 05031 if (!dialog->socket.type) 05032 set_socket_transport(&dialog->socket, SIP_TRANSPORT_UDP); 05033 if (!dialog->socket.port) { 05034 dialog->socket.port = htons(ast_sockaddr_port(&bindaddr)); 05035 } 05036 05037 if (!ast_sockaddr_port(&dialog->sa)) { 05038 ast_sockaddr_set_port(&dialog->sa, 05039 (dialog->socket.type == SIP_TRANSPORT_TLS) ? 05040 STANDARD_TLS_PORT : STANDARD_SIP_PORT); 05041 } 05042 ast_sockaddr_copy(&dialog->recv, &dialog->sa); 05043 return 0; 05044 }
| 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 4803 of file chan_sip.c.
References accountcode, ao2_t_link, ao2_t_unlink, ast_cc_copy_config_params(), ast_clear_flag, ast_copy_flags, ast_debug, ast_duplicate_ha_list(), ast_rtp_codecs_packetization_set(), AST_RTP_DTMF, ast_rtp_instance_get_codecs(), ast_rtp_instance_set_hold_timeout(), ast_rtp_instance_set_prop(), ast_rtp_instance_set_timeout(), AST_RTP_PROPERTY_DTMF, AST_RTP_PROPERTY_DTMF_COMPENSATE, ast_set_flag, ast_sockaddr_isnull(), ast_sockaddr_stringify_host(), ast_strdupa, ast_string_field_build, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_udptl_destroy(), ast_udptl_new_with_bindaddr(), bindaddr, check_request_transport, cid_name, cid_num, context, copy_socket_data(), copy_vars(), dialog_initialize_rtp(), language, mohinterpret, mohsuggest, obproxy_get(), parkinglot, ref_proxy(), and set_t38_capabilities().
Referenced by create_addr(), and sip_send_mwi_to_peer().
04804 { 04805 /* this checks that the dialog is contacting the peer on a valid 04806 * transport type based on the peers transport configuration, 04807 * otherwise, this function bails out */ 04808 if (dialog->socket.type && check_request_transport(peer, dialog)) 04809 return -1; 04810 copy_socket_data(&dialog->socket, &peer->socket); 04811 04812 if (!(ast_sockaddr_isnull(&peer->addr) && ast_sockaddr_isnull(&peer->defaddr)) && 04813 (!peer->maxms || ((peer->lastms >= 0) && (peer->lastms <= peer->maxms)))) { 04814 dialog->sa = ast_sockaddr_isnull(&peer->addr) ? peer->defaddr : peer->addr; 04815 dialog->recv = dialog->sa; 04816 } else 04817 return -1; 04818 04819 /* XXX TODO: get flags directly from peer only as they are needed using dialog->relatedpeer */ 04820 ast_copy_flags(&dialog->flags[0], &peer->flags[0], SIP_FLAGS_TO_COPY); 04821 ast_copy_flags(&dialog->flags[1], &peer->flags[1], SIP_PAGE2_FLAGS_TO_COPY); 04822 ast_copy_flags(&dialog->flags[2], &peer->flags[2], SIP_PAGE3_FLAGS_TO_COPY); 04823 dialog->capability = peer->capability; 04824 dialog->prefs = peer->prefs; 04825 if (ast_test_flag(&dialog->flags[1], SIP_PAGE2_T38SUPPORT)) { 04826 /* t38pt_udptl was enabled in the peer and not in [general] */ 04827 if (dialog->udptl || (!dialog->udptl && (dialog->udptl = ast_udptl_new_with_bindaddr(sched, io, 0, &bindaddr)))) { 04828 dialog->t38_maxdatagram = peer->t38_maxdatagram; 04829 set_t38_capabilities(dialog); 04830 } else { 04831 /* It is impossible to support T38 without udptl */ 04832 ast_debug(1, "UDPTL creation failed on dialog.\n"); 04833 ast_clear_flag(&dialog->flags[1], SIP_PAGE2_T38SUPPORT); 04834 } 04835 } else if (dialog->udptl) { 04836 ast_udptl_destroy(dialog->udptl); 04837 dialog->udptl = NULL; 04838 } 04839 04840 ast_string_field_set(dialog, engine, peer->engine); 04841 04842 if (dialog_initialize_rtp(dialog)) { 04843 return -1; 04844 } 04845 04846 if (dialog->rtp) { /* Audio */ 04847 ast_rtp_instance_set_prop(dialog->rtp, AST_RTP_PROPERTY_DTMF, ast_test_flag(&dialog->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833); 04848 ast_rtp_instance_set_prop(dialog->rtp, AST_RTP_PROPERTY_DTMF_COMPENSATE, ast_test_flag(&dialog->flags[1], SIP_PAGE2_RFC2833_COMPENSATE)); 04849 ast_rtp_instance_set_timeout(dialog->rtp, peer->rtptimeout); 04850 ast_rtp_instance_set_hold_timeout(dialog->rtp, peer->rtpholdtimeout); 04851 /* Set Frame packetization */ 04852 ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(dialog->rtp), dialog->rtp, &dialog->prefs); 04853 dialog->autoframing = peer->autoframing; 04854 } 04855 if (dialog->vrtp) { /* Video */ 04856 ast_rtp_instance_set_timeout(dialog->vrtp, peer->rtptimeout); 04857 ast_rtp_instance_set_hold_timeout(dialog->vrtp, peer->rtpholdtimeout); 04858 } 04859 if (dialog->trtp) { /* Realtime text */ 04860 ast_rtp_instance_set_timeout(dialog->trtp, peer->rtptimeout); 04861 ast_rtp_instance_set_hold_timeout(dialog->trtp, peer->rtpholdtimeout); 04862 } 04863 04864 /* XXX TODO: get fields directly from peer only as they are needed using dialog->relatedpeer */ 04865 ast_string_field_set(dialog, peername, peer->name); 04866 ast_string_field_set(dialog, authname, peer->username); 04867 ast_string_field_set(dialog, username, peer->username); 04868 ast_string_field_set(dialog, peersecret, peer->secret); 04869 ast_string_field_set(dialog, peermd5secret, peer->md5secret); 04870 ast_string_field_set(dialog, mohsuggest, peer->mohsuggest); 04871 ast_string_field_set(dialog, mohinterpret, peer->mohinterpret); 04872 ast_string_field_set(dialog, tohost, peer->tohost); 04873 ast_string_field_set(dialog, fullcontact, peer->fullcontact); 04874 ast_string_field_set(dialog, accountcode, peer->accountcode); 04875 ast_string_field_set(dialog, context, peer->context); 04876 ast_string_field_set(dialog, cid_num, peer->cid_num); 04877 ast_string_field_set(dialog, cid_name, peer->cid_name); 04878 ast_string_field_set(dialog, cid_tag, peer->cid_tag); 04879 ast_string_field_set(dialog, mwi_from, peer->mwi_from); 04880 ast_string_field_set(dialog, parkinglot, peer->parkinglot); 04881 ast_string_field_set(dialog, engine, peer->engine); 04882 ref_proxy(dialog, obproxy_get(dialog, peer)); 04883 dialog->callgroup = peer->callgroup; 04884 dialog->pickupgroup = peer->pickupgroup; 04885 dialog->allowtransfer = peer->allowtransfer; 04886 dialog->jointnoncodeccapability = dialog->noncodeccapability; 04887 dialog->rtptimeout = peer->rtptimeout; 04888 dialog->peerauth = peer->auth; 04889 dialog->maxcallbitrate = peer->maxcallbitrate; 04890 dialog->disallowed_methods = peer->disallowed_methods; 04891 ast_cc_copy_config_params(dialog->cc_params, peer->cc_params); 04892 if (ast_strlen_zero(dialog->tohost)) 04893 ast_string_field_set(dialog, tohost, ast_sockaddr_stringify_host(&dialog->sa)); 04894 if (!ast_strlen_zero(peer->fromdomain)) { 04895 ast_string_field_set(dialog, fromdomain, peer->fromdomain); 04896 if (!dialog->initreq.headers) { 04897 char *c; 04898 char *tmpcall = ast_strdupa(dialog->callid); 04899 /* this sure looks to me like we are going to change the callid on this dialog!! */ 04900 c = strchr(tmpcall, '@'); 04901 if (c) { 04902 *c = '\0'; 04903 ao2_t_unlink(dialogs, dialog, "About to change the callid -- remove the old name"); 04904 ast_string_field_build(dialog, callid, "%s@%s", tmpcall, peer->fromdomain); 04905 ao2_t_link(dialogs, dialog, "New dialog callid -- inserted back into table"); 04906 } 04907 } 04908 } 04909 if (!ast_strlen_zero(peer->fromuser)) 04910 ast_string_field_set(dialog, fromuser, peer->fromuser); 04911 if (!ast_strlen_zero(peer->language)) 04912 ast_string_field_set(dialog, language, peer->language); 04913 /* Set timer T1 to RTT for this peer (if known by qualify=) */ 04914 /* Minimum is settable or default to 100 ms */ 04915 /* If there is a maxms and lastms from a qualify use that over a manual T1 04916 value. Otherwise, use the peer's T1 value. */ 04917 if (peer->maxms && peer->lastms) 04918 dialog->timer_t1 = peer->lastms < global_t1min ? global_t1min : peer->lastms; 04919 else 04920 dialog->timer_t1 = peer->timer_t1; 04921 04922 /* Set timer B to control transaction timeouts, the peer setting is the default and overrides 04923 the known timer */ 04924 if (peer->timer_b) 04925 dialog->timer_b = peer->timer_b; 04926 else 04927 dialog->timer_b = 64 * dialog->timer_t1; 04928 04929 if ((ast_test_flag(&dialog->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833) || 04930 (ast_test_flag(&dialog->flags[0], SIP_DTMF) == SIP_DTMF_AUTO)) 04931 dialog->noncodeccapability |= AST_RTP_DTMF; 04932 else 04933 dialog->noncodeccapability &= ~AST_RTP_DTMF; 04934 dialog->directmediaha = ast_duplicate_ha_list(peer->directmediaha); 04935 if (peer->call_limit) 04936 ast_set_flag(&dialog->flags[0], SIP_CALL_LIMIT); 04937 if (!dialog->portinuri) 04938 dialog->portinuri = peer->portinuri; 04939 dialog->chanvars = copy_vars(peer->chanvars); 04940 if (peer->fromdomainport) 04941 dialog->fromdomainport = peer->fromdomainport; 04942 04943 return 0; 04944 }
| static struct sip_epa_entry* create_epa_entry | ( | const char *const | event_package, | |
| const char *const | destination | |||
| ) | [static, read] |
Definition at line 900 of file chan_sip.c.
References ao2_t_alloc, ast_copy_string(), and find_static_data().
Referenced by sip_cc_monitor_suspend().
00901 { 00902 struct sip_epa_entry *epa_entry; 00903 const struct epa_static_data *static_data; 00904 00905 if (!(static_data = find_static_data(event_package))) { 00906 return NULL; 00907 } 00908 00909 if (!(epa_entry = ao2_t_alloc(sizeof(*epa_entry), static_data->destructor, "Allocate new EPA entry"))) { 00910 return NULL; 00911 } 00912 00913 epa_entry->static_data = static_data; 00914 ast_copy_string(epa_entry->destination, destination, sizeof(epa_entry->destination)); 00915 return epa_entry; 00916 }
| 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 1026 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().
01027 { 01028 struct sip_esc_entry *esc_entry; 01029 int expires_ms; 01030 01031 if (!(esc_entry = ao2_alloc(sizeof(*esc_entry), esc_entry_destructor))) { 01032 return NULL; 01033 } 01034 01035 esc_entry->event = esc->name; 01036 01037 expires_ms = expires * 1000; 01038 /* Bump refcount for scheduler */ 01039 ao2_ref(esc_entry, +1); 01040 esc_entry->sched_id = ast_sched_add(sched, expires_ms, publish_expire, esc_entry); 01041 01042 /* Note: This links the esc_entry into the ESC properly */ 01043 create_new_sip_etag(esc_entry, 0); 01044 01045 return esc_entry; 01046 }
| static void create_new_sip_etag | ( | struct sip_esc_entry * | esc_entry, | |
| int | is_linked | |||
| ) | [static] |
Definition at line 1013 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().
01014 { 01015 int new_etag = ast_atomic_fetchadd_int(&esc_etag_counter, +1); 01016 struct event_state_compositor *esc = get_esc(esc_entry->event); 01017 01018 ast_assert(esc != NULL); 01019 if (is_linked) { 01020 ao2_unlink(esc->compositor, esc_entry); 01021 } 01022 snprintf(esc_entry->entity_tag, sizeof(esc_entry->entity_tag), "%d", new_etag); 01023 ao2_link(esc->compositor, esc_entry); 01024 }
| static void deinit_req | ( | struct sip_request * | req | ) | [static] |
Deinitialize SIP response/request.
Definition at line 9370 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().
09371 { 09372 if (req->data) { 09373 ast_free(req->data); 09374 req->data = NULL; 09375 } 09376 if (req->content) { 09377 ast_free(req->content); 09378 req->content = NULL; 09379 } 09380 }
| static void destroy_association | ( | struct sip_peer * | peer | ) | [static] |
Remove registration data from realtime database or AST/DB when registration expires.
Definition at line 12664 of file chan_sip.c.
References ast_check_realtime(), ast_db_del(), ast_update_realtime(), SENTINEL, and sip_cfg.
Referenced by build_peer(), expire_register(), and parse_register_contact().
12665 { 12666 int realtimeregs = ast_check_realtime("sipregs"); 12667 char *tablename = (realtimeregs) ? "sipregs" : "sippeers"; 12668 12669 if (!sip_cfg.ignore_regexpire) { 12670 if (peer->rt_fromcontact && sip_cfg.peer_rtupdate) { 12671 ast_update_realtime(tablename, "name", peer->name, "fullcontact", "", "ipaddr", "", "port", "", "regseconds", "0", peer->deprecated_username ? "username" : "defaultuser", "", "regserver", "", "useragent", "", "lastms", "", SENTINEL); 12672 } else { 12673 ast_db_del("SIP/Registry", peer->name); 12674 ast_db_del("SIP/PeerMethods", peer->name); 12675 } 12676 } 12677 }
| static void destroy_escs | ( | void | ) | [static] |
Definition at line 1060 of file chan_sip.c.
References ao2_ref, ARRAY_LEN, and event_state_compositors.
Referenced by unload_module().
01061 { 01062 int i; 01063 for (i = 0; i < ARRAY_LEN(event_state_compositors); i++) { 01064 ao2_ref(event_state_compositors[i].compositor, -1); 01065 } 01066 }
| static void destroy_mailbox | ( | struct sip_mailbox * | mailbox | ) | [static] |
Destroy mailbox subscriptions
Definition at line 4259 of file chan_sip.c.
References ast_event_unsubscribe(), and ast_free.
Referenced by build_peer(), and clear_peer_mailboxes().
04260 { 04261 if (mailbox->event_sub) 04262 ast_event_unsubscribe(mailbox->event_sub); 04263 ast_free(mailbox); 04264 }
| static int determine_firstline_parts | ( | struct sip_request * | req | ) | [static] |
Parse first line of incoming SIP request.
Definition at line 10889 of file chan_sip.c.
References ast_debug, ast_skip_blanks(), ast_skip_nonblanks(), and ast_trim_blanks().
Referenced by parse_request().
10890 { 10891 char *e = ast_skip_blanks(req->data->str); /* there shouldn't be any */ 10892 char *local_rlPart1; 10893 10894 if (!*e) 10895 return -1; 10896 req->rlPart1 = e - req->data->str; /* method or protocol */ 10897 local_rlPart1 = e; 10898 e = ast_skip_nonblanks(e); 10899 if (*e) 10900 *e++ = '\0'; 10901 /* Get URI or status code */ 10902 e = ast_skip_blanks(e); 10903 if ( !*e ) 10904 return -1; 10905 ast_trim_blanks(e); 10906 10907 if (!strcasecmp(local_rlPart1, "SIP/2.0") ) { /* We have a response */ 10908 if (strlen(e) < 3) /* status code is 3 digits */ 10909 return -1; 10910 req->rlPart2 = e - req->data->str; 10911 } else { /* We have a request */ 10912 if ( *e == '<' ) { /* XXX the spec says it must not be in <> ! */ 10913 ast_debug(3, "Oops. Bogus uri in <> %s\n", e); 10914 e++; 10915 if (!*e) 10916 return -1; 10917 } 10918 req->rlPart2 = e - req->data->str; /* URI */ 10919 e = ast_skip_nonblanks(e); 10920 if (*e) 10921 *e++ = '\0'; 10922 e = ast_skip_blanks(e); 10923 if (strcasecmp(e, "SIP/2.0") ) { 10924 ast_debug(3, "Skipping packet - Bad request protocol %s\n", e); 10925 return -1; 10926 } 10927 } 10928 return 1; 10929 }
| 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 22393 of file chan_sip.c.
References ast_assert, and ast_strlen_zero().
Referenced by handle_request_publish().
22394 { 22395 int etag_present = !ast_strlen_zero(etag); 22396 int body_present = req->lines > 0; 22397 22398 ast_assert(expires_int != NULL); 22399 22400 if (ast_strlen_zero(expires)) { 22401 /* Section 6, item 4, second bullet point of RFC 3903 says to 22402 * use a locally-configured default expiration if none is provided 22403 * in the request 22404 */ 22405 *expires_int = DEFAULT_PUBLISH_EXPIRES; 22406 } else if (sscanf(expires, "%30d", expires_int) != 1) { 22407 return SIP_PUBLISH_UNKNOWN; 22408 } 22409 22410 if (*expires_int == 0) { 22411 return SIP_PUBLISH_REMOVE; 22412 } else if (!etag_present && body_present) { 22413 return SIP_PUBLISH_INITIAL; 22414 } else if (etag_present && !body_present) { 22415 return SIP_PUBLISH_REFRESH; 22416 } else if (etag_present && body_present) { 22417 return SIP_PUBLISH_MODIFY; 22418 } 22419 22420 return SIP_PUBLISH_UNKNOWN; 22421 }
| static int dialog_cmp_cb | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 28085 of file chan_sip.c.
References CMP_MATCH, and CMP_STOP.
Referenced by load_module().
28086 { 28087 struct sip_pvt *pvt = obj, *pvt2 = arg; 28088 28089 return !strcasecmp(pvt->callid, pvt2->callid) ? CMP_MATCH | CMP_STOP : 0; 28090 }
| static int dialog_dump_func | ( | void * | userobj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 15699 of file chan_sip.c.
References ao2_t_ref, ast_cli(), and ast_cli_args::fd.
Referenced by sip_show_objects().
15700 { 15701 struct sip_pvt *pvt = userobj; 15702 int refc = ao2_t_ref(userobj, 0, ""); 15703 struct ast_cli_args *a = (struct ast_cli_args *) arg; 15704 15705 ast_cli(a->fd, "name: %s\ntype: dialog\nobjflags: %d\nrefcount: %d\n\n", 15706 pvt->callid, 0, refc); 15707 return 0; 15708 }
| static int dialog_find_multiple | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 28075 of file chan_sip.c.
References CMP_MATCH.
Referenced by find_call().
28076 { 28077 struct sip_pvt *pvt = obj, *pvt2 = arg; 28078 28079 return !strcasecmp(pvt->callid, pvt2->callid) ? CMP_MATCH : 0; 28080 }
| static int dialog_hash_cb | ( | const void * | obj, | |
| const int | flags | |||
| ) | [static] |
Definition at line 28065 of file chan_sip.c.
References ast_str_case_hash().
Referenced by load_module().
28066 { 28067 const struct sip_pvt *pvt = obj; 28068 28069 return ast_str_case_hash(pvt->callid); 28070 }
| static int dialog_initialize_rtp | ( | struct sip_pvt * | dialog | ) | [static] |
Initialize RTP portion of a dialog.
Definition at line 4748 of file chan_sip.c.
References AST_FORMAT_VIDEO_MASK, ast_rtp_instance_new(), ast_rtp_instance_set_hold_timeout(), 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().
04749 { 04750 struct ast_sockaddr bindaddr_tmp; 04751 04752 if (!sip_methods[dialog->method].need_rtp) { 04753 return 0; 04754 } 04755 04756 ast_sockaddr_copy(&bindaddr_tmp, &bindaddr); 04757 if (!(dialog->rtp = ast_rtp_instance_new(dialog->engine, sched, &bindaddr_tmp, NULL))) { 04758 return -1; 04759 } 04760 04761 if (ast_test_flag(&dialog->flags[1], SIP_PAGE2_VIDEOSUPPORT_ALWAYS) || 04762 (ast_test_flag(&dialog->flags[1], SIP_PAGE2_VIDEOSUPPORT) && (dialog->capability & AST_FORMAT_VIDEO_MASK))) { 04763 if (!(dialog->vrtp = ast_rtp_instance_new(dialog->engine, sched, &bindaddr_tmp, NULL))) { 04764 return -1; 04765 } 04766 ast_rtp_instance_set_timeout(dialog->vrtp, global_rtptimeout); 04767 ast_rtp_instance_set_hold_timeout(dialog->vrtp, global_rtpholdtimeout); 04768 04769 ast_rtp_instance_set_prop(dialog->vrtp, AST_RTP_PROPERTY_RTCP, 1); 04770 } 04771 04772 if (ast_test_flag(&dialog->flags[1], SIP_PAGE2_TEXTSUPPORT)) { 04773 if (!(dialog->trtp = ast_rtp_instance_new(dialog->engine, sched, &bindaddr_tmp, NULL))) { 04774 return -1; 04775 } 04776 ast_rtp_instance_set_timeout(dialog->trtp, global_rtptimeout); 04777 ast_rtp_instance_set_hold_timeout(dialog->trtp, global_rtpholdtimeout); 04778 04779 ast_rtp_instance_set_prop(dialog->trtp, AST_RTP_PROPERTY_RTCP, 1); 04780 } 04781 04782 ast_rtp_instance_set_timeout(dialog->rtp, global_rtptimeout); 04783 ast_rtp_instance_set_hold_timeout(dialog->rtp, global_rtpholdtimeout); 04784 04785 ast_rtp_instance_set_prop(dialog->rtp, AST_RTP_PROPERTY_RTCP, 1); 04786 ast_rtp_instance_set_prop(dialog->rtp, AST_RTP_PROPERTY_DTMF, ast_test_flag(&dialog->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833); 04787 ast_rtp_instance_set_prop(dialog->rtp, AST_RTP_PROPERTY_DTMF_COMPENSATE, ast_test_flag(&dialog->flags[1], SIP_PAGE2_RFC2833_COMPENSATE)); 04788 04789 ast_rtp_instance_set_qos(dialog->rtp, global_tos_audio, global_cos_audio, "SIP RTP"); 04790 04791 do_setnat(dialog); 04792 04793 return 0; 04794 }
| 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. It will return CMP_MATCH for candidates, and they will be unlinked.
Definition at line 15818 of file chan_sip.c.
References ast_debug, ast_rtp_instance_get_bridged(), check_rtp_timeout(), dialog_unlink_all(), FALSE, sip_methods, sip_pvt_trylock, sip_pvt_unlock, cfsip_methods::text, and TRUE.
Referenced by do_monitor().
15819 { 15820 struct sip_pvt *dialog = dialogobj; 15821 time_t *t = arg; 15822 15823 if (sip_pvt_trylock(dialog)) { 15824 /* Don't block the monitor thread. This function is called often enough 15825 * that we can wait for the next time around. */ 15826 return 0; 15827 } 15828 15829 /* We absolutely cannot destroy the rtp struct while a bridge is active or we WILL crash */ 15830 if (dialog->rtp && ast_rtp_instance_get_bridged(dialog->rtp)) { 15831 ast_debug(2, "Bridge still active. Delaying destroy of SIP dialog '%s' Method: %s\n", dialog->callid, sip_methods[dialog->method].text); 15832 sip_pvt_unlock(dialog); 15833 return 0; 15834 } 15835 15836 if (dialog->vrtp && ast_rtp_instance_get_bridged(dialog->vrtp)) { 15837 ast_debug(2, "Bridge still active. Delaying destroy of SIP dialog '%s' Method: %s\n", dialog->callid, sip_methods[dialog->method].text); 15838 sip_pvt_unlock(dialog); 15839 return 0; 15840 } 15841 15842 /* Check RTP timeouts and kill calls if we have a timeout set and do not get RTP */ 15843 check_rtp_timeout(dialog, *t); 15844 15845 /* If we have sessions that needs to be destroyed, do it now */ 15846 /* Check if we have outstanding requests not responsed to or an active call 15847 - if that's the case, wait with destruction */ 15848 if (dialog->needdestroy && !dialog->packets && !dialog->owner) { 15849 /* We absolutely cannot destroy the rtp struct while a bridge is active or we WILL crash */ 15850 if (dialog->rtp && ast_rtp_instance_get_bridged(dialog->rtp)) { 15851 ast_debug(2, "Bridge still active. Delaying destruction of SIP dialog '%s' Method: %s\n", dialog->callid, sip_methods[dialog->method].text); 15852 sip_pvt_unlock(dialog); 15853 return 0; 15854 } 15855 15856 if (dialog->vrtp && ast_rtp_instance_get_bridged(dialog->vrtp)) { 15857 ast_debug(2, "Bridge still active. Delaying destroy of SIP dialog '%s' Method: %s\n", dialog->callid, sip_methods[dialog->method].text); 15858 sip_pvt_unlock(dialog); 15859 return 0; 15860 } 15861 15862 sip_pvt_unlock(dialog); 15863 /* no, the unlink should handle this: dialog_unref(dialog, "needdestroy: one more refcount decrement to allow dialog to be destroyed"); */ 15864 /* the CMP_MATCH will unlink this dialog from the dialog hash table */ 15865 dialog_unlink_all(dialog, TRUE, FALSE); 15866 return 0; /* the unlink_all should unlink this from the table, so.... no need to return a match */ 15867 } 15868 15869 sip_pvt_unlock(dialog); 15870 15871 return 0; 15872 }
| struct sip_pvt* dialog_ref_debug | ( | struct sip_pvt * | p, | |
| char * | tag, | |||
| char * | file, | |||
| int | line, | |||
| const char * | func | |||
| ) | [read] |
Definition at line 2172 of file chan_sip.c.
References __ao2_ref_debug(), ao2_ref, ast_log(), and LOG_ERROR.
02173 { 02174 if (p) 02175 #ifdef REF_DEBUG 02176 __ao2_ref_debug(p, 1, tag, file, line, func); 02177 #else 02178 ao2_ref(p, 1); 02179 #endif 02180 else 02181 ast_log(LOG_ERROR, "Attempt to Ref a null pointer\n"); 02182 return p; 02183 }
| void* dialog_unlink_all | ( | struct sip_pvt * | dialog, | |
| int | lockowner, | |||
| int | lockdialoglist | |||
| ) |
Unlink a dialog from the dialogs container, as well as any other places that it may be currently stored.
Definition at line 2702 of file chan_sip.c.
References ao2_t_unlink, ast_channel_lock, ast_channel_unlock, ast_debug, ast_extension_state_del(), ast_free, AST_SCHED_DEL, AST_SCHED_DEL_UNREF, and registry_unref().
Referenced by __sip_autodestruct(), __sip_subscribe_mwi_do(), dialog_needdestroy(), handle_request_subscribe(), manager_sipnotify(), reload_config(), sip_cli_notify(), sip_destroy_peer(), sip_poke_noanswer(), sip_poke_peer(), sip_registry_destroy(), sip_request_call(), sip_send_mwi_to_peer(), transmit_publish(), transmit_register(), and unload_module().
02703 { 02704 struct sip_pkt *cp; 02705 02706 dialog_ref(dialog, "Let's bump the count in the unlink so it doesn't accidentally become dead before we are done"); 02707 02708 ao2_t_unlink(dialogs, dialog, "unlinking dialog via ao2_unlink"); 02709 02710 /* Unlink us from the owner (channel) if we have one */ 02711 if (dialog->owner) { 02712 if (lockowner) 02713 ast_channel_lock(dialog->owner); 02714 ast_debug(1, "Detaching from channel %s\n", dialog->owner->name); 02715 dialog->owner->tech_pvt = dialog_unref(dialog->owner->tech_pvt, "resetting channel dialog ptr in unlink_all"); 02716 if (lockowner) { 02717 ast_channel_unlock(dialog->owner); 02718 } 02719 } 02720 if (dialog->registry) { 02721 if (dialog->registry->call == dialog) { 02722 dialog->registry->call = dialog_unref(dialog->registry->call, "nulling out the registry's call dialog field in unlink_all"); 02723 } 02724 dialog->registry = registry_unref(dialog->registry, "delete dialog->registry"); 02725 } 02726 if (dialog->stateid > -1) { 02727 ast_extension_state_del(dialog->stateid, NULL); 02728 dialog_unref(dialog, "removing extension_state, should unref the associated dialog ptr that was stored there."); 02729 dialog->stateid = -1; /* shouldn't we 'zero' this out? */ 02730 } 02731 /* Remove link from peer to subscription of MWI */ 02732 if (dialog->relatedpeer && dialog->relatedpeer->mwipvt == dialog) { 02733 dialog->relatedpeer->mwipvt = dialog_unref(dialog->relatedpeer->mwipvt, "delete ->relatedpeer->mwipvt"); 02734 } 02735 if (dialog->relatedpeer && dialog->relatedpeer->call == dialog) { 02736 dialog->relatedpeer->call = dialog_unref(dialog->relatedpeer->call, "unset the relatedpeer->call field in tandem with relatedpeer field itself"); 02737 } 02738 02739 /* remove all current packets in this dialog */ 02740 while((cp = dialog->packets)) { 02741 dialog->packets = dialog->packets->next; 02742 AST_SCHED_DEL(sched, cp->retransid); 02743 dialog_unref(cp->owner, "remove all current packets in this dialog, and the pointer to the dialog too as part of __sip_destroy"); 02744 if (cp->data) { 02745 ast_free(cp->data); 02746 } 02747 ast_free(cp); 02748 } 02749 02750 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")); 02751 02752 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")); 02753 02754 if (dialog->autokillid > -1) { 02755 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")); 02756 } 02757 02758 if (dialog->request_queue_sched_id > -1) { 02759 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")); 02760 } 02761 02762 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")); 02763 02764 if (dialog->t38id > -1) { 02765 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")); 02766 } 02767 02768 dialog_unref(dialog, "Let's unbump the count in the unlink so the poor pvt can disappear if it is time"); 02769 return NULL; 02770 }
| struct sip_pvt* dialog_unref_debug | ( | struct sip_pvt * | p, | |
| char * | tag, | |||
| char * | file, | |||
| int | line, | |||
| const char * | func | |||
| ) | [read] |
Definition at line 2185 of file chan_sip.c.
References __ao2_ref_debug(), and ao2_ref.
02186 { 02187 if (p) 02188 #ifdef REF_DEBUG 02189 __ao2_ref_debug(p, -1, tag, file, line, func); 02190 #else 02191 ao2_ref(p, -1); 02192 #endif 02193 return NULL; 02194 }
| static void disable_dsp_detect | ( | struct sip_pvt * | p | ) | [static] |
Definition at line 3971 of file chan_sip.c.
References ast_dsp_free().
Referenced by sip_dtmfmode(), sip_hangup(), and sip_setoption().
03972 { 03973 if (p->dsp) { 03974 ast_dsp_free(p->dsp); 03975 p->dsp = NULL; 03976 } 03977 }
| static int do_magic_pickup | ( | struct ast_channel * | channel, | |
| const char * | extension, | |||
| const char * | context | |||
| ) | [static] |
Definition at line 20697 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().
20698 { 20699 struct ast_str *str = ast_str_alloca(AST_MAX_EXTENSION + AST_MAX_CONTEXT + 2); 20700 struct ast_app *pickup = pbx_findapp("Pickup"); 20701 20702 if (!pickup) { 20703 ast_log(LOG_ERROR, "Unable to perform pickup: Application 'Pickup' not loaded (app_directed_pickup.so).\n"); 20704 return -1; 20705 } 20706 20707 ast_str_set(&str, 0, "%s@%s", extension, sip_cfg.notifycid == IGNORE_CONTEXT ? "PICKUPMARK" : context); 20708 20709 ast_debug(2, "About to call Pickup(%s)\n", str->str); 20710 20711 /* There is no point in capturing the return value since pickup_exec 20712 doesn't return anything meaningful unless the passed data is an empty 20713 string (which in our case it will not be) */ 20714 pbx_exec(channel, pickup, str->str); 20715 20716 return 0; 20717 }
| static void * do_monitor | ( | void * | data | ) | [static] |
The SIP monitoring thread.
Definition at line 24231 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_needdestroy(), FALSE, monlock, OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, sip_do_reload(), sip_reload_lock, and sipsock_read().
24232 { 24233 int res; 24234 time_t t; 24235 int reloading; 24236 24237 /* Add an I/O event to our SIP UDP socket */ 24238 if (sipsock > -1) 24239 sipsock_read_id = ast_io_add(io, sipsock, sipsock_read, AST_IO_IN, NULL); 24240 24241 /* From here on out, we die whenever asked */ 24242 for(;;) { 24243 /* Check for a reload request */ 24244 ast_mutex_lock(&sip_reload_lock); 24245 reloading = sip_reloading; 24246 sip_reloading = FALSE; 24247 ast_mutex_unlock(&sip_reload_lock); 24248 if (reloading) { 24249 ast_verb(1, "Reloading SIP\n"); 24250 sip_do_reload(sip_reloadreason); 24251 24252 /* Change the I/O fd of our UDP socket */ 24253 if (sipsock > -1) { 24254 if (sipsock_read_id) 24255 sipsock_read_id = ast_io_change(io, sipsock_read_id, sipsock, NULL, 0, NULL); 24256 else 24257 sipsock_read_id = ast_io_add(io, sipsock, sipsock_read, AST_IO_IN, NULL); 24258 } else if (sipsock_read_id) { 24259 ast_io_remove(io, sipsock_read_id); 24260 sipsock_read_id = NULL; 24261 } 24262 } 24263 24264 /* Check for dialogs needing to be killed */ 24265 t = time(NULL); 24266 /* don't scan the dialogs list if it hasn't been a reasonable period 24267 of time since the last time we did it (when MWI is being sent, we can 24268 get back to this point every millisecond or less) 24269 */ 24270 ao2_t_callback(dialogs, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, dialog_needdestroy, &t, 24271 "callback to remove dialogs w/needdestroy"); 24272 24273 /* the old methodology would be to restart the search for dialogs to delete with every 24274 dialog that was found and destroyed, probably because the list contents would change, 24275 so we'd need to restart. This isn't the best thing to do with callbacks. */ 24276 24277 /* XXX TODO The scheduler usage in this module does not have sufficient 24278 * synchronization being done between running the scheduler and places 24279 * scheduling tasks. As it is written, any scheduled item may not run 24280 * any sooner than about 1 second, regardless of whether a sooner time 24281 * was asked for. */ 24282 24283 pthread_testcancel(); 24284 /* Wait for sched or io */ 24285 res = ast_sched_wait(sched); 24286 if ((res < 0) || (res > 1000)) 24287 res = 1000; 24288 res = ast_io_wait(io, res); 24289 if (res > 20) 24290 ast_debug(1, "chan_sip: ast_io_wait ran %d all at once\n", res); 24291 ast_mutex_lock(&monlock); 24292 res = ast_sched_runq(sched); 24293 if (res >= 20) 24294 ast_debug(1, "chan_sip: ast_sched_runq ran %d all at once\n", res); 24295 ast_mutex_unlock(&monlock); 24296 } 24297 24298 /* Never reached */ 24299 return NULL; 24300 }
| 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 17917 of file chan_sip.c.
References ast_calloc, ast_debug, auth_headers(), reply_digest(), 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().
17918 { 17919 char *header, *respheader; 17920 char digest[1024]; 17921 17922 if (!p->options && !(p->options = ast_calloc(1, sizeof(*p->options)))) 17923 return -2; 17924 17925 p->authtries++; 17926 auth_headers(code, &header, &respheader); 17927 ast_debug(2, "Auth attempt %d on %s\n", p->authtries, sip_methods[sipmethod].text); 17928 memset(digest, 0, sizeof(digest)); 17929 if (reply_digest(p, req, header, sipmethod, digest, sizeof(digest) )) { 17930 /* No way to authenticate */ 17931 return -1; 17932 } 17933 /* Now we have a reply digest */ 17934 p->options->auth = digest; 17935 p->options->authheader = respheader; 17936 return transmit_invite(p, sipmethod, sipmethod == SIP_INVITE, init, NULL); 17937 }
| 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 17893 of file chan_sip.c.
References append_history, ast_verbose, auth_headers(), reply_digest(), sip_debug_test_pvt(), and transmit_register().
Referenced by handle_response_register().
17894 { 17895 char *header, *respheader; 17896 char digest[1024]; 17897 17898 p->authtries++; 17899 auth_headers(code, &header, &respheader); 17900 memset(digest, 0, sizeof(digest)); 17901 if (reply_digest(p, req, header, SIP_REGISTER, digest, sizeof(digest))) { 17902 /* There's nothing to use for authentication */ 17903 /* No digest challenge in request */ 17904 if (sip_debug_test_pvt(p) && p->registry) 17905 ast_verbose("No authentication challenge, sending blank registration to domain/host name %s\n", p->registry->hostname); 17906 /* No old challenge */ 17907 return -1; 17908 } 17909 if (p->do_history) 17910 append_history(p, "RegistryAuth", "Try: %d", p->authtries); 17911 if (sip_debug_test_pvt(p) && p->registry) 17912 ast_verbose("Responding to challenge, registration to domain/host name %s\n", p->registry->hostname); 17913 return transmit_register(p->registry, SIP_REGISTER, digest, respheader); 17914 }
| static void do_setnat | ( | struct sip_pvt * | p | ) | [static] |
Set nat mode on the various data sockets.
Definition at line 4642 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().
04643 { 04644 const char *mode; 04645 int natflags; 04646 04647 natflags = ast_test_flag(&p->flags[1], SIP_PAGE2_SYMMETRICRTP); 04648 mode = natflags ? "On" : "Off"; 04649 04650 if (p->rtp) { 04651 ast_debug(1, "Setting NAT on RTP to %s\n", mode); 04652 ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_NAT, natflags); 04653 } 04654 if (p->vrtp) { 04655 ast_debug(1, "Setting NAT on VRTP to %s\n", mode); 04656 ast_rtp_instance_set_prop(p->vrtp, AST_RTP_PROPERTY_NAT, natflags); 04657 } 04658 if (p->udptl) { 04659 ast_debug(1, "Setting NAT on UDPTL to %s\n", mode); 04660 ast_udptl_setnat(p->udptl, natflags); 04661 } 04662 if (p->trtp) { 04663 ast_debug(1, "Setting NAT on TRTP to %s\n", mode); 04664 ast_rtp_instance_set_prop(p->trtp, AST_RTP_PROPERTY_NAT, natflags); 04665 } 04666 }
| static const char * domain_mode_to_text | ( | const enum domain_mode | mode | ) | [static] |
Print domain mode to cli.
Definition at line 16027 of file chan_sip.c.
Referenced by sip_show_domains().
16028 { 16029 switch (mode) { 16030 case SIP_DOMAIN_AUTO: 16031 return "[Automatic]"; 16032 case SIP_DOMAIN_CONFIG: 16033 return "[Configured]"; 16034 } 16035 16036 return ""; 16037 }
| static const char * dtmfmode2str | ( | int | mode | ) | [static] |
Convert DTMF mode to printable string.
Definition at line 15755 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 3938 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().
03939 { 03940 int features = 0; 03941 03942 if (p->dsp) { 03943 return; 03944 } 03945 03946 if ((ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_INBAND) || 03947 (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO)) { 03948 if (!p->rtp || ast_rtp_instance_dtmf_mode_set(p->rtp, AST_RTP_DTMF_MODE_INBAND)) { 03949 features |= DSP_FEATURE_DIGIT_DETECT; 03950 } 03951 } 03952 03953 if (ast_test_flag(&p->flags[1], SIP_PAGE2_FAX_DETECT_CNG)) { 03954 features |= DSP_FEATURE_FAX_DETECT; 03955 } 03956 03957 if (!features) { 03958 return; 03959 } 03960 03961 if (!(p->dsp = ast_dsp_new())) { 03962 return; 03963 } 03964 03965 ast_dsp_set_features(p->dsp, features); 03966 if (global_relaxdtmf) { 03967 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | DSP_DIGITMODE_RELAXDTMF); 03968 } 03969 }
| static int esc_cmp_fn | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 972 of file chan_sip.c.
References CMP_MATCH, and CMP_STOP.
Referenced by initialize_escs().
00973 { 00974 struct sip_esc_entry *entry1 = obj; 00975 struct sip_esc_entry *entry2 = arg; 00976 00977 return (!strcmp(entry1->entity_tag, entry2->entity_tag)) ? (CMP_MATCH | CMP_STOP) : 0; 00978 }
| static void esc_entry_destructor | ( | void * | obj | ) | [static] |
Definition at line 958 of file chan_sip.c.
References AST_SCHED_DEL.
Referenced by create_esc_entry().
00959 { 00960 struct sip_esc_entry *esc_entry = obj; 00961 if (esc_entry->sched_id > -1) { 00962 AST_SCHED_DEL(sched, esc_entry->sched_id); 00963 } 00964 }
| static int esc_hash_fn | ( | const void * | obj, | |
| const int | flags | |||
| ) | [static] |
Definition at line 966 of file chan_sip.c.
References ast_str_hash().
Referenced by initialize_escs().
00967 { 00968 const struct sip_esc_entry *entry = obj; 00969 return ast_str_hash(entry->entity_tag); 00970 }
| static int expire_register | ( | const void * | data | ) | [static] |
Expire registration of SIP peer.
Definition at line 12693 of file chan_sip.c.
References ao2_ref, ast_debug, AST_DEVICE_UNKNOWN, ast_devstate_changed(), ast_test_flag, destroy_association(), EVENT_FLAG_SYSTEM, FALSE, manager_event, register_peer_exten(), set_socket_transport(), unlink_peer_from_tables(), and unref_peer().
Referenced by parse_register_contact(), realtime_peer(), reg_source_db(), sip_show_sched(), and sip_unregister().
12694 { 12695 struct sip_peer *peer = (struct sip_peer *)data; 12696 12697 if (!peer) { /* Hmmm. We have no peer. Weird. */ 12698 return 0; 12699 } 12700 12701 peer->expire = -1; 12702 peer->portinuri = 0; 12703 12704 destroy_association(peer); /* remove registration data from storage */ 12705 set_socket_transport(&peer->socket, peer->default_outbound_transport); 12706 12707 if (peer->socket.tcptls_session) { 12708 ao2_ref(peer->socket.tcptls_session, -1); 12709 peer->socket.tcptls_session = NULL; 12710 } 12711 12712 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: SIP\r\nPeer: SIP/%s\r\nPeerStatus: Unregistered\r\nCause: Expired\r\n", peer->name); 12713 register_peer_exten(peer, FALSE); /* Remove regexten */ 12714 ast_devstate_changed(AST_DEVICE_UNKNOWN, "SIP/%s", peer->name); 12715 12716 /* Do we need to release this peer from memory? 12717 Only for realtime peers and autocreated peers 12718 */ 12719 if (peer->is_realtime) { 12720 ast_debug(3, "-REALTIME- peer expired registration. Name: %s. Realtime peer objects now %d\n", peer->name, rpeerobjs); 12721 } 12722 12723 if (peer->selfdestruct || 12724 ast_test_flag(&peer->flags[1], SIP_PAGE2_RTAUTOCLEAR)) { 12725 unlink_peer_from_tables(peer); 12726 } 12727 12728 /* Only clear the addr after we check for destruction. The addr must remain 12729 * in order to unlink from the peers_by_ip container correctly */ 12730 memset(&peer->addr, 0, sizeof(peer->addr)); 12731 12732 unref_peer(peer, "removing peer ref for expire_register"); 12733 12734 return 0; 12735 }
| static void extract_uri | ( | struct sip_pvt * | p, | |
| struct sip_request * | req | |||
| ) | [static] |
Check Contact: URI of SIP message.
Definition at line 10997 of file chan_sip.c.
References ast_copy_string(), ast_string_field_set, ast_strlen_zero(), get_header(), and remove_uri_parameters().
Referenced by handle_incoming(), and handle_request_invite().
10998 { 10999 char stripped[SIPBUFSIZE]; 11000 char *c; 11001 11002 ast_copy_string(stripped, get_header(req, "Contact"), sizeof(stripped)); 11003 c = get_in_brackets(stripped); 11004 /* Cut the URI at the at sign after the @, not in the username part */ 11005 c = remove_uri_parameters(c); 11006 if (!ast_strlen_zero(c)) { 11007 ast_string_field_set(p, uri, c); 11008 } 11009 11010 }
| static const char* faxec2str | ( | int | faxec | ) | [static] |
Definition at line 16191 of file chan_sip.c.
References map_x_s().
Referenced by _sip_show_peer(), and sip_show_settings().
16192 { 16193 return map_x_s(faxecmodes, faxec, "Unknown"); 16194 }
| static int finalize_content | ( | struct sip_request * | req | ) | [static] |
Add 'Content-Length' header and content to SIP message.
Definition at line 9083 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().
09084 { 09085 char clen[10]; 09086 09087 if (req->lines) { 09088 ast_log(LOG_WARNING, "finalize_content() called on a message that has already been finalized\n"); 09089 return -1; 09090 } 09091 09092 snprintf(clen, sizeof(clen), "%zd", ast_str_strlen(req->content)); 09093 add_header(req, "Content-Length", clen); 09094 09095 if (ast_str_strlen(req->content)) { 09096 ast_str_append(&req->data, 0, "\r\n%s", ast_str_buffer(req->content)); 09097 req->len = ast_str_strlen(req->data); 09098 } 09099 req->lines = ast_str_strlen(req->content) ? 1 : 0; 09100 return 0; 09101 }
| static const char * find_alias | ( | const char * | name, | |
| const char * | _default | |||
| ) | [static] |
Find compressed SIP alias.
Structure for conversion between compressed SIP and "normal" SIP
Definition at line 6740 of file chan_sip.c.
References aliases, and ARRAY_LEN.
06741 { 06742 /*! \brief Structure for conversion between compressed SIP and "normal" SIP */ 06743 static const struct cfalias { 06744 char * const fullname; 06745 char * const shortname; 06746 } aliases[] = { 06747 { "Content-Type", "c" }, 06748 { "Content-Encoding", "e" }, 06749 { "From", "f" }, 06750 { "Call-ID", "i" }, 06751 { "Contact", "m" }, 06752 { "Content-Length", "l" }, 06753 { "Subject", "s" }, 06754 { "To", "t" }, 06755 { "Supported", "k" }, 06756 { "Refer-To", "r" }, 06757 { "Referred-By", "b" }, 06758 { "Allow-Events", "u" }, 06759 { "Event", "o" }, 06760 { "Via", "v" }, 06761 { "Accept-Contact", "a" }, 06762 { "Reject-Contact", "j" }, 06763 { "Request-Disposition", "d" }, 06764 { "Session-Expires", "x" }, 06765 { "Identity", "y" }, 06766 { "Identity-Info", "n" }, 06767 }; 06768 int x; 06769 06770 for (x = 0; x < ARRAY_LEN(aliases); x++) { 06771 if (!strcasecmp(aliases[x].fullname, name)) 06772 return aliases[x].shortname; 06773 } 06774 06775 return _default; 06776 }
| static int find_by_callid_helper | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 1652 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().
01653 { 01654 struct ast_cc_agent *agent = obj; 01655 struct sip_cc_agent_pvt *agent_pvt = agent->private_data; 01656 struct sip_pvt *call_pvt = arg; 01657 01658 return !strcmp(agent_pvt->original_callid, call_pvt->callid) ? CMP_MATCH | CMP_STOP : 0; 01659 }
| static int find_by_name | ( | void * | obj, | |
| void * | arg, | |||
| void * | data, | |||
| int | flags | |||
| ) | [static] |
Definition at line 4553 of file chan_sip.c.
References CMP_MATCH, CMP_STOP, and match().
Referenced by find_peer().
04554 { 04555 struct sip_peer *search = obj, *match = arg; 04556 int *which_objects = data; 04557 04558 /* Usernames in SIP uri's are case sensitive. Domains are not */ 04559 if (strcmp(search->name, match->name)) { 04560 return 0; 04561 } 04562 04563 switch (*which_objects) { 04564 case FINDUSERS: 04565 if (!(search->type & SIP_TYPE_USER)) { 04566 return 0; 04567 } 04568 break; 04569 case FINDPEERS: 04570 if (!(search->type & SIP_TYPE_PEER)) { 04571 return 0; 04572 } 04573 break; 04574 case FINDALLDEVICES: 04575 break; 04576 } 04577 04578 return CMP_MATCH | CMP_STOP; 04579 }
| static int find_by_notify_uri_helper | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 1622 of file chan_sip.c.
References CMP_MATCH, CMP_STOP, and ast_cc_agent::private_data.
Referenced by find_sip_cc_agent_by_notify_uri().
01623 { 01624 struct ast_cc_agent *agent = obj; 01625 struct sip_cc_agent_pvt *agent_pvt = agent->private_data; 01626 const char *uri = arg; 01627 01628 return !strcmp(agent_pvt->notify_uri, uri) ? CMP_MATCH | CMP_STOP : 0; 01629 }
| static int find_by_subscribe_uri_helper | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 1637 of file chan_sip.c.
References CMP_MATCH, CMP_STOP, and ast_cc_agent::private_data.
Referenced by find_sip_cc_agent_by_subscribe_uri().
01638 { 01639 struct ast_cc_agent *agent = obj; 01640 struct sip_cc_agent_pvt *agent_pvt = agent->private_data; 01641 const char *uri = arg; 01642 01643 return !strcmp(agent_pvt->subscribe_uri, uri) ? CMP_MATCH | CMP_STOP : 0; 01644 }
| 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_incoming(), sipsock_read
Definition at line 7334 of file chan_sip.c.
References ao2_iterator_destroy(), ao2_iterator_next, ao2_t_callback, ao2_t_find, args, ast_debug, ast_strdupa, ast_strlen_zero(), match_req_args::authentication_present, match_req_args::callid, dialog_find_multiple(), match_req_args::fromtag, get_header(), gettag(), match_req_to_dialog(), match_req_args::method, OBJ_MULTIPLE, OBJ_POINTER, match_req_args::ruri, match_req_args::seqno, sip_alloc(), sip_cfg, sip_methods, sip_pvt_lock, 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().
07335 { 07336 struct sip_pvt *p = NULL; 07337 char totag[128]; 07338 char fromtag[128]; 07339 const char *callid = get_header(req, "Call-ID"); 07340 const char *from = get_header(req, "From"); 07341 const char *to = get_header(req, "To"); 07342 const char *cseq = get_header(req, "Cseq"); 07343 struct sip_pvt *sip_pvt_ptr; 07344 unsigned int seqno; 07345 /* Call-ID, to, from and Cseq are required by RFC 3261. (Max-forwards and via too - ignored now) */ 07346 /* get_header always returns non-NULL so we must use ast_strlen_zero() */ 07347 if (ast_strlen_zero(callid) || ast_strlen_zero(to) || 07348 ast_strlen_zero(from) || ast_strlen_zero(cseq) || 07349 (sscanf(cseq, "%30u", &seqno) != 1)) { 07350 07351 /* RFC 3261 section 24.4.1. Send a 400 Bad Request if the request is malformed. */ 07352 if (intended_method != SIP_RESPONSE && intended_method != SIP_ACK) { 07353 transmit_response_using_temp(callid, addr, 1, intended_method, 07354 req, "400 Bad Request"); 07355 } 07356 return NULL; /* Invalid packet */ 07357 } 07358 07359 if (sip_cfg.pedanticsipchecking) { 07360 /* In principle Call-ID's uniquely identify a call, but with a forking SIP proxy 07361 we need more to identify a branch - so we have to check branch, from 07362 and to tags to identify a call leg. 07363 For Asterisk to behave correctly, you need to turn on pedanticsipchecking 07364 in sip.conf 07365 */ 07366 if (gettag(req, "To", totag, sizeof(totag))) 07367 req->has_to_tag = 1; /* Used in handle_request/response */ 07368 gettag(req, "From", fromtag, sizeof(fromtag)); 07369 07370 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); 07371 07372 /* All messages must always have From: tag */ 07373 if (ast_strlen_zero(fromtag)) { 07374 ast_debug(5, "%s request has no from tag, dropping callid: %s from: %s\n", sip_methods[req->method].text , callid, from ); 07375 return NULL; 07376 } 07377 /* reject requests that must always have a To: tag */ 07378 if (ast_strlen_zero(totag) && (req->method == SIP_ACK || req->method == SIP_BYE || req->method == SIP_INFO )) { 07379 if (req->method != SIP_ACK) { 07380 transmit_response_using_temp(callid, addr, 1, intended_method, req, "481 Call leg/transaction does not exist"); 07381 } 07382 ast_debug(5, "%s must have a to tag. dropping callid: %s from: %s\n", sip_methods[req->method].text , callid, from ); 07383 return NULL; 07384 } 07385 } 07386 07387 if (!sip_cfg.pedanticsipchecking) { 07388 struct sip_pvt tmp_dialog = { 07389 .callid = callid, 07390 }; 07391 sip_pvt_ptr = ao2_t_find(dialogs, &tmp_dialog, OBJ_POINTER, "ao2_find in dialogs"); 07392 if (sip_pvt_ptr) { /* well, if we don't find it-- what IS in there? */ 07393 /* Found the call */ 07394 sip_pvt_lock(sip_pvt_ptr); 07395 return sip_pvt_ptr; 07396 } 07397 } else { /* in pedantic mode! -- do the fancy search */ 07398 struct sip_pvt tmp_dialog = { 07399 .callid = callid, 07400 }; 07401 struct match_req_args args = { 0, }; 07402 int found; 07403 struct ao2_iterator *iterator = ao2_t_callback(dialogs, 07404 OBJ_POINTER | OBJ_MULTIPLE, 07405 dialog_find_multiple, 07406 &tmp_dialog, 07407 "pedantic ao2_find in dialogs"); 07408 07409 args.method = req->method; 07410 args.callid = NULL; /* we already matched this. */ 07411 args.totag = totag; 07412 args.fromtag = fromtag; 07413 args.seqno = seqno; 07414 07415 /* If this is a Request, set the Via and Authorization header arguments */ 07416 if (req->method != SIP_RESPONSE) { 07417 args.ruri = REQ_OFFSET_TO_STR(req, rlPart2); 07418 get_viabranch(ast_strdupa(get_header(req, "Via")), (char **) &args.viasentby, (char **) &args.viabranch); 07419 if (!ast_strlen_zero(get_header(req, "Authorization")) || 07420 !ast_strlen_zero(get_header(req, "Proxy-Authorization"))) { 07421 args.authentication_present = 1; 07422 } 07423 } 07424 07425 /* Iterate a list of dialogs already matched by Call-id */ 07426 while (iterator && (sip_pvt_ptr = ao2_iterator_next(iterator))) { 07427 found = match_req_to_dialog(sip_pvt_ptr, &args); 07428 07429 switch (found) { 07430 case SIP_REQ_MATCH: 07431 sip_pvt_lock(sip_pvt_ptr); 07432 ao2_iterator_destroy(iterator); 07433 return sip_pvt_ptr; /* return pvt with ref */ 07434 case SIP_REQ_LOOP_DETECTED: 07435 /* This is likely a forked Request that somehow resulted in us receiving multiple parts of the fork. 07436 * RFC 3261 section 8.2.2.2, Indicate that we want to merge requests by sending a 482 response. */ 07437 transmit_response_using_temp(callid, addr, 1, intended_method, req, "482 (Loop Detected)"); 07438 dialog_unref(sip_pvt_ptr, "pvt did not match incoming SIP msg, unref from search."); 07439 ao2_iterator_destroy(iterator); 07440 return NULL; 07441 case SIP_REQ_NOT_MATCH: 07442 default: 07443 dialog_unref(sip_pvt_ptr, "pvt did not match incoming SIP msg, unref from search"); 07444 } 07445 } 07446 if (iterator) { 07447 ao2_iterator_destroy(iterator); 07448 } 07449 } /* end of pedantic mode Request/Reponse to Dialog matching */ 07450 07451 /* See if the method is capable of creating a dialog */ 07452 if (sip_methods[intended_method].can_create == CAN_CREATE_DIALOG) { 07453 if (intended_method == SIP_REFER) { 07454 /* We do support REFER, but not outside of a dialog yet */ 07455 transmit_response_using_temp(callid, addr, 1, intended_method, req, "603 Declined (no dialog)"); 07456 } else { 07457 /* Ok, time to create a new SIP dialog object, a pvt */ 07458 if ((p = sip_alloc(callid, addr, 1, intended_method, req))) { 07459 /* Ok, we've created a dialog, let's go and process it */ 07460 sip_pvt_lock(p); 07461 } else { 07462 /* We have a memory or file/socket error (can't allocate RTP sockets or something) so we're not 07463 getting a dialog from sip_alloc. 07464 07465 Without a dialog we can't retransmit and handle ACKs and all that, but at least 07466 send an error message. 07467 07468 Sorry, we apologize for the inconvienience 07469 */ 07470 transmit_response_using_temp(callid, addr, 1, intended_method, req, "500 Server internal error"); 07471 ast_debug(4, "Failed allocating SIP dialog, sending 500 Server internal error and giving up\n"); 07472 } 07473 } 07474 return p; /* can be NULL */ 07475 } else if( sip_methods[intended_method].can_create == CAN_CREATE_DIALOG_UNSUPPORTED_METHOD) { 07476 /* A method we do not support, let's take it on the volley */ 07477 transmit_response_using_temp(callid, addr, 1, intended_method, req, "501 Method Not Implemented"); 07478 ast_debug(2, "Got a request with unsupported SIP method.\n"); 07479 } else if (intended_method != SIP_RESPONSE && intended_method != SIP_ACK) { 07480 /* This is a request outside of a dialog that we don't know about */ 07481 transmit_response_using_temp(callid, addr, 1, intended_method, req, "481 Call leg/transaction does not exist"); 07482 ast_debug(2, "That's odd... Got a request in unknown dialog. Callid %s\n", callid ? callid : "<unknown>"); 07483 } 07484 /* We do not respond to responses for dialogs that we don't know about, we just drop 07485 the session quickly */ 07486 if (intended_method == SIP_RESPONSE) 07487 ast_debug(2, "That's odd... Got a response on a call we don't know about. Callid %s\n", callid ? callid : "<unknown>"); 07488 07489 return NULL; 07490 }
| 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 11536 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().
11537 { 11538 struct ast_channel *c = obj; 11539 struct sip_pvt *p = data; 11540 int res; 11541 11542 ast_channel_lock(c); 11543 11544 res = (c->pbx && 11545 (!strcasecmp(c->macroexten, p->exten) || !strcasecmp(c->exten, p->exten)) && 11546 (sip_cfg.notifycid == IGNORE_CONTEXT || !strcasecmp(c->context, p->context))); 11547 11548 ast_channel_unlock(c); 11549 11550 return res ? CMP_MATCH | CMP_STOP : 0; 11551 }
| 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 4098 of file chan_sip.c.
Referenced by parse_moved_contact().
04099 { 04100 char last_char = '\0'; 04101 const char *s; 04102 for (s = start; *s && s != lim; last_char = *s++) { 04103 if (*s == '"' && last_char != '\\') 04104 break; 04105 } 04106 return s; 04107 }
| static struct sip_peer * find_peer | ( | const char * | peer, | |
| struct ast_sockaddr * | addr, | |||
| int | realtime, | |||
| int | which_objects, | |||
| int | devstate_only, | |||
| int | transport | |||
| ) | [static, read] |
Locate device by name or ip address.
| peer,sin,realtime,devstate_only,transport | ||
| which_objects | Define which objects should be matched when doing a lookup by name. Valid options are FINDUSERS, FINDPEERS, or FINDALLDEVICES. Note that this option is not used at all when doing a lookup by IP. |
Definition at line 4594 of file chan_sip.c.
References ao2_t_callback_data, ao2_t_find, ast_copy_string(), ast_set_flag, ast_sockaddr_copy(), find_by_name(), OBJ_POINTER, realtime_peer(), and unref_peer().
04595 { 04596 struct sip_peer *p = NULL; 04597 struct sip_peer tmp_peer; 04598 04599 if (peer) { 04600 ast_copy_string(tmp_peer.name, peer, sizeof(tmp_peer.name)); 04601 p = ao2_t_callback_data(peers, OBJ_POINTER, find_by_name, &tmp_peer, &which_objects, "ao2_find in peers table"); 04602 } else if (addr) { /* search by addr? */ 04603 ast_sockaddr_copy(&tmp_peer.addr, addr); 04604 tmp_peer.flags[0].flags = 0; 04605 tmp_peer.transports = transport; 04606 p = ao2_t_find(peers_by_ip, &tmp_peer, OBJ_POINTER, "ao2_find in peers_by_ip table"); /* WAS: p = ASTOBJ_CONTAINER_FIND_FULL(&peerl, sin, name, sip_addr_hashfunc, 1, sip_addrcmp); */ 04607 if (!p) { 04608 ast_set_flag(&tmp_peer.flags[0], SIP_INSECURE_PORT); 04609 p = ao2_t_find(peers_by_ip, &tmp_peer, OBJ_POINTER, "ao2_find in peers_by_ip table 2"); /* WAS: p = ASTOBJ_CONTAINER_FIND_FULL(&peerl, sin, name, sip_addr_hashfunc, 1, sip_addrcmp); */ 04610 if (p) { 04611 return p; 04612 } 04613 } 04614 } 04615 04616 if (!p && (realtime || devstate_only)) { 04617 p = realtime_peer(peer, addr, devstate_only); 04618 if (p) { 04619 switch (which_objects) { 04620 case FINDUSERS: 04621 if (!(p->type & SIP_TYPE_USER)) { 04622 unref_peer(p, "Wrong type of realtime SIP endpoint"); 04623 return NULL; 04624 } 04625 break; 04626 case FINDPEERS: 04627 if (!(p->type & SIP_TYPE_PEER)) { 04628 unref_peer(p, "Wrong type of realtime SIP endpoint"); 04629 return NULL; 04630 } 04631 break; 04632 case FINDALLDEVICES: 04633 break; 04634 } 04635 } 04636 } 04637 04638 return p; 04639 }
| static struct sip_auth * find_realm_authentication | ( | struct sip_auth * | authlist, | |
| const char * | realm | |||
| ) | [static, read] |
Find authentication for a specific realm.
Definition at line 25419 of file chan_sip.c.
Referenced by build_reply_digest().
25420 { 25421 struct sip_auth *a; 25422 25423 for (a = authlist; a; a = a->next) { 25424 if (!strcasecmp(a->realm, realm)) 25425 break; 25426 } 25427 25428 return a; 25429 }
| 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 7838 of file chan_sip.c.
References ast_log(), ast_strdupa, ast_strlen_zero(), FALSE, get_header(), LOG_WARNING, strcasestr(), and TRUE.
Referenced by handle_incoming(), handle_request_invite(), handle_response(), and handle_response_invite().
07839 { 07840 const char *content_type; 07841 const char *content_length; 07842 const char *search; 07843 char *boundary; 07844 unsigned int x; 07845 int boundaryisquoted = FALSE; 07846 int found_application_sdp = FALSE; 07847 int found_end_of_headers = FALSE; 07848 07849 content_length = get_header(req, "Content-Length"); 07850 07851 if (!ast_strlen_zero(content_length)) { 07852 if (sscanf(content_length, "%30u", &x) != 1) { 07853 ast_log(LOG_WARNING, "Invalid Content-Length: %s\n", content_length); 07854 return 0; 07855 } 07856 07857 /* Content-Length of zero means there can't possibly be an 07858 SDP here, even if the Content-Type says there is */ 07859 if (x == 0) 07860 return 0; 07861 } 07862 07863 content_type = get_header(req, "Content-Type"); 07864 07865 /* if the body contains only SDP, this is easy */ 07866 if (!strncasecmp(content_type, "application/sdp", 15)) { 07867 req->sdp_start = 0; 07868 req->sdp_count = req->lines; 07869 return req->lines ? 1 : 0; 07870 } 07871 07872 /* if it's not multipart/mixed, there cannot be an SDP */ 07873 if (strncasecmp(content_type, "multipart/mixed", 15)) 07874 return 0; 07875 07876 /* if there is no boundary marker, it's invalid */ 07877 if ((search = strcasestr(content_type, ";boundary="))) 07878 search += 10; 07879 else if ((search = strcasestr(content_type, "; boundary="))) 07880 search += 11; 07881 else 07882 return 0; 07883 07884 if (ast_strlen_zero(search)) 07885 return 0; 07886 07887 /* If the boundary is quoted with ", remove quote */ 07888 if (*search == '\"') { 07889 search++; 07890 boundaryisquoted = TRUE; 07891 } 07892 07893 /* make a duplicate of the string, with two extra characters 07894 at the beginning */ 07895 boundary = ast_strdupa(search - 2); 07896 boundary[0] = boundary[1] = '-'; 07897 /* Remove final quote */ 07898 if (boundaryisquoted) 07899 boundary[strlen(boundary) - 1] = '\0'; 07900 07901 /* search for the boundary marker, the empty line delimiting headers from 07902 sdp part and the end boundry if it exists */ 07903 07904 for (x = 0; x < (req->lines); x++) { 07905 const char *line = REQ_OFFSET_TO_STR(req, line[x]); 07906 if (!strncasecmp(line, boundary, strlen(boundary))){ 07907 if (found_application_sdp && found_end_of_headers) { 07908 req->sdp_count = (x - 1) - req->sdp_start; 07909 return 1; 07910 } 07911 found_application_sdp = FALSE; 07912 } 07913 if (!strcasecmp(line, "Content-Type: application/sdp")) 07914 found_application_sdp = TRUE; 07915 07916 if (ast_strlen_zero(line)) { 07917 if (found_application_sdp && !found_end_of_headers){ 07918 req->sdp_start = x; 07919 found_end_of_headers = TRUE; 07920 } 07921 } 07922 } 07923 if (found_application_sdp && found_end_of_headers) { 07924 req->sdp_count = x - req->sdp_start; 07925 return TRUE; 07926 } 07927 return FALSE; 07928 }
| static struct ast_cc_agent* find_sip_cc_agent_by_notify_uri | ( | const char *const | uri | ) | [static, read] |
Definition at line 1631 of file chan_sip.c.
References ast_cc_agent_callback(), and find_by_notify_uri_helper().
Referenced by get_destination().
01632 { 01633 struct ast_cc_agent *agent = ast_cc_agent_callback(0, find_by_notify_uri_helper, (char *)uri, "SIP"); 01634 return agent; 01635 }
| static struct ast_cc_agent* find_sip_cc_agent_by_original_callid | ( | struct sip_pvt * | pvt | ) | [static, read] |
Definition at line 1661 of file chan_sip.c.
References ast_cc_agent_callback(), and find_by_callid_helper().
Referenced by add_cc_call_info_to_response().
01662 { 01663 struct ast_cc_agent *agent = ast_cc_agent_callback(0, find_by_callid_helper, pvt, "SIP"); 01664 return agent; 01665 }
| static struct ast_cc_agent* find_sip_cc_agent_by_subscribe_uri | ( | const char *const | uri | ) | [static, read] |
Definition at line 1646 of file chan_sip.c.
References ast_cc_agent_callback(), and find_by_subscribe_uri_helper().
Referenced by handle_cc_subscribe().
01647 { 01648 struct ast_cc_agent *agent = ast_cc_agent_callback(0, find_by_subscribe_uri_helper, (char *)uri, "SIP"); 01649 return agent; 01650 }
| static int find_sip_method | ( | const char * | msg | ) | [static] |
find_sip_method: Find SIP method from header
Definition at line 2912 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().
02913 { 02914 int i, res = 0; 02915 02916 if (ast_strlen_zero(msg)) { 02917 return 0; 02918 } 02919 for (i = 1; i < ARRAY_LEN(sip_methods) && !res; i++) { 02920 if (method_match(i, msg)) { 02921 res = sip_methods[i].id; 02922 } 02923 } 02924 return res; 02925 }
| static int find_sip_monitor_instance_by_subscription_pvt | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 1843 of file chan_sip.c.
References CMP_MATCH, and CMP_STOP.
Referenced by handle_cc_notify(), and handle_response().
01844 { 01845 struct sip_monitor_instance *monitor_instance = obj; 01846 return monitor_instance->subscription_pvt == arg ? CMP_MATCH | CMP_STOP : 0; 01847 }
| static int find_sip_monitor_instance_by_suspension_entry | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 1849 of file chan_sip.c.
References CMP_MATCH, and CMP_STOP.
Referenced by cc_handle_publish_error().
01850 { 01851 struct sip_monitor_instance *monitor_instance = obj; 01852 return monitor_instance->suspension_entry == arg ? CMP_MATCH | CMP_STOP : 0; 01853 }
| static struct epa_static_data* find_static_data | ( | const char *const | event_package | ) | [static, read] |
Definition at line 886 of file chan_sip.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, and AST_LIST_UNLOCK.
Referenced by create_epa_entry().
00887 { 00888 const struct epa_backend *backend = NULL; 00889 00890 AST_LIST_LOCK(&epa_static_data_list); 00891 AST_LIST_TRAVERSE(&epa_static_data_list, backend, next) { 00892 if (!strcmp(backend->static_data->name, event_package)) { 00893 break; 00894 } 00895 } 00896 AST_LIST_UNLOCK(&epa_static_data_list); 00897 return backend ? backend->static_data : NULL; 00898 }
| static struct cfsubscription_types * find_subscription_type | ( | enum subscriptiontype | subtype | ) | [static, read] |
Find subscription type in array.
Definition at line 17034 of file chan_sip.c.
References ARRAY_LEN, subscription_types, and type.
Referenced by transmit_state_notify().
17035 { 17036 int i; 17037 17038 for (i = 1; i < ARRAY_LEN(subscription_types); i++) { 17039 if (subscription_types[i].type == subtype) { 17040 return &subscription_types[i]; 17041 } 17042 } 17043 return &subscription_types[0]; 17044 }
| static void free_old_route | ( | struct sip_route * | route | ) | [static] |
Remove route from route list.
Definition at line 13100 of file chan_sip.c.
References ast_free.
Referenced by __sip_destroy(), and build_route().
13101 { 13102 struct sip_route *next; 13103 13104 while (route) { 13105 next = route->next; 13106 ast_free(route); 13107 route = next; 13108 } 13109 }
| 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 18154 of file chan_sip.c.
References ast_copy_string(), ast_log(), ast_strlen_zero(), check_sip_domain(), and LOG_WARNING.
18155 { 18156 if (ast_strlen_zero(data)) { 18157 ast_log(LOG_WARNING, "CHECKSIPDOMAIN requires an argument - A domain name\n"); 18158 return -1; 18159 } 18160 if (check_sip_domain(data, NULL, 0)) 18161 ast_copy_string(buf, data, len); 18162 else 18163 buf[0] = '\0'; 18164 return 0; 18165 }
| 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 18095 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.
18096 { 18097 struct sip_pvt *p; 18098 const char *content = NULL; 18099 AST_DECLARE_APP_ARGS(args, 18100 AST_APP_ARG(header); 18101 AST_APP_ARG(number); 18102 ); 18103 int i, number, start = 0; 18104 18105 if (ast_strlen_zero(data)) { 18106 ast_log(LOG_WARNING, "This function requires a header name.\n"); 18107 return -1; 18108 } 18109 18110 ast_channel_lock(chan); 18111 if (!IS_SIP_TECH(chan->tech)) { 18112 ast_log(LOG_WARNING, "This function can only be used on SIP channels.\n"); 18113 ast_channel_unlock(chan); 18114 return -1; 18115 } 18116 18117 AST_STANDARD_APP_ARGS(args, data); 18118 if (!args.number) { 18119 number = 1; 18120 } else { 18121 sscanf(args.number, "%30d", &number); 18122 if (number < 1) 18123 number = 1; 18124 } 18125 18126 p = chan->tech_pvt; 18127 18128 /* If there is no private structure, this channel is no longer alive */ 18129 if (!p) { 18130 ast_channel_unlock(chan); 18131 return -1; 18132 } 18133 18134 for (i = 0; i < number; i++) 18135 content = __get_header(&p->initreq, args.header, &start); 18136 18137 if (ast_strlen_zero(content)) { 18138 ast_channel_unlock(chan); 18139 return -1; 18140 } 18141 18142 ast_copy_string(buf, content, len); 18143 ast_channel_unlock(chan); 18144 18145 return 0; 18146 }
| 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 18272 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.
18273 { 18274 struct sip_pvt *p; 18275 static int deprecated = 0; 18276 18277 *buf = 0; 18278 18279 if (!data) { 18280 ast_log(LOG_WARNING, "This function requires a parameter name.\n"); 18281 return -1; 18282 } 18283 18284 ast_channel_lock(chan); 18285 if (!IS_SIP_TECH(chan->tech)) { 18286 ast_log(LOG_WARNING, "This function can only be used on SIP channels.\n"); 18287 ast_channel_unlock(chan); 18288 return -1; 18289 } 18290 18291 if (deprecated++ % 20 == 0) { 18292 /* Deprecated in 1.6.1 */ 18293 ast_log(LOG_WARNING, "SIPCHANINFO() is deprecated. Please transition to using CHANNEL().\n"); 18294 } 18295 18296 p = chan->tech_pvt; 18297 18298 /* If there is no private structure, this channel is no longer alive */ 18299 if (!p) { 18300 ast_channel_unlock(chan); 18301 return -1; 18302 } 18303 18304 if (!strcasecmp(data, "peerip")) { 18305 ast_copy_string(buf, ast_sockaddr_stringify_addr(&p->sa), len); 18306 } else if (!strcasecmp(data, "recvip")) { 18307 ast_copy_string(buf, ast_sockaddr_stringify_addr(&p->recv), len); 18308 } else if (!strcasecmp(data, "from")) { 18309 ast_copy_string(buf, p->from, len); 18310 } else if (!strcasecmp(data, "uri")) { 18311 ast_copy_string(buf, p->uri, len); 18312 } else if (!strcasecmp(data, "useragent")) { 18313 ast_copy_string(buf, p->useragent, len); 18314 } else if (!strcasecmp(data, "peername")) { 18315 ast_copy_string(buf, p->peername, len); 18316 } else if (!strcasecmp(data, "t38passthrough")) { 18317 if (p->t38.state == T38_DISABLED) { 18318 ast_copy_string(buf, "0", len); 18319 } else { /* T38 is offered or enabled in this call */ 18320 ast_copy_string(buf, "1", len); 18321 } 18322 } else { 18323 ast_channel_unlock(chan); 18324 return -1; 18325 } 18326 ast_channel_unlock(chan); 18327 18328 return 0; 18329 }
| 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 18173 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, find_peer(), LOG_WARNING, ast_variable::name, ast_variable::next, peer_mailboxes_to_str(), peer_status(), strsep(), TRUE, unref_peer(), and ast_variable::value.
18174 { 18175 struct sip_peer *peer; 18176 char *colname; 18177 18178 if ((colname = strchr(data, ':'))) { /*! \todo Will be deprecated after 1.4 */ 18179 static int deprecation_warning = 0; 18180 *colname++ = '\0'; 18181 if (deprecation_warning++ % 10 == 0) 18182 ast_log(LOG_WARNING, "SIPPEER(): usage of ':' to separate arguments is deprecated. Please use ',' instead.\n"); 18183 } else if ((colname = strchr(data, ','))) 18184 *colname++ = '\0'; 18185 else 18186 colname = "ip"; 18187 18188 if (!(peer = find_peer(data, NULL, TRUE, FINDPEERS, FALSE, 0))) 18189 return -1; 18190 18191 if (!strcasecmp(colname, "ip")) { 18192 ast_copy_string(buf, ast_sockaddr_stringify_addr(&peer->addr), len); 18193 } else if (!strcasecmp(colname, "port")) { 18194 snprintf(buf, len, "%d", ast_sockaddr_port(&peer->addr)); 18195 } else if (!strcasecmp(colname, "status")) { 18196 peer_status(peer, buf, len); 18197 } else if (!strcasecmp(colname, "language")) { 18198 ast_copy_string(buf, peer->language, len); 18199 } else if (!strcasecmp(colname, "regexten")) { 18200 ast_copy_string(buf, peer->regexten, len); 18201 } else if (!strcasecmp(colname, "limit")) { 18202 snprintf(buf, len, "%d", peer->call_limit); 18203 } else if (!strcasecmp(colname, "busylevel")) { 18204 snprintf(buf, len, "%d", peer->busy_level); 18205 } else if (!strcasecmp(colname, "curcalls")) { 18206 snprintf(buf, len, "%d", peer->inUse); 18207 } else if (!strcasecmp(colname, "maxforwards")) { 18208 snprintf(buf, len, "%d", peer->maxforwards); 18209 } else if (!strcasecmp(colname, "accountcode")) { 18210 ast_copy_string(buf, peer->accountcode, len); 18211 } else if (!strcasecmp(colname, "callgroup")) { 18212 ast_print_group(buf, len, peer->callgroup); 18213 } else if (!strcasecmp(colname, "pickupgroup")) { 18214 ast_print_group(buf, len, peer->pickupgroup); 18215 } else if (!strcasecmp(colname, "useragent")) { 18216 ast_copy_string(buf, peer->useragent, len); 18217 } else if (!strcasecmp(colname, "mailbox")) { 18218 struct ast_str *mailbox_str = ast_str_alloca(512); 18219 peer_mailboxes_to_str(&mailbox_str, peer); 18220 ast_copy_string(buf, mailbox_str->str, len); 18221 } else if (!strcasecmp(colname, "context")) { 18222 ast_copy_string(buf, peer->context, len); 18223 } else if (!strcasecmp(colname, "expire")) { 18224 snprintf(buf, len, "%d", peer->expire); 18225 } else if (!strcasecmp(colname, "dynamic")) { 18226 ast_copy_string(buf, peer->host_dynamic ? "yes" : "no", len); 18227 } else if (!strcasecmp(colname, "callerid_name")) { 18228 ast_copy_string(buf, peer->cid_name, len); 18229 } else if (!strcasecmp(colname, "callerid_num")) { 18230 ast_copy_string(buf, peer->cid_num, len); 18231 } else if (!strcasecmp(colname, "codecs")) { 18232 ast_getformatname_multiple(buf, len -1, peer->capability); 18233 } else if (!strcasecmp(colname, "encryption")) { 18234 snprintf(buf, len, "%d", ast_test_flag(&peer->flags[1], SIP_PAGE2_USE_SRTP)); 18235 } else if (!strncasecmp(colname, "chanvar[", 8)) { 18236 char *chanvar=colname + 8; 18237 struct ast_variable *v; 18238 18239 chanvar = strsep(&chanvar, "]"); 18240 for (v = peer->chanvars ; v ; v = v->next) { 18241 if (!strcasecmp(v->name, chanvar)) { 18242 ast_copy_string(buf, v->value, len); 18243 } 18244 } 18245 } else if (!strncasecmp(colname, "codec[", 6)) { 18246 char *codecnum; 18247 format_t codec = 0; 18248 18249 codecnum = colname + 6; /* move past the '[' */ 18250 codecnum = strsep(&codecnum, "]"); /* trim trailing ']' if any */ 18251 if((codec = ast_codec_pref_index(&peer->prefs, atoi(codecnum)))) { 18252 ast_copy_string(buf, ast_getformatname(codec), len); 18253 } else { 18254 buf[0] = '\0'; 18255 } 18256 } else { 18257 buf[0] = '\0'; 18258 } 18259 18260 unref_peer(peer, "unref_peer from function_sippeer, just before return"); 18261 18262 return 0; 18263 }
| static char * generate_random_string | ( | char * | buf, | |
| size_t | size | |||
| ) | [static] |
Generate 32 byte random string for callid's etc.
Definition at line 6957 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().
06958 { 06959 long val[4]; 06960 int x; 06961 06962 for (x=0; x<4; x++) 06963 val[x] = ast_random(); 06964 snprintf(buf, size, "%08lx%08lx%08lx%08lx", val[0], val[1], val[2], val[3]); 06965 06966 return buf; 06967 }
| static char* generate_uri | ( | struct sip_pvt * | pvt, | |
| char * | buf, | |||
| size_t | size | |||
| ) | [static] |
Definition at line 6969 of file chan_sip.c.
References ast_copy_string(), ast_sockaddr_stringify(), 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().
06970 { 06971 struct ast_str *uri = ast_str_alloca(size); 06972 ast_str_set(&uri, 0, "%s", pvt->socket.type == SIP_TRANSPORT_TLS ? "sips:" : "sip:"); 06973 /* Here would be a great place to generate a UUID, but for now we'll 06974 * use the handy random string generation function we already have 06975 */ 06976 ast_str_append(&uri, 0, "%s", generate_random_string(buf, size)); 06977 ast_str_append(&uri, 0, "@%s", ast_sockaddr_stringify(&pvt->ourip)); 06978 ast_copy_string(buf, ast_str_buffer(uri), size); 06979 return buf; 06980 }
| int get_address_family_filter | ( | const struct ast_sockaddr * | addr | ) | [static] |
Helper for dns resolution to filter by address family.
Definition at line 23938 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(), and transmit_register().
23939 { 23940 if (ast_sockaddr_is_ipv6(addr) && ast_sockaddr_is_any(addr)) { 23941 return 0; 23942 } 23943 23944 return addr->ss.ss_family; 23945 }
| 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 14644 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_header(), LOG_WARNING, pbx_builtin_getvar_helper(), S_OR, sip_cfg, sip_debug_test_pvt(), SIP_PEDANTIC_DECODE, and sip_refer_allocate().
Referenced by handle_request_bye().
14645 { 14646 char tmp[256] = "", *c, *a; 14647 struct sip_request *req = oreq ? oreq : &p->initreq; 14648 struct sip_refer *referdata = NULL; 14649 const char *transfer_context = NULL; 14650 14651 if (!p->refer && !sip_refer_allocate(p)) 14652 return -1; 14653 14654 referdata = p->refer; 14655 14656 ast_copy_string(tmp, get_header(req, "Also"), sizeof(tmp)); 14657 c = get_in_brackets(tmp); 14658 14659 if (parse_uri(c, "sip:,sips:", &c, NULL, &a, NULL)) { 14660 ast_log(LOG_WARNING, "Huh? Not a SIP header in Also: transfer (%s)?\n", c); 14661 return -1; 14662 } 14663 14664 SIP_PEDANTIC_DECODE(c); 14665 SIP_PEDANTIC_DECODE(a); 14666 14667 if (!ast_strlen_zero(a)) { 14668 ast_copy_string(referdata->refer_to_domain, a, sizeof(referdata->refer_to_domain)); 14669 } 14670 14671 if (sip_debug_test_pvt(p)) 14672 ast_verbose("Looking for %s in %s\n", c, p->context); 14673 14674 if (p->owner) /* Mimic behaviour in res_features.c */ 14675 transfer_context = pbx_builtin_getvar_helper(p->owner, "TRANSFER_CONTEXT"); 14676 14677 /* By default, use the context in the channel sending the REFER */ 14678 if (ast_strlen_zero(transfer_context)) { 14679 transfer_context = S_OR(p->owner->macrocontext, 14680 S_OR(p->context, sip_cfg.default_context)); 14681 } 14682 if (ast_exists_extension(NULL, transfer_context, c, 1, NULL)) { 14683 /* This is a blind transfer */ 14684 ast_debug(1, "SIP Bye-also transfer to Extension %s@%s \n", c, transfer_context); 14685 ast_copy_string(referdata->refer_to, c, sizeof(referdata->refer_to)); 14686 ast_copy_string(referdata->referred_by, "", sizeof(referdata->referred_by)); 14687 ast_copy_string(referdata->refer_contact, "", sizeof(referdata->refer_contact)); 14688 referdata->refer_call = dialog_unref(referdata->refer_call, "unreffing referdata->refer_call"); 14689 /* Set new context */ 14690 ast_string_field_set(p, context, transfer_context); 14691 return 0; 14692 } else if (ast_canmatch_extension(NULL, p->context, c, 1, NULL)) { 14693 return 1; 14694 } 14695 14696 return -1; 14697 }
| static char* get_body | ( | struct sip_request * | req, | |
| char * | name, | |||
| char | delimiter | |||
| ) | [static] |
Get a specific line from the message body.
Definition at line 6724 of file chan_sip.c.
References get_body_by_line(), and len().
Referenced by handle_cc_notify(), handle_request_info(), and handle_request_notify().
06725 { 06726 int x; 06727 int len = strlen(name); 06728 char *r; 06729 06730 for (x = 0; x < req->lines; x++) { 06731 r = get_body_by_line(REQ_OFFSET_TO_STR(req, line[x]), name, len, delimiter); 06732 if (r[0] != '\0') 06733 return r; 06734 } 06735 06736 return ""; 06737 }
| 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 6669 of file chan_sip.c.
References ast_skip_blanks().
Referenced by get_body(), and get_sdp_iterate().
06670 { 06671 if (!strncasecmp(line, name, nameLen) && line[nameLen] == delimiter) 06672 return ast_skip_blanks(line + nameLen + 1); 06673 06674 return ""; 06675 }
| static int get_cached_mwi | ( | struct sip_peer * | peer, | |
| int * | new, | |||
| int * | old | |||
| ) | [static] |
Get cached MWI info.
| 0 | At least one message is waiting | |
| 1 | no messages waiting |
Definition at line 24081 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().
24082 { 24083 struct sip_mailbox *mailbox; 24084 24085 AST_LIST_TRAVERSE(&peer->mailboxes, mailbox, entry) { 24086 struct ast_event *event; 24087 event = ast_event_get_cached(AST_EVENT_MWI, 24088 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox->mailbox, 24089 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, S_OR(mailbox->context, "default"), 24090 AST_EVENT_IE_END); 24091 if (!event) 24092 continue; 24093 *new += ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS); 24094 *old += ast_event_get_ie_uint(event, AST_EVENT_IE_OLDMSGS); 24095 ast_event_destroy(event); 24096 } 24097 24098 return (*new || *old) ? 0 : 1; 24099 }
| static void get_crypto_attrib | ( | struct sip_srtp * | srtp, | |
| const char ** | a_crypto | |||
| ) | [static] |
Definition at line 10382 of file chan_sip.c.
References ast_log(), and LOG_WARNING.
Referenced by add_sdp().
10383 { 10384 /* Set encryption properties */ 10385 if (srtp) { 10386 if (!srtp->crypto) { 10387 srtp->crypto = sdp_crypto_setup(); 10388 } 10389 if (srtp->crypto && (sdp_crypto_offer(srtp->crypto) >= 0)) { 10390 *a_crypto = sdp_crypto_attrib(srtp->crypto); 10391 } 10392 10393 if (!*a_crypto) { 10394 ast_log(LOG_WARNING, "No SRTP key management enabled\n"); 10395 } 10396 } 10397 }
| 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 14230 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_verbose, check_sip_domain(), context, ast_cc_agent::core_id, ast_cc_agent::device_name, dummy(), exten, find_sip_cc_agent_by_notify_uri(), get_header(), LOG_WARNING, ast_cc_agent::private_data, S_OR, sip_cfg, sip_debug_test_pvt(), sip_methods, SIP_PEDANTIC_DECODE, and cfsip_methods::text.
Referenced by handle_request_invite(), handle_request_options(), and handle_request_subscribe().
14231 { 14232 char tmp[256] = "", *uri, *domain, *dummy = NULL; 14233 char tmpf[256] = "", *from = NULL; 14234 struct sip_request *req; 14235 char *decoded_uri; 14236 14237 req = oreq; 14238 if (!req) { 14239 req = &p->initreq; 14240 } 14241 14242 /* Find the request URI */ 14243 if (req->rlPart2) 14244 ast_copy_string(tmp, REQ_OFFSET_TO_STR(req, rlPart2), sizeof(tmp)); 14245 14246 uri = ast_strdupa(get_in_brackets(tmp)); 14247 14248 if (parse_uri(uri, "sip:,sips:", &uri, &dummy, &domain, NULL)) { 14249 ast_log(LOG_WARNING, "Not a SIP header (%s)?\n", uri); 14250 return SIP_GET_DEST_INVALID_URI; 14251 } 14252 14253 SIP_PEDANTIC_DECODE(domain); 14254 SIP_PEDANTIC_DECODE(uri); 14255 14256 ast_string_field_set(p, domain, domain); 14257 14258 /* Now find the From: caller ID and name */ 14259 /* XXX Why is this done in get_destination? Isn't it already done? 14260 Needs to be checked 14261 */ 14262 ast_copy_string(tmpf, get_header(req, "From"), sizeof(tmpf)); 14263 if (!ast_strlen_zero(tmpf)) { 14264 from = get_in_brackets(tmpf); 14265 if (parse_uri(from, "sip:,sips:", &from, NULL, &domain, NULL)) { 14266 ast_log(LOG_WARNING, "Not a SIP header (%s)?\n", from); 14267 return SIP_GET_DEST_INVALID_URI; 14268 } 14269 14270 SIP_PEDANTIC_DECODE(from); 14271 SIP_PEDANTIC_DECODE(domain); 14272 14273 ast_string_field_set(p, fromdomain, domain); 14274 } 14275 14276 if (!AST_LIST_EMPTY(&domain_list)) { 14277 char domain_context[AST_MAX_EXTENSION]; 14278 14279 domain_context[0] = '\0'; 14280 if (!check_sip_domain(p->domain, domain_context, sizeof(domain_context))) { 14281 if (!sip_cfg.allow_external_domains && (req->method == SIP_INVITE || req->method == SIP_REFER)) { 14282 ast_debug(1, "Got SIP %s to non-local domain '%s'; refusing request.\n", sip_methods[req->method].text, p->domain); 14283 return SIP_GET_DEST_REFUSED; 14284 } 14285 } 14286 /* If we don't have a peer (i.e. we're a guest call), 14287 * overwrite the original context */ 14288 if (!ast_test_flag(&p->flags[1], SIP_PAGE2_HAVEPEERCONTEXT) && !ast_strlen_zero(domain_context)) { 14289 ast_string_field_set(p, context, domain_context); 14290 } 14291 } 14292 14293 /* If the request coming in is a subscription and subscribecontext has been specified use it */ 14294 if (req->method == SIP_SUBSCRIBE && !ast_strlen_zero(p->subscribecontext)) { 14295 ast_string_field_set(p, context, p->subscribecontext); 14296 } 14297 14298 if (sip_debug_test_pvt(p)) { 14299 ast_verbose("Looking for %s in %s (domain %s)\n", uri, p->context, p->domain); 14300 } 14301 14302 /* If this is a subscription we actually just need to see if a hint exists for the extension */ 14303 if (req->method == SIP_SUBSCRIBE) { 14304 char hint[AST_MAX_EXTENSION]; 14305 return (ast_get_hint(hint, sizeof(hint), NULL, 0, NULL, p->context, p->exten) ? 14306 SIP_GET_DEST_EXTEN_FOUND : 14307 SIP_GET_DEST_EXTEN_NOT_FOUND); 14308 } else { 14309 struct ast_cc_agent *agent; 14310 decoded_uri = ast_strdupa(uri); 14311 ast_uri_decode(decoded_uri); 14312 /* Check the dialplan for the username part of the request URI, 14313 the domain will be stored in the SIPDOMAIN variable 14314 Since extensions.conf can have unescaped characters, try matching a decoded 14315 uri in addition to the non-decoded uri 14316 Return 0 if we have a matching extension */ 14317 if (ast_exists_extension(NULL, p->context, uri, 1, S_OR(p->cid_num, from)) || 14318 ast_exists_extension(NULL, p->context, decoded_uri, 1, S_OR(p->cid_num, from)) || 14319 !strcmp(decoded_uri, ast_pickup_ext())) { 14320 if (!oreq) { 14321 ast_string_field_set(p, exten, decoded_uri); 14322 } 14323 return SIP_GET_DEST_EXTEN_FOUND; 14324 } else if ((agent = find_sip_cc_agent_by_notify_uri(tmp))) { 14325 struct sip_cc_agent_pvt *agent_pvt = agent->private_data; 14326 /* This is a CC recall. We can set p's extension to the exten from 14327 * the original INVITE 14328 */ 14329 ast_string_field_set(p, exten, agent_pvt->original_exten); 14330 /* And we need to let the CC core know that the caller is attempting 14331 * his recall 14332 */ 14333 ast_cc_agent_recalling(agent->core_id, "SIP caller %s is attempting recall", 14334 agent->device_name); 14335 if (cc_recall_core_id) { 14336 *cc_recall_core_id = agent->core_id; 14337 } 14338 ao2_ref(agent, -1); 14339 return SIP_GET_DEST_EXTEN_FOUND; 14340 } 14341 } 14342 14343 /* Return 1 for pickup extension or overlap dialling support (if we support it) */ 14344 if((ast_test_flag(&global_flags[1], SIP_PAGE2_ALLOWOVERLAP) && 14345 ast_canmatch_extension(NULL, p->context, decoded_uri, 1, S_OR(p->cid_num, from))) || 14346 !strncmp(decoded_uri, ast_pickup_ext(), strlen(decoded_uri))) { 14347 return SIP_GET_DEST_PICKUP_EXTEN_FOUND; 14348 } 14349 14350 return SIP_GET_DEST_EXTEN_NOT_FOUND; 14351 }
| static int get_domain | ( | const char * | str, | |
| char * | domain, | |||
| int | len | |||
| ) | [static] |
Extract domain from SIP To/From header.
Definition at line 9889 of file chan_sip.c.
References ast_copy_string(), ast_log(), ast_strlen_zero(), and LOG_WARNING.
Referenced by get_realm().
09890 { 09891 char tmpf[256]; 09892 char *a, *from; 09893 09894 *domain = '\0'; 09895 ast_copy_string(tmpf, str, sizeof(tmpf)); 09896 from = get_in_brackets(tmpf); 09897 if (!ast_strlen_zero(from)) { 09898 if (strncasecmp(from, "sip:", 4)) { 09899 ast_log(LOG_WARNING, "Huh? Not a SIP header (%s)?\n", from); 09900 return -1; 09901 } 09902 from += 4; 09903 } else 09904 from = NULL; 09905 09906 if (from) { 09907 int bracket = 0; 09908 09909 /* Strip any params or options from user */ 09910 if ((a = strchr(from, ';'))) 09911 *a = '\0'; 09912 /* Strip port from domain if present */ 09913 for (a = from; *a != '\0'; ++a) { 09914 if (*a == ':' && bracket == 0) { 09915 *a = '\0'; 09916 break; 09917 } else if (*a == '[') { 09918 ++bracket; 09919 } else if (*a == ']') { 09920 --bracket; 09921 } 09922 } 09923 if ((a = strchr(from, '@'))) { 09924 *a = '\0'; 09925 ast_copy_string(domain, a + 1, len); 09926 } else 09927 ast_copy_string(domain, from, len); 09928 } 09929 09930 return ast_strlen_zero(domain); 09931 }
| static struct event_state_compositor* get_esc | ( | const char *const | event_package | ) | [static, read] |
Definition at line 980 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().
00980 { 00981 int i; 00982 for (i = 0; i < ARRAY_LEN(event_state_compositors); i++) { 00983 if (!strcasecmp(event_package, event_state_compositors[i].name)) { 00984 return &event_state_compositors[i]; 00985 } 00986 } 00987 return NULL; 00988 }
| static struct sip_esc_entry* get_esc_entry | ( | const char * | entity_tag, | |
| struct event_state_compositor * | esc | |||
| ) | [static, read] |
Definition at line 990 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().
00990 { 00991 struct sip_esc_entry *entry; 00992 struct sip_esc_entry finder; 00993 00994 ast_copy_string(finder.entity_tag, entity_tag, sizeof(finder.entity_tag)); 00995 00996 entry = ao2_find(esc->compositor, &finder, OBJ_POINTER); 00997 00998 return entry; 00999 }
| static const char * get_header | ( | const struct sip_request * | req, | |
| const char * | name | |||
| ) | [static] |
Get header from SIP request.
Definition at line 6817 of file chan_sip.c.
References __get_header().
06818 { 06819 int start = 0; 06820 return __get_header(req, name, &start); 06821 }
| static struct ast_variable * get_insecure_variable_from_config | ( | struct ast_config * | config | ) | [static, read] |
Definition at line 4341 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 realtime_peer().
04342 { 04343 struct ast_variable *var = NULL; 04344 struct ast_flags flags = {0}; 04345 char *cat = NULL; 04346 const char *insecure; 04347 while ((cat = ast_category_browse(cfg, cat))) { 04348 insecure = ast_variable_retrieve(cfg, cat, "insecure"); 04349 set_insecure_flags(&flags, insecure, -1); 04350 if (ast_test_flag(&flags, SIP_INSECURE_PORT)) { 04351 var = ast_category_root(cfg, cat); 04352 break; 04353 } 04354 } 04355 return var; 04356 }
| 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 7931 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().
07932 { 07933 const char *m; 07934 const char *c; 07935 int miterator = req->sdp_start; 07936 int citerator = req->sdp_start; 07937 int x = 0; 07938 int numberofports; 07939 int len; 07940 int af; 07941 char proto[4], host[258] = ""; /*Initialize to empty so we will know if we have any input */ 07942 07943 c = get_sdp_iterate(&citerator, req, "c"); 07944 if (sscanf(c, "IN %3s %256s", proto, host) != 2) { 07945 ast_log(LOG_WARNING, "Invalid host in c= line, '%s'\n", c); 07946 /* Continue since there may be a valid host in a c= line specific to the audio stream */ 07947 } 07948 /* We only want the m and c lines for audio */ 07949 for (m = get_sdp_iterate(&miterator, req, "m"); !ast_strlen_zero(m); m = get_sdp_iterate(&miterator, req, "m")) { 07950 if ((media == SDP_AUDIO && ((sscanf(m, "audio %30u/%30u RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) || 07951 (sscanf(m, "audio %30u RTP/AVP %n", &x, &len) == 1 && len > 0))) || 07952 (media == SDP_VIDEO && ((sscanf(m, "video %30u/%30u RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) || 07953 (sscanf(m, "video %30u RTP/AVP %n", &x, &len) == 1 && len > 0)))) { 07954 /* See if there's a c= line for this media stream. 07955 * XXX There is no guarantee that we'll be grabbing the c= line for this 07956 * particular media stream here. However, this is the same logic used in process_sdp. 07957 */ 07958 c = get_sdp_iterate(&citerator, req, "c"); 07959 if (!ast_strlen_zero(c)) { 07960 sscanf(c, "IN %3s %256s", proto, host); 07961 } 07962 break; 07963 } 07964 } 07965 07966 if (!strcmp("IP4", proto)) { 07967 af = AF_INET; 07968 } else if (!strcmp("IP6", proto)) { 07969 af = AF_INET6; 07970 } else { 07971 ast_log(LOG_WARNING, "Unknown protocol '%s'.\n", proto); 07972 return -1; 07973 } 07974 07975 if (ast_strlen_zero(host) || x == 0) { 07976 ast_log(LOG_WARNING, "Failed to read an alternate host or port in SDP. Expect %s problems\n", media == SDP_AUDIO ? "audio" : "video"); 07977 return -1; 07978 } 07979 07980 if (ast_sockaddr_resolve_first_af(addr, host, 0, af)) { 07981 ast_log(LOG_WARNING, "Could not look up IP address of alternate hostname. Expect %s problems\n", media == SDP_AUDIO? "audio" : "video"); 07982 return -1; 07983 } 07984 07985 return 0; 07986 }
| static int get_msg_text | ( | char * | buf, | |
| int | len, | |||
| struct sip_request * | req, | |||
| int | addnewline | |||
| ) | [static] |
Get text out of a SIP MESSAGE packet.
Definition at line 15106 of file chan_sip.c.
Referenced by handle_request_info(), handle_request_notify(), and receive_message().
15107 { 15108 int x; 15109 int y; 15110 15111 buf[0] = '\0'; 15112 /*XXX isn't strlen(buf) going to always be 0? */ 15113 y = len - strlen(buf) - 5; 15114 if (y < 0) 15115 y = 0; 15116 for (x = 0; x < req->lines; x++) { 15117 const char *line = REQ_OFFSET_TO_STR(req, line[x]); 15118 strncat(buf, line, y); /* safe */ 15119 y -= strlen(line) + 1; 15120 if (y < 0) 15121 y = 0; 15122 if (y != 0 && addnewline) 15123 strcat(buf, "\n"); /* safe */ 15124 } 15125 return 0; 15126 }
| static const char * get_name_from_variable | ( | struct ast_variable * | var, | |
| const char * | newpeername | |||
| ) | [static] |
Definition at line 4358 of file chan_sip.c.
References ast_variable::name, ast_variable::next, and ast_variable::value.
Referenced by realtime_peer().
04359 { 04360 struct ast_variable *tmp; 04361 for (tmp = var; tmp; tmp = tmp->next) { 04362 if (!newpeername && !strcasecmp(tmp->name, "name")) 04363 newpeername = tmp->value; 04364 } 04365 return newpeername; 04366 }
| 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 10289 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().
10293 { 10294 int use_externip = 0; 10295 10296 /* First, get our address */ 10297 ast_rtp_instance_get_local_address(p->rtp, addr); 10298 if (p->vrtp) { 10299 ast_rtp_instance_get_local_address(p->vrtp, vaddr); 10300 } 10301 if (p->trtp) { 10302 ast_rtp_instance_get_local_address(p->trtp, taddr); 10303 } 10304 10305 /* If our real IP differs from the local address returned by the RTP engine, use it. */ 10306 /* The premise is that if we are already using that IP to communicate with the client, */ 10307 /* we should be using it for RTP too. */ 10308 use_externip = ast_sockaddr_cmp_addr(&p->ourip, addr); 10309 10310 /* Now, try to figure out where we want them to send data */ 10311 /* Is this a re-invite to move the media out, then use the original offer from caller */ 10312 if (!ast_sockaddr_isnull(&p->redirip)) { /* If we have a redirection IP, use it */ 10313 ast_sockaddr_copy(dest, &p->redirip); 10314 } else { 10315 /* 10316 * Audio Destination IP: 10317 * 10318 * 1. Specifically configured media address. 10319 * 2. Local address as specified by the RTP engine. 10320 * 3. The local IP as defined by chan_sip. 10321 * 10322 * Audio Destination Port: 10323 * 10324 * 1. Provided by the RTP engine. 10325 */ 10326 ast_sockaddr_copy(dest, 10327 !ast_sockaddr_isnull(&media_address) ? &media_address : 10328 !ast_sockaddr_is_any(addr) && !use_externip ? addr : 10329 &p->ourip); 10330 ast_sockaddr_set_port(dest, ast_sockaddr_port(addr)); 10331 } 10332 10333 if (needvideo) { 10334 /* Determine video destination */ 10335 if (!ast_sockaddr_isnull(&p->vredirip)) { 10336 ast_sockaddr_copy(vdest, &p->vredirip); 10337 } else { 10338 /* 10339 * Video Destination IP: 10340 * 10341 * 1. Specifically configured media address. 10342 * 2. Local address as specified by the RTP engine. 10343 * 3. The local IP as defined by chan_sip. 10344 * 10345 * Video Destination Port: 10346 * 10347 * 1. Provided by the RTP engine. 10348 */ 10349 ast_sockaddr_copy(vdest, 10350 !ast_sockaddr_isnull(&media_address) ? &media_address : 10351 !ast_sockaddr_is_any(vaddr) && !use_externip ? vaddr : 10352 &p->ourip); 10353 ast_sockaddr_set_port(vdest, ast_sockaddr_port(vaddr)); 10354 } 10355 } 10356 10357 if (needtext) { 10358 /* Determine text destination */ 10359 if (!ast_sockaddr_isnull(&p->tredirip)) { 10360 ast_sockaddr_copy(tdest, &p->tredirip); 10361 } else { 10362 /* 10363 * Text Destination IP: 10364 * 10365 * 1. Specifically configured media address. 10366 * 2. Local address as specified by the RTP engine. 10367 * 3. The local IP as defined by chan_sip. 10368 * 10369 * Text Destination Port: 10370 * 10371 * 1. Provided by the RTP engine. 10372 */ 10373 ast_sockaddr_copy(tdest, 10374 !ast_sockaddr_isnull(&media_address) ? &media_address : 10375 !ast_sockaddr_is_any(taddr) && !use_externip ? taddr : 10376 &p->ourip); 10377 ast_sockaddr_set_port(tdest, ast_sockaddr_port(taddr)); 10378 } 10379 } 10380 }
| 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 13951 of file chan_sip.c.
References ast_copy_string(), 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_skip_blanks(), ast_strdupa, ast_string_field_set, ast_strlen_zero(), cid_name, cid_num, and get_header().
Referenced by get_rpid().
13952 { 13953 char pai[256]; 13954 char privacy[64]; 13955 char *cid_num = ""; 13956 char *cid_name = ""; 13957 int callingpres = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED; 13958 char *start = NULL, *end = NULL, *uri = NULL; 13959 13960 ast_copy_string(pai, get_header(req, "P-Asserted-Identity"), sizeof(pai)); 13961 13962 if (ast_strlen_zero(pai)) { 13963 return 0; 13964 } 13965 13966 start = pai; 13967 if (*start == '"') { 13968 *start++ = '\0'; 13969 end = strchr(start, '"'); 13970 if (!end) { 13971 return 0; 13972 } 13973 *end++ = '\0'; 13974 cid_name = start; 13975 start = ast_skip_blanks(end); 13976 } 13977 13978 if (*start != '<') 13979 return 0; 13980 /* At this point, 'start' points to the URI in brackets. 13981 * We need a copy so that our comparison to the anonymous 13982 * URI is valid. 13983 */ 13984 uri = ast_strdupa(start); 13985 *start++ = '\0'; 13986 end = strchr(start, '@'); 13987 if (!end) { 13988 return 0; 13989 } 13990 *end++ = '\0'; 13991 if (!strncasecmp(uri, "anonymous@anonymous.invalid", 27)) { 13992 callingpres = AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED; 13993 /*XXX Assume no change in cid_num. Perhaps it should be 13994 * blanked? 13995 */ 13996 cid_num = (char *)p->cid_num; 13997 } else if (!strncasecmp(start, "sip:", 4)) { 13998 cid_num = start + 4; 13999 if (global_shrinkcallerid && ast_is_shrinkable_phonenumber(cid_num)) 14000 ast_shrink_phone_number(cid_num); 14001 start = end; 14002 14003 end = strchr(start, '>'); 14004 if (!end) { 14005 return 0; 14006 } 14007 *end = '\0'; 14008 } else { 14009 return 0; 14010 } 14011 14012 ast_copy_string(privacy, get_header(req, "Privacy"), sizeof(privacy)); 14013 if (!ast_strlen_zero(privacy) && strncmp(privacy, "id", 2)) { 14014 callingpres = AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED; 14015 } 14016 14017 /* Only return true if the supplied caller id is different */ 14018 if (!strcasecmp(p->cid_num, cid_num) && !strcasecmp(p->cid_name, cid_name) && p->callingpres == callingpres) { 14019 return 0; 14020 } 14021 14022 ast_string_field_set(p, cid_num, cid_num); 14023 ast_string_field_set(p, cid_name, cid_name); 14024 p->callingpres = callingpres; 14025 14026 if (p->owner) { 14027 ast_set_callerid(p->owner, cid_num, cid_name, NULL); 14028 p->owner->caller.id.name.presentation = callingpres; 14029 p->owner->caller.id.number.presentation = callingpres; 14030 } 14031 14032 return 1; 14033 }
| 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 14136 of file chan_sip.c.
References ast_copy_string(), ast_log(), ast_strdup, ast_strip_quoted(), ast_strlen_zero(), ast_verbose, exten, get_header(), LOG_WARNING, pbx_builtin_setvar_helper(), sip_debug_test_pvt(), sip_reason_str_to_code(), sip_set_redirstr(), strcasestr(), and strsep().
Referenced by change_redirecting_information().
14137 { 14138 char tmp[256], *exten, *rexten, *rdomain, *rname = NULL; 14139 char *params, *reason_param = NULL; 14140 struct sip_request *req; 14141 14142 req = oreq ? oreq : &p->initreq; 14143 14144 ast_copy_string(tmp, get_header(req, "Diversion"), sizeof(tmp)); 14145 if (ast_strlen_zero(tmp)) 14146 return -1; 14147 14148 if ((params = strchr(tmp, '>'))) { 14149 params = strchr(params, ';'); 14150 } 14151 14152 exten = get_in_brackets(tmp); 14153 if (!strncasecmp(exten, "sip:", 4)) { 14154 exten += 4; 14155 } else if (!strncasecmp(exten, "sips:", 5)) { 14156 exten += 5; 14157 } else { 14158 ast_log(LOG_WARNING, "Huh? Not an RDNIS SIP header (%s)?\n", exten); 14159 return -1; 14160 } 14161 14162 /* Get diversion-reason param if present */ 14163 if (params) { 14164 *params = '\0'; /* Cut off parameters */ 14165 params++; 14166 while (*params == ';' || *params == ' ') 14167 params++; 14168 /* Check if we have a reason parameter */ 14169 if ((reason_param = strcasestr(params, "reason="))) { 14170 char *end; 14171 reason_param+=7; 14172 if ((end = strchr(reason_param, ';'))) { 14173 *end = '\0'; 14174 } 14175 /* Remove enclosing double-quotes */ 14176 if (*reason_param == '"') 14177 ast_strip_quoted(reason_param, "\"", "\""); 14178 if (!ast_strlen_zero(reason_param)) { 14179 sip_set_redirstr(p, reason_param); 14180 if (p->owner) { 14181 pbx_builtin_setvar_helper(p->owner, "__PRIREDIRECTREASON", p->redircause); 14182 pbx_builtin_setvar_helper(p->owner, "__SIPREDIRECTREASON", reason_param); 14183 } 14184 } 14185 } 14186 } 14187 14188 rdomain = exten; 14189 rexten = strsep(&rdomain, "@"); /* trim anything after @ */ 14190 if (p->owner) 14191 pbx_builtin_setvar_helper(p->owner, "__SIPRDNISDOMAIN", rdomain); 14192 14193 if (sip_debug_test_pvt(p)) 14194 ast_verbose("RDNIS for this call is %s (reason %s)\n", exten, reason ? reason_param : ""); 14195 14196 /*ast_string_field_set(p, rdnis, rexten);*/ 14197 14198 if (*tmp == '\"') { 14199 char *end_quote; 14200 rname = tmp + 1; 14201 end_quote = strchr(rname, '\"'); 14202 *end_quote = '\0'; 14203 } 14204 14205 if (number) { 14206 *number = ast_strdup(rexten); 14207 } 14208 14209 if (name && rname) { 14210 *name = ast_strdup(rname); 14211 } 14212 14213 if (reason && !ast_strlen_zero(reason_param)) { 14214 *reason = sip_reason_str_to_code(reason_param); 14215 } 14216 14217 return 0; 14218 }
| 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 9937 of file chan_sip.c.
References AST_LIST_EMPTY, ast_string_field_set, ast_strlen_zero(), check_sip_domain(), get_domain(), get_header(), MAXHOSTNAMELEN, and sip_cfg.
Referenced by transmit_response_with_auth().
09938 { 09939 char domain[MAXHOSTNAMELEN]; 09940 09941 if (!ast_strlen_zero(p->realm)) 09942 return; 09943 09944 if (sip_cfg.domainsasrealm && 09945 !AST_LIST_EMPTY(&domain_list)) 09946 { 09947 /* Check From header first */ 09948 if (!get_domain(get_header(req, "From"), domain, sizeof(domain))) { 09949 if (check_sip_domain(domain, NULL, 0)) { 09950 ast_string_field_set(p, realm, domain); 09951 return; 09952 } 09953 } 09954 /* Check To header */ 09955 if (!get_domain(get_header(req, "To"), domain, sizeof(domain))) { 09956 if (check_sip_domain(domain, NULL, 0)) { 09957 ast_string_field_set(p, realm, domain); 09958 return; 09959 } 09960 } 09961 } 09962 09963 /* Use default realm from config file */ 09964 ast_string_field_set(p, realm, sip_cfg.realm); 09965 }
| 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 14445 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_verbose, ast_channel::context, get_header(), LOG_WARNING, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), S_OR, sip_cfg, sip_debug_test_pvt(), SIP_PEDANTIC_DECODE, and strcasestr().
Referenced by handle_request_refer().
14446 { 14447 14448 const char *p_referred_by = NULL; 14449 char *h_refer_to = NULL; 14450 char *h_referred_by = NULL; 14451 char *refer_to; 14452 const char *p_refer_to; 14453 char *referred_by_uri = NULL; 14454 char *ptr; 14455 struct sip_request *req = NULL; 14456 const char *transfer_context = NULL; 14457 struct sip_refer *referdata; 14458 14459 14460 req = outgoing_req; 14461 referdata = transferer->refer; 14462 14463 if (!req) { 14464 req = &transferer->initreq; 14465 } 14466 14467 p_refer_to = get_header(req, "Refer-To"); 14468 if (ast_strlen_zero(p_refer_to)) { 14469 ast_log(LOG_WARNING, "Refer-To Header missing. Skipping transfer.\n"); 14470 return -2; /* Syntax error */ 14471 } 14472 h_refer_to = ast_strdupa(p_refer_to); 14473 refer_to = get_in_brackets(h_refer_to); 14474 if (!strncasecmp(refer_to, "sip:", 4)) { 14475 refer_to += 4; /* Skip sip: */ 14476 } else if (!strncasecmp(refer_to, "sips:", 5)) { 14477 refer_to += 5; 14478 } else { 14479 ast_log(LOG_WARNING, "Can't transfer to non-sip: URI. (Refer-to: %s)?\n", refer_to); 14480 return -3; 14481 } 14482 14483 /* Get referred by header if it exists */ 14484 p_referred_by = get_header(req, "Referred-By"); 14485 14486 /* Give useful transfer information to the dialplan */ 14487 if (transferer->owner) { 14488 struct ast_channel *peer = ast_bridged_channel(transferer->owner); 14489 if (peer) { 14490 pbx_builtin_setvar_helper(peer, "SIPREFERRINGCONTEXT", transferer->context); 14491 pbx_builtin_setvar_helper(peer, "SIPREFERREDBYHDR", p_referred_by); 14492 } 14493 } 14494 14495 if (!ast_strlen_zero(p_referred_by)) { 14496 char *lessthan; 14497 h_referred_by = ast_strdupa(p_referred_by); 14498 14499 /* Store referrer's caller ID name */ 14500 ast_copy_string(referdata->referred_by_name, h_referred_by, sizeof(referdata->referred_by_name)); 14501 if ((lessthan = strchr(referdata->referred_by_name, '<'))) { 14502 *(lessthan - 1) = '\0'; /* Space */ 14503 } 14504 14505 referred_by_uri = get_in_brackets(h_referred_by); 14506 14507 if (!strncasecmp(referred_by_uri, "sip:", 4)) { 14508 referred_by_uri += 4; /* Skip sip: */ 14509 } else if (!strncasecmp(referred_by_uri, "sips:", 5)) { 14510 referred_by_uri += 5; /* Skip sips: */ 14511 } else { 14512 ast_log(LOG_WARNING, "Huh? Not a sip: header (Referred-by: %s). Skipping.\n", referred_by_uri); 14513 referred_by_uri = NULL; 14514 } 14515 } 14516 14517 /* Check for arguments in the refer_to header */ 14518 if ((ptr = strcasestr(refer_to, "replaces="))) { 14519 char *to = NULL, *from = NULL; 14520 14521 /* This is an attended transfer */ 14522 referdata->attendedtransfer = 1; 14523 ast_copy_string(referdata->replaces_callid, ptr+9, sizeof(referdata->replaces_callid)); 14524 ast_uri_decode(referdata->replaces_callid); 14525 if ((ptr = strchr(referdata->replaces_callid, ';'))) /* Find options */ { 14526 *ptr++ = '\0'; 14527 } 14528 14529 if (ptr) { 14530 /* Find the different tags before we destroy the string */ 14531 to = strcasestr(ptr, "to-tag="); 14532 from = strcasestr(ptr, "from-tag="); 14533 } 14534 14535 /* Grab the to header */ 14536 if (to) { 14537 ptr = to + 7; 14538 if ((to = strchr(ptr, '&'))) { 14539 *to = '\0'; 14540 } 14541 if ((to = strchr(ptr, ';'))) { 14542 *to = '\0'; 14543 } 14544 ast_copy_string(referdata->replaces_callid_totag, ptr, sizeof(referdata->replaces_callid_totag)); 14545 } 14546 14547 if (from) { 14548 ptr = from + 9; 14549 if ((to = strchr(ptr, '&'))) { 14550 *to = '\0'; 14551 } 14552 if ((to = strchr(ptr, ';'))) { 14553 *to = '\0'; 14554 } 14555 ast_copy_string(referdata->replaces_callid_fromtag, ptr, sizeof(referdata->replaces_callid_fromtag)); 14556 } 14557 14558 if (!sip_cfg.pedanticsipchecking) { 14559 ast_debug(2, "Attended transfer: Will use Replace-Call-ID : %s (No check of from/to tags)\n", referdata->replaces_callid ); 14560 } else { 14561 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>" ); 14562 } 14563 } 14564 14565 if ((ptr = strchr(refer_to, '@'))) { /* Separate domain */ 14566 char *urioption = NULL, *domain; 14567 int bracket = 0; 14568 *ptr++ = '\0'; 14569 14570 if ((urioption = strchr(ptr, ';'))) { /* Separate urioptions */ 14571 *urioption++ = '\0'; 14572 } 14573 14574 domain = ptr; 14575 14576 /* Remove :port */ 14577 for (; *ptr != '\0'; ++ptr) { 14578 if (*ptr == ':' && bracket == 0) { 14579 *ptr = '\0'; 14580 break; 14581 } else if (*ptr == '[') { 14582 ++bracket; 14583 } else if (*ptr == ']') { 14584 --bracket; 14585 } 14586 } 14587 14588 SIP_PEDANTIC_DECODE(domain); 14589 SIP_PEDANTIC_DECODE(urioption); 14590 14591 /* Save the domain for the dial plan */ 14592 ast_copy_string(referdata->refer_to_domain, domain, sizeof(referdata->refer_to_domain)); 14593 if (urioption) { 14594 ast_copy_string(referdata->refer_to_urioption, urioption, sizeof(referdata->refer_to_urioption)); 14595 } 14596 } 14597 14598 if ((ptr = strchr(refer_to, ';'))) /* Remove options */ 14599 *ptr = '\0'; 14600 14601 SIP_PEDANTIC_DECODE(refer_to); 14602 ast_copy_string(referdata->refer_to, refer_to, sizeof(referdata->refer_to)); 14603 14604 if (referred_by_uri) { 14605 if ((ptr = strchr(referred_by_uri, ';'))) /* Remove options */ 14606 *ptr = '\0'; 14607 SIP_PEDANTIC_DECODE(referred_by_uri); 14608 ast_copy_string(referdata->referred_by, referred_by_uri, sizeof(referdata->referred_by)); 14609 } else { 14610 referdata->referred_by[0] = '\0'; 14611 } 14612 14613 /* Determine transfer context */ 14614 if (transferer->owner) /* Mimic behaviour in res_features.c */ 14615 transfer_context = pbx_builtin_getvar_helper(transferer->owner, "TRANSFER_CONTEXT"); 14616 14617 /* By default, use the context in the channel sending the REFER */ 14618 if (ast_strlen_zero(transfer_context)) { 14619 transfer_context = S_OR(transferer->owner->macrocontext, 14620 S_OR(transferer->context, sip_cfg.default_context)); 14621 } 14622 14623 ast_copy_string(referdata->refer_to_context, transfer_context, sizeof(referdata->refer_to_context)); 14624 14625 /* Either an existing extension or the parking extension */ 14626 if (referdata->attendedtransfer || ast_exists_extension(NULL, transfer_context, refer_to, 1, NULL) ) { 14627 if (sip_debug_test_pvt(transferer)) { 14628 ast_verbose("SIP transfer to extension %s@%s by %s\n", refer_to, transfer_context, referred_by_uri); 14629 } 14630 /* We are ready to transfer to the extension */ 14631 return 0; 14632 } 14633 if (sip_debug_test_pvt(transferer)) 14634 ast_verbose("Failed SIP Transfer to non-existing extension %s in context %s\n n", refer_to, transfer_context); 14635 14636 /* Failure, we can't find this extension */ 14637 return -1; 14638 }
| 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 14039 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_header(), and get_pai().
Referenced by check_peer_ok(), check_user_full(), handle_request_invite(), handle_request_update(), and handle_response_invite().
14040 { 14041 char tmp[256]; 14042 struct sip_request *req; 14043 char *cid_num = ""; 14044 char *cid_name = ""; 14045 int callingpres = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED; 14046 char *privacy = ""; 14047 char *screen = ""; 14048 char *start, *end; 14049 14050 if (!ast_test_flag(&p->flags[0], SIP_TRUSTRPID)) 14051 return 0; 14052 req = oreq; 14053 if (!req) 14054 req = &p->initreq; 14055 ast_copy_string(tmp, get_header(req, "Remote-Party-ID"), sizeof(tmp)); 14056 if (ast_strlen_zero(tmp)) { 14057 return get_pai(p, req); 14058 } 14059 14060 start = tmp; 14061 if (*start == '"') { 14062 *start++ = '\0'; 14063 end = strchr(start, '"'); 14064 if (!end) 14065 return 0; 14066 *end++ = '\0'; 14067 cid_name = start; 14068 start = ast_skip_blanks(end); 14069 } 14070 14071 if (*start != '<') 14072 return 0; 14073 *start++ = '\0'; 14074 end = strchr(start, '@'); 14075 if (!end) 14076 return 0; 14077 *end++ = '\0'; 14078 if (strncasecmp(start, "sip:", 4)) 14079 return 0; 14080 cid_num = start + 4; 14081 if (global_shrinkcallerid && ast_is_shrinkable_phonenumber(cid_num)) 14082 ast_shrink_phone_number(cid_num); 14083 start = end; 14084 14085 end = strchr(start, '>'); 14086 if (!end) 14087 return 0; 14088 *end++ = '\0'; 14089 if (*end) { 14090 start = end; 14091 if (*start != ';') 14092 return 0; 14093 *start++ = '\0'; 14094 while (!ast_strlen_zero(start)) { 14095 end = strchr(start, ';'); 14096 if (end) 14097 *end++ = '\0'; 14098 if (!strncasecmp(start, "privacy=", 8)) 14099 privacy = start + 8; 14100 else if (!strncasecmp(start, "screen=", 7)) 14101 screen = start + 7; 14102 start = end; 14103 } 14104 14105 if (!strcasecmp(privacy, "full")) { 14106 if (!strcasecmp(screen, "yes")) 14107 callingpres = AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN; 14108 else if (!strcasecmp(screen, "no")) 14109 callingpres = AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED; 14110 } else { 14111 if (!strcasecmp(screen, "yes")) 14112 callingpres = AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN; 14113 else if (!strcasecmp(screen, "no")) 14114 callingpres = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED; 14115 } 14116 } 14117 14118 /* Only return true if the supplied caller id is different */ 14119 if (!strcasecmp(p->cid_num, cid_num) && !strcasecmp(p->cid_name, cid_name) && p->callingpres == callingpres) 14120 return 0; 14121 14122 ast_string_field_set(p, cid_num, cid_num); 14123 ast_string_field_set(p, cid_name, cid_name); 14124 p->callingpres = callingpres; 14125 14126 if (p->owner) { 14127 ast_set_callerid(p->owner, cid_num, cid_name, NULL); 14128 p->owner->caller.id.name.presentation = callingpres; 14129 p->owner->caller.id.number.presentation = callingpres; 14130 } 14131 14132 return 1; 14133 }
| 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 6681 of file chan_sip.c.
References get_body_by_line(), and len().
06682 { 06683 int len = strlen(name); 06684 06685 while (*start < (req->sdp_start + req->sdp_count)) { 06686 const char *r = get_body_by_line(REQ_OFFSET_TO_STR(req, line[(*start)++]), name, len, '='); 06687 if (r[0] != '\0') 06688 return r; 06689 } 06690 06691 /* if the line was not found, ensure that *start points past the SDP */ 06692 (*start)++; 06693 06694 return ""; 06695 }
| 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 6702 of file chan_sip.c.
References ast_skip_blanks(), and type.
Referenced by process_sdp().
06703 { 06704 char type = '\0'; 06705 const char *line = NULL; 06706 06707 if (stop > (req->sdp_start + req->sdp_count)) { 06708 stop = req->sdp_start + req->sdp_count; 06709 } 06710 06711 while (*start < stop) { 06712 line = REQ_OFFSET_TO_STR(req, line[(*start)++]); 06713 if (line[1] == '=') { 06714 type = line[0]; 06715 *value = ast_skip_blanks(line + 2); 06716 break; 06717 } 06718 } 06719 06720 return type; 06721 }
| 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 14356 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().
14357 { 14358 struct sip_pvt *sip_pvt_ptr; 14359 struct sip_pvt tmp_dialog = { 14360 .callid = callid, 14361 }; 14362 14363 if (totag) { 14364 ast_debug(4, "Looking for callid %s (fromtag %s totag %s)\n", callid, fromtag ? fromtag : "<no fromtag>", totag ? totag : "<no totag>"); 14365 } 14366 14367 /* Search dialogs and find the match */ 14368 14369 sip_pvt_ptr = ao2_t_find(dialogs, &tmp_dialog, OBJ_POINTER, "ao2_find of dialog in dialogs table"); 14370 if (sip_pvt_ptr) { 14371 /* Go ahead and lock it (and its owner) before returning */ 14372 sip_pvt_lock(sip_pvt_ptr); 14373 if (sip_cfg.pedanticsipchecking) { 14374 unsigned char frommismatch = 0, tomismatch = 0; 14375 14376 if (ast_strlen_zero(fromtag)) { 14377 sip_pvt_unlock(sip_pvt_ptr); 14378 ast_debug(4, "Matched %s call for callid=%s - no from tag specified, pedantic check fails\n", 14379 sip_pvt_ptr->outgoing_call == TRUE ? "OUTGOING": "INCOMING", sip_pvt_ptr->callid); 14380 return NULL; 14381 } 14382 14383 if (ast_strlen_zero(totag)) { 14384 sip_pvt_unlock(sip_pvt_ptr); 14385 ast_debug(4, "Matched %s call for callid=%s - no to tag specified, pedantic check fails\n", 14386 sip_pvt_ptr->outgoing_call == TRUE ? "OUTGOING": "INCOMING", sip_pvt_ptr->callid); 14387 return NULL; 14388 } 14389 /* RFC 3891 14390 * > 3. User Agent Server Behavior: Receiving a Replaces Header 14391 * > The Replaces header contains information used to match an existing 14392 * > SIP dialog (call-id, to-tag, and from-tag). Upon receiving an INVITE 14393 * > with a Replaces header, the User Agent (UA) attempts to match this 14394 * > information with a confirmed or early dialog. The User Agent Server 14395 * > (UAS) matches the to-tag and from-tag parameters as if they were tags 14396 * > present in an incoming request. In other words, the to-tag parameter 14397 * > is compared to the local tag, and the from-tag parameter is compared 14398 * > to the remote tag. 14399 * 14400 * Thus, the totag is always compared to the local tag, regardless if 14401 * this our call is an incoming or outgoing call. 14402 */ 14403 frommismatch = !!strcmp(fromtag, sip_pvt_ptr->theirtag); 14404 tomismatch = !!strcmp(totag, sip_pvt_ptr->tag); 14405 14406 if (frommismatch || tomismatch) { 14407 sip_pvt_unlock(sip_pvt_ptr); 14408 if (frommismatch) { 14409 ast_debug(4, "Matched %s call for callid=%s - pedantic from tag check fails; their tag is %s our tag is %s\n", 14410 sip_pvt_ptr->outgoing_call == TRUE ? "OUTGOING": "INCOMING", sip_pvt_ptr->callid, 14411 fromtag, sip_pvt_ptr->theirtag); 14412 } 14413 if (tomismatch) { 14414 ast_debug(4, "Matched %s call for callid=%s - pedantic to tag check fails; their tag is %s our tag is %s\n", 14415 sip_pvt_ptr->outgoing_call == TRUE ? "OUTGOING": "INCOMING", sip_pvt_ptr->callid, 14416 totag, sip_pvt_ptr->tag); 14417 } 14418 return NULL; 14419 } 14420 } 14421 14422 if (totag) 14423 ast_debug(4, "Matched %s call - their tag is %s Our tag is %s\n", 14424 sip_pvt_ptr->outgoing_call == TRUE ? "OUTGOING": "INCOMING", 14425 sip_pvt_ptr->theirtag, sip_pvt_ptr->tag); 14426 14427 /* deadlock avoidance... */ 14428 while (sip_pvt_ptr->owner && ast_channel_trylock(sip_pvt_ptr->owner)) { 14429 sip_pvt_unlock(sip_pvt_ptr); 14430 usleep(1); 14431 sip_pvt_lock(sip_pvt_ptr); 14432 } 14433 } 14434 14435 return sip_pvt_ptr; 14436 }
| static const char* get_srv_protocol | ( | enum sip_transport | t | ) | [inline, static] |
Return protocol string for srv dns query.
Definition at line 3034 of file chan_sip.c.
Referenced by __sip_subscribe_mwi_do(), build_peer(), create_addr(), and transmit_register().
03035 { 03036 switch (t) { 03037 case SIP_TRANSPORT_UDP: 03038 return "udp"; 03039 case SIP_TRANSPORT_TLS: 03040 case SIP_TRANSPORT_TCP: 03041 return "tcp"; 03042 } 03043 03044 return "udp"; 03045 }
| static const char* get_srv_service | ( | enum sip_transport | t | ) | [inline, static] |
Return service string for srv dns query.
Definition at line 3048 of file chan_sip.c.
Referenced by __sip_subscribe_mwi_do(), build_peer(), create_addr(), and transmit_register().
03049 { 03050 switch (t) { 03051 case SIP_TRANSPORT_TCP: 03052 case SIP_TRANSPORT_UDP: 03053 return "sip"; 03054 case SIP_TRANSPORT_TLS: 03055 return "sips"; 03056 } 03057 return "sip"; 03058 }
| static const char* get_transport | ( | enum sip_transport | t | ) | [inline, static] |
Return transport as string.
Definition at line 3019 of file chan_sip.c.
Referenced by _sip_show_peer(), ast_sip_ouraddrfor(), build_contact(), get_transport_pvt(), handle_request_do(), parse_moved_contact(), sip_show_settings(), sip_show_tcp(), and transmit_notify_with_mwi().
03020 { 03021 switch (t) { 03022 case SIP_TRANSPORT_UDP: 03023 return "UDP"; 03024 case SIP_TRANSPORT_TCP: 03025 return "TCP"; 03026 case SIP_TRANSPORT_TLS: 03027 return "TLS"; 03028 } 03029 03030 return "UNKNOWN"; 03031 }
| static const char* get_transport_list | ( | unsigned int | transports | ) | [inline, static] |
Return configuration of transports for a device.
Definition at line 2998 of file chan_sip.c.
Referenced by _sip_show_peer(), peers_data_provider_get(), and sip_show_settings().
02998 { 02999 switch (transports) { 03000 case SIP_TRANSPORT_UDP: 03001 return "UDP"; 03002 case SIP_TRANSPORT_TCP: 03003 return "TCP"; 03004 case SIP_TRANSPORT_TLS: 03005 return "TLS"; 03006 case SIP_TRANSPORT_UDP | SIP_TRANSPORT_TCP: 03007 return "TCP,UDP"; 03008 case SIP_TRANSPORT_UDP | SIP_TRANSPORT_TLS: 03009 return "TLS,UDP"; 03010 case SIP_TRANSPORT_TCP | SIP_TRANSPORT_TLS: 03011 return "TLS,TCP"; 03012 default: 03013 return transports ? 03014 "TLS,TCP,UDP" : "UNKNOWN"; 03015 } 03016 }
| static const char* get_transport_pvt | ( | struct sip_pvt * | p | ) | [inline, static] |
Return transport of dialog.
Definition at line 3066 of file chan_sip.c.
References get_transport(), and set_socket_transport().
Referenced by __sip_xmit(), and build_via().
03067 { 03068 if (p->outboundproxy && p->outboundproxy->transport) { 03069 set_socket_transport(&p->socket, p->outboundproxy->transport); 03070 } 03071 03072 return get_transport(p->socket.type); 03073 }
| 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 2976 of file chan_sip.c.
References ast_strlen_zero().
Referenced by __set_address_from_contact(), and parse_register_contact().
02977 { 02978 int res = 0; 02979 02980 if (ast_strlen_zero(transport)) { 02981 return res; 02982 } 02983 02984 if (!strcasecmp(transport, "udp")) { 02985 res |= SIP_TRANSPORT_UDP; 02986 } 02987 if (!strcasecmp(transport, "tcp")) { 02988 res |= SIP_TRANSPORT_TCP; 02989 } 02990 if (!strcasecmp(transport, "tls")) { 02991 res |= SIP_TRANSPORT_TLS; 02992 } 02993 02994 return res; 02995 }
| static const char * gettag | ( | const struct sip_request * | req, | |
| const char * | header, | |||
| char * | tagbuf, | |||
| int | tagbufsize | |||
| ) | [static] |
Get tag from packet.
Definition at line 20251 of file chan_sip.c.
References ast_copy_string(), get_header(), strcasestr(), and strsep().
Referenced by find_call(), handle_incoming(), handle_request_subscribe(), and handle_response().
20252 { 20253 const char *thetag; 20254 20255 if (!tagbuf) 20256 return NULL; 20257 tagbuf[0] = '\0'; /* reset the buffer */ 20258 thetag = get_header(req, header); 20259 thetag = strcasestr(thetag, ";tag="); 20260 if (thetag) { 20261 thetag += 5; 20262 ast_copy_string(tagbuf, thetag, tagbufsize); 20263 return strsep(&tagbuf, ";"); 20264 } 20265 return NULL; 20266 }
| static int handle_cc_notify | ( | struct sip_pvt * | pvt, | |
| struct sip_request * | req | |||
| ) | [static] |
Definition at line 20268 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_header(), status, transmit_publish(), and transmit_response().
Referenced by handle_request_notify().
20269 { 20270 struct sip_monitor_instance *monitor_instance = ao2_callback(sip_monitor_instances, 0, 20271 find_sip_monitor_instance_by_subscription_pvt, pvt); 20272 const char *status = get_body(req, "cc-state", ':'); 20273 struct cc_epa_entry *cc_entry; 20274 char *uri; 20275 20276 if (!monitor_instance) { 20277 transmit_response(pvt, "400 Bad Request", req); 20278 return -1; 20279 } 20280 20281 if (ast_strlen_zero(status)) { 20282 ao2_ref(monitor_instance, -1); 20283 transmit_response(pvt, "400 Bad Request", req); 20284 return -1; 20285 } 20286 20287 if (!strcmp(status, "queued")) { 20288 /* We've been told that we're queued. This is the endpoint's way of telling 20289 * us that it has accepted our CC request. We need to alert the core of this 20290 * development 20291 */ 20292 ast_cc_monitor_request_acked(monitor_instance->core_id, "SIP endpoint %s accepted request", monitor_instance->device_name); 20293 transmit_response(pvt, "200 OK", req); 20294 ao2_ref(monitor_instance, -1); 20295 return 0; 20296 } 20297 20298 /* It's open! Yay! */ 20299 uri = get_body(req, "cc-URI", ':'); 20300 if (ast_strlen_zero(uri)) { 20301 uri = get_in_brackets((char *)get_header(req, "From")); 20302 } 20303 20304 ast_string_field_set(monitor_instance, notify_uri, uri); 20305 if (monitor_instance->suspension_entry) { 20306 cc_entry = monitor_instance->suspension_entry->instance_data; 20307 if (cc_entry->current_state == CC_CLOSED) { 20308 /* If we've created a suspension entry and the current state is closed, then that means 20309 * we got a notice from the CC core earlier to suspend monitoring, but because this particular 20310 * call leg had not yet notified us that it was ready for recall, it meant that we 20311 * could not yet send a PUBLISH. Now, however, we can. 20312 */ 20313 construct_pidf_body(CC_CLOSED, monitor_instance->suspension_entry->body, 20314 sizeof(monitor_instance->suspension_entry->body), monitor_instance->peername); 20315 transmit_publish(monitor_instance->suspension_entry, SIP_PUBLISH_INITIAL, monitor_instance->notify_uri); 20316 } else { 20317 ast_cc_monitor_callee_available(monitor_instance->core_id, "SIP monitored callee has become available"); 20318 } 20319 } else { 20320 ast_cc_monitor_callee_available(monitor_instance->core_id, "SIP monitored callee has become available"); 20321 } 20322 ao2_ref(monitor_instance, -1); 20323 transmit_response(pvt, "200 OK", req); 20324 20325 return 0; 20326 }
| static int handle_cc_subscribe | ( | struct sip_pvt * | p, | |
| struct sip_request * | req | |||
| ) | [static] |
Definition at line 22895 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(), get_header(), LOG_WARNING, ast_cc_agent::private_data, and transmit_response().
Referenced by handle_request_subscribe().
22896 { 22897 const char *uri = REQ_OFFSET_TO_STR(req, rlPart2); 22898 char *param_separator; 22899 struct ast_cc_agent *agent; 22900 struct sip_cc_agent_pvt *agent_pvt; 22901 const char *expires_str = get_header(req, "Expires"); 22902 int expires = -1; /* Just need it to be non-zero */ 22903 22904 if (!ast_strlen_zero(expires_str)) { 22905 sscanf(expires_str, "%d", &expires); 22906 } 22907 22908 if ((param_separator = strchr(uri, ';'))) { 22909 *param_separator = '\0'; 22910 } 22911 22912 if (!(agent = find_sip_cc_agent_by_subscribe_uri(uri))) { 22913 if (!expires) { 22914 /* Typically, if a 0 Expires reaches us and we can't find 22915 * the corresponding agent, it means that the CC transaction 22916 * has completed and so the calling side is just trying to 22917 * clean up its subscription. We'll just respond with a 22918 * 200 OK and be done with it 22919 */ 22920 transmit_response(p, "200 OK", req); 22921 return 0; 22922 } 22923 ast_log(LOG_WARNING, "Invalid URI '%s' in CC subscribe\n", uri); 22924 transmit_response(p, "404 Not Found", req); 22925 return -1; 22926 } 22927 22928 agent_pvt = agent->private_data; 22929 22930 if (!expires) { 22931 /* We got sent a SUBSCRIBE and found an agent. This means that CC 22932 * is being canceled. 22933 */ 22934 ast_cc_failed(agent->core_id, "CC is being canceled by %s", agent->device_name); 22935 transmit_response(p, "200 OK", req); 22936 ao2_ref(agent, -1); 22937 return 0; 22938 } 22939 22940 agent_pvt->subscribe_pvt = dialog_ref(p, "SIP CC agent gains reference to subscription dialog"); 22941 ast_cc_agent_accept_request(agent->core_id, "SIP caller %s has requested CC via SUBSCRIBE", 22942 agent->device_name); 22943 p->subscribed = CALL_COMPLETION; 22944 22945 /* We don't send a response here. That is done in the agent's ack callback or in the 22946 * agent destructor, should a failure occur before we have responded 22947 */ 22948 ao2_ref(agent, -1); 22949 return 0; 22950 }
| 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 two struct ast_flags | |
| mask | array of two struct ast_flags | |
| v | linked list of config variables to process |
Definition at line 25136 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(), strsep(), ast_variable::value, and word.
Referenced by build_peer(), and reload_config().
25137 { 25138 int res = 1; 25139 25140 if (!strcasecmp(v->name, "trustrpid")) { 25141 ast_set_flag(&mask[0], SIP_TRUSTRPID); 25142 ast_set2_flag(&flags[0], ast_true(v->value), SIP_TRUSTRPID); 25143 } else if (!strcasecmp(v->name, "sendrpid")) { 25144 ast_set_flag(&mask[0], SIP_SENDRPID); 25145 if (!strcasecmp(v->value, "pai")) { 25146 ast_set_flag(&flags[0], SIP_SENDRPID_PAI); 25147 } else if (!strcasecmp(v->value, "rpid")) { 25148 ast_set_flag(&flags[0], SIP_SENDRPID_RPID); 25149 } else if (ast_true(v->value)) { 25150 ast_set_flag(&flags[0], SIP_SENDRPID_RPID); 25151 } 25152 } else if (!strcasecmp(v->name, "rpid_update")) { 25153 ast_set_flag(&mask[1], SIP_PAGE2_RPID_UPDATE); 25154 ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_RPID_UPDATE); 25155 } else if (!strcasecmp(v->name, "rpid_immediate")) { 25156 ast_set_flag(&mask[1], SIP_PAGE2_RPID_IMMEDIATE); 25157 ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_RPID_IMMEDIATE); 25158 } else if (!strcasecmp(v->name, "g726nonstandard")) { 25159 ast_set_flag(&mask[0], SIP_G726_NONSTANDARD); 25160 ast_set2_flag(&flags[0], ast_true(v->value), SIP_G726_NONSTANDARD); 25161 } else if (!strcasecmp(v->name, "useclientcode")) { 25162 ast_set_flag(&mask[0], SIP_USECLIENTCODE); 25163 ast_set2_flag(&flags[0], ast_true(v->value), SIP_USECLIENTCODE); 25164 } else if (!strcasecmp(v->name, "dtmfmode")) { 25165 ast_set_flag(&mask[0], SIP_DTMF); 25166 ast_clear_flag(&flags[0], SIP_DTMF); 25167 if (!strcasecmp(v->value, "inband")) 25168 ast_set_flag(&flags[0], SIP_DTMF_INBAND); 25169 else if (!strcasecmp(v->value, "rfc2833")) 25170 ast_set_flag(&flags[0], SIP_DTMF_RFC2833); 25171 else if (!strcasecmp(v->value, "info")) 25172 ast_set_flag(&flags[0], SIP_DTMF_INFO); 25173 else if (!strcasecmp(v->value, "shortinfo")) 25174 ast_set_flag(&flags[0], SIP_DTMF_SHORTINFO); 25175 else if (!strcasecmp(v->value, "auto")) 25176 ast_set_flag(&flags[0], SIP_DTMF_AUTO); 25177 else { 25178 ast_log(LOG_WARNING, "Unknown dtmf mode '%s' on line %d, using rfc2833\n", v->value, v->lineno); 25179 ast_set_flag(&flags[0], SIP_DTMF_RFC2833); 25180 } 25181 } else if (!strcasecmp(v->name, "nat")) { 25182 ast_set_flag(&mask[0], SIP_NAT_FORCE_RPORT); 25183 if (!strcasecmp(v->value, "no")) { 25184 ast_clear_flag(&flags[0], SIP_NAT_FORCE_RPORT); 25185 } else if (!strcasecmp(v->value, "force_rport")) { 25186 ast_set_flag(&flags[0], SIP_NAT_FORCE_RPORT); 25187 } else if (!strcasecmp(v->value, "yes")) { 25188 ast_set_flag(&flags[0], SIP_NAT_FORCE_RPORT); 25189 ast_set_flag(&mask[1], SIP_PAGE2_SYMMETRICRTP); 25190 ast_set_flag(&flags[1], SIP_PAGE2_SYMMETRICRTP); 25191 } else if (!strcasecmp(v->value, "comedia")) { 25192 ast_clear_flag(&flags[0], SIP_NAT_FORCE_RPORT); 25193 ast_set_flag(&mask[1], SIP_PAGE2_SYMMETRICRTP); 25194 ast_set_flag(&flags[1], SIP_PAGE2_SYMMETRICRTP); 25195 } 25196 } else if (!strcasecmp(v->name, "directmedia") || !strcasecmp(v->name, "canreinvite")) { 25197 ast_set_flag(&mask[0], SIP_REINVITE); 25198 ast_clear_flag(&flags[0], SIP_REINVITE); 25199 if (ast_true(v->value)) { 25200 ast_set_flag(&flags[0], SIP_DIRECT_MEDIA | SIP_DIRECT_MEDIA_NAT); 25201 } else if (!ast_false(v->value)) { 25202 char buf[64]; 25203 char *word, *next = buf; 25204 25205 ast_copy_string(buf, v->value, sizeof(buf)); 25206 while ((word = strsep(&next, ","))) { 25207 if (!strcasecmp(word, "update")) { 25208 ast_set_flag(&flags[0], SIP_REINVITE_UPDATE | SIP_DIRECT_MEDIA); 25209 } else if (!strcasecmp(word, "nonat")) { 25210 ast_set_flag(&flags[0], SIP_DIRECT_MEDIA); 25211 ast_clear_flag(&flags[0], SIP_DIRECT_MEDIA_NAT); 25212 } else { 25213 ast_log(LOG_WARNING, "Unknown directmedia mode '%s' on line %d\n", v->value, v->lineno); 25214 } 25215 } 25216 } 25217 } else if (!strcasecmp(v->name, "insecure")) { 25218 ast_set_flag(&mask[0], SIP_INSECURE); 25219 ast_clear_flag(&flags[0], SIP_INSECURE); 25220 set_insecure_flags(&flags[0], v->value, v->lineno); 25221 } else if (!strcasecmp(v->name, "progressinband")) { 25222 ast_set_flag(&mask[0], SIP_PROG_INBAND); 25223 ast_clear_flag(&flags[0], SIP_PROG_INBAND); 25224 if (ast_true(v->value)) 25225 ast_set_flag(&flags[0], SIP_PROG_INBAND_YES); 25226 else if (strcasecmp(v->value, "never")) 25227 ast_set_flag(&flags[0], SIP_PROG_INBAND_NO); 25228 } else if (!strcasecmp(v->name, "promiscredir")) { 25229 ast_set_flag(&mask[0], SIP_PROMISCREDIR); 25230 ast_set2_flag(&flags[0], ast_true(v->value), SIP_PROMISCREDIR); 25231 } else if (!strcasecmp(v->name, "videosupport")) { 25232 if (!strcasecmp(v->value, "always")) { 25233 ast_set_flag(&mask[1], SIP_PAGE2_VIDEOSUPPORT_ALWAYS); 25234 ast_set_flag(&flags[1], SIP_PAGE2_VIDEOSUPPORT_ALWAYS); 25235 } else { 25236 ast_set_flag(&mask[1], SIP_PAGE2_VIDEOSUPPORT); 25237 ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_VIDEOSUPPORT); 25238 } 25239 } else if (!strcasecmp(v->name, "textsupport")) { 25240 ast_set_flag(&mask[1], SIP_PAGE2_TEXTSUPPORT); 25241 ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_TEXTSUPPORT); 25242 res = 1; 25243 } else if (!strcasecmp(v->name, "allowoverlap")) { 25244 ast_set_flag(&mask[1], SIP_PAGE2_ALLOWOVERLAP); 25245 ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_ALLOWOVERLAP); 25246 } else if (!strcasecmp(v->name, "allowsubscribe")) { 25247 ast_set_flag(&mask[1], SIP_PAGE2_ALLOWSUBSCRIBE); 25248 ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_ALLOWSUBSCRIBE); 25249 } else if (!strcasecmp(v->name, "ignoresdpversion")) { 25250 ast_set_flag(&mask[1], SIP_PAGE2_IGNORESDPVERSION); 25251 ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_IGNORESDPVERSION); 25252 } else if (!strcasecmp(v->name, "faxdetect")) { 25253 ast_set_flag(&mask[1], SIP_PAGE2_FAX_DETECT); 25254 if (ast_true(v->value)) { 25255 ast_set_flag(&flags[1], SIP_PAGE2_FAX_DETECT_BOTH); 25256 } else if (ast_false(v->value)) { 25257 ast_clear_flag(&flags[1], SIP_PAGE2_FAX_DETECT_BOTH); 25258 } else { 25259 char *buf = ast_strdupa(v->value); 25260 char *word, *next = buf; 25261 25262 while ((word = strsep(&next, ","))) { 25263 if (!strcasecmp(word, "cng")) { 25264 ast_set_flag(&flags[1], SIP_PAGE2_FAX_DETECT_CNG); 25265 } else if (!strcasecmp(word, "t38")) { 25266 ast_set_flag(&flags[1], SIP_PAGE2_FAX_DETECT_T38); 25267 } else { 25268 ast_log(LOG_WARNING, "Unknown faxdetect mode '%s' on line %d.\n", word, v->lineno); 25269 } 25270 } 25271 } 25272 } else if (!strcasecmp(v->name, "rfc2833compensate")) { 25273 ast_set_flag(&mask[1], SIP_PAGE2_RFC2833_COMPENSATE); 25274 ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_RFC2833_COMPENSATE); 25275 } else if (!strcasecmp(v->name, "buggymwi")) { 25276 ast_set_flag(&mask[1], SIP_PAGE2_BUGGY_MWI); 25277 ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_BUGGY_MWI); 25278 } else 25279 res = 0; 25280 25281 return res; 25282 }
| 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).
Definition at line 23392 of file chan_sip.c.
References __sip_ack(), ast_channel_ref, ast_channel_unlock, ast_channel_unref, ast_debug, ast_log(), ast_skip_blanks(), ast_sockaddr_stringify(), ast_string_field_set, ast_strlen_zero(), ast_verbose, check_pendings(), debug, extract_uri(), find_sdp(), get_header(), 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, ast_channel::name, pbx_builtin_setvar_helper(), process_sdp(), pvt_set_needdestroy(), sip_cfg, sip_debug_test_pvt(), sip_methods, sip_pvt_lock, sip_pvt_unlock, sip_scheddestroy(), cfsip_methods::text, transmit_response(), transmit_response_reliable(), and transmit_response_with_allow().
Referenced by handle_request_do(), and process_request_queue().
23393 { 23394 /* Called with p->lock held, as well as p->owner->lock if appropriate, keeping things 23395 relatively static */ 23396 const char *cmd; 23397 const char *cseq; 23398 const char *useragent; 23399 int seqno; 23400 int len; 23401 int respid; 23402 int res = 0; 23403 int debug = sip_debug_test_pvt(p); 23404 const char *e; 23405 int error = 0; 23406 int oldmethod = p->method; 23407 int acked = 0; 23408 23409 /* Get Method and Cseq */ 23410 cseq = get_header(req, "Cseq"); 23411 cmd = REQ_OFFSET_TO_STR(req, header[0]); 23412 23413 /* Must have Cseq */ 23414 if (ast_strlen_zero(cmd) || ast_strlen_zero(cseq)) { 23415 ast_log(LOG_ERROR, "Missing Cseq. Dropping this SIP message, it's incomplete.\n"); 23416 error = 1; 23417 } 23418 if (!error && sscanf(cseq, "%30d%n", &seqno, &len) != 1) { 23419 ast_log(LOG_ERROR, "No seqno in '%s'. Dropping incomplete message.\n", cmd); 23420 error = 1; 23421 } 23422 if (error) { 23423 if (!p->initreq.headers) { /* New call */ 23424 pvt_set_needdestroy(p, "no headers"); 23425 } 23426 return -1; 23427 } 23428 /* Get the command XXX */ 23429 23430 cmd = REQ_OFFSET_TO_STR(req, rlPart1); 23431 e = ast_skip_blanks(REQ_OFFSET_TO_STR(req, rlPart2)); 23432 23433 /* Save useragent of the client */ 23434 useragent = get_header(req, "User-Agent"); 23435 if (!ast_strlen_zero(useragent)) 23436 ast_string_field_set(p, useragent, useragent); 23437 23438 /* Find out SIP method for incoming request */ 23439 if (req->method == SIP_RESPONSE) { /* Response to our request */ 23440 /* ignore means "don't do anything with it" but still have to 23441 * respond appropriately. 23442 * But in this case this is a response already, so we really 23443 * have nothing to do with this message, and even setting the 23444 * ignore flag is pointless. 23445 */ 23446 if (ast_strlen_zero(e)) { 23447 return 0; 23448 } 23449 if (sscanf(e, "%30d %n", &respid, &len) != 1) { 23450 ast_log(LOG_WARNING, "Invalid response: '%s'\n", e); 23451 return 0; 23452 } 23453 if (respid <= 0) { 23454 ast_log(LOG_WARNING, "Invalid SIP response code: '%d'\n", respid); 23455 return 0; 23456 } 23457 if (p->ocseq && (p->ocseq < seqno)) { 23458 ast_debug(1, "Ignoring out of order response %d (expecting %d)\n", seqno, p->ocseq); 23459 return -1; 23460 } else { 23461 char causevar[256], causeval[256]; 23462 23463 if ((respid == 200) || ((respid >= 300) && (respid <= 399))) { 23464 extract_uri(p, req); 23465 } 23466 23467 handle_response(p, respid, e + len, req, seqno); 23468 23469 if (p->owner) { 23470 struct ast_channel *owner = p->owner; 23471 23472 snprintf(causevar, sizeof(causevar), "MASTER_CHANNEL(HASH(SIP_CAUSE,%s))", owner->name); 23473 snprintf(causeval, sizeof(causeval), "SIP %s", REQ_OFFSET_TO_STR(req, rlPart2)); 23474 23475 ast_channel_ref(owner); 23476 sip_pvt_unlock(p); 23477 ast_channel_unlock(owner); 23478 *nounlock = 1; 23479 pbx_builtin_setvar_helper(owner, causevar, causeval); 23480 ast_channel_unref(owner); 23481 sip_pvt_lock(p); 23482 } 23483 } 23484 return 0; 23485 } 23486 23487 /* New SIP request coming in 23488 (could be new request in existing SIP dialog as well...) 23489 */ 23490 23491 p->method = req->method; /* Find out which SIP method they are using */ 23492 ast_debug(4, "**** Received %s (%d) - Command in SIP %s\n", sip_methods[p->method].text, sip_methods[p->method].id, cmd); 23493 23494 if (p->icseq && (p->icseq > seqno) ) { 23495 if (p->pendinginvite && seqno == p->pendinginvite && (req->method == SIP_ACK || req->method == SIP_CANCEL)) { 23496 ast_debug(2, "Got CANCEL or ACK on INVITE with transactions in between.\n"); 23497 } else { 23498 ast_debug(1, "Ignoring too old SIP packet packet %d (expecting >= %d)\n", seqno, p->icseq); 23499 if (req->method != SIP_ACK) 23500 transmit_response(p, "503 Server error", req); /* We must respond according to RFC 3261 sec 12.2 */ 23501 return -1; 23502 } 23503 } else if (p->icseq && 23504 p->icseq == seqno && 23505 req->method != SIP_ACK && 23506 (p->method != SIP_CANCEL || p->alreadygone)) { 23507 /* ignore means "don't do anything with it" but still have to 23508 respond appropriately. We do this if we receive a repeat of 23509 the last sequence number */ 23510 req->ignore = 1; 23511 ast_debug(3, "Ignoring SIP message because of retransmit (%s Seqno %d, ours %d)\n", sip_methods[p->method].text, p->icseq, seqno); 23512 } 23513 23514 /* RFC 3261 section 9. "CANCEL has no effect on a request to which a UAS has 23515 * already given a final response." */ 23516 if (!p->pendinginvite && (req->method == SIP_CANCEL)) { 23517 transmit_response(p, "481 Call/Transaction Does Not Exist", req); 23518 return res; 23519 } 23520 23521 if (seqno >= p->icseq) 23522 /* Next should follow monotonically (but not necessarily 23523 incrementally -- thanks again to the genius authors of SIP -- 23524 increasing */ 23525 p->icseq = seqno; 23526 23527 /* Find their tag if we haven't got it */ 23528 if (ast_strlen_zero(p->theirtag)) { 23529 char tag[128]; 23530 23531 gettag(req, "From", tag, sizeof(tag)); 23532 ast_string_field_set(p, theirtag, tag); 23533 } 23534 snprintf(p->lastmsg, sizeof(p->lastmsg), "Rx: %s", cmd); 23535 23536 if (sip_cfg.pedanticsipchecking) { 23537 /* If this is a request packet without a from tag, it's not 23538 correct according to RFC 3261 */ 23539 /* Check if this a new request in a new dialog with a totag already attached to it, 23540 RFC 3261 - section 12.2 - and we don't want to mess with recovery */ 23541 if (!p->initreq.headers && req->has_to_tag) { 23542 /* If this is a first request and it got a to-tag, it is not for us */ 23543 if (!req->ignore && req->method == SIP_INVITE) { 23544 transmit_response_reliable(p, "481 Call/Transaction Does Not Exist", req); 23545 /* Will cease to exist after ACK */ 23546 } else if (req->method != SIP_ACK) { 23547 transmit_response(p, "481 Call/Transaction Does Not Exist", req); 23548 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 23549 } else { 23550 ast_debug(1, "Got ACK for unknown dialog... strange.\n"); 23551 } 23552 return res; 23553 } 23554 } 23555 23556 if (!e && (p->method == SIP_INVITE || p->method == SIP_SUBSCRIBE || p->method == SIP_REGISTER || p->method == SIP_NOTIFY || p->method == SIP_PUBLISH)) { 23557 transmit_response(p, "400 Bad request", req); 23558 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 23559 return -1; 23560 } 23561 23562 /* Handle various incoming SIP methods in requests */ 23563 switch (p->method) { 23564 case SIP_OPTIONS: 23565 res = handle_request_options(p, req, addr, e); 23566 break; 23567 case SIP_INVITE: 23568 res = handle_request_invite(p, req, debug, seqno, addr, recount, e, nounlock); 23569 break; 23570 case SIP_REFER: 23571 res = handle_request_refer(p, req, debug, seqno, nounlock); 23572 break; 23573 case SIP_CANCEL: 23574 res = handle_request_cancel(p, req); 23575 break; 23576 case SIP_BYE: 23577 res = handle_request_bye(p, req); 23578 break; 23579 case SIP_MESSAGE: 23580 res = handle_request_message(p, req); 23581 break; 23582 case SIP_PUBLISH: 23583 res = handle_request_publish(p, req, addr, seqno, e); 23584 break; 23585 case SIP_SUBSCRIBE: 23586 res = handle_request_subscribe(p, req, addr, seqno, e); 23587 break; 23588 case SIP_REGISTER: 23589 res = handle_request_register(p, req, addr, e); 23590 break; 23591 case SIP_INFO: 23592 if (req->debug) 23593 ast_verbose("Receiving INFO!\n"); 23594 if (!req->ignore) 23595 handle_request_info(p, req); 23596 else /* if ignoring, transmit response */ 23597 transmit_response(p, "200 OK", req); 23598 break; 23599 case SIP_NOTIFY: 23600 res = handle_request_notify(p, req, addr, seqno, e); 23601 break; 23602 case SIP_UPDATE: 23603 res = handle_request_update(p, req); 23604 break; 23605 case SIP_ACK: 23606 /* Make sure we don't ignore this */ 23607 if (seqno == p->pendinginvite) { 23608 p->invitestate = INV_TERMINATED; 23609 p->pendinginvite = 0; 23610 acked = __sip_ack(p, seqno, 1 /* response */, 0); 23611 if (find_sdp(req)) { 23612 if (process_sdp(p, req, SDP_T38_NONE)) 23613 return -1; 23614 } 23615 check_pendings(p); 23616 } else if (p->glareinvite == seqno) { 23617 /* handle ack for the 491 pending sent for glareinvite */ 23618 p->glareinvite = 0; 23619 acked = __sip_ack(p, seqno, 1, 0); 23620 } 23621 if (!acked) { 23622 /* Got an ACK that did not match anything. Ignore 23623 * silently and restore previous method */ 23624 p->method = oldmethod; 23625 } 23626 if (!p->lastinvite && ast_strlen_zero(p->randdata)) { 23627 pvt_set_needdestroy(p, "unmatched ACK"); 23628 } 23629 break; 23630 default: 23631 transmit_response_with_allow(p, "501 Method Not Implemented", req, 0); 23632 ast_log(LOG_NOTICE, "Unknown SIP command '%s' from '%s'\n", 23633 cmd, ast_sockaddr_stringify(&p->sa)); 23634 /* If this is some new method, and we don't have a call, destroy it now */ 23635 if (!p->initreq.headers) { 23636 pvt_set_needdestroy(p, "unimplemented method"); 23637 } 23638 break; 23639 } 23640 return res; 23641 }
| static int handle_invite_replaces | ( | struct sip_pvt * | p, | |
| struct sip_request * | req, | |||
| int | debug, | |||
| int | 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 20573 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_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, ast_channel::name, 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().
20574 { 20575 int earlyreplace = 0; 20576 int oneleggedreplace = 0; /* Call with no bridge, propably IVR or voice message */ 20577 struct ast_channel *c = p->owner; /* Our incoming call */ 20578 struct ast_channel *replacecall = p->refer->refer_call->owner; /* The channel we're about to take over */ 20579 struct ast_channel *targetcall; /* The bridge to the take-over target */ 20580 20581 /* Check if we're in ring state */ 20582 if (replacecall->_state == AST_STATE_RING) 20583 earlyreplace = 1; 20584 20585 /* Check if we have a bridge */ 20586 if (!(targetcall = ast_bridged_channel(replacecall))) { 20587 /* We have no bridge */ 20588 if (!earlyreplace) { 20589 ast_debug(2, " Attended transfer attempted to replace call with no bridge (maybe ringing). Channel %s!\n", replacecall->name); 20590 oneleggedreplace = 1; 20591 } 20592 } 20593 if (targetcall && targetcall->_state == AST_STATE_RINGING) 20594 ast_debug(4, "SIP transfer: Target channel is in ringing state\n"); 20595 20596 if (targetcall) 20597 ast_debug(4, "SIP transfer: Invite Replace incoming channel should bridge to channel %s while hanging up channel %s\n", targetcall->name, replacecall->name); 20598 else 20599 ast_debug(4, "SIP transfer: Invite Replace incoming channel should replace and hang up channel %s (one call leg)\n", replacecall->name); 20600 20601 if (req->ignore) { 20602 ast_log(LOG_NOTICE, "Ignoring this INVITE with replaces in a stupid way.\n"); 20603 /* We should answer something here. If we are here, the 20604 call we are replacing exists, so an accepted 20605 can't harm */ 20606 transmit_response_with_sdp(p, "200 OK", req, XMIT_RELIABLE, FALSE, FALSE); 20607 /* Do something more clever here */ 20608 if (c) { 20609 *nounlock = 1; 20610 ast_channel_unlock(c); 20611 } 20612 ast_channel_unlock(replacecall); 20613 sip_pvt_unlock(p->refer->refer_call); 20614 return 1; 20615 } 20616 if (!c) { 20617 /* What to do if no channel ??? */ 20618 ast_log(LOG_ERROR, "Unable to create new channel. Invite/replace failed.\n"); 20619 transmit_response_reliable(p, "503 Service Unavailable", req); 20620 append_history(p, "Xfer", "INVITE/Replace Failed. No new channel."); 20621 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 20622 ast_channel_unlock(replacecall); 20623 sip_pvt_unlock(p->refer->refer_call); 20624 return 1; 20625 } 20626 append_history(p, "Xfer", "INVITE/Replace received"); 20627 /* We have three channels to play with 20628 channel c: New incoming call 20629 targetcall: Call from PBX to target 20630 p->refer->refer_call: SIP pvt dialog from transferer to pbx. 20631 replacecall: The owner of the previous 20632 We need to masq C into refer_call to connect to 20633 targetcall; 20634 If we are talking to internal audio stream, target call is null. 20635 */ 20636 20637 /* Fake call progress */ 20638 transmit_response(p, "100 Trying", req); 20639 ast_setstate(c, AST_STATE_RING); 20640 20641 /* Masquerade the new call into the referred call to connect to target call 20642 Targetcall is not touched by the masq */ 20643 20644 /* Answer the incoming call and set channel to UP state */ 20645 transmit_response_with_sdp(p, "200 OK", req, XMIT_RELIABLE, FALSE, FALSE); 20646 20647 ast_setstate(c, AST_STATE_UP); 20648 20649 /* Stop music on hold and other generators */ 20650 ast_quiet_chan(replacecall); 20651 ast_quiet_chan(targetcall); 20652 ast_debug(4, "Invite/Replaces: preparing to masquerade %s into %s\n", c->name, replacecall->name); 20653 20654 /* Make sure that the masq does not free our PVT for the old call */ 20655 if (! earlyreplace && ! oneleggedreplace ) 20656 ast_set_flag(&p->refer->refer_call->flags[0], SIP_DEFER_BYE_ON_TRANSFER); /* Delay hangup */ 20657 20658 /* Prepare the masquerade - if this does not happen, we will be gone */ 20659 if(ast_channel_masquerade(replacecall, c)) 20660 ast_log(LOG_ERROR, "Failed to masquerade C into Replacecall\n"); 20661 else 20662 ast_debug(4, "Invite/Replaces: Going to masquerade %s into %s\n", c->name, replacecall->name); 20663 20664 /* C should now be in place of replacecall. all channel locks and pvt locks should be removed 20665 * before issuing the masq. Since we are unlocking both the pvt (p) and its owner channel (c) 20666 * it is possible for channel c to be destroyed on us. To prevent this, we must give c a reference 20667 * before any unlocking takes place and remove it only once we are completely done with it */ 20668 ast_channel_ref(c); 20669 ast_channel_unlock(replacecall); 20670 ast_channel_unlock(c); 20671 sip_pvt_unlock(p->refer->refer_call); 20672 sip_pvt_unlock(p); 20673 if (ast_do_masquerade(replacecall)) { 20674 ast_log(LOG_WARNING, "Failed to perform masquerade with INVITE replaces\n"); 20675 } 20676 ast_channel_lock(c); 20677 if (earlyreplace || oneleggedreplace ) { 20678 c->hangupcause = AST_CAUSE_SWITCH_CONGESTION; 20679 } 20680 ast_setstate(c, AST_STATE_DOWN); 20681 ast_channel_unlock(c); 20682 20683 /* The call should be down with no ast_channel, so hang it up */ 20684 c->tech_pvt = dialog_unref(c->tech_pvt, "unref dialog c->tech_pvt"); 20685 20686 /* c and c's tech pvt must be unlocked at this point for ast_hangup */ 20687 ast_hangup(c); 20688 /* this indicates to handle_request_do that the owner channel has already been unlocked */ 20689 *nounlock = 1; 20690 /* lock PVT structure again after hangup */ 20691 sip_pvt_lock(p); 20692 ast_channel_unref(c); 20693 return 0; 20694 }
| static int handle_request_bye | ( | struct sip_pvt * | p, | |
| struct sip_request * | req | |||
| ) | [static] |
Handle incoming BYE request.
Definition at line 22250 of file chan_sip.c.
References __sip_pretend_ack(), append_history, ast_async_goto(), ast_bridged_channel(), AST_CAUSE_PROTOCOL_ERROR, ast_channel_lock, 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(), get_header(), LOG_NOTICE, LOG_WARNING, pbx_builtin_setvar_helper(), quality, sip_alreadygone(), sip_cfg, 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(), and transmit_response_reliable().
Referenced by handle_incoming().
22251 { 22252 struct ast_channel *c=NULL; 22253 int res; 22254 struct ast_channel *bridged_to; 22255 22256 /* If we have an INCOMING invite that we haven't answered, terminate that transaction */ 22257 if (p->pendinginvite && !ast_test_flag(&p->flags[0], SIP_OUTGOING) && !req->ignore) { 22258 transmit_response_reliable(p, "487 Request Terminated", &p->initreq); 22259 } 22260 22261 __sip_pretend_ack(p); 22262 22263 p->invitestate = INV_TERMINATED; 22264 22265 copy_request(&p->initreq, req); 22266 if (sipdebug) 22267 ast_debug(1, "Initializing initreq for method %s - callid %s\n", sip_methods[req->method].text, p->callid); 22268 check_via(p, req); 22269 sip_alreadygone(p); 22270 22271 /* Get RTCP quality before end of call */ 22272 if (p->do_history || p->owner) { 22273 char quality_buf[AST_MAX_USER_FIELD], *quality; 22274 struct ast_channel *bridge = p->owner ? ast_bridged_channel(p->owner) : NULL; 22275 22276 /* We need to get the lock on bridge because ast_rtp_instance_set_stats_vars will attempt 22277 * to lock the bridge. This may get hairy... 22278 */ 22279 while (bridge && ast_channel_trylock(bridge)) { 22280 ast_channel_unlock(p->owner); 22281 do { 22282 /* Can't use DEADLOCK_AVOIDANCE since p is an ao2 object */ 22283 sip_pvt_unlock(p); 22284 usleep(1); 22285 sip_pvt_lock(p); 22286 } while (p->owner && ast_channel_trylock(p->owner)); 22287 bridge = p->owner ? ast_bridged_channel(p->owner) : NULL; 22288 } 22289 22290 22291 if (p->rtp && (quality = ast_rtp_instance_get_quality(p->rtp, AST_RTP_INSTANCE_STAT_FIELD_QUALITY, quality_buf, sizeof(quality_buf)))) { 22292 if (p->do_history) { 22293 append_history(p, "RTCPaudio", "Quality:%s", quality); 22294 22295 if ((quality = ast_rtp_instance_get_quality(p->rtp, AST_RTP_INSTANCE_STAT_FIELD_QUALITY_JITTER, quality_buf, sizeof(quality_buf)))) { 22296 append_history(p, "RTCPaudioJitter", "Quality:%s", quality); 22297 } 22298 if ((quality = ast_rtp_instance_get_quality(p->rtp, AST_RTP_INSTANCE_STAT_FIELD_QUALITY_LOSS, quality_buf, sizeof(quality_buf)))) { 22299 append_history(p, "RTCPaudioLoss", "Quality:%s", quality); 22300 } 22301 if ((quality = ast_rtp_instance_get_quality(p->rtp, AST_RTP_INSTANCE_STAT_FIELD_QUALITY_RTT, quality_buf, sizeof(quality_buf)))) { 22302 append_history(p, "RTCPaudioRTT", "Quality:%s", quality); 22303 } 22304 } 22305 22306 if (p->owner) { 22307 ast_rtp_instance_set_stats_vars(p->owner, p->rtp); 22308 } 22309 22310 } 22311 22312 if (bridge) { 22313 struct sip_pvt *q = bridge->tech_pvt; 22314 22315 if (IS_SIP_TECH(bridge->tech) && q && q->rtp) { 22316 ast_rtp_instance_set_stats_vars(bridge, q->rtp); 22317 } 22318 ast_channel_unlock(bridge); 22319 } 22320 22321 if (p->vrtp && (quality = ast_rtp_instance_get_quality(p->vrtp, AST_RTP_INSTANCE_STAT_FIELD_QUALITY, quality_buf, sizeof(quality_buf)))) { 22322 if (p->do_history) { 22323 append_history(p, "RTCPvideo", "Quality:%s", quality); 22324 } 22325 if (p->owner) { 22326 pbx_builtin_setvar_helper(p->owner, "RTPVIDEOQOS", quality); 22327 } 22328 } 22329 if (p->trtp && (quality = ast_rtp_instance_get_quality(p->trtp, AST_RTP_INSTANCE_STAT_FIELD_QUALITY, quality_buf, sizeof(quality_buf)))) { 22330 if (p->do_history) { 22331 append_history(p, "RTCPtext", "Quality:%s", quality); 22332 } 22333 if (p->owner) { 22334 pbx_builtin_setvar_helper(p->owner, "RTPTEXTQOS", quality); 22335 } 22336 } 22337 } 22338 22339 stop_media_flows(p); /* Immediately stop RTP, VRTP and UDPTL as applicable */ 22340 stop_session_timer(p); /* Stop Session-Timer */ 22341 22342 if (!ast_strlen_zero(get_header(req, "Also"))) { 22343 ast_log(LOG_NOTICE, "Client '%s' using deprecated BYE/Also transfer method. Ask vendor to support REFER instead\n", 22344 ast_sockaddr_stringify(&p->recv)); 22345 if (ast_strlen_zero(p->context)) 22346 ast_string_field_set(p, context, sip_cfg.default_context); 22347 res = get_also_info(p, req); 22348 if (!res) { 22349 c = p->owner; 22350 if (c) { 22351 bridged_to = ast_bridged_channel(c); 22352 if (bridged_to) { 22353 /* Don't actually hangup here... */ 22354 ast_queue_control(c, AST_CONTROL_UNHOLD); 22355 ast_channel_unlock(c); /* async_goto can do a masquerade, no locks can be held during a masq */ 22356 ast_async_goto(bridged_to, p->context, p->refer->refer_to, 1); 22357 ast_channel_lock(c); 22358 } else 22359 ast_queue_hangup(p->owner); 22360 } 22361 } else { 22362 ast_log(LOG_WARNING, "Invalid transfer information from '%s'\n", ast_sockaddr_stringify(&p->recv)); 22363 if (p->owner) 22364 ast_queue_hangup_with_cause(p->owner, AST_CAUSE_PROTOCOL_ERROR); 22365 } 22366 } else if (p->owner) { 22367 ast_set_hangupsource(p->owner, p->owner->name, 0); 22368 ast_queue_hangup(p->owner); 22369 sip_scheddestroy_final(p, DEFAULT_TRANS_TIMEOUT); 22370 ast_debug(3, "Received bye, issuing owner hangup\n"); 22371 } else { 22372 sip_scheddestroy_final(p, DEFAULT_TRANS_TIMEOUT); 22373 ast_debug(3, "Received bye, no owner, selfdestruct soon.\n"); 22374 } 22375 ast_clear_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED); 22376 transmit_response(p, "200 OK", req); 22377 22378 return 1; 22379 }
| static int handle_request_cancel | ( | struct sip_pvt * | p, | |
| struct sip_request * | req | |||
| ) | [static] |
Handle incoming CANCEL request.
Definition at line 22185 of file chan_sip.c.
References __sip_pretend_ack(), ast_debug, ast_free, ast_queue_hangup(), AST_SCHED_DEL, ast_set_hangupsource(), AST_STATE_UP, 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().
22186 { 22187 22188 check_via(p, req); 22189 sip_alreadygone(p); 22190 22191 if (p->owner && p->owner->_state == AST_STATE_UP) { 22192 /* This call is up, cancel is ignored, we need a bye */ 22193 transmit_response(p, "200 OK", req); 22194 ast_debug(1, "Got CANCEL on an answered call. Ignoring... \n"); 22195 return 0; 22196 } 22197 22198 /* At this point, we could have cancelled the invite at the same time 22199 as the other side sends a CANCEL. Our final reply with error code 22200 might not have been received by the other side before the CANCEL 22201 was sent, so let's just give up retransmissions and waiting for 22202 ACK on our error code. The call is hanging up any way. */ 22203 if (p->invitestate == INV_TERMINATED || p->invitestate == INV_COMPLETED) { 22204 __sip_pretend_ack(p); 22205 } 22206 if (p->invitestate != INV_TERMINATED) 22207 p->invitestate = INV_CANCELLED; 22208 22209 if (ast_test_flag(&p->flags[0], SIP_INC_COUNT) || ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD)) 22210 update_call_counter(p, DEC_CALL_LIMIT); 22211 22212 stop_media_flows(p); /* Immediately stop RTP, VRTP and UDPTL as applicable */ 22213 if (p->owner) { 22214 ast_set_hangupsource(p->owner, p->owner->name, 0); 22215 ast_queue_hangup(p->owner); 22216 } 22217 else 22218 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 22219 if (p->initreq.len > 0) { 22220 struct sip_pkt *pkt, *prev_pkt; 22221 /* If the CANCEL we are receiving is a retransmission, and we already have scheduled 22222 * a reliable 487, then we don't want to schedule another one on top of the previous 22223 * one. 22224 * 22225 * As odd as this may sound, we can't rely on the previously-transmitted "reliable" 22226 * response in this situation. What if we've sent all of our reliable responses 22227 * already and now all of a sudden, we get this second CANCEL? 22228 * 22229 * The only way to do this correctly is to cancel our previously-scheduled reliably- 22230 * transmitted response and send a new one in its place. 22231 */ 22232 for (pkt = p->packets, prev_pkt = NULL; pkt; prev_pkt = pkt, pkt = pkt->next) { 22233 if (pkt->seqno == p->lastinvite && pkt->response_code == 487) { 22234 AST_SCHED_DEL(sched, pkt->retransid); 22235 UNLINK(pkt, p->packets, prev_pkt); 22236 ast_free(pkt); 22237 break; 22238 } 22239 } 22240 transmit_response_reliable(p, "487 Request Terminated", &p->initreq); 22241 transmit_response(p, "200 OK", req); 22242 return 1; 22243 } else { 22244 transmit_response(p, "481 Call Leg Does Not Exist", req); 22245 return 0; 22246 } 22247 }
| 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 23781 of file chan_sip.c.
References ao2_t_ref, append_history, ast_channel_trylock, ast_channel_unlock, ast_debug, AST_LIST_EMPTY, ast_log(), ast_mutex_lock, ast_mutex_unlock, AST_SCHED_DEL_UNREF, ast_sockaddr_copy(), ast_sockaddr_stringify(), ast_str_reset(), ast_update_use_count(), ast_verbose, copy_socket_data(), find_call(), find_sip_method(), get_header(), get_transport(), handle_incoming(), LOG_ERROR, lws2sws(), netlock, parse_request(), process_request_queue(), queue_request(), S_OR, sip_cfg, sip_debug_test_addr(), sip_pvt_unlock, and transmit_response().
Referenced by _sip_tcp_helper_thread(), and sipsock_read().
23782 { 23783 struct sip_pvt *p; 23784 int recount = 0; 23785 int nounlock = 0; 23786 int lockretry; 23787 23788 if (sip_debug_test_addr(addr)) /* Set the debug flag early on packet level */ 23789 req->debug = 1; 23790 if (sip_cfg.pedanticsipchecking) 23791 req->len = lws2sws(req->data->str, req->len); /* Fix multiline headers */ 23792 if (req->debug) { 23793 ast_verbose("\n<--- SIP read from %s:%s --->\n%s\n<------------->\n", 23794 get_transport(req->socket.type), ast_sockaddr_stringify(addr), req->data->str); 23795 } 23796 23797 if (parse_request(req) == -1) { /* Bad packet, can't parse */ 23798 ast_str_reset(req->data); /* nulling this out is NOT a good idea here. */ 23799 return 1; 23800 } 23801 req->method = find_sip_method(REQ_OFFSET_TO_STR(req, rlPart1)); 23802 23803 if (req->debug) 23804 ast_verbose("--- (%d headers %d lines)%s ---\n", req->headers, req->lines, (req->headers + req->lines == 0) ? " Nat keepalive" : ""); 23805 23806 if (req->headers < 2) { /* Must have at least two headers */ 23807 ast_str_reset(req->data); /* nulling this out is NOT a good idea here. */ 23808 return 1; 23809 } 23810 23811 /* Process request, with netlock held, and with usual deadlock avoidance */ 23812 for (lockretry = 10; lockretry > 0; lockretry--) { 23813 ast_mutex_lock(&netlock); 23814 23815 /* Find the active SIP dialog or create a new one */ 23816 p = find_call(req, addr, req->method); /* returns p locked */ 23817 if (p == NULL) { 23818 ast_debug(1, "Invalid SIP message - rejected , no callid, len %d\n", req->len); 23819 ast_mutex_unlock(&netlock); 23820 return 1; 23821 } 23822 23823 copy_socket_data(&p->socket, &req->socket); 23824 23825 /* Go ahead and lock the owner if it has one -- we may need it */ 23826 /* becaues this is deadlock-prone, we need to try and unlock if failed */ 23827 if (!p->owner || !ast_channel_trylock(p->owner)) 23828 break; /* locking succeeded */ 23829 23830 if (lockretry != 1) { 23831 sip_pvt_unlock(p); 23832 ao2_t_ref(p, -1, "release p (from find_call) inside lockretry loop"); /* we'll look for it again, but p is dead now */ 23833 ast_mutex_unlock(&netlock); 23834 /* Sleep for a very short amount of time */ 23835 usleep(1); 23836 } 23837 } 23838 ast_sockaddr_copy(&p->recv, addr); 23839 23840 if (p->do_history) /* This is a request or response, note what it was for */ 23841 append_history(p, "Rx", "%s / %s / %s", req->data->str, get_header(req, "CSeq"), REQ_OFFSET_TO_STR(req, rlPart2)); 23842 23843 if (!lockretry) { 23844 if (!queue_request(p, req)) { 23845 /* the request has been queued for later handling */ 23846 sip_pvt_unlock(p); 23847 ao2_t_ref(p, -1, "release p (from find_call) after queueing request"); 23848 ast_mutex_unlock(&netlock); 23849 return 1; 23850 } 23851 23852 if (p->owner) 23853 ast_log(LOG_ERROR, "Channel lock for %s could not be obtained, and request was unable to be queued.\n", S_OR(p->owner->name, "- no channel name ??? - ")); 23854 ast_log(LOG_ERROR, "SIP transaction failed: %s \n", p->callid); 23855 if (req->method != SIP_ACK) 23856 transmit_response(p, "503 Server error", req); /* We must respond according to RFC 3261 sec 12.2 */ 23857 /* XXX We could add retry-after to make sure they come back */ 23858 append_history(p, "LockFail", "Owner lock failed, transaction failed."); 23859 sip_pvt_unlock(p); 23860 ao2_t_ref(p, -1, "release p (from find_call) at end of lockretry"); /* p is gone after the return */ 23861 ast_mutex_unlock(&netlock); 23862 return 1; 23863 } 23864 23865 /* if there are queued requests on this sip_pvt, process them first, so that everything is 23866 handled in order 23867 */ 23868 if (!AST_LIST_EMPTY(&p->request_queue)) { 23869 AST_SCHED_DEL_UNREF(sched, p->request_queue_sched_id, dialog_unref(p, "when you delete the request_queue_sched_id sched, you should dec the refcount for the stored dialog ptr")); 23870 process_request_queue(p, &recount, &nounlock); 23871 } 23872 23873 if (handle_incoming(p, req, addr, &recount, &nounlock) == -1) { 23874 /* Request failed */ 23875 ast_debug(1, "SIP message could not be handled, bad request: %-70.70s\n", p->callid[0] ? p->callid : "<no callid>"); 23876 } 23877 23878 if (recount) 23879 ast_update_use_count(); 23880 23881 if (p->owner && !nounlock) 23882 ast_channel_unlock(p->owner); 23883 sip_pvt_unlock(p); 23884 ast_mutex_unlock(&netlock); 23885 ao2_t_ref(p, -1, "throw away dialog ptr from find_call at end of routine"); /* p is gone after the return */ 23886 return 1; 23887 }
| static void handle_request_info | ( | struct sip_pvt * | p, | |
| struct sip_request * | req | |||
| ) | [static] |
Receive SIP INFO Message.
Definition at line 17511 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_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_header(), get_msg_text(), ast_frame_subclass::integer, ast_frame::len, LOG_WARNING, sip_scheddestroy(), ast_frame::subclass, transmit_response(), and TRUE.
Referenced by handle_incoming().
17512 { 17513 char buf[1024]; 17514 unsigned int event; 17515 const char *c = get_header(req, "Content-Type"); 17516 17517 /* Need to check the media/type */ 17518 if (!strcasecmp(c, "application/dtmf-relay") || 17519 !strcasecmp(c, "application/vnd.nortelnetworks.digits")) { 17520 unsigned int duration = 0; 17521 17522 if (!p->owner) { /* not a PBX call */ 17523 transmit_response(p, "481 Call leg/transaction does not exist", req); 17524 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 17525 return; 17526 } 17527 17528 /* Try getting the "signal=" part */ 17529 if (ast_strlen_zero(c = get_body(req, "Signal", '=')) && ast_strlen_zero(c = get_body(req, "d", '='))) { 17530 ast_log(LOG_WARNING, "Unable to retrieve DTMF signal from INFO message from %s\n", p->callid); 17531 transmit_response(p, "200 OK", req); /* Should return error */ 17532 return; 17533 } else { 17534 ast_copy_string(buf, c, sizeof(buf)); 17535 } 17536 17537 if (!ast_strlen_zero((c = get_body(req, "Duration", '=')))) { 17538 duration = atoi(c); 17539 } 17540 if (!duration) { 17541 duration = 100; /* 100 ms */ 17542 } 17543 17544 17545 if (ast_strlen_zero(buf)) { 17546 transmit_response(p, "200 OK", req); 17547 return; 17548 } 17549 17550 if (buf[0] == '*') { 17551 event = 10; 17552 } else if (buf[0] == '#') { 17553 event = 11; 17554 } else if ((buf[0] >= 'A') && (buf[0] <= 'D')) { 17555 event = 12 + buf[0] - 'A'; 17556 } else if (buf[0] == '!') { 17557 event = 16; 17558 } else { 17559 event = atoi(buf); 17560 } 17561 if (event == 16) { 17562 /* send a FLASH event */ 17563 struct ast_frame f = { AST_FRAME_CONTROL, { AST_CONTROL_FLASH, } }; 17564 ast_queue_frame(p->owner, &f); 17565 if (sipdebug) { 17566 ast_verbose("* DTMF-relay event received: FLASH\n"); 17567 } 17568 } else { 17569 /* send a DTMF event */ 17570 struct ast_frame f = { AST_FRAME_DTMF, }; 17571 if (event < 10) { 17572 f.subclass.integer = '0' + event; 17573 } else if (event == 10) { 17574 f.subclass.integer = '*'; 17575 } else if (event == 11) { 17576 f.subclass.integer = '#'; 17577 } else if (event < 16) { 17578 f.subclass.integer = 'A' + (event - 12); 17579 } 17580 f.len = duration; 17581 ast_queue_frame(p->owner, &f); 17582 if (sipdebug) { 17583 ast_verbose("* DTMF-relay event received: %c\n", (int) f.subclass.integer); 17584 } 17585 } 17586 transmit_response(p, "200 OK", req); 17587 return; 17588 } else if (!strcasecmp(c, "application/dtmf")) { 17589 /*! \todo Note: Doesn't read the duration of the DTMF. Should be fixed. */ 17590 unsigned int duration = 0; 17591 17592 if (!p->owner) { /* not a PBX call */ 17593 transmit_response(p, "481 Call leg/transaction does not exist", req); 17594 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 17595 return; 17596 } 17597 17598 get_msg_text(buf, sizeof(buf), req, TRUE); 17599 duration = 100; /* 100 ms */ 17600 17601 if (ast_strlen_zero(buf)) { 17602 transmit_response(p, "200 OK", req); 17603 return; 17604 } 17605 event = atoi(buf); 17606 if (event == 16) { 17607 /* send a FLASH event */ 17608 struct ast_frame f = { AST_FRAME_CONTROL, { AST_CONTROL_FLASH }, }; 17609 ast_queue_frame(p->owner, &f); 17610 if (sipdebug) { 17611 ast_verbose("* DTMF-relay event received: FLASH\n"); 17612 } 17613 } else { 17614 /* send a DTMF event */ 17615 struct ast_frame f = { AST_FRAME_DTMF, }; 17616 if (event < 10) { 17617 f.subclass.integer = '0' + event; 17618 } else if (event == 10) { 17619 f.subclass.integer = '*'; 17620 } else if (event == 11) { 17621 f.subclass.integer = '#'; 17622 } else if (event < 16) { 17623 f.subclass.integer = 'A' + (event - 12); 17624 } 17625 f.len = duration; 17626 ast_queue_frame(p->owner, &f); 17627 if (sipdebug) { 17628 ast_verbose("* DTMF-relay event received: %c\n", (int) f.subclass.integer); 17629 } 17630 } 17631 transmit_response(p, "200 OK", req); 17632 return; 17633 17634 } else if (!strcasecmp(c, "application/media_control+xml")) { 17635 /* Eh, we'll just assume it's a fast picture update for now */ 17636 if (p->owner) { 17637 ast_queue_control(p->owner, AST_CONTROL_VIDUPDATE); 17638 } 17639 transmit_response(p, "200 OK", req); 17640 return; 17641 } else if (!ast_strlen_zero(c = get_header(req, "X-ClientCode"))) { 17642 /* Client code (from SNOM phone) */ 17643 if (ast_test_flag(&p->flags[0], SIP_USECLIENTCODE)) { 17644 if (p->owner && p->owner->cdr) { 17645 ast_cdr_setuserfield(p->owner, c); 17646 } 17647 if (p->owner && ast_bridged_channel(p->owner) && ast_bridged_channel(p->owner)->cdr) { 17648 ast_cdr_setuserfield(ast_bridged_channel(p->owner), c); 17649 } 17650 transmit_response(p, "200 OK", req); 17651 } else { 17652 transmit_response(p, "403 Forbidden", req); 17653 } 17654 return; 17655 } else if (!ast_strlen_zero(c = get_header(req, "Record"))) { 17656 /* INFO messages generated by some phones to start/stop recording 17657 on phone calls. 17658 OEJ: I think this should be something that is enabled/disabled 17659 per device. I don't want incoming callers to record calls in my 17660 pbx. 17661 */ 17662 /* first, get the feature string, if it exists */ 17663 struct ast_call_feature *feat; 17664 int j; 17665 struct ast_frame f = { AST_FRAME_DTMF, }; 17666 17667 ast_rdlock_call_features(); 17668 feat = ast_find_call_feature("automon"); 17669 if (!feat || ast_strlen_zero(feat->exten)) { 17670 ast_log(LOG_WARNING, "Recording requested, but no One Touch Monitor registered. (See features.conf)\n"); 17671 /* 403 means that we don't support this feature, so don't request it again */ 17672 transmit_response(p, "403 Forbidden", req); 17673 ast_unlock_call_features(); 17674 return; 17675 } 17676 /* Send the feature code to the PBX as DTMF, just like the handset had sent it */ 17677 f.len = 100; 17678 for (j=0; j < strlen(feat->exten); j++) { 17679 f.subclass.integer = feat->exten[j]; 17680 ast_queue_frame(p->owner, &f); 17681 if (sipdebug) { 17682 ast_verbose("* DTMF-relay event faked: %c\n", f.subclass.integer); 17683 } 17684 } 17685 ast_unlock_call_features(); 17686 17687 ast_debug(1, "Got a Request to Record the channel, state %s\n", c); 17688 transmit_response(p, "200 OK", req); 17689 return; 17690 } else if (ast_strlen_zero(c = get_header(req, "Content-Length")) || !strcasecmp(c, "0")) { 17691 /* This is probably just a packet making sure the signalling is still up, just send back a 200 OK */ 17692 transmit_response(p, "200 OK", req); 17693 return; 17694 } 17695 17696 /* Other type of INFO message, not really understood by Asterisk */ 17697 /* if (get_msg_text(buf, sizeof(buf), req)) { */ 17698 17699 ast_log(LOG_WARNING, "Unable to parse INFO message from %s. Content %s\n", p->callid, buf); 17700 transmit_response(p, "415 Unsupported media type", req); 17701 return; 17702 }
| static int handle_request_invite | ( | struct sip_pvt * | p, | |
| struct sip_request * | req, | |||
| int | debug, | |||
| int | 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 20789 of file chan_sip.c.
References __sip_ack(), ast_channel::_state, append_history, ARRAY_LEN, AST_CAUSE_CALL_REJECTED, AST_CAUSE_NORMAL_CLEARING, ast_cc_agent_set_interfaces_chanvar(), ast_channel_lock, 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_copy_string(), ast_debug, 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_call(), 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_set_flag, ast_setstate(), ast_setup_cc_recall_datastore(), ast_skip_blanks(), 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_udptl_new_with_bindaddr(), ast_uri_decode(), ast_verbose, bindaddr, build_contact(), build_route(), 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_header(), 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_channel::name, 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(), ast_party_name::presentation, ast_party_number::presentation, process_sdp(), ref_peer(), restart_session_timer(), S_OR, set_pvt_allowed_methods(), set_t38_capabilities(), sip_alreadygone(), sip_cancel_destroy(), sip_cfg, sip_methods, sip_new(), sip_pvt_lock, sip_pvt_unlock, sip_refer_allocate(), sip_scheddestroy(), sip_st_alloc(), sip_t38_abort(), 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, unref_peer(), update_call_counter(), update_redirecting(), ast_party_name::valid, and ast_party_number::valid.
Referenced by handle_incoming().
20790 { 20791 int res = 1; 20792 int gotdest; 20793 const char *p_replaces; 20794 char *replace_id = NULL; 20795 int refer_locked = 0; 20796 const char *required; 20797 unsigned int required_profile = 0; 20798 struct ast_channel *c = NULL; /* New channel */ 20799 struct sip_peer *authpeer = NULL; /* Matching Peer */ 20800 int reinvite = 0; 20801 int rtn; 20802 struct ast_party_redirecting redirecting; 20803 struct ast_set_party_redirecting update_redirecting; 20804 20805 const char *p_uac_se_hdr; /* UAC's Session-Expires header string */ 20806 const char *p_uac_min_se; /* UAC's requested Min-SE interval (char string) */ 20807 int uac_max_se = -1; /* UAC's Session-Expires in integer format */ 20808 int uac_min_se = -1; /* UAC's Min-SE in integer format */ 20809 int st_active = FALSE; /* Session-Timer on/off boolean */ 20810 int st_interval = 0; /* Session-Timer negotiated refresh interval */ 20811 enum st_refresher st_ref; /* Session-Timer session refresher */ 20812 int dlg_min_se = -1; 20813 struct { 20814 char exten[AST_MAX_EXTENSION]; 20815 char context[AST_MAX_CONTEXT]; 20816 } pickup = { 20817 .exten = "", 20818 }; 20819 st_ref = SESSION_TIMER_REFRESHER_AUTO; 20820 20821 /* Find out what they support */ 20822 if (!p->sipoptions) { 20823 const char *supported = get_header(req, "Supported"); 20824 if (!ast_strlen_zero(supported)) { 20825 p->sipoptions = parse_sip_options(supported, NULL, 0); 20826 } 20827 } 20828 20829 /* Find out what they require */ 20830 required = get_header(req, "Require"); 20831 if (!ast_strlen_zero(required)) { 20832 char unsupported[256] = { 0, }; 20833 required_profile = parse_sip_options(required, unsupported, ARRAY_LEN(unsupported)); 20834 20835 /* If there are any options required that we do not support, 20836 * then send a 420 with only those unsupported options listed */ 20837 if (!ast_strlen_zero(unsupported)) { 20838 transmit_response_with_unsupported(p, "420 Bad extension (unsupported)", req, unsupported); 20839 ast_log(LOG_WARNING, "Received SIP INVITE with unsupported required extension: required:%s unsupported:%s\n", required, unsupported); 20840 p->invitestate = INV_COMPLETED; 20841 if (!p->lastinvite) 20842 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 20843 res = -1; 20844 goto request_invite_cleanup; 20845 } 20846 } 20847 20848 /* The option tags may be present in Supported: or Require: headers. 20849 Include the Require: option tags for further processing as well */ 20850 p->sipoptions |= required_profile; 20851 p->reqsipoptions = required_profile; 20852 20853 /* Check if this is a loop */ 20854 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) { 20855 /* This is a call to ourself. Send ourselves an error code and stop 20856 processing immediately, as SIP really has no good mechanism for 20857 being able to call yourself */ 20858 /* If pedantic is on, we need to check the tags. If they're different, this is 20859 in fact a forked call through a SIP proxy somewhere. */ 20860 int different; 20861 const char *initial_rlPart2 = REQ_OFFSET_TO_STR(&p->initreq, rlPart2); 20862 const char *this_rlPart2 = REQ_OFFSET_TO_STR(req, rlPart2); 20863 if (sip_cfg.pedanticsipchecking) 20864 different = sip_uri_cmp(initial_rlPart2, this_rlPart2); 20865 else 20866 different = strcmp(initial_rlPart2, this_rlPart2); 20867 if (!different) { 20868 transmit_response(p, "482 Loop Detected", req); 20869 p->invitestate = INV_COMPLETED; 20870 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 20871 res = 0; 20872 goto request_invite_cleanup; 20873 } else { 20874 /*! This is a spiral. What we need to do is to just change the outgoing INVITE 20875 * so that it now routes to the new Request URI. Since we created the INVITE ourselves 20876 * that should be all we need to do. 20877 * 20878 * \todo XXX This needs to be reviewed. YOu don't change the request URI really, you route the packet 20879 * correctly instead... 20880 */ 20881 char *uri = ast_strdupa(this_rlPart2); 20882 char *at = strchr(uri, '@'); 20883 char *peerorhost; 20884 ast_debug(2, "Potential spiral detected. Original RURI was %s, new RURI is %s\n", initial_rlPart2, this_rlPart2); 20885 transmit_response(p, "100 Trying", req); 20886 if (at) { 20887 *at = '\0'; 20888 } 20889 /* Parse out "sip:" */ 20890 if ((peerorhost = strchr(uri, ':'))) { 20891 *peerorhost++ = '\0'; 20892 } 20893 ast_string_field_set(p, theirtag, NULL); 20894 /* Treat this as if there were a call forward instead... 20895 */ 20896 ast_string_field_set(p->owner, call_forward, peerorhost); 20897 ast_queue_control(p->owner, AST_CONTROL_BUSY); 20898 res = 0; 20899 goto request_invite_cleanup; 20900 } 20901 } 20902 20903 if (!req->ignore && p->pendinginvite) { 20904 if (!ast_test_flag(&p->flags[0], SIP_OUTGOING) && (p->invitestate == INV_COMPLETED || p->invitestate == INV_TERMINATED)) { 20905 /* What do these circumstances mean? We have received an INVITE for an "incoming" dialog for which we 20906 * have sent a final response. We have not yet received an ACK, though (which is why p->pendinginvite is non-zero). 20907 * We also know that the INVITE is not a retransmission, because otherwise the "ignore" flag would be set. 20908 * This means that either we are receiving a reinvite for a terminated dialog, or we are receiving an INVITE with 20909 * credentials based on one we challenged earlier. 20910 * 20911 * The action to take in either case is to treat the INVITE as though it contains an implicit ACK for the previous 20912 * transaction. Calling __sip_ack will take care of this by clearing the p->pendinginvite and removing the response 20913 * from the previous transaction from the list of outstanding packets. 20914 */ 20915 __sip_ack(p, p->pendinginvite, 1, 0); 20916 } else { 20917 /* We already have a pending invite. Sorry. You are on hold. */ 20918 p->glareinvite = seqno; 20919 if (p->rtp && find_sdp(req)) { 20920 struct ast_sockaddr addr; 20921 if (get_ip_and_port_from_sdp(req, SDP_AUDIO, &addr)) { 20922 ast_log(LOG_WARNING, "Failed to set an alternate media source on glared reinvite. Audio may not work properly on this call.\n"); 20923 } else { 20924 ast_rtp_instance_set_alt_remote_address(p->rtp, &addr); 20925 } 20926 if (p->vrtp) { 20927 if (get_ip_and_port_from_sdp(req, SDP_VIDEO, &addr)) { 20928 ast_log(LOG_WARNING, "Failed to set an alternate media source on glared reinvite. Video may not work properly on this call.\n"); 20929 } else { 20930 ast_rtp_instance_set_alt_remote_address(p->vrtp, &addr); 20931 } 20932 } 20933 } 20934 transmit_response_reliable(p, "491 Request Pending", req); 20935 ast_debug(1, "Got INVITE on call where we already have pending INVITE, deferring that - %s\n", p->callid); 20936 /* Don't destroy dialog here */ 20937 res = 0; 20938 goto request_invite_cleanup; 20939 } 20940 } 20941 20942 p_replaces = get_header(req, "Replaces"); 20943 if (!ast_strlen_zero(p_replaces)) { 20944 /* We have a replaces header */ 20945 char *ptr; 20946 char *fromtag = NULL; 20947 char *totag = NULL; 20948 char *start, *to; 20949 int error = 0; 20950 20951 if (p->owner) { 20952 ast_debug(3, "INVITE w Replaces on existing call? Refusing action. [%s]\n", p->callid); 20953 transmit_response_reliable(p, "400 Bad request", req); /* The best way to not not accept the transfer */ 20954 /* Do not destroy existing call */ 20955 res = -1; 20956 goto request_invite_cleanup; 20957 } 20958 20959 if (sipdebug) 20960 ast_debug(3, "INVITE part of call transfer. Replaces [%s]\n", p_replaces); 20961 /* Create a buffer we can manipulate */ 20962 replace_id = ast_strdupa(p_replaces); 20963 ast_uri_decode(replace_id); 20964 20965 if (!p->refer && !sip_refer_allocate(p)) { 20966 transmit_response_reliable(p, "500 Server Internal Error", req); 20967 append_history(p, "Xfer", "INVITE/Replace Failed. Out of memory."); 20968 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 20969 p->invitestate = INV_COMPLETED; 20970 res = -1; 20971 goto request_invite_cleanup; 20972 } 20973 20974 /* Todo: (When we find phones that support this) 20975 if the replaces header contains ";early-only" 20976 we can only replace the call in early 20977 stage, not after it's up. 20978 20979 If it's not in early mode, 486 Busy. 20980 */ 20981 20982 /* Skip leading whitespace */ 20983 replace_id = ast_skip_blanks(replace_id); 20984 20985 start = replace_id; 20986 while ( (ptr = strsep(&start, ";")) ) { 20987 ptr = ast_skip_blanks(ptr); /* XXX maybe unnecessary ? */ 20988 if ( (to = strcasestr(ptr, "to-tag=") ) ) 20989 totag = to + 7; /* skip the keyword */ 20990 else if ( (to = strcasestr(ptr, "from-tag=") ) ) { 20991 fromtag = to + 9; /* skip the keyword */ 20992 fromtag = strsep(&fromtag, "&"); /* trim what ? */ 20993 } 20994 } 20995 20996 if (sipdebug) 20997 ast_debug(4, "Invite/replaces: Will use Replace-Call-ID : %s Fromtag: %s Totag: %s\n", 20998 replace_id, 20999 fromtag ? fromtag : "<no from tag>", 21000 totag ? totag : "<no to tag>"); 21001 21002 /* Try to find call that we are replacing. 21003 If we have a Replaces header, we need to cancel that call if we succeed with this call. 21004 First we cheat a little and look for a magic call-id from phones that support 21005 dialog-info+xml so we can do technology independent pickup... */ 21006 if (strncmp(replace_id, "pickup-", 7) == 0) { 21007 struct sip_pvt *subscription = NULL; 21008 replace_id += 7; /* Worst case we are looking at \0 */ 21009 21010 if ((subscription = get_sip_pvt_byid_locked(replace_id, totag, fromtag)) == NULL) { 21011 ast_log(LOG_NOTICE, "Unable to find subscription with call-id: %s\n", replace_id); 21012 transmit_response_reliable(p, "481 Call Leg Does Not Exist (Replaces)", req); 21013 error = 1; 21014 } else { 21015 ast_log(LOG_NOTICE, "Trying to pick up %s@%s\n", subscription->exten, subscription->context); 21016 ast_copy_string(pickup.exten, subscription->exten, sizeof(pickup.exten)); 21017 ast_copy_string(pickup.context, subscription->context, sizeof(pickup.context)); 21018 sip_pvt_unlock(subscription); 21019 if (subscription->owner) { 21020 ast_channel_unlock(subscription->owner); 21021 } 21022 } 21023 } 21024 21025 /* This locks both refer_call pvt and refer_call pvt's owner!!!*/ 21026 if (!error && ast_strlen_zero(pickup.exten) && (p->refer->refer_call = get_sip_pvt_byid_locked(replace_id, totag, fromtag)) == NULL) { 21027 ast_log(LOG_NOTICE, "Supervised transfer attempted to replace non-existent call id (%s)!\n", replace_id); 21028 transmit_response_reliable(p, "481 Call Leg Does Not Exist (Replaces)", req); 21029 error = 1; 21030 } else { 21031 refer_locked = 1; 21032 } 21033 21034 /* The matched call is the call from the transferer to Asterisk . 21035 We want to bridge the bridged part of the call to the 21036 incoming invite, thus taking over the refered call */ 21037 21038 if (p->refer->refer_call == p) { 21039 ast_log(LOG_NOTICE, "INVITE with replaces into it's own call id (%s == %s)!\n", replace_id, p->callid); 21040 p->refer->refer_call = dialog_unref(p->refer->refer_call, "unref dialog p->refer->refer_call"); 21041 transmit_response_reliable(p, "400 Bad request", req); /* The best way to not not accept the transfer */ 21042 error = 1; 21043 } 21044 21045 if (!error && ast_strlen_zero(pickup.exten) && !p->refer->refer_call->owner) { 21046 /* Oops, someting wrong anyway, no owner, no call */ 21047 ast_log(LOG_NOTICE, "Supervised transfer attempted to replace non-existing call id (%s)!\n", replace_id); 21048 /* Check for better return code */ 21049 transmit_response_reliable(p, "481 Call Leg Does Not Exist (Replace)", req); 21050 error = 1; 21051 } 21052 21053 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) { 21054 ast_log(LOG_NOTICE, "Supervised transfer attempted to replace non-ringing or active call id (%s)!\n", replace_id); 21055 transmit_response_reliable(p, "603 Declined (Replaces)", req); 21056 error = 1; 21057 } 21058 21059 if (error) { /* Give up this dialog */ 21060 append_history(p, "Xfer", "INVITE/Replace Failed."); 21061 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 21062 sip_pvt_unlock(p); 21063 if (p->refer->refer_call) { 21064 sip_pvt_unlock(p->refer->refer_call); 21065 if (p->refer->refer_call->owner) { 21066 ast_channel_unlock(p->refer->refer_call->owner); 21067 } 21068 } 21069 refer_locked = 0; 21070 p->invitestate = INV_COMPLETED; 21071 res = -1; 21072 goto request_invite_cleanup; 21073 } 21074 } 21075 21076 /* Check if this is an INVITE that sets up a new dialog or 21077 a re-invite in an existing dialog */ 21078 21079 if (!req->ignore) { 21080 int newcall = (p->initreq.headers ? TRUE : FALSE); 21081 21082 if (sip_cancel_destroy(p)) 21083 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 21084 /* This also counts as a pending invite */ 21085 p->pendinginvite = seqno; 21086 check_via(p, req); 21087 21088 copy_request(&p->initreq, req); /* Save this INVITE as the transaction basis */ 21089 if (sipdebug) 21090 ast_debug(1, "Initializing initreq for method %s - callid %s\n", sip_methods[req->method].text, p->callid); 21091 if (!p->owner) { /* Not a re-invite */ 21092 if (debug) 21093 ast_verbose("Using INVITE request as basis request - %s\n", p->callid); 21094 if (newcall) 21095 append_history(p, "Invite", "New call: %s", p->callid); 21096 parse_ok_contact(p, req); 21097 } else { /* Re-invite on existing call */ 21098 ast_clear_flag(&p->flags[0], SIP_OUTGOING); /* This is now an inbound dialog */ 21099 if (get_rpid(p, req)) { 21100 struct ast_party_connected_line connected; 21101 struct ast_set_party_connected_line update_connected; 21102 21103 ast_party_connected_line_init(&connected); 21104 memset(&update_connected, 0, sizeof(update_connected)); 21105 if (p->cid_num) { 21106 update_connected.id.number = 1; 21107 connected.id.number.valid = 1; 21108 connected.id.number.str = (char *) p->cid_num; 21109 connected.id.number.presentation = p->callingpres; 21110 } 21111 if (p->cid_name) { 21112 update_connected.id.name = 1; 21113 connected.id.name.valid = 1; 21114 connected.id.name.str = (char *) p->cid_name; 21115 connected.id.name.presentation = p->callingpres; 21116 } 21117 connected.id.tag = (char *) p->cid_tag; 21118 connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER; 21119 ast_channel_queue_connected_line_update(p->owner, &connected, 21120 &update_connected); 21121 } 21122 /* Handle SDP here if we already have an owner */ 21123 if (find_sdp(req)) { 21124 if (process_sdp(p, req, SDP_T38_INITIATE)) { 21125 transmit_response_reliable(p, "488 Not acceptable here", req); 21126 if (!p->lastinvite) 21127 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 21128 res = -1; 21129 goto request_invite_cleanup; 21130 } 21131 ast_queue_control(p->owner, AST_CONTROL_SRCUPDATE); 21132 } else { 21133 p->jointcapability = p->capability; 21134 ast_debug(1, "Hm.... No sdp for the moment\n"); 21135 } 21136 if (p->do_history) /* This is a response, note what it was for */ 21137 append_history(p, "ReInv", "Re-invite received"); 21138 } 21139 } else if (debug) 21140 ast_verbose("Ignoring this INVITE request\n"); 21141 21142 if (!p->lastinvite && !req->ignore && !p->owner) { 21143 /* This is a new invite */ 21144 /* Handle authentication if this is our first invite */ 21145 int cc_recall_core_id = -1; 21146 set_pvt_allowed_methods(p, req); 21147 res = check_user_full(p, req, SIP_INVITE, e, XMIT_RELIABLE, addr, &authpeer); 21148 if (res == AUTH_CHALLENGE_SENT) { 21149 p->invitestate = INV_COMPLETED; /* Needs to restart in another INVITE transaction */ 21150 res = 0; 21151 goto request_invite_cleanup; 21152 } 21153 if (res < 0) { /* Something failed in authentication */ 21154 if (res == AUTH_FAKE_AUTH) { 21155 ast_log(LOG_NOTICE, "Sending fake auth rejection for device %s\n", get_header(req, "From")); 21156 transmit_fake_auth_response(p, SIP_INVITE, req, XMIT_RELIABLE); 21157 } else { 21158 ast_log(LOG_NOTICE, "Failed to authenticate device %s\n", get_header(req, "From")); 21159 transmit_response_reliable(p, "403 Forbidden", req); 21160 } 21161 p->invitestate = INV_COMPLETED; 21162 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 21163 ast_string_field_set(p, theirtag, NULL); 21164 res = 0; 21165 goto request_invite_cleanup; 21166 } 21167 21168 /* Successful authentication and peer matching so record the peer related to this pvt (for easy access to peer settings) */ 21169 if (p->relatedpeer) { 21170 p->relatedpeer = unref_peer(p->relatedpeer,"unsetting the relatedpeer field in the dialog, before it is set to something else."); 21171 } 21172 if (authpeer) { 21173 p->relatedpeer = ref_peer(authpeer, "setting dialog's relatedpeer pointer"); 21174 } 21175 /* If T38 is needed but not present, then make it magically appear */ 21176 if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT) && !p->udptl) { 21177 if ((p->udptl = ast_udptl_new_with_bindaddr(sched, io, 0, &bindaddr))) { 21178 p->t38_maxdatagram = global_t38_maxdatagram; 21179 set_t38_capabilities(p); 21180 } else { 21181 /* udptl creation failed, T38 can not be supported on this dialog */ 21182 ast_debug(1, "UDPTL creation failed on dialog.\n"); 21183 ast_clear_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT); 21184 } 21185 } 21186 21187 /* We have a successful authentication, process the SDP portion if there is one */ 21188 if (find_sdp(req)) { 21189 if (process_sdp(p, req, SDP_T38_INITIATE)) { 21190 /* Unacceptable codecs */ 21191 transmit_response_reliable(p, "488 Not acceptable here", req); 21192 p->invitestate = INV_COMPLETED; 21193 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 21194 ast_debug(1, "No compatible codecs for this SIP call.\n"); 21195 res = -1; 21196 goto request_invite_cleanup; 21197 } 21198 } else { /* No SDP in invite, call control session */ 21199 p->jointcapability = p->capability; 21200 ast_debug(2, "No SDP in Invite, third party call control\n"); 21201 } 21202 21203 /* Queue NULL frame to prod ast_rtp_bridge if appropriate */ 21204 /* This seems redundant ... see !p-owner above */ 21205 if (p->owner) 21206 ast_queue_frame(p->owner, &ast_null_frame); 21207 21208 21209 /* Initialize the context if it hasn't been already */ 21210 if (ast_strlen_zero(p->context)) 21211 ast_string_field_set(p, context, sip_cfg.default_context); 21212 21213 21214 /* Check number of concurrent calls -vs- incoming limit HERE */ 21215 ast_debug(1, "Checking SIP call limits for device %s\n", p->username); 21216 if ((res = update_call_counter(p, INC_CALL_LIMIT))) { 21217 if (res < 0) { 21218 ast_log(LOG_NOTICE, "Failed to place call for device %s, too many calls\n", p->username); 21219 transmit_response_reliable(p, "480 Temporarily Unavailable (Call limit) ", req); 21220 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 21221 p->invitestate = INV_COMPLETED; 21222 } 21223 res = 0; 21224 goto request_invite_cleanup; 21225 } 21226 gotdest = get_destination(p, NULL, &cc_recall_core_id); /* Get destination right away */ 21227 extract_uri(p, req); /* Get the Contact URI */ 21228 build_contact(p); /* Build our contact header */ 21229 21230 if (p->rtp) { 21231 ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_DTMF, ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833); 21232 ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_DTMF_COMPENSATE, ast_test_flag(&p->flags[1], SIP_PAGE2_RFC2833_COMPENSATE)); 21233 } 21234 21235 if (!replace_id && (gotdest != SIP_GET_DEST_EXTEN_FOUND)) { /* No matching extension found */ 21236 switch(gotdest) { 21237 case SIP_GET_DEST_INVALID_URI: 21238 transmit_response_reliable(p, "416 Unsupported URI scheme", req); 21239 break; 21240 case SIP_GET_DEST_PICKUP_EXTEN_FOUND: 21241 if (ast_test_flag(&p->flags[1], SIP_PAGE2_ALLOWOVERLAP)) { 21242 transmit_response_reliable(p, "484 Address Incomplete", req); 21243 break; 21244 } 21245 /* INTENTIONAL FALL THROUGH */ 21246 case SIP_GET_DEST_EXTEN_NOT_FOUND: 21247 case SIP_GET_DEST_REFUSED: 21248 default: 21249 { 21250 char *decoded_exten = ast_strdupa(p->exten); 21251 transmit_response_reliable(p, "404 Not Found", req); 21252 ast_uri_decode(decoded_exten); 21253 ast_log(LOG_NOTICE, "Call from '%s' to extension" 21254 " '%s' rejected because extension not found in context '%s'.\n", 21255 S_OR(p->username, p->peername), decoded_exten, p->context); 21256 } 21257 } /* end switch */ 21258 21259 p->invitestate = INV_COMPLETED; 21260 update_call_counter(p, DEC_CALL_LIMIT); 21261 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 21262 res = 0; 21263 goto request_invite_cleanup; 21264 } else { 21265 21266 /* If no extension was specified, use the s one */ 21267 /* Basically for calling to IP/Host name only */ 21268 if (ast_strlen_zero(p->exten)) 21269 ast_string_field_set(p, exten, "s"); 21270 /* Initialize our tag */ 21271 21272 make_our_tag(p->tag, sizeof(p->tag)); 21273 /* First invitation - create the channel */ 21274 c = sip_new(p, AST_STATE_DOWN, S_OR(p->peername, NULL), NULL); 21275 if (cc_recall_core_id != -1) { 21276 ast_setup_cc_recall_datastore(c, cc_recall_core_id); 21277 ast_cc_agent_set_interfaces_chanvar(c); 21278 } 21279 *recount = 1; 21280 21281 /* Save Record-Route for any later requests we make on this dialogue */ 21282 build_route(p, req, 0); 21283 21284 if (c) { 21285 ast_party_redirecting_init(&redirecting); 21286 memset(&update_redirecting, 0, sizeof(update_redirecting)); 21287 /* Pre-lock the call */ 21288 ast_channel_lock(c); 21289 change_redirecting_information(p, req, &redirecting, &update_redirecting, 21290 FALSE); /*Will return immediately if no Diversion header is present */ 21291 ast_channel_set_redirecting(c, &redirecting, &update_redirecting); 21292 ast_party_redirecting_free(&redirecting); 21293 } 21294 } 21295 } else { 21296 ast_party_redirecting_init(&redirecting); 21297 memset(&update_redirecting, 0, sizeof(update_redirecting)); 21298 if (sipdebug) { 21299 if (!req->ignore) 21300 ast_debug(2, "Got a SIP re-invite for call %s\n", p->callid); 21301 else 21302 ast_debug(2, "Got a SIP re-transmit of INVITE for call %s\n", p->callid); 21303 } 21304 if (!req->ignore) 21305 reinvite = 1; 21306 c = p->owner; 21307 change_redirecting_information(p, req, &redirecting, &update_redirecting, FALSE); /*Will return immediately if no Diversion header is present */ 21308 if (c) { 21309 ast_channel_set_redirecting(c, &redirecting, &update_redirecting); 21310 } 21311 ast_party_redirecting_free(&redirecting); 21312 } 21313 21314 /* Session-Timers */ 21315 if ((p->sipoptions & SIP_OPT_TIMER) && !ast_strlen_zero(get_header(req, "Session-Expires"))) { 21316 /* The UAC has requested session-timers for this session. Negotiate 21317 the session refresh interval and who will be the refresher */ 21318 ast_debug(2, "Incoming INVITE with 'timer' option supported and \"Session-Expires\" header.\n"); 21319 21320 /* Allocate Session-Timers struct w/in the dialog */ 21321 if (!p->stimer) 21322 sip_st_alloc(p); 21323 21324 /* Parse the Session-Expires header */ 21325 p_uac_se_hdr = get_header(req, "Session-Expires"); 21326 rtn = parse_session_expires(p_uac_se_hdr, &uac_max_se, &st_ref); 21327 if (rtn != 0) { 21328 transmit_response_reliable(p, "400 Session-Expires Invalid Syntax", req); 21329 p->invitestate = INV_COMPLETED; 21330 if (!p->lastinvite) { 21331 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 21332 } 21333 res = -1; 21334 goto request_invite_cleanup; 21335 } 21336 21337 /* Parse the Min-SE header */ 21338 p_uac_min_se = get_header(req, "Min-SE"); 21339 if (!ast_strlen_zero(p_uac_min_se)) { 21340 rtn = parse_minse(p_uac_min_se, &uac_min_se); 21341 if (rtn != 0) { 21342 transmit_response_reliable(p, "400 Min-SE Invalid Syntax", req); 21343 p->invitestate = INV_COMPLETED; 21344 if (!p->lastinvite) { 21345 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 21346 } 21347 res = -1; 21348 goto request_invite_cleanup; 21349 } 21350 } 21351 21352 dlg_min_se = st_get_se(p, FALSE); 21353 switch (st_get_mode(p)) { 21354 case SESSION_TIMER_MODE_ACCEPT: 21355 case SESSION_TIMER_MODE_ORIGINATE: 21356 if (uac_max_se > 0 && uac_max_se < dlg_min_se) { 21357 transmit_response_with_minse(p, "422 Session Interval Too Small", req, dlg_min_se); 21358 p->invitestate = INV_COMPLETED; 21359 if (!p->lastinvite) { 21360 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 21361 } 21362 res = -1; 21363 goto request_invite_cleanup; 21364 } 21365 21366 p->stimer->st_active_peer_ua = TRUE; 21367 st_active = TRUE; 21368 if (st_ref == SESSION_TIMER_REFRESHER_AUTO) { 21369 st_ref = st_get_refresher(p); 21370 } 21371 21372 if (uac_max_se > 0) { 21373 int dlg_max_se = st_get_se(p, TRUE); 21374 if (dlg_max_se >= uac_min_se) { 21375 st_interval = (uac_max_se < dlg_max_se) ? uac_max_se : dlg_max_se; 21376 } else { 21377 st_interval = uac_max_se; 21378 } 21379 } else { 21380 /* Set to default max value */ 21381 st_interval = global_max_se; 21382 } 21383 break; 21384 21385 case SESSION_TIMER_MODE_REFUSE: 21386 if (p->reqsipoptions & SIP_OPT_TIMER) { 21387 transmit_response_with_unsupported(p, "420 Option Disabled", req, required); 21388 ast_log(LOG_WARNING, "Received SIP INVITE with supported but disabled option: %s\n", required); 21389 p->invitestate = INV_COMPLETED; 21390 if (!p->lastinvite) { 21391 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 21392 } 21393 res = -1; 21394 goto request_invite_cleanup; 21395 } 21396 break; 21397 21398 default: 21399 ast_log(LOG_ERROR, "Internal Error %d at %s:%d\n", st_get_mode(p), __FILE__, __LINE__); 21400 break; 21401 } 21402 } else { 21403 /* The UAC did not request session-timers. Asterisk (UAS), will now decide 21404 (based on session-timer-mode in sip.conf) whether to run session-timers for 21405 this session or not. */ 21406 switch (st_get_mode(p)) { 21407 case SESSION_TIMER_MODE_ORIGINATE: 21408 st_active = TRUE; 21409 st_interval = st_get_se(p, TRUE); 21410 st_ref = SESSION_TIMER_REFRESHER_UAS; 21411 p->stimer->st_active_peer_ua = FALSE; 21412 break; 21413 21414 default: 21415 break; 21416 } 21417 } 21418 21419 if (reinvite == 0) { 21420 /* Session-Timers: Start session refresh timer based on negotiation/config */ 21421 if (st_active == TRUE) { 21422 p->stimer->st_active = TRUE; 21423 p->stimer->st_interval = st_interval; 21424 p->stimer->st_ref = st_ref; 21425 start_session_timer(p); 21426 } 21427 } else { 21428 if (p->stimer->st_active == TRUE) { 21429 /* Session-Timers: A re-invite request sent within a dialog will serve as 21430 a refresh request, no matter whether the re-invite was sent for refreshing 21431 the session or modifying it.*/ 21432 ast_debug (2, "Restarting session-timers on a refresh - %s\n", p->callid); 21433 21434 /* The UAC may be adjusting the session-timers mid-session */ 21435 if (st_interval > 0) { 21436 p->stimer->st_interval = st_interval; 21437 p->stimer->st_ref = st_ref; 21438 } 21439 21440 restart_session_timer(p); 21441 if (p->stimer->st_expirys > 0) { 21442 p->stimer->st_expirys--; 21443 } 21444 } 21445 } 21446 21447 if (!req->ignore && p) 21448 p->lastinvite = seqno; 21449 21450 if (replace_id) { /* Attended transfer or call pickup - we're the target */ 21451 if (!ast_strlen_zero(pickup.exten)) { 21452 append_history(p, "Xfer", "INVITE/Replace received"); 21453 21454 /* Let the caller know we're giving it a shot */ 21455 transmit_response(p, "100 Trying", req); 21456 p->invitestate = INV_PROCEEDING; 21457 ast_setstate(c, AST_STATE_RING); 21458 21459 /* Do the pickup itself */ 21460 ast_channel_unlock(c); 21461 *nounlock = 1; 21462 21463 /* since p->owner (c) is unlocked, we need to go ahead and unlock pvt for both 21464 * magic pickup and ast_hangup. Both of these functions will attempt to lock 21465 * p->owner again, which can cause a deadlock if we already hold a lock on p. 21466 * Locking order is, channel then pvt. Dead lock avoidance must be used if 21467 * called the other way around. */ 21468 sip_pvt_unlock(p); 21469 do_magic_pickup(c, pickup.exten, pickup.context); 21470 /* Now we're either masqueraded or we failed to pickup, in either case we... */ 21471 ast_hangup(c); 21472 sip_pvt_lock(p); /* pvt is expected to remain locked on return, so re-lock it */ 21473 21474 res = 0; 21475 goto request_invite_cleanup; 21476 } else { 21477 /* Go and take over the target call */ 21478 if (sipdebug) 21479 ast_debug(4, "Sending this call to the invite/replcaes handler %s\n", p->callid); 21480 res = handle_invite_replaces(p, req, debug, seqno, addr, nounlock); 21481 refer_locked = 0; 21482 goto request_invite_cleanup; 21483 } 21484 } 21485 21486 21487 if (c) { /* We have a call -either a new call or an old one (RE-INVITE) */ 21488 enum ast_channel_state c_state = c->_state; 21489 21490 if (c_state != AST_STATE_UP && reinvite && 21491 (p->invitestate == INV_TERMINATED || p->invitestate == INV_CONFIRMED)) { 21492 /* If these conditions are true, and the channel is still in the 'ringing' 21493 * state, then this likely means that we have a situation where the initial 21494 * INVITE transaction has completed *but* the channel's state has not yet been 21495 * changed to UP. The reason this could happen is if the reinvite is received 21496 * on the SIP socket prior to an application calling ast_read on this channel 21497 * to read the answer frame we earlier queued on it. In this case, the reinvite 21498 * is completely legitimate so we need to handle this the same as if the channel 21499 * were already UP. Thus we are purposely falling through to the AST_STATE_UP case. 21500 */ 21501 c_state = AST_STATE_UP; 21502 } 21503 21504 switch(c_state) { 21505 case AST_STATE_DOWN: 21506 ast_debug(2, "%s: New call is still down.... Trying... \n", c->name); 21507 transmit_provisional_response(p, "100 Trying", req, 0); 21508 p->invitestate = INV_PROCEEDING; 21509 ast_setstate(c, AST_STATE_RING); 21510 if (strcmp(p->exten, ast_pickup_ext())) { /* Call to extension -start pbx on this call */ 21511 enum ast_pbx_result result; 21512 21513 result = ast_pbx_start(c); 21514 21515 switch(result) { 21516 case AST_PBX_FAILED: 21517 ast_log(LOG_WARNING, "Failed to start PBX :(\n"); 21518 p->invitestate = INV_COMPLETED; 21519 transmit_response_reliable(p, "503 Unavailable", req); 21520 break; 21521 case AST_PBX_CALL_LIMIT: 21522 ast_log(LOG_WARNING, "Failed to start PBX (call limit reached) \n"); 21523 p->invitestate = INV_COMPLETED; 21524 transmit_response_reliable(p, "480 Temporarily Unavailable", req); 21525 break; 21526 case AST_PBX_SUCCESS: 21527 /* nothing to do */ 21528 break; 21529 } 21530 21531 if (result) { 21532 21533 /* Unlock locks so ast_hangup can do its magic */ 21534 ast_channel_unlock(c); 21535 sip_pvt_unlock(p); 21536 ast_hangup(c); 21537 sip_pvt_lock(p); 21538 c = NULL; 21539 } 21540 } else { /* Pickup call in call group */ 21541 ast_channel_unlock(c); 21542 *nounlock = 1; 21543 if (ast_pickup_call(c)) { 21544 ast_log(LOG_NOTICE, "Nothing to pick up for %s\n", p->callid); 21545 transmit_response_reliable(p, "503 Unavailable", req); 21546 sip_alreadygone(p); 21547 /* Unlock locks so ast_hangup can do its magic */ 21548 sip_pvt_unlock(p); 21549 c->hangupcause = AST_CAUSE_CALL_REJECTED; 21550 } else { 21551 sip_pvt_unlock(p); 21552 c->hangupcause = AST_CAUSE_NORMAL_CLEARING; 21553 } 21554 p->invitestate = INV_COMPLETED; 21555 ast_hangup(c); 21556 sip_pvt_lock(p); 21557 c = NULL; 21558 } 21559 break; 21560 case AST_STATE_RING: 21561 transmit_provisional_response(p, "100 Trying", req, 0); 21562 p->invitestate = INV_PROCEEDING; 21563 break; 21564 case AST_STATE_RINGING: 21565 transmit_provisional_response(p, "180 Ringing", req, 0); 21566 p->invitestate = INV_PROCEEDING; 21567 break; 21568 case AST_STATE_UP: 21569 ast_debug(2, "%s: This call is UP.... \n", c->name); 21570 21571 transmit_response(p, "100 Trying", req); 21572 21573 if (p->t38.state == T38_PEER_REINVITE) { 21574 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.")); 21575 } else if (p->t38.state == T38_ENABLED) { 21576 ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED); 21577 transmit_response_with_t38_sdp(p, "200 OK", req, (reinvite ? XMIT_RELIABLE : (req->ignore ? XMIT_UNRELIABLE : XMIT_CRITICAL))); 21578 } else if (p->t38.state == T38_DISABLED) { 21579 /* If this is not a re-invite or something to ignore - it's critical */ 21580 if (p->srtp && !ast_test_flag(p->srtp, SRTP_CRYPTO_OFFER_OK)) { 21581 ast_log(LOG_WARNING, "Target does not support required crypto\n"); 21582 transmit_response_reliable(p, "488 Not Acceptable Here (crypto)", req); 21583 } else { 21584 ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED); 21585 transmit_response_with_sdp(p, "200 OK", req, (reinvite ? XMIT_RELIABLE : (req->ignore ? XMIT_UNRELIABLE : XMIT_CRITICAL)), p->session_modify == TRUE ? FALSE : TRUE, FALSE); 21586 } 21587 } 21588 21589 p->invitestate = INV_TERMINATED; 21590 break; 21591 default: 21592 ast_log(LOG_WARNING, "Don't know how to handle INVITE in state %d\n", c->_state); 21593 transmit_response(p, "100 Trying", req); 21594 break; 21595 } 21596 } else { 21597 if (p && (p->autokillid == -1)) { 21598 const char *msg; 21599 21600 if (!p->jointcapability) 21601 msg = "488 Not Acceptable Here (codec error)"; 21602 else { 21603 ast_log(LOG_NOTICE, "Unable to create/find SIP channel for this INVITE\n"); 21604 msg = "503 Unavailable"; 21605 } 21606 transmit_response_reliable(p, msg, req); 21607 p->invitestate = INV_COMPLETED; 21608 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 21609 } 21610 } 21611 21612 request_invite_cleanup: 21613 21614 if (refer_locked && p->refer && p->refer->refer_call) { 21615 sip_pvt_unlock(p->refer->refer_call); 21616 if (p->refer->refer_call->owner) { 21617 ast_channel_unlock(p->refer->refer_call->owner); 21618 } 21619 } 21620 if (authpeer) { 21621 authpeer = unref_peer(authpeer, "unref_peer, from handle_request_invite authpeer"); 21622 } 21623 21624 return res; 21625 }
| static int handle_request_message | ( | struct sip_pvt * | p, | |
| struct sip_request * | req | |||
| ) | [static] |
Handle incoming MESSAGE request.
Definition at line 22382 of file chan_sip.c.
References ast_verbose, receive_message(), and transmit_response().
Referenced by handle_incoming().
22383 { 22384 if (!req->ignore) { 22385 if (req->debug) 22386 ast_verbose("Receiving message!\n"); 22387 receive_message(p, req); 22388 } else 22389 transmit_response(p, "202 Accepted", req); 22390 return 1; 22391 }
| static int handle_request_notify | ( | struct sip_pvt * | p, | |
| struct sip_request * | req, | |||
| struct ast_sockaddr * | addr, | |||
| int | seqno, | |||
| const char * | e | |||
| ) | [static] |
Handle incoming notifications.
Definition at line 20329 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, find_peer(), get_body(), get_header(), get_msg_text(), handle_cc_notify(), LOG_NOTICE, LOG_WARNING, mailbox, sip_scheddestroy(), strsep(), transmit_response(), TRUE, and unref_peer().
Referenced by handle_incoming().
20330 { 20331 /* This is mostly a skeleton for future improvements */ 20332 /* Mostly created to return proper answers on notifications on outbound REFER's */ 20333 int res = 0; 20334 const char *event = get_header(req, "Event"); 20335 char *eventid = NULL; 20336 char *sep; 20337 20338 if( (sep = strchr(event, ';')) ) { /* XXX bug here - overwriting string ? */ 20339 *sep++ = '\0'; 20340 eventid = sep; 20341 } 20342 20343 if (sipdebug) 20344 ast_debug(2, "Got NOTIFY Event: %s\n", event); 20345 20346 if (!strcmp(event, "refer")) { 20347 /* Save nesting depth for now, since there might be other events we will 20348 support in the future */ 20349 20350 /* Handle REFER notifications */ 20351 20352 char buf[1024]; 20353 char *cmd, *code; 20354 int respcode; 20355 int success = TRUE; 20356 20357 /* EventID for each transfer... EventID is basically the REFER cseq 20358 20359 We are getting notifications on a call that we transfered 20360 We should hangup when we are getting a 200 OK in a sipfrag 20361 Check if we have an owner of this event */ 20362 20363 /* Check the content type */ 20364 if (strncasecmp(get_header(req, "Content-Type"), "message/sipfrag", strlen("message/sipfrag"))) { 20365 /* We need a sipfrag */ 20366 transmit_response(p, "400 Bad request", req); 20367 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 20368 return -1; 20369 } 20370 20371 /* Get the text of the attachment */ 20372 if (get_msg_text(buf, sizeof(buf), req, TRUE)) { 20373 ast_log(LOG_WARNING, "Unable to retrieve attachment from NOTIFY %s\n", p->callid); 20374 transmit_response(p, "400 Bad request", req); 20375 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 20376 return -1; 20377 } 20378 20379 /* 20380 From the RFC... 20381 A minimal, but complete, implementation can respond with a single 20382 NOTIFY containing either the body: 20383 SIP/2.0 100 Trying 20384 20385 if the subscription is pending, the body: 20386 SIP/2.0 200 OK 20387 if the reference was successful, the body: 20388 SIP/2.0 503 Service Unavailable 20389 if the reference failed, or the body: 20390 SIP/2.0 603 Declined 20391 20392 if the REFER request was accepted before approval to follow the 20393 reference could be obtained and that approval was subsequently denied 20394 (see Section 2.4.7). 20395 20396 If there are several REFERs in the same dialog, we need to 20397 match the ID of the event header... 20398 */ 20399 ast_debug(3, "* SIP Transfer NOTIFY Attachment: \n---%s\n---\n", buf); 20400 cmd = ast_skip_blanks(buf); 20401 code = cmd; 20402 /* We are at SIP/2.0 */ 20403 while(*code && (*code > 32)) { /* Search white space */ 20404 code++; 20405 } 20406 *code++ = '\0'; 20407 code = ast_skip_blanks(code); 20408 sep = code; 20409 sep++; 20410 while(*sep && (*sep > 32)) { /* Search white space */ 20411 sep++; 20412 } 20413 *sep++ = '\0'; /* Response string */ 20414 respcode = atoi(code); 20415 switch (respcode) { 20416 case 200: /* OK: The new call is up, hangup this call */ 20417 /* Hangup the call that we are replacing */ 20418 break; 20419 case 301: /* Moved permenantly */ 20420 case 302: /* Moved temporarily */ 20421 /* Do we get the header in the packet in this case? */ 20422 success = FALSE; 20423 break; 20424 case 503: /* Service Unavailable: The new call failed */ 20425 case 603: /* Declined: Not accepted */ 20426 /* Cancel transfer, continue the current call */ 20427 success = FALSE; 20428 break; 20429 case 0: /* Parse error */ 20430 /* Cancel transfer, continue the current call */ 20431 ast_log(LOG_NOTICE, "Error parsing sipfrag in NOTIFY in response to REFER.\n"); 20432 success = FALSE; 20433 break; 20434 default: 20435 if (respcode < 200) { 20436 /* ignore provisional responses */ 20437 success = -1; 20438 } else { 20439 ast_log(LOG_NOTICE, "Got unknown code '%d' in NOTIFY in response to REFER.\n", respcode); 20440 success = FALSE; 20441 } 20442 break; 20443 } 20444 if (success == FALSE) { 20445 ast_log(LOG_NOTICE, "Transfer failed. Sorry. Nothing further to do with this call\n"); 20446 } 20447 20448 if (p->owner && success != -1) { 20449 enum ast_control_transfer message = success ? AST_TRANSFER_SUCCESS : AST_TRANSFER_FAILED; 20450 ast_queue_control_data(p->owner, AST_CONTROL_TRANSFER, &message, sizeof(message)); 20451 } 20452 /* Confirm that we received this packet */ 20453 transmit_response(p, "200 OK", req); 20454 } else if (!strcmp(event, "message-summary")) { 20455 const char *mailbox = NULL; 20456 char *c = ast_strdupa(get_body(req, "Voice-Message", ':')); 20457 20458 if (!p->mwi) { 20459 struct sip_peer *peer = find_peer(NULL, &p->recv, TRUE, FINDPEERS, FALSE, p->socket.type); 20460 20461 if (peer) { 20462 mailbox = ast_strdupa(peer->unsolicited_mailbox); 20463 unref_peer(peer, "removing unsolicited mwi ref"); 20464 } 20465 } else { 20466 mailbox = p->mwi->mailbox; 20467 } 20468 20469 if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(c)) { 20470 char *old = strsep(&c, " "); 20471 char *new = strsep(&old, "/"); 20472 struct ast_event *event; 20473 20474 if ((event = ast_event_new(AST_EVENT_MWI, 20475 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox, 20476 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, "SIP_Remote", 20477 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, atoi(new), 20478 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, atoi(old), 20479 AST_EVENT_IE_END))) { 20480 ast_event_queue_and_cache(event); 20481 } 20482 transmit_response(p, "200 OK", req); 20483 } else { 20484 transmit_response(p, "489 Bad event", req); 20485 res = -1; 20486 } 20487 } else if (!strcmp(event, "keep-alive")) { 20488 /* Used by Sipura/Linksys for NAT pinhole, 20489 * just confirm that we recieved the packet. */ 20490 transmit_response(p, "200 OK", req); 20491 } else if (!strcmp(event, "call-completion")) { 20492 res = handle_cc_notify(p, req); 20493 } else { 20494 /* We don't understand this event. */ 20495 transmit_response(p, "489 Bad event", req); 20496 res = -1; 20497 } 20498 20499 if (!p->lastinvite) 20500 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 20501 20502 return res; 20503 }
| 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 20508 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(), get_header(), LOG_NOTICE, set_pvt_allowed_methods(), sip_cfg, sip_scheddestroy(), transmit_fake_auth_response(), transmit_response(), and transmit_response_with_allow().
Referenced by handle_incoming().
20509 { 20510 int res; 20511 20512 if (p->lastinvite) { 20513 /* if this is a request in an active dialog, just confirm that the dialog exists. */ 20514 transmit_response_with_allow(p, "200 OK", req, 0); 20515 return 0; 20516 } 20517 20518 if (sip_cfg.auth_options_requests) { 20519 /* Do authentication if this OPTIONS request began the dialog */ 20520 copy_request(&p->initreq, req); 20521 set_pvt_allowed_methods(p, req); 20522 res = check_user(p, req, SIP_OPTIONS, e, XMIT_UNRELIABLE, addr); 20523 if (res == AUTH_CHALLENGE_SENT) { 20524 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 20525 return 0; 20526 } 20527 if (res < 0) { /* Something failed in authentication */ 20528 if (res == AUTH_FAKE_AUTH) { 20529 ast_log(LOG_NOTICE, "Sending fake auth rejection for device %s\n", get_header(req, "From")); 20530 transmit_fake_auth_response(p, SIP_OPTIONS, req, XMIT_UNRELIABLE); 20531 } else { 20532 ast_log(LOG_NOTICE, "Failed to authenticate device %s\n", get_header(req, "From")); 20533 transmit_response(p, "403 Forbidden", req); 20534 } 20535 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 20536 return 0; 20537 } 20538 } 20539 20540 /* must go through authentication before getting here */ 20541 res = (get_destination(p, req, NULL) == SIP_GET_DEST_EXTEN_FOUND ? 0 : -1); 20542 build_contact(p); 20543 20544 if (ast_strlen_zero(p->context)) 20545 ast_string_field_set(p, context, sip_cfg.default_context); 20546 20547 if (ast_shutting_down()) 20548 transmit_response_with_allow(p, "503 Unavailable", req, 0); 20549 else if (res < 0) 20550 transmit_response_with_allow(p, "404 Not Found", req, 0); 20551 else 20552 transmit_response_with_allow(p, "200 OK", req, 0); 20553 20554 /* Destroy if this OPTIONS was the opening request, but not if 20555 it's in the middle of a normal call flow. */ 20556 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 20557 20558 return res; 20559 }
| static int handle_request_publish | ( | struct sip_pvt * | p, | |
| struct sip_request * | req, | |||
| struct ast_sockaddr * | addr, | |||
| const int | seqno, | |||
| const char * | uri | |||
| ) | [static] |
Definition at line 22813 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(), get_header(), handle_sip_publish_initial(), handle_sip_publish_modify(), handle_sip_publish_refresh(), handle_sip_publish_remove(), LOG_NOTICE, sip_scheddestroy(), transmit_fake_auth_response(), transmit_response(), and transmit_response_reliable().
Referenced by handle_incoming().
22814 { 22815 const char *etag = get_header(req, "SIP-If-Match"); 22816 const char *event = get_header(req, "Event"); 22817 struct event_state_compositor *esc; 22818 enum sip_publish_type publish_type; 22819 const char *expires_str = get_header(req, "Expires"); 22820 int expires_int; 22821 int auth_result; 22822 int handler_result = -1; 22823 22824 if (ast_strlen_zero(event)) { 22825 transmit_response(p, "489 Bad Event", req); 22826 return -1; 22827 } 22828 22829 if (!(esc = get_esc(event))) { 22830 transmit_response(p, "489 Bad Event", req); 22831 return -1; 22832 } 22833 22834 auth_result = check_user(p, req, SIP_PUBLISH, uri, XMIT_RELIABLE, addr); 22835 if (auth_result == AUTH_CHALLENGE_SENT) { 22836 p->lastinvite = seqno; 22837 return 0; 22838 } else if (auth_result < 0) { 22839 if (auth_result == AUTH_FAKE_AUTH) { 22840 ast_log(LOG_NOTICE, "Sending fake auth rejection for device %s\n", get_header(req, "From")); 22841 transmit_fake_auth_response(p, SIP_INVITE, req, XMIT_RELIABLE); 22842 } else { 22843 ast_log(LOG_NOTICE, "Failed to authenticate device %s\n", get_header(req, "From")); 22844 transmit_response_reliable(p, "403 Forbidden", req); 22845 } 22846 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 22847 ast_string_field_set(p, theirtag, NULL); 22848 return 0; 22849 } else if (auth_result == AUTH_SUCCESSFUL && p->lastinvite) { 22850 /* We need to stop retransmitting the 401 */ 22851 __sip_ack(p, p->lastinvite, 1, 0); 22852 } 22853 22854 publish_type = determine_sip_publish_type(req, event, etag, expires_str, &expires_int); 22855 22856 /* It is the responsibility of these handlers to formulate any response 22857 * sent for a PUBLISH 22858 */ 22859 switch (publish_type) { 22860 case SIP_PUBLISH_UNKNOWN: 22861 transmit_response(p, "400 Bad Request", req); 22862 break; 22863 case SIP_PUBLISH_INITIAL: 22864 handler_result = handle_sip_publish_initial(p, req, esc, expires_int); 22865 break; 22866 case SIP_PUBLISH_REFRESH: 22867 handler_result = handle_sip_publish_refresh(p, req, esc, etag, expires_int); 22868 break; 22869 case SIP_PUBLISH_MODIFY: 22870 handler_result = handle_sip_publish_modify(p, req, esc, etag, expires_int); 22871 break; 22872 case SIP_PUBLISH_REMOVE: 22873 handler_result = handle_sip_publish_remove(p, req, esc, etag); 22874 break; 22875 default: 22876 transmit_response(p, "400 Impossible Condition", req); 22877 break; 22878 } 22879 22880 return handler_result; 22881 }
| static int handle_request_refer | ( | struct sip_pvt * | p, | |
| struct sip_request * | req, | |||
| int | debug, | |||
| int | seqno, | |||
| int * | nounlock | |||
| ) | [static] |
Definition at line 21881 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_ref, ast_channel_trylock, ast_channel_unlock, ast_channel_unref, ast_clear_flag, AST_CONTROL_UNHOLD, ast_debug, AST_LIST_EMPTY, ast_manager_event_multichan, ast_parking_ext(), ast_queue_control(), ast_set_flag, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_verbose, check_sip_domain(), context, copy_request(), EVENT_FLAG_CALL, FALSE, get_refer_info(), local_attended_transfer(), ast_channel::name, 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().
21882 { 21883 struct sip_dual current; /* Chan1: Call between asterisk and transferer */ 21884 /* Chan2: Call between asterisk and transferee */ 21885 21886 int res = 0; 21887 struct ast_channel *chans[2]; 21888 current.req.data = NULL; 21889 21890 if (req->debug) 21891 ast_verbose("Call %s got a SIP call transfer from %s: (REFER)!\n", p->callid, ast_test_flag(&p->flags[0], SIP_OUTGOING) ? "callee" : "caller"); 21892 21893 if (!p->owner) { 21894 /* This is a REFER outside of an existing SIP dialog */ 21895 /* We can't handle that, so decline it */ 21896 ast_debug(3, "Call %s: Declined REFER, outside of dialog...\n", p->callid); 21897 transmit_response(p, "603 Declined (No dialog)", req); 21898 if (!req->ignore) { 21899 append_history(p, "Xfer", "Refer failed. Outside of dialog."); 21900 sip_alreadygone(p); 21901 pvt_set_needdestroy(p, "outside of dialog"); 21902 } 21903 return 0; 21904 } 21905 21906 21907 /* Check if transfer is allowed from this device */ 21908 if (p->allowtransfer == TRANSFER_CLOSED ) { 21909 /* Transfer not allowed, decline */ 21910 transmit_response(p, "603 Declined (policy)", req); 21911 append_history(p, "Xfer", "Refer failed. Allowtransfer == closed."); 21912 /* Do not destroy SIP session */ 21913 return 0; 21914 } 21915 21916 if (!req->ignore && ast_test_flag(&p->flags[0], SIP_GOTREFER)) { 21917 /* Already have a pending REFER */ 21918 transmit_response(p, "491 Request pending", req); 21919 append_history(p, "Xfer", "Refer failed. Request pending."); 21920 return 0; 21921 } 21922 21923 /* Allocate memory for call transfer data */ 21924 if (!p->refer && !sip_refer_allocate(p)) { 21925 transmit_response(p, "500 Internal Server Error", req); 21926 append_history(p, "Xfer", "Refer failed. Memory allocation error."); 21927 return -3; 21928 } 21929 21930 res = get_refer_info(p, req); /* Extract headers */ 21931 21932 p->refer->status = REFER_SENT; 21933 21934 if (res != 0) { 21935 switch (res) { 21936 case -2: /* Syntax error */ 21937 transmit_response(p, "400 Bad Request (Refer-to missing)", req); 21938 append_history(p, "Xfer", "Refer failed. Refer-to missing."); 21939 if (req->debug) 21940 ast_debug(1, "SIP transfer to black hole can't be handled (no refer-to: )\n"); 21941 break; 21942 case -3: 21943 transmit_response(p, "603 Declined (Non sip: uri)", req); 21944 append_history(p, "Xfer", "Refer failed. Non SIP uri"); 21945 if (req->debug) 21946 ast_debug(1, "SIP transfer to non-SIP uri denied\n"); 21947 break; 21948 default: 21949 /* Refer-to extension not found, fake a failed transfer */ 21950 transmit_response(p, "202 Accepted", req); 21951 append_history(p, "Xfer", "Refer failed. Bad extension."); 21952 transmit_notify_with_sipfrag(p, seqno, "404 Not found", TRUE); 21953 ast_clear_flag(&p->flags[0], SIP_GOTREFER); 21954 if (req->debug) 21955 ast_debug(1, "SIP transfer to bad extension: %s\n", p->refer->refer_to); 21956 break; 21957 } 21958 return 0; 21959 } 21960 if (ast_strlen_zero(p->context)) 21961 ast_string_field_set(p, context, sip_cfg.default_context); 21962 21963 /* If we do not support SIP domains, all transfers are local */ 21964 if (sip_cfg.allow_external_domains && check_sip_domain(p->refer->refer_to_domain, NULL, 0)) { 21965 p->refer->localtransfer = 1; 21966 if (sipdebug) 21967 ast_debug(3, "This SIP transfer is local : %s\n", p->refer->refer_to_domain); 21968 } else if (AST_LIST_EMPTY(&domain_list) || check_sip_domain(p->refer->refer_to_domain, NULL, 0)) { 21969 /* This PBX doesn't bother with SIP domains or domain is local, so this transfer is local */ 21970 p->refer->localtransfer = 1; 21971 } else if (sipdebug) 21972 ast_debug(3, "This SIP transfer is to a remote SIP extension (remote domain %s)\n", p->refer->refer_to_domain); 21973 21974 /* Is this a repeat of a current request? Ignore it */ 21975 /* Don't know what else to do right now. */ 21976 if (req->ignore) 21977 return res; 21978 21979 /* If this is a blind transfer, we have the following 21980 channels to work with: 21981 - chan1, chan2: The current call between transferer and transferee (2 channels) 21982 - target_channel: A new call from the transferee to the target (1 channel) 21983 We need to stay tuned to what happens in order to be able 21984 to bring back the call to the transferer */ 21985 21986 /* If this is a attended transfer, we should have all call legs within reach: 21987 - chan1, chan2: The call between the transferer and transferee (2 channels) 21988 - target_channel, targetcall_pvt: The call between the transferer and the target (2 channels) 21989 We want to bridge chan2 with targetcall_pvt! 21990 21991 The replaces call id in the refer message points 21992 to the call leg between Asterisk and the transferer. 21993 So we need to connect the target and the transferee channel 21994 and hangup the two other channels silently 21995 21996 If the target is non-local, the call ID could be on a remote 21997 machine and we need to send an INVITE with replaces to the 21998 target. We basically handle this as a blind transfer 21999 and let the sip_call function catch that we need replaces 22000 header in the INVITE. 22001 */ 22002 22003 22004 /* Get the transferer's channel */ 22005 chans[0] = current.chan1 = p->owner; 22006 22007 /* Find the other part of the bridge (2) - transferee */ 22008 chans[1] = current.chan2 = ast_bridged_channel(current.chan1); 22009 22010 if (sipdebug) 22011 ast_debug(3, "SIP %s transfer: Transferer channel %s, transferee channel %s\n", p->refer->attendedtransfer ? "attended" : "blind", current.chan1->name, current.chan2 ? current.chan2->name : "<none>"); 22012 22013 if (!current.chan2 && !p->refer->attendedtransfer) { 22014 /* No bridged channel, propably IVR or echo or similar... */ 22015 /* Guess we should masquerade or something here */ 22016 /* Until we figure it out, refuse transfer of such calls */ 22017 if (sipdebug) 22018 ast_debug(3, "Refused SIP transfer on non-bridged channel.\n"); 22019 p->refer->status = REFER_FAILED; 22020 append_history(p, "Xfer", "Refer failed. Non-bridged channel."); 22021 transmit_response(p, "603 Declined", req); 22022 return -1; 22023 } 22024 22025 if (current.chan2) { 22026 if (sipdebug) 22027 ast_debug(4, "Got SIP transfer, applying to bridged peer '%s'\n", current.chan2->name); 22028 22029 ast_queue_control(current.chan1, AST_CONTROL_UNHOLD); 22030 } 22031 22032 ast_set_flag(&p->flags[0], SIP_GOTREFER); 22033 22034 /* Attended transfer: Find all call legs and bridge transferee with target*/ 22035 if (p->refer->attendedtransfer) { 22036 if ((res = local_attended_transfer(p, ¤t, req, seqno, nounlock))) 22037 return res; /* We're done with the transfer */ 22038 /* Fall through for remote transfers that we did not find locally */ 22039 if (sipdebug) 22040 ast_debug(4, "SIP attended transfer: Still not our call - generating INVITE with replaces\n"); 22041 /* Fallthrough if we can't find the call leg internally */ 22042 } 22043 22044 22045 /* Parking a call */ 22046 if (p->refer->localtransfer && !strcmp(p->refer->refer_to, ast_parking_ext())) { 22047 /* Must release c's lock now, because it will not longer be accessible after the transfer! */ 22048 *nounlock = 1; 22049 ast_channel_unlock(current.chan1); 22050 copy_request(¤t.req, req); 22051 ast_clear_flag(&p->flags[0], SIP_GOTREFER); 22052 p->refer->status = REFER_200OK; 22053 append_history(p, "Xfer", "REFER to call parking."); 22054 ast_manager_event_multichan(EVENT_FLAG_CALL, "Transfer", 2, chans, "TransferMethod: SIP\r\nTransferType: Blind\r\nChannel: %s\r\nUniqueid: %s\r\nSIP-Callid: %s\r\nTargetChannel: %s\r\nTargetUniqueid: %s\r\nTransferExten: %s\r\nTransfer2Parking: Yes\r\n", 22055 current.chan1->name, 22056 current.chan1->uniqueid, 22057 p->callid, 22058 current.chan2->name, 22059 current.chan2->uniqueid, 22060 p->refer->refer_to); 22061 if (sipdebug) 22062 ast_debug(4, "SIP transfer to parking: trying to park %s. Parked by %s\n", current.chan2->name, current.chan1->name); 22063 sip_park(current.chan2, current.chan1, req, seqno); 22064 return res; 22065 } 22066 22067 /* Blind transfers and remote attended xfers */ 22068 transmit_response(p, "202 Accepted", req); 22069 22070 if (current.chan1 && current.chan2) { 22071 ast_debug(3, "chan1->name: %s\n", current.chan1->name); 22072 pbx_builtin_setvar_helper(current.chan1, "BLINDTRANSFER", current.chan2->name); 22073 } 22074 if (current.chan2) { 22075 pbx_builtin_setvar_helper(current.chan2, "BLINDTRANSFER", current.chan1->name); 22076 pbx_builtin_setvar_helper(current.chan2, "SIPDOMAIN", p->refer->refer_to_domain); 22077 pbx_builtin_setvar_helper(current.chan2, "SIPTRANSFER", "yes"); 22078 /* One for the new channel */ 22079 pbx_builtin_setvar_helper(current.chan2, "_SIPTRANSFER", "yes"); 22080 /* Attended transfer to remote host, prepare headers for the INVITE */ 22081 if (p->refer->referred_by) 22082 pbx_builtin_setvar_helper(current.chan2, "_SIPTRANSFER_REFERER", p->refer->referred_by); 22083 } 22084 /* Generate a Replaces string to be used in the INVITE during attended transfer */ 22085 if (!ast_strlen_zero(p->refer->replaces_callid)) { 22086 char tempheader[SIPBUFSIZE]; 22087 snprintf(tempheader, sizeof(tempheader), "%s%s%s%s%s", p->refer->replaces_callid, 22088 p->refer->replaces_callid_totag ? ";to-tag=" : "", 22089 p->refer->replaces_callid_totag, 22090 p->refer->replaces_callid_fromtag ? ";from-tag=" : "", 22091 p->refer->replaces_callid_fromtag); 22092 if (current.chan2) 22093 pbx_builtin_setvar_helper(current.chan2, "_SIPTRANSFER_REPLACES", tempheader); 22094 } 22095 /* Must release lock now, because it will not longer 22096 be accessible after the transfer! */ 22097 *nounlock = 1; 22098 /* 22099 * Increase ref count so that we can delay channel destruction until after 22100 * we get a chance to fire off some events. 22101 */ 22102 ast_channel_ref(current.chan1); 22103 ast_channel_unlock(current.chan1); 22104 22105 /* Connect the call */ 22106 22107 /* FAKE ringing if not attended transfer */ 22108 if (!p->refer->attendedtransfer) 22109 transmit_notify_with_sipfrag(p, seqno, "183 Ringing", FALSE); 22110 22111 /* For blind transfer, this will lead to a new call */ 22112 /* For attended transfer to remote host, this will lead to 22113 a new SIP call with a replaces header, if the dial plan allows it 22114 */ 22115 if (!current.chan2) { 22116 /* We have no bridge, so we're talking with Asterisk somehow */ 22117 /* We need to masquerade this call */ 22118 /* What to do to fix this situation: 22119 * Set up the new call in a new channel 22120 * Let the new channel masq into this channel 22121 Please add that code here :-) 22122 */ 22123 p->refer->status = REFER_FAILED; 22124 transmit_notify_with_sipfrag(p, seqno, "503 Service Unavailable (can't handle one-legged xfers)", TRUE); 22125 ast_clear_flag(&p->flags[0], SIP_GOTREFER); 22126 append_history(p, "Xfer", "Refer failed (only bridged calls)."); 22127 ast_channel_unref(current.chan1); 22128 return -1; 22129 } 22130 ast_set_flag(&p->flags[0], SIP_DEFER_BYE_ON_TRANSFER); /* Delay hangup */ 22131 22132 22133 /* For blind transfers, move the call to the new extensions. For attended transfers on multiple 22134 servers - generate an INVITE with Replaces. Either way, let the dial plan decided */ 22135 res = ast_async_goto(current.chan2, p->refer->refer_to_context, p->refer->refer_to, 1); 22136 22137 if (!res) { 22138 ast_manager_event_multichan(EVENT_FLAG_CALL, "Transfer", 2, chans, "TransferMethod: SIP\r\nTransferType: Blind\r\nChannel: %s\r\nUniqueid: %s\r\nSIP-Callid: %s\r\nTargetChannel: %s\r\nTargetUniqueid: %s\r\nTransferExten: %s\r\nTransferContext: %s\r\n", 22139 current.chan1->name, 22140 current.chan1->uniqueid, 22141 p->callid, 22142 current.chan2->name, 22143 current.chan2->uniqueid, 22144 p->refer->refer_to, p->refer->refer_to_context); 22145 /* Success - we have a new channel */ 22146 ast_debug(3, "%s transfer succeeded. Telling transferer.\n", p->refer->attendedtransfer? "Attended" : "Blind"); 22147 22148 while (ast_channel_trylock(current.chan1)) { 22149 sip_pvt_unlock(p); 22150 sched_yield(); 22151 sip_pvt_lock(p); 22152 } 22153 22154 /* XXX - what to we put in CEL 'extra' for attended transfers to external systems? NULL for now */ 22155 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); 22156 ast_channel_unlock(current.chan1); 22157 22158 transmit_notify_with_sipfrag(p, seqno, "200 Ok", TRUE); 22159 if (p->refer->localtransfer) 22160 p->refer->status = REFER_200OK; 22161 if (p->owner) 22162 p->owner->hangupcause = AST_CAUSE_NORMAL_CLEARING; 22163 append_history(p, "Xfer", "Refer succeeded."); 22164 ast_clear_flag(&p->flags[0], SIP_GOTREFER); 22165 /* Do not hangup call, the other side do that when we say 200 OK */ 22166 /* We could possibly implement a timer here, auto congestion */ 22167 res = 0; 22168 } else { 22169 ast_clear_flag(&p->flags[0], SIP_DEFER_BYE_ON_TRANSFER); /* Don't delay hangup */ 22170 ast_debug(3, "%s transfer failed. Resuming original call.\n", p->refer->attendedtransfer? "Attended" : "Blind"); 22171 append_history(p, "Xfer", "Refer failed."); 22172 /* Failure of some kind */ 22173 p->refer->status = REFER_FAILED; 22174 transmit_notify_with_sipfrag(p, seqno, "503 Service Unavailable", TRUE); 22175 ast_clear_flag(&p->flags[0], SIP_GOTREFER); 22176 res = -1; 22177 } 22178 22179 ast_channel_unref(current.chan1); 22180 22181 return res; 22182 }
| 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 23336 of file chan_sip.c.
References append_history, ast_debug, ast_log(), ast_sockaddr_stringify(), check_via(), copy_request(), get_header(), LOG_NOTICE, register_verify(), sip_methods, sip_scheddestroy(), and cfsip_methods::text.
Referenced by handle_incoming().
23337 { 23338 enum check_auth_result res; 23339 23340 /* Use this as the basis */ 23341 copy_request(&p->initreq, req); 23342 if (sipdebug) 23343 ast_debug(4, "Initializing initreq for method %s - callid %s\n", sip_methods[req->method].text, p->callid); 23344 check_via(p, req); 23345 if ((res = register_verify(p, addr, req, e)) < 0) { 23346 const char *reason; 23347 23348 switch (res) { 23349 case AUTH_SECRET_FAILED: 23350 reason = "Wrong password"; 23351 break; 23352 case AUTH_USERNAME_MISMATCH: 23353 reason = "Username/auth name mismatch"; 23354 break; 23355 case AUTH_NOT_FOUND: 23356 reason = "No matching peer found"; 23357 break; 23358 case AUTH_UNKNOWN_DOMAIN: 23359 reason = "Not a local domain"; 23360 break; 23361 case AUTH_PEER_NOT_DYNAMIC: 23362 reason = "Peer is not supposed to register"; 23363 break; 23364 case AUTH_ACL_FAILED: 23365 reason = "Device does not match ACL"; 23366 break; 23367 case AUTH_BAD_TRANSPORT: 23368 reason = "Device not configured to use this transport type"; 23369 break; 23370 default: 23371 reason = "Unknown failure"; 23372 break; 23373 } 23374 ast_log(LOG_NOTICE, "Registration from '%s' failed for '%s' - %s\n", 23375 get_header(req, "To"), ast_sockaddr_stringify(addr), 23376 reason); 23377 append_history(p, "RegRequest", "Failed : Account %s : %s", get_header(req, "To"), reason); 23378 } else 23379 append_history(p, "RegRequest", "Succeeded : Account %s", get_header(req, "To")); 23380 23381 if (res < 1) { 23382 /* Destroy the session, but keep us around for just a bit in case they don't 23383 get our 200 OK */ 23384 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 23385 } 23386 return res; 23387 }
| static int handle_request_subscribe | ( | struct sip_pvt * | p, | |
| struct sip_request * | req, | |||
| struct ast_sockaddr * | addr, | |||
| int | seqno, | |||
| const char * | e | |||
| ) | [static] |
Handle incoming SUBSCRIBE request.
Definition at line 22953 of file chan_sip.c.
References __get_header(), add_peer_mwi_subs(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_lock, ao2_t_iterator_next, ao2_t_ref, ao2_unlock, append_history, ast_debug, AST_EXTENSION_REMOVED, ast_extension_state(), ast_extension_state2str(), ast_extension_state_add(), 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(), check_user_full(), check_via(), copy_request(), dialog_unlink_all(), FALSE, get_destination(), get_header(), gettag(), handle_cc_subscribe(), LOG_DEBUG, LOG_NOTICE, LOG_WARNING, make_our_tag(), NONE, option_debug, parse_ok_contact(), pvt_set_needdestroy(), ref_peer(), set_pvt_allowed_methods(), sip_cancel_destroy(), sip_cfg, sip_methods, sip_pvt_lock, sip_pvt_unlock, sip_scheddestroy(), sip_send_mwi_to_peer(), cfsip_methods::text, transmit_fake_auth_response(), transmit_response(), transmit_response_reliable(), transmit_response_with_minexpires(), transmit_state_notify(), TRUE, and unref_peer().
Referenced by handle_incoming().
22954 { 22955 int gotdest = 0; 22956 int res = 0; 22957 int firststate = AST_EXTENSION_REMOVED; 22958 struct sip_peer *authpeer = NULL; 22959 const char *eventheader = get_header(req, "Event"); /* Get Event package name */ 22960 int resubscribe = (p->subscribed != NONE); 22961 char *temp, *event; 22962 struct ao2_iterator i; 22963 22964 if (p->initreq.headers) { 22965 /* We already have a dialog */ 22966 if (p->initreq.method != SIP_SUBSCRIBE) { 22967 /* This is a SUBSCRIBE within another SIP dialog, which we do not support */ 22968 /* For transfers, this could happen, but since we haven't seen it happening, let us just refuse this */ 22969 transmit_response(p, "403 Forbidden (within dialog)", req); 22970 /* Do not destroy session, since we will break the call if we do */ 22971 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); 22972 return 0; 22973 } else if (req->debug) { 22974 if (resubscribe) 22975 ast_debug(1, "Got a re-subscribe on existing subscription %s\n", p->callid); 22976 else 22977 ast_debug(1, "Got a new subscription %s (possibly with auth)\n", p->callid); 22978 } 22979 } 22980 22981 /* Check if we have a global disallow setting on subscriptions. 22982 if so, we don't have to check peer settings after auth, which saves a lot of processing 22983 */ 22984 if (!sip_cfg.allowsubscribe) { 22985 transmit_response(p, "403 Forbidden (policy)", req); 22986 pvt_set_needdestroy(p, "forbidden"); 22987 return 0; 22988 } 22989 22990 if (!req->ignore && !resubscribe) { /* Set up dialog, new subscription */ 22991 const char *to = get_header(req, "To"); 22992 char totag[128]; 22993 set_pvt_allowed_methods(p, req); 22994 22995 /* Check to see if a tag was provided, if so this is actually a resubscription of a dialog we no longer know about */ 22996 if (!ast_strlen_zero(to) && gettag(req, "To", totag, sizeof(totag))) { 22997 if (req->debug) 22998 ast_verbose("Received resubscription for a dialog we no longer know about. Telling remote side to subscribe again.\n"); 22999 transmit_response(p, "481 Subscription does not exist", req); 23000 pvt_set_needdestroy(p, "subscription does not exist"); 23001 return 0; 23002 } 23003 23004 /* Use this as the basis */ 23005 if (req->debug) 23006 ast_verbose("Creating new subscription\n"); 23007 23008 copy_request(&p->initreq, req); 23009 if (sipdebug) 23010 ast_debug(4, "Initializing initreq for method %s - callid %s\n", sip_methods[req->method].text, p->callid); 23011 check_via(p, req); 23012 build_route(p, req, 0); 23013 } else if (req->debug && req->ignore) 23014 ast_verbose("Ignoring this SUBSCRIBE request\n"); 23015 23016 /* Find parameters to Event: header value and remove them for now */ 23017 if (ast_strlen_zero(eventheader)) { 23018 transmit_response(p, "489 Bad Event", req); 23019 ast_debug(2, "Received SIP subscribe for unknown event package: <none>\n"); 23020 pvt_set_needdestroy(p, "unknown event package in subscribe"); 23021 return 0; 23022 } 23023 23024 if ( (strchr(eventheader, ';'))) { 23025 event = ast_strdupa(eventheader); /* Since eventheader is a const, we can't change it */ 23026 temp = strchr(event, ';'); 23027 *temp = '\0'; /* Remove any options for now */ 23028 /* We might need to use them later :-) */ 23029 } else 23030 event = (char *) eventheader; /* XXX is this legal ? */ 23031 23032 /* Handle authentication */ 23033 res = check_user_full(p, req, SIP_SUBSCRIBE, e, 0, addr, &authpeer); 23034 /* if an authentication response was sent, we are done here */ 23035 if (res == AUTH_CHALLENGE_SENT) /* authpeer = NULL here */ 23036 return 0; 23037 if (res < 0) { 23038 if (res == AUTH_FAKE_AUTH) { 23039 ast_log(LOG_NOTICE, "Sending fake auth rejection for device %s\n", get_header(req, "From")); 23040 transmit_fake_auth_response(p, SIP_SUBSCRIBE, req, XMIT_UNRELIABLE); 23041 } else { 23042 ast_log(LOG_NOTICE, "Failed to authenticate device %s for SUBSCRIBE\n", get_header(req, "From")); 23043 transmit_response_reliable(p, "403 Forbidden", req); 23044 } 23045 pvt_set_needdestroy(p, "authentication failed"); 23046 return 0; 23047 } 23048 23049 /* At this point, authpeer cannot be NULL. Remember we hold a reference, 23050 * so we must release it when done. 23051 * XXX must remove all the checks for authpeer == NULL. 23052 */ 23053 23054 /* Check if this device is allowed to subscribe at all */ 23055 if (!ast_test_flag(&p->flags[1], SIP_PAGE2_ALLOWSUBSCRIBE)) { 23056 transmit_response(p, "403 Forbidden (policy)", req); 23057 pvt_set_needdestroy(p, "subscription not allowed"); 23058 if (authpeer) 23059 unref_peer(authpeer, "unref_peer, from handle_request_subscribe (authpeer 1)"); 23060 return 0; 23061 } 23062 23063 if (strcmp(event, "message-summary") && strcmp(event, "call-completion")) { 23064 /* Get destination right away */ 23065 gotdest = get_destination(p, NULL, NULL); 23066 } 23067 23068 /* Get full contact header - this needs to be used as a request URI in NOTIFY's */ 23069 parse_ok_contact(p, req); 23070 23071 build_contact(p); 23072 if (gotdest != SIP_GET_DEST_EXTEN_FOUND) { 23073 if (gotdest == SIP_GET_DEST_INVALID_URI) { 23074 transmit_response(p, "416 Unsupported URI scheme", req); 23075 } else { 23076 transmit_response(p, "404 Not Found", req); 23077 } 23078 pvt_set_needdestroy(p, "subscription target not found"); 23079 if (authpeer) 23080 unref_peer(authpeer, "unref_peer, from handle_request_subscribe (authpeer 2)"); 23081 return 0; 23082 } 23083 23084 /* Initialize tag for new subscriptions */ 23085 if (ast_strlen_zero(p->tag)) 23086 make_our_tag(p->tag, sizeof(p->tag)); 23087 23088 if (!strcmp(event, "presence") || !strcmp(event, "dialog")) { /* Presence, RFC 3842 */ 23089 unsigned int pidf_xml; 23090 const char *accept; 23091 int start = 0; 23092 enum subscriptiontype subscribed = NONE; 23093 const char *unknown_acceptheader = NULL; 23094 23095 if (authpeer) /* We do not need the authpeer any more */ 23096 unref_peer(authpeer, "unref_peer, from handle_request_subscribe (authpeer 2)"); 23097 23098 /* Header from Xten Eye-beam Accept: multipart/related, application/rlmi+xml, application/pidf+xml, application/xpidf+xml */ 23099 accept = __get_header(req, "Accept", &start); 23100 while ((subscribed == NONE) && !ast_strlen_zero(accept)) { 23101 pidf_xml = strstr(accept, "application/pidf+xml") ? 1 : 0; 23102 23103 /* Older versions of Polycom firmware will claim pidf+xml, but really 23104 * they only support xpidf+xml. */ 23105 if (pidf_xml && strstr(p->useragent, "Polycom")) { 23106 subscribed = XPIDF_XML; 23107 } else if (pidf_xml) { 23108 subscribed = PIDF_XML; /* RFC 3863 format */ 23109 } else if (strstr(accept, "application/dialog-info+xml")) { 23110 subscribed = DIALOG_INFO_XML; 23111 /* IETF draft: draft-ietf-sipping-dialog-package-05.txt */ 23112 } else if (strstr(accept, "application/cpim-pidf+xml")) { 23113 subscribed = CPIM_PIDF_XML; /* RFC 3863 format */ 23114 } else if (strstr(accept, "application/xpidf+xml")) { 23115 subscribed = XPIDF_XML; /* Early pre-RFC 3863 format with MSN additions (Microsoft Messenger) */ 23116 } else { 23117 unknown_acceptheader = accept; 23118 } 23119 /* check to see if there is another Accept header present */ 23120 accept = __get_header(req, "Accept", &start); 23121 } 23122 23123 if (!start) { 23124 if (p->subscribed == NONE) { /* if the subscribed field is not already set, and there is no accept header... */ 23125 transmit_response(p, "489 Bad Event", req); 23126 ast_log(LOG_WARNING,"SUBSCRIBE failure: no Accept header: pvt: " 23127 "stateid: %d, laststate: %d, dialogver: %d, subscribecont: " 23128 "'%s', subscribeuri: '%s'\n", 23129 p->stateid, 23130 p->laststate, 23131 p->dialogver, 23132 p->subscribecontext, 23133 p->subscribeuri); 23134 pvt_set_needdestroy(p, "no Accept header"); 23135 return 0; 23136 } 23137 /* if p->subscribed is non-zero, then accept is not obligatory; according to rfc 3265 section 3.1.3, at least. 23138 so, we'll just let it ride, keeping the value from a previous subscription, and not abort the subscription */ 23139 } else if (subscribed == NONE) { 23140 /* Can't find a format for events that we know about */ 23141 char mybuf[200]; 23142 if (!ast_strlen_zero(unknown_acceptheader)) { 23143 snprintf(mybuf, sizeof(mybuf), "489 Bad Event (format %s)", unknown_acceptheader); 23144 } else { 23145 snprintf(mybuf, sizeof(mybuf), "489 Bad Event"); 23146 } 23147 transmit_response(p, mybuf, req); 23148 ast_log(LOG_WARNING,"SUBSCRIBE failure: unrecognized format:" 23149 "'%s' pvt: subscribed: %d, stateid: %d, laststate: %d," 23150 "dialogver: %d, subscribecont: '%s', subscribeuri: '%s'\n", 23151 unknown_acceptheader, 23152 (int)p->subscribed, 23153 p->stateid, 23154 p->laststate, 23155 p->dialogver, 23156 p->subscribecontext, 23157 p->subscribeuri); 23158 pvt_set_needdestroy(p, "unrecognized format"); 23159 return 0; 23160 } else { 23161 p->subscribed = subscribed; 23162 } 23163 } else if (!strcmp(event, "message-summary")) { 23164 int start = 0; 23165 int found_supported = 0; 23166 const char *acceptheader; 23167 23168 acceptheader = __get_header(req, "Accept", &start); 23169 while (!found_supported && !ast_strlen_zero(acceptheader)) { 23170 found_supported = strcmp(acceptheader, "application/simple-message-summary") ? 0 : 1; 23171 if (!found_supported && (option_debug > 2)) { 23172 ast_log(LOG_DEBUG, "Received SIP mailbox subscription for unknown format: %s\n", acceptheader); 23173 } 23174 acceptheader = __get_header(req, "Accept", &start); 23175 } 23176 if (start && !found_supported) { 23177 /* Format requested that we do not support */ 23178 transmit_response(p, "406 Not Acceptable", req); 23179 ast_debug(2, "Received SIP mailbox subscription for unknown format: %s\n", acceptheader); 23180 pvt_set_needdestroy(p, "unknown format"); 23181 if (authpeer) 23182 unref_peer(authpeer, "unref_peer, from handle_request_subscribe (authpeer 3)"); 23183 return 0; 23184 } 23185 /* Looks like they actually want a mailbox status 23186 This version of Asterisk supports mailbox subscriptions 23187 The subscribed URI needs to exist in the dial plan 23188 In most devices, this is configurable to the voicemailmain extension you use 23189 */ 23190 if (!authpeer || AST_LIST_EMPTY(&authpeer->mailboxes)) { 23191 transmit_response(p, "404 Not found (no mailbox)", req); 23192 pvt_set_needdestroy(p, "received 404 response"); 23193 ast_log(LOG_NOTICE, "Received SIP subscribe for peer without mailbox: %s\n", authpeer->name); 23194 if (authpeer) 23195 unref_peer(authpeer, "unref_peer, from handle_request_subscribe (authpeer 4)"); 23196 return 0; 23197 } 23198 23199 p->subscribed = MWI_NOTIFICATION; 23200 if (ast_test_flag(&authpeer->flags[1], SIP_PAGE2_SUBSCRIBEMWIONLY)) { 23201 add_peer_mwi_subs(authpeer); 23202 } 23203 if (authpeer->mwipvt && authpeer->mwipvt != p) { /* Destroy old PVT if this is a new one */ 23204 /* We only allow one subscription per peer */ 23205 dialog_unlink_all(authpeer->mwipvt, TRUE, TRUE); 23206 authpeer->mwipvt = dialog_unref(authpeer->mwipvt, "unref dialog authpeer->mwipvt"); 23207 /* sip_destroy(authpeer->mwipvt); */ 23208 } 23209 if (authpeer->mwipvt) 23210 dialog_unref(authpeer->mwipvt, "Unref previously stored mwipvt dialog pointer"); 23211 authpeer->mwipvt = dialog_ref(p, "setting peers' mwipvt to p"); /* Link from peer to pvt UH- should this be dialog_ref()? */ 23212 if (p->relatedpeer) 23213 unref_peer(p->relatedpeer, "Unref previously stored relatedpeer ptr"); 23214 p->relatedpeer = ref_peer(authpeer, "setting dialog's relatedpeer pointer"); /* already refcounted...Link from pvt to peer UH- should this be dialog_ref()? */ 23215 /* Do not release authpeer here */ 23216 } else if (!strcmp(event, "call-completion")) { 23217 handle_cc_subscribe(p, req); 23218 } else { /* At this point, Asterisk does not understand the specified event */ 23219 transmit_response(p, "489 Bad Event", req); 23220 ast_debug(2, "Received SIP subscribe for unknown event package: %s\n", event); 23221 pvt_set_needdestroy(p, "unknown event package"); 23222 if (authpeer) 23223 unref_peer(authpeer, "unref_peer, from handle_request_subscribe (authpeer 5)"); 23224 return 0; 23225 } 23226 23227 /* Add subscription for extension state from the PBX core */ 23228 if (p->subscribed != MWI_NOTIFICATION && p->subscribed != CALL_COMPLETION && !resubscribe) { 23229 if (p->stateid > -1) { 23230 ast_extension_state_del(p->stateid, cb_extensionstate); 23231 /* we need to dec the refcount, now that the extensionstate is removed */ 23232 dialog_unref(p, "the extensionstate containing this dialog ptr was deleted"); 23233 } 23234 p->stateid = ast_extension_state_add(p->context, p->exten, cb_extensionstate, dialog_ref(p,"copying dialog ptr into extension state struct")); 23235 } 23236 23237 if (!req->ignore && p) 23238 p->lastinvite = seqno; 23239 if (p && !p->needdestroy) { 23240 p->expiry = atoi(get_header(req, "Expires")); 23241 23242 /* check if the requested expiry-time is within the approved limits from sip.conf */ 23243 if (p->expiry > max_expiry) { 23244 p->expiry = max_expiry; 23245 } else if (p->expiry < min_expiry && p->expiry > 0) { 23246 transmit_response_with_minexpires(p, "423 Interval too small", req); 23247 ast_log(LOG_WARNING, "Received subscription for extension \"%s\" context \"%s\" " 23248 "with Expire header less that 'minexpire' limit. Received \"Expire: %d\" min is %d\n", 23249 p->exten, p->context, p->expiry, min_expiry); 23250 p->expiry = min_expiry; 23251 pvt_set_needdestroy(p, "Expires is less that the min expires allowed. "); 23252 return 0; 23253 } 23254 23255 if (sipdebug) { 23256 if (p->subscribed == MWI_NOTIFICATION && p->relatedpeer) { 23257 ast_debug(2, "Adding subscription for mailbox notification - peer %s\n", p->relatedpeer->name); 23258 } else if (p->subscribed == CALL_COMPLETION) { 23259 ast_debug(2, "Adding CC subscription for peer %s\n", p->username); 23260 } else { 23261 ast_debug(2, "Adding subscription for extension %s context %s for peer %s\n", p->exten, p->context, p->username); 23262 } 23263 } 23264 if (p->autokillid > -1 && sip_cancel_destroy(p)) /* Remove subscription expiry for renewals */ 23265 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 23266 if (p->expiry > 0) 23267 sip_scheddestroy(p, (p->expiry + 10) * 1000); /* Set timer for destruction of call at expiration */ 23268 23269 if (p->subscribed == MWI_NOTIFICATION) { 23270 ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED); 23271 transmit_response(p, "200 OK", req); 23272 if (p->relatedpeer) { /* Send first notification */ 23273 ao2_lock(p->relatedpeer); /* was WRLOCK */ 23274 sip_send_mwi_to_peer(p->relatedpeer, NULL, 0); 23275 ao2_unlock(p->relatedpeer); 23276 } 23277 } else if (p->subscribed != CALL_COMPLETION) { 23278 struct sip_pvt *p_old; 23279 23280 if ((firststate = ast_extension_state(NULL, p->context, p->exten)) < 0) { 23281 23282 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)); 23283 transmit_response(p, "404 Not found", req); 23284 pvt_set_needdestroy(p, "no extension for SUBSCRIBE"); 23285 return 0; 23286 } 23287 ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED); 23288 transmit_response(p, "200 OK", req); 23289 transmit_state_notify(p, firststate, 1, FALSE); /* Send first notification */ 23290 append_history(p, "Subscribestatus", "%s", ast_extension_state2str(firststate)); 23291 /* hide the 'complete' exten/context in the refer_to field for later display */ 23292 ast_string_field_build(p, subscribeuri, "%s@%s", p->exten, p->context); 23293 23294 /* remove any old subscription from this peer for the same exten/context, 23295 as the peer has obviously forgotten about it and it's wasteful to wait 23296 for it to expire and send NOTIFY messages to the peer only to have them 23297 ignored (or generate errors) 23298 */ 23299 i = ao2_iterator_init(dialogs, 0); 23300 while ((p_old = ao2_t_iterator_next(&i, "iterate thru dialogs"))) { 23301 if (p_old == p) { 23302 ao2_t_ref(p_old, -1, "toss dialog ptr from iterator_next before continue"); 23303 continue; 23304 } 23305 if (p_old->initreq.method != SIP_SUBSCRIBE) { 23306 ao2_t_ref(p_old, -1, "toss dialog ptr from iterator_next before continue"); 23307 continue; 23308 } 23309 if (p_old->subscribed == NONE) { 23310 ao2_t_ref(p_old, -1, "toss dialog ptr from iterator_next before continue"); 23311 continue; 23312 } 23313 sip_pvt_lock(p_old); 23314 if (!strcmp(p_old->username, p->username)) { 23315 if (!strcmp(p_old->exten, p->exten) && 23316 !strcmp(p_old->context, p->context)) { 23317 pvt_set_needdestroy(p_old, "replacing subscription"); 23318 sip_pvt_unlock(p_old); 23319 ao2_t_ref(p_old, -1, "toss dialog ptr from iterator_next before break"); 23320 break; 23321 } 23322 } 23323 sip_pvt_unlock(p_old); 23324 ao2_t_ref(p_old, -1, "toss dialog ptr from iterator_next"); 23325 } 23326 ao2_iterator_destroy(&i); 23327 } 23328 if (!p->expiry) { 23329 pvt_set_needdestroy(p, "forcing expiration"); 23330 } 23331 } 23332 return 1; 23333 }
| 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 20751 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_header(), 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, 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().
20752 { 20753 if (ast_strlen_zero(get_header(req, "X-Asterisk-rpid-update"))) { 20754 transmit_response(p, "501 Method Not Implemented", req); 20755 return 0; 20756 } 20757 if (get_rpid(p, req)) { 20758 struct ast_party_connected_line connected; 20759 struct ast_set_party_connected_line update_connected; 20760 ast_party_connected_line_init(&connected); 20761 memset(&update_connected, 0, sizeof(update_connected)); 20762 if (p->cid_num) { 20763 update_connected.id.number = 1; 20764 connected.id.number.valid = 1; 20765 connected.id.number.str = (char *) p->cid_num; 20766 connected.id.number.presentation = p->callingpres; 20767 } 20768 if (p->cid_name) { 20769 update_connected.id.name = 1; 20770 connected.id.name.valid = 1; 20771 connected.id.name.str = (char *) p->cid_name; 20772 connected.id.name.presentation = p->callingpres; 20773 } 20774 connected.id.tag = (char *) p->cid_tag; 20775 connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER; 20776 ast_channel_queue_connected_line_update(p->owner, &connected, &update_connected); 20777 } 20778 transmit_response(p, "200 OK", req); 20779 return 0; 20780 }
| static void handle_response | ( | struct sip_pvt * | p, | |
| int | resp, | |||
| const char * | rest, | |||
| struct sip_request * | req, | |||
| int | seqno | |||
| ) | [static] |
Handle SIP response in dialogue.
Definition at line 19546 of file chan_sip.c.
References __sip_ack(), __sip_semi_ack(), ao2_callback, append_history, AST_CAUSE_PROTOCOL_ERROR, AST_CC_CCBS, ast_cc_monitor_failed(), 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, cb_extensionstate(), change_redirecting_information(), do_proxy_auth(), FALSE, find_sdp(), find_sip_method(), find_sip_monitor_instance_by_subscription_pvt(), get_header(), gettag(), handle_response_invite(), 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_handle_cc(), sip_methods, stop_media_flows(), text, transmit_request(), TRUE, and update_redirecting().
19547 { 19548 struct ast_channel *owner; 19549 int sipmethod; 19550 int res = 1; 19551 const char *c = get_header(req, "Cseq"); 19552 /* 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 */ 19553 char *c_copy = ast_strdupa(c); 19554 /* Skip the Cseq and its subsequent spaces */ 19555 const char *msg = ast_skip_blanks(ast_skip_nonblanks(c_copy)); 19556 19557 if (!msg) 19558 msg = ""; 19559 19560 sipmethod = find_sip_method(msg); 19561 19562 owner = p->owner; 19563 if (owner) { 19564 const char *rp = NULL, *rh = NULL; 19565 19566 owner->hangupcause = 0; 19567 if (ast_test_flag(&p->flags[1], SIP_PAGE2_Q850_REASON) && (rh = get_header(req, "Reason"))) { 19568 rh = ast_skip_blanks(rh); 19569 if (!strncasecmp(rh, "Q.850", 5)) { 19570 rp = strstr(rh, "cause="); 19571 if (rp && sscanf(rp + 6, "%30d", &owner->hangupcause) == 1) { 19572 owner->hangupcause &= 0x7f; 19573 if (req->debug) 19574 ast_verbose("Using Reason header for cause code: %d\n", owner->hangupcause); 19575 } 19576 } 19577 } 19578 19579 if (!owner->hangupcause) 19580 owner->hangupcause = hangup_sip2cause(resp); 19581 } 19582 19583 if (p->socket.type == SIP_TRANSPORT_UDP) { 19584 int ack_res = FALSE; 19585 19586 /* Acknowledge whatever it is destined for */ 19587 if ((resp >= 100) && (resp <= 199)) { 19588 /* NON-INVITE messages do not ack a 1XX response. RFC 3261 section 17.1.2.2 */ 19589 if (sipmethod == SIP_INVITE) { 19590 ack_res = __sip_semi_ack(p, seqno, 0, sipmethod); 19591 } 19592 } else { 19593 ack_res = __sip_ack(p, seqno, 0, sipmethod); 19594 } 19595 19596 if (ack_res == FALSE) { 19597 /* RFC 3261 13.2.2.4 and 17.1.1.2 - We must re-send ACKs to re-transmitted final responses */ 19598 if (sipmethod == SIP_INVITE && resp >= 200) { 19599 transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, resp < 300 ? TRUE: FALSE); 19600 } 19601 19602 append_history(p, "Ignore", "Ignoring this retransmit\n"); 19603 return; 19604 } 19605 } 19606 19607 /* If this is a NOTIFY for a subscription clear the flag that indicates that we have a NOTIFY pending */ 19608 if (!p->owner && sipmethod == SIP_NOTIFY && p->pendinginvite) 19609 p->pendinginvite = 0; 19610 19611 /* Get their tag if we haven't already */ 19612 if (ast_strlen_zero(p->theirtag) || (resp >= 200)) { 19613 char tag[128]; 19614 19615 gettag(req, "To", tag, sizeof(tag)); 19616 ast_string_field_set(p, theirtag, tag); 19617 } 19618 /* This needs to be configurable on a channel/peer level, 19619 not mandatory for all communication. Sadly enough, NAT implementations 19620 are not so stable so we can always rely on these headers. 19621 Temporarily disabled, while waiting for fix. 19622 Fix assigned to Rizzo :-) 19623 */ 19624 /* check_via_response(p, req); */ 19625 19626 /* RFC 3261 Section 15 specifies that if we receive a 408 or 481 19627 * in response to a BYE, then we should end the current dialog 19628 * and session. It is known that at least one phone manufacturer 19629 * potentially will send a 404 in response to a BYE, so we'll be 19630 * liberal in what we accept and end the dialog and session if we 19631 * receive any of those responses to a BYE. 19632 */ 19633 if ((resp == 404 || resp == 408 || resp == 481) && sipmethod == SIP_BYE) { 19634 pvt_set_needdestroy(p, "received 4XX response to a BYE"); 19635 return; 19636 } 19637 19638 if (p->relatedpeer && p->method == SIP_OPTIONS) { 19639 /* We don't really care what the response is, just that it replied back. 19640 Well, as long as it's not a 100 response... since we might 19641 need to hang around for something more "definitive" */ 19642 if (resp != 100) 19643 handle_response_peerpoke(p, resp, req); 19644 } else if (sipmethod == SIP_REFER && resp >= 200) { 19645 handle_response_refer(p, resp, rest, req, seqno); 19646 } else if (sipmethod == SIP_PUBLISH) { 19647 /* SIP PUBLISH transcends this morass of doodoo and instead 19648 * we just always call the response handler. Good gravy! 19649 */ 19650 handle_response_publish(p, resp, rest, req, seqno); 19651 } else if (ast_test_flag(&p->flags[0], SIP_OUTGOING)) { 19652 switch(resp) { 19653 case 100: /* 100 Trying */ 19654 case 101: /* 101 Dialog establishment */ 19655 case 183: /* 183 Session Progress */ 19656 case 180: /* 180 Ringing */ 19657 case 182: /* 182 Queued */ 19658 case 181: /* 181 Call Is Being Forwarded */ 19659 if (sipmethod == SIP_INVITE) 19660 handle_response_invite(p, resp, rest, req, seqno); 19661 break; 19662 case 200: /* 200 OK */ 19663 p->authtries = 0; /* Reset authentication counter */ 19664 if (sipmethod == SIP_MESSAGE || sipmethod == SIP_INFO) { 19665 /* We successfully transmitted a message 19666 or a video update request in INFO */ 19667 /* Nothing happens here - the message is inside a dialog */ 19668 } else if (sipmethod == SIP_INVITE) { 19669 handle_response_invite(p, resp, rest, req, seqno); 19670 } else if (sipmethod == SIP_NOTIFY) { 19671 handle_response_notify(p, resp, rest, req, seqno); 19672 } else if (sipmethod == SIP_REGISTER) { 19673 res = handle_response_register(p, resp, rest, req, seqno); 19674 } else if (sipmethod == SIP_SUBSCRIBE) { 19675 ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED); 19676 handle_response_subscribe(p, resp, rest, req, seqno); 19677 } else if (sipmethod == SIP_BYE) { /* Ok, we're ready to go */ 19678 pvt_set_needdestroy(p, "received 200 response"); 19679 ast_clear_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED); 19680 } 19681 break; 19682 case 401: /* Not www-authorized on SIP method */ 19683 case 407: /* Proxy auth required */ 19684 if (sipmethod == SIP_INVITE) 19685 handle_response_invite(p, resp, rest, req, seqno); 19686 else if (sipmethod == SIP_NOTIFY) 19687 handle_response_notify(p, resp, rest, req, seqno); 19688 else if (sipmethod == SIP_SUBSCRIBE) 19689 handle_response_subscribe(p, resp, rest, req, seqno); 19690 else if (p->registry && sipmethod == SIP_REGISTER) 19691 res = handle_response_register(p, resp, rest, req, seqno); 19692 else if (sipmethod == SIP_UPDATE) { 19693 handle_response_update(p, resp, rest, req, seqno); 19694 } else if (sipmethod == SIP_BYE) { 19695 if (p->options) 19696 p->options->auth_type = resp; 19697 if (ast_strlen_zero(p->authname)) { 19698 ast_log(LOG_WARNING, "Asked to authenticate %s, to %s but we have no matching peer!\n", 19699 msg, ast_sockaddr_stringify(&p->recv)); 19700 pvt_set_needdestroy(p, "unable to authenticate BYE"); 19701 } else if ((p->authtries == MAX_AUTHTRIES) || do_proxy_auth(p, req, resp, sipmethod, 0)) { 19702 ast_log(LOG_NOTICE, "Failed to authenticate on %s to '%s'\n", msg, get_header(&p->initreq, "From")); 19703 pvt_set_needdestroy(p, "failed to authenticate BYE"); 19704 } 19705 } else { 19706 ast_log(LOG_WARNING, "Got authentication request (%d) on %s to '%s'\n", resp, sip_methods[sipmethod].text, get_header(req, "To")); 19707 pvt_set_needdestroy(p, "received 407 response"); 19708 } 19709 break; 19710 case 403: /* Forbidden - we failed authentication */ 19711 if (sipmethod == SIP_INVITE) 19712 handle_response_invite(p, resp, rest, req, seqno); 19713 else if (sipmethod == SIP_SUBSCRIBE) 19714 handle_response_subscribe(p, resp, rest, req, seqno); 19715 else if (p->registry && sipmethod == SIP_REGISTER) 19716 res = handle_response_register(p, resp, rest, req, seqno); 19717 else { 19718 ast_log(LOG_WARNING, "Forbidden - maybe wrong password on authentication for %s\n", msg); 19719 pvt_set_needdestroy(p, "received 403 response"); 19720 } 19721 break; 19722 case 404: /* Not found */ 19723 if (p->registry && sipmethod == SIP_REGISTER) 19724 res = handle_response_register(p, resp, rest, req, seqno); 19725 else if (sipmethod == SIP_INVITE) 19726 handle_response_invite(p, resp, rest, req, seqno); 19727 else if (sipmethod == SIP_SUBSCRIBE) 19728 handle_response_subscribe(p, resp, rest, req, seqno); 19729 else if (owner) 19730 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 19731 break; 19732 case 423: /* Interval too brief */ 19733 if (sipmethod == SIP_REGISTER) 19734 res = handle_response_register(p, resp, rest, req, seqno); 19735 break; 19736 case 408: /* Request timeout - terminate dialog */ 19737 if (sipmethod == SIP_INVITE) 19738 handle_response_invite(p, resp, rest, req, seqno); 19739 else if (sipmethod == SIP_REGISTER) 19740 res = handle_response_register(p, resp, rest, req, seqno); 19741 else if (sipmethod == SIP_BYE) { 19742 pvt_set_needdestroy(p, "received 408 response"); 19743 ast_debug(4, "Got timeout on bye. Thanks for the answer. Now, kill this call\n"); 19744 } else { 19745 if (owner) 19746 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 19747 pvt_set_needdestroy(p, "received 408 response"); 19748 } 19749 break; 19750 19751 case 422: /* Session-Timers: Session Interval Too Small */ 19752 if (sipmethod == SIP_INVITE) { 19753 handle_response_invite(p, resp, rest, req, seqno); 19754 } 19755 break; 19756 19757 case 481: /* Call leg does not exist */ 19758 if (sipmethod == SIP_INVITE) { 19759 handle_response_invite(p, resp, rest, req, seqno); 19760 } else if (sipmethod == SIP_SUBSCRIBE) { 19761 handle_response_subscribe(p, resp, rest, req, seqno); 19762 } else if (sipmethod == SIP_BYE) { 19763 /* The other side has no transaction to bye, 19764 just assume it's all right then */ 19765 ast_log(LOG_WARNING, "Remote host can't match request %s to call '%s'. Giving up.\n", sip_methods[sipmethod].text, p->callid); 19766 } else if (sipmethod == SIP_CANCEL) { 19767 /* The other side has no transaction to cancel, 19768 just assume it's all right then */ 19769 ast_log(LOG_WARNING, "Remote host can't match request %s to call '%s'. Giving up.\n", sip_methods[sipmethod].text, p->callid); 19770 } else { 19771 ast_log(LOG_WARNING, "Remote host can't match request %s to call '%s'. Giving up.\n", sip_methods[sipmethod].text, p->callid); 19772 /* Guessing that this is not an important request */ 19773 } 19774 break; 19775 case 487: 19776 if (sipmethod == SIP_INVITE) 19777 handle_response_invite(p, resp, rest, req, seqno); 19778 break; 19779 case 415: /* Unsupported media type */ 19780 case 488: /* Not acceptable here - codec error */ 19781 case 606: /* Not Acceptable */ 19782 if (sipmethod == SIP_INVITE) 19783 handle_response_invite(p, resp, rest, req, seqno); 19784 break; 19785 case 491: /* Pending */ 19786 if (sipmethod == SIP_INVITE) 19787 handle_response_invite(p, resp, rest, req, seqno); 19788 else { 19789 ast_debug(1, "Got 491 on %s, unsupported. Call ID %s\n", sip_methods[sipmethod].text, p->callid); 19790 pvt_set_needdestroy(p, "received 491 response"); 19791 } 19792 break; 19793 case 405: 19794 case 501: /* Not Implemented */ 19795 mark_method_unallowed(&p->allowed_methods, sipmethod); 19796 if (p->relatedpeer) { 19797 mark_method_allowed(&p->relatedpeer->disallowed_methods, sipmethod); 19798 } 19799 if (sipmethod == SIP_INVITE) 19800 handle_response_invite(p, resp, rest, req, seqno); 19801 else 19802 ast_log(LOG_WARNING, "Host '%s' does not implement '%s'\n", ast_sockaddr_stringify(&p->sa), msg); 19803 break; 19804 /* Fallthrough */ 19805 default: 19806 if ((resp >= 300) && (resp < 700)) { 19807 /* Fatal response */ 19808 if ((resp != 487)) 19809 ast_verb(3, "Got SIP response %d \"%s\" back from %s\n", resp, rest, ast_sockaddr_stringify(&p->sa)); 19810 19811 if (sipmethod == SIP_INVITE) 19812 stop_media_flows(p); /* Immediately stop RTP, VRTP and UDPTL as applicable */ 19813 19814 /* XXX Locking issues?? XXX */ 19815 switch(resp) { 19816 case 300: /* Multiple Choices */ 19817 case 301: /* Moved permanently */ 19818 case 302: /* Moved temporarily */ 19819 case 305: /* Use Proxy */ 19820 if (p->owner) { 19821 struct ast_party_redirecting redirecting; 19822 struct ast_set_party_redirecting update_redirecting; 19823 19824 ast_party_redirecting_init(&redirecting); 19825 change_redirecting_information(p, req, &redirecting, 19826 &update_redirecting, TRUE); 19827 ast_channel_set_redirecting(p->owner, &redirecting, 19828 &update_redirecting); 19829 ast_party_redirecting_free(&redirecting); 19830 } 19831 /* Fall through */ 19832 case 486: /* Busy here */ 19833 case 600: /* Busy everywhere */ 19834 case 603: /* Decline */ 19835 if (p->owner) { 19836 sip_handle_cc(p, req, AST_CC_CCBS); 19837 ast_queue_control(p->owner, AST_CONTROL_BUSY); 19838 } 19839 break; 19840 case 482: /* Loop Detected */ 19841 case 480: /* Temporarily Unavailable */ 19842 case 404: /* Not Found */ 19843 case 410: /* Gone */ 19844 case 400: /* Bad Request */ 19845 case 500: /* Server error */ 19846 if (sipmethod == SIP_SUBSCRIBE) { 19847 handle_response_subscribe(p, resp, rest, req, seqno); 19848 break; 19849 } 19850 /* Fall through */ 19851 case 502: /* Bad gateway */ 19852 case 503: /* Service Unavailable */ 19853 case 504: /* Server Timeout */ 19854 if (owner) 19855 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 19856 break; 19857 default: 19858 /* Send hangup */ 19859 if (owner && sipmethod != SIP_MESSAGE && sipmethod != SIP_INFO && sipmethod != SIP_BYE) 19860 ast_queue_hangup_with_cause(p->owner, AST_CAUSE_PROTOCOL_ERROR); 19861 break; 19862 } 19863 /* ACK on invite */ 19864 if (sipmethod == SIP_INVITE) 19865 transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); 19866 if (sipmethod != SIP_MESSAGE && sipmethod != SIP_INFO) 19867 sip_alreadygone(p); 19868 if (!p->owner) { 19869 pvt_set_needdestroy(p, "transaction completed"); 19870 } 19871 } else if ((resp >= 100) && (resp < 200)) { 19872 if (sipmethod == SIP_INVITE) { 19873 if (!req->ignore && sip_cancel_destroy(p)) 19874 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 19875 if (find_sdp(req)) 19876 process_sdp(p, req, SDP_T38_NONE); 19877 if (p->owner) { 19878 /* Queue a progress frame */ 19879 ast_queue_control(p->owner, AST_CONTROL_PROGRESS); 19880 } 19881 } 19882 } else 19883 ast_log(LOG_NOTICE, "Don't know how to handle a %d %s response from %s\n", resp, rest, p->owner ? p->owner->name : ast_sockaddr_stringify(&p->sa)); 19884 } 19885 } else { 19886 /* Responses to OUTGOING SIP requests on INCOMING calls 19887 get handled here. As well as out-of-call message responses */ 19888 if (req->debug) 19889 ast_verbose("SIP Response message for INCOMING dialog %s arrived\n", msg); 19890 19891 if (sipmethod == SIP_INVITE && resp == 200) { 19892 /* Tags in early session is replaced by the tag in 200 OK, which is 19893 the final reply to our INVITE */ 19894 char tag[128]; 19895 19896 gettag(req, "To", tag, sizeof(tag)); 19897 ast_string_field_set(p, theirtag, tag); 19898 } 19899 19900 if (sipmethod == SIP_SUBSCRIBE && resp >= 400) { 19901 struct sip_monitor_instance *monitor_instance = ao2_callback(sip_monitor_instances, 19902 0, find_sip_monitor_instance_by_subscription_pvt, p); 19903 if (monitor_instance) { 19904 ast_cc_monitor_failed(monitor_instance->core_id, monitor_instance->device_name, 19905 "Received error response to our SUBSCRIBE"); 19906 return; 19907 } 19908 } 19909 19910 switch(resp) { 19911 case 200: 19912 if (sipmethod == SIP_INVITE) { 19913 handle_response_invite(p, resp, rest, req, seqno); 19914 } else if (sipmethod == SIP_CANCEL) { 19915 ast_debug(1, "Got 200 OK on CANCEL\n"); 19916 19917 /* Wait for 487, then destroy */ 19918 } else if (sipmethod == SIP_NOTIFY) { 19919 /* They got the notify, this is the end */ 19920 if (p->owner) { 19921 if (p->refer) { 19922 ast_debug(1, "Got 200 OK on NOTIFY for transfer\n"); 19923 } else 19924 ast_log(LOG_WARNING, "Notify answer on an owned channel?\n"); 19925 /* ast_queue_hangup(p->owner); Disabled */ 19926 } else { 19927 if (!p->subscribed && !p->refer) { 19928 pvt_set_needdestroy(p, "transaction completed"); 19929 } 19930 if (ast_test_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE)) { 19931 /* Ready to send the next state we have on queue */ 19932 ast_clear_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE); 19933 cb_extensionstate((char *)p->context, (char *)p->exten, p->laststate, (void *) p); 19934 } 19935 } 19936 } else if (sipmethod == SIP_BYE) { 19937 pvt_set_needdestroy(p, "transaction completed"); 19938 } else if (sipmethod == SIP_MESSAGE || sipmethod == SIP_INFO) { 19939 /* We successfully transmitted a message or 19940 a video update request in INFO */ 19941 ; 19942 } 19943 break; 19944 case 401: /* www-auth */ 19945 case 407: 19946 if (sipmethod == SIP_INVITE) 19947 handle_response_invite(p, resp, rest, req, seqno); 19948 else if (sipmethod == SIP_BYE) { 19949 if (p->authtries == MAX_AUTHTRIES || do_proxy_auth(p, req, resp, sipmethod, 0)) { 19950 ast_log(LOG_NOTICE, "Failed to authenticate on %s to '%s'\n", msg, get_header(&p->initreq, "From")); 19951 pvt_set_needdestroy(p, "failed to authenticate BYE"); 19952 } 19953 } 19954 break; 19955 case 481: /* Call leg does not exist */ 19956 if (sipmethod == SIP_INVITE) { 19957 /* Re-invite failed */ 19958 handle_response_invite(p, resp, rest, req, seqno); 19959 } else if (sipmethod == SIP_BYE) { 19960 pvt_set_needdestroy(p, "received 481 response"); 19961 } else if (sipdebug) { 19962 ast_debug(1, "Remote host can't match request %s to call '%s'. Giving up\n", sip_methods[sipmethod].text, p->callid); 19963 } 19964 break; 19965 case 501: /* Not Implemented */ 19966 if (sipmethod == SIP_INVITE) 19967 handle_response_invite(p, resp, rest, req, seqno); 19968 break; 19969 default: /* Errors without handlers */ 19970 if ((resp >= 100) && (resp < 200)) { 19971 if (sipmethod == SIP_INVITE) { /* re-invite */ 19972 if (!req->ignore && sip_cancel_destroy(p)) 19973 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 19974 } 19975 } 19976 if ((resp >= 300) && (resp < 700)) { 19977 if ((resp != 487)) 19978 ast_verb(3, "Incoming call: Got SIP response %d \"%s\" back from %s\n", resp, rest, ast_sockaddr_stringify(&p->sa)); 19979 switch(resp) { 19980 case 415: /* Unsupported media type */ 19981 case 488: /* Not acceptable here - codec error */ 19982 case 603: /* Decline */ 19983 case 500: /* Server error */ 19984 case 502: /* Bad gateway */ 19985 case 503: /* Service Unavailable */ 19986 case 504: /* Server timeout */ 19987 19988 /* re-invite failed */ 19989 if (sipmethod == SIP_INVITE && sip_cancel_destroy(p)) 19990 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 19991 break; 19992 } 19993 } 19994 break; 19995 } 19996 } 19997 }
| static void handle_response_invite | ( | struct sip_pvt * | p, | |
| int | resp, | |||
| const char * | rest, | |||
| struct sip_request * | req, | |||
| int | seqno | |||
| ) | [static] |
Handle SIP response to INVITE dialogue.
Definition at line 18703 of file chan_sip.c.
References append_history, AST_CAUSE_NORMAL_CLEARING, AST_CC_CCNR, ast_channel_queue_connected_line_update(), ast_channel_queue_redirecting_update(), AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER, AST_CONTROL_ANSWER, AST_CONTROL_CONGESTION, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, ast_debug, ast_log(), ast_null_frame, ast_party_connected_line_init(), ast_party_redirecting_free(), ast_party_redirecting_init(), 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_header(), 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_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().
18704 { 18705 int outgoing = ast_test_flag(&p->flags[0], SIP_OUTGOING); 18706 int res = 0; 18707 int xmitres = 0; 18708 int reinvite = (p->owner && p->owner->_state == AST_STATE_UP); 18709 char *p_hdrval; 18710 int rtn; 18711 struct ast_party_connected_line connected; 18712 struct ast_set_party_connected_line update_connected; 18713 18714 if (reinvite) 18715 ast_debug(4, "SIP response %d to RE-invite on %s call %s\n", resp, outgoing ? "outgoing" : "incoming", p->callid); 18716 else 18717 ast_debug(4, "SIP response %d to standard invite\n", resp); 18718 18719 if (p->alreadygone) { /* This call is already gone */ 18720 ast_debug(1, "Got response on call that is already terminated: %s (ignoring)\n", p->callid); 18721 return; 18722 } 18723 18724 /* Acknowledge sequence number - This only happens on INVITE from SIP-call */ 18725 /* Don't auto congest anymore since we've gotten something useful back */ 18726 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")); 18727 18728 /* RFC3261 says we must treat every 1xx response (but not 100) 18729 that we don't recognize as if it was 183. 18730 */ 18731 if (resp > 100 && resp < 200 && resp!=101 && resp != 180 && resp != 181 && resp != 182 && resp != 183) 18732 resp = 183; 18733 18734 /* Any response between 100 and 199 is PROCEEDING */ 18735 if (resp >= 100 && resp < 200 && p->invitestate == INV_CALLING) 18736 p->invitestate = INV_PROCEEDING; 18737 18738 /* Final response, not 200 ? */ 18739 if (resp >= 300 && (p->invitestate == INV_CALLING || p->invitestate == INV_PROCEEDING || p->invitestate == INV_EARLY_MEDIA )) 18740 p->invitestate = INV_COMPLETED; 18741 18742 /* Final response, clear out pending invite */ 18743 if ((resp == 200 || resp >= 300) && p->pendinginvite && seqno == p->pendinginvite) 18744 p->pendinginvite = 0; 18745 18746 /* If this is a response to our initial INVITE, we need to set what we can use 18747 * for this peer. 18748 */ 18749 if (!reinvite) { 18750 set_pvt_allowed_methods(p, req); 18751 } 18752 18753 switch (resp) { 18754 case 100: /* Trying */ 18755 case 101: /* Dialog establishment */ 18756 if (!req->ignore && p->invitestate != INV_CANCELLED && sip_cancel_destroy(p)) 18757 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 18758 check_pendings(p); 18759 break; 18760 18761 case 180: /* 180 Ringing */ 18762 case 182: /* 182 Queued */ 18763 if (!req->ignore && p->invitestate != INV_CANCELLED && sip_cancel_destroy(p)) 18764 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 18765 if (!req->ignore && p->owner) { 18766 if (get_rpid(p, req)) { 18767 ast_party_connected_line_init(&connected); 18768 memset(&update_connected, 0, sizeof(update_connected)); 18769 if (p->cid_num) { 18770 update_connected.id.number = 1; 18771 connected.id.number.valid = 1; 18772 connected.id.number.str = (char *) p->cid_num; 18773 connected.id.number.presentation = p->callingpres; 18774 } 18775 if (p->cid_name) { 18776 update_connected.id.name = 1; 18777 connected.id.name.valid = 1; 18778 connected.id.name.str = (char *) p->cid_name; 18779 connected.id.name.presentation = p->callingpres; 18780 } 18781 connected.id.tag = (char *) p->cid_tag; 18782 connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER; 18783 ast_channel_queue_connected_line_update(p->owner, &connected, 18784 &update_connected); 18785 } 18786 sip_handle_cc(p, req, AST_CC_CCNR); 18787 ast_queue_control(p->owner, AST_CONTROL_RINGING); 18788 if (p->owner->_state != AST_STATE_UP) { 18789 ast_setstate(p->owner, AST_STATE_RINGING); 18790 } 18791 } 18792 if (find_sdp(req)) { 18793 if (p->invitestate != INV_CANCELLED) 18794 p->invitestate = INV_EARLY_MEDIA; 18795 res = process_sdp(p, req, SDP_T38_NONE); 18796 if (!req->ignore && p->owner) { 18797 /* Queue a progress frame only if we have SDP in 180 or 182 */ 18798 ast_queue_control(p->owner, AST_CONTROL_PROGRESS); 18799 } 18800 ast_rtp_instance_activate(p->rtp); 18801 } 18802 check_pendings(p); 18803 break; 18804 18805 case 181: /* Call Is Being Forwarded */ 18806 if (!req->ignore && (p->invitestate != INV_CANCELLED) && sip_cancel_destroy(p)) 18807 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 18808 if (!req->ignore && p->owner) { 18809 struct ast_party_redirecting redirecting; 18810 struct ast_set_party_redirecting update_redirecting; 18811 18812 ast_party_redirecting_init(&redirecting); 18813 memset(&update_redirecting, 0, sizeof(update_redirecting)); 18814 change_redirecting_information(p, req, &redirecting, &update_redirecting, 18815 FALSE); 18816 ast_channel_queue_redirecting_update(p->owner, &redirecting, 18817 &update_redirecting); 18818 ast_party_redirecting_free(&redirecting); 18819 sip_handle_cc(p, req, AST_CC_CCNR); 18820 } 18821 check_pendings(p); 18822 break; 18823 18824 case 183: /* Session progress */ 18825 if (!req->ignore && (p->invitestate != INV_CANCELLED) && sip_cancel_destroy(p)) 18826 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 18827 if (!req->ignore && p->owner) { 18828 if (get_rpid(p, req)) { 18829 /* Queue a connected line update */ 18830 ast_party_connected_line_init(&connected); 18831 memset(&update_connected, 0, sizeof(update_connected)); 18832 if (p->cid_num) { 18833 update_connected.id.number = 1; 18834 connected.id.number.valid = 1; 18835 connected.id.number.str = (char *) p->cid_num; 18836 connected.id.number.presentation = p->callingpres; 18837 } 18838 if (p->cid_name) { 18839 update_connected.id.name = 1; 18840 connected.id.name.valid = 1; 18841 connected.id.name.str = (char *) p->cid_name; 18842 connected.id.name.presentation = p->callingpres; 18843 } 18844 connected.id.tag = (char *) p->cid_tag; 18845 connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER; 18846 ast_channel_queue_connected_line_update(p->owner, &connected, 18847 &update_connected); 18848 } 18849 sip_handle_cc(p, req, AST_CC_CCNR); 18850 } 18851 if (find_sdp(req)) { 18852 if (p->invitestate != INV_CANCELLED) 18853 p->invitestate = INV_EARLY_MEDIA; 18854 res = process_sdp(p, req, SDP_T38_NONE); 18855 if (!req->ignore && p->owner) { 18856 /* Queue a progress frame */ 18857 ast_queue_control(p->owner, AST_CONTROL_PROGRESS); 18858 } 18859 ast_rtp_instance_activate(p->rtp); 18860 } else { 18861 /* Alcatel PBXs are known to send 183s with no SDP after sending 18862 * a 100 Trying response. We're just going to treat this sort of thing 18863 * the same as we would treat a 180 Ringing 18864 */ 18865 if (!req->ignore && p->owner) { 18866 ast_queue_control(p->owner, AST_CONTROL_RINGING); 18867 } 18868 } 18869 check_pendings(p); 18870 break; 18871 18872 case 200: /* 200 OK on invite - someone's answering our call */ 18873 if (!req->ignore && (p->invitestate != INV_CANCELLED) && sip_cancel_destroy(p)) 18874 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 18875 p->authtries = 0; 18876 if (find_sdp(req)) { 18877 if ((res = process_sdp(p, req, SDP_T38_ACCEPT)) && !req->ignore) 18878 if (!reinvite) 18879 /* This 200 OK's SDP is not acceptable, so we need to ack, then hangup */ 18880 /* For re-invites, we try to recover */ 18881 ast_set_flag(&p->flags[0], SIP_PENDINGBYE); 18882 ast_rtp_instance_activate(p->rtp); 18883 } 18884 18885 if (!req->ignore && p->owner && (get_rpid(p, req) || !reinvite)) { 18886 /* Queue a connected line update */ 18887 ast_party_connected_line_init(&connected); 18888 memset(&update_connected, 0, sizeof(update_connected)); 18889 if (p->cid_num) { 18890 update_connected.id.number = 1; 18891 connected.id.number.valid = 1; 18892 connected.id.number.str = (char *) p->cid_num; 18893 connected.id.number.presentation = p->callingpres; 18894 } 18895 if (p->cid_name) { 18896 update_connected.id.name = 1; 18897 connected.id.name.valid = 1; 18898 connected.id.name.str = (char *) p->cid_name; 18899 connected.id.name.presentation = p->callingpres; 18900 } 18901 connected.id.tag = (char *) p->cid_tag; 18902 connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER; 18903 ast_channel_queue_connected_line_update(p->owner, &connected, 18904 &update_connected); 18905 } 18906 18907 /* Parse contact header for continued conversation */ 18908 /* When we get 200 OK, we know which device (and IP) to contact for this call */ 18909 /* This is important when we have a SIP proxy between us and the phone */ 18910 if (outgoing) { 18911 update_call_counter(p, DEC_CALL_RINGING); 18912 parse_ok_contact(p, req); 18913 /* Save Record-Route for any later requests we make on this dialogue */ 18914 if (!reinvite) 18915 build_route(p, req, 1); 18916 18917 if(set_address_from_contact(p)) { 18918 /* Bad contact - we don't know how to reach this device */ 18919 /* We need to ACK, but then send a bye */ 18920 if (!p->route && !req->ignore) 18921 ast_set_flag(&p->flags[0], SIP_PENDINGBYE); 18922 } 18923 18924 } 18925 18926 if (!req->ignore && p->owner) { 18927 if (!reinvite) { 18928 ast_queue_control(p->owner, AST_CONTROL_ANSWER); 18929 if (sip_cfg.callevents) 18930 manager_event(EVENT_FLAG_SYSTEM, "ChannelUpdate", 18931 "Channel: %s\r\nChanneltype: %s\r\nUniqueid: %s\r\nSIPcallid: %s\r\nSIPfullcontact: %s\r\nPeername: %s\r\n", 18932 p->owner->name, "SIP", p->owner->uniqueid, p->callid, p->fullcontact, p->peername); 18933 } else { /* RE-invite */ 18934 ast_queue_frame(p->owner, &ast_null_frame); 18935 } 18936 } else { 18937 /* It's possible we're getting an 200 OK after we've tried to disconnect 18938 by sending CANCEL */ 18939 /* First send ACK, then send bye */ 18940 if (!req->ignore) 18941 ast_set_flag(&p->flags[0], SIP_PENDINGBYE); 18942 } 18943 18944 /* Check for Session-Timers related headers */ 18945 if (st_get_mode(p) != SESSION_TIMER_MODE_REFUSE && p->outgoing_call == TRUE && !reinvite) { 18946 p_hdrval = (char*)get_header(req, "Session-Expires"); 18947 if (!ast_strlen_zero(p_hdrval)) { 18948 /* UAS supports Session-Timers */ 18949 enum st_refresher tmp_st_ref = SESSION_TIMER_REFRESHER_AUTO; 18950 int tmp_st_interval = 0; 18951 rtn = parse_session_expires(p_hdrval, &tmp_st_interval, &tmp_st_ref); 18952 if (rtn != 0) { 18953 ast_set_flag(&p->flags[0], SIP_PENDINGBYE); 18954 } 18955 if (tmp_st_ref == SESSION_TIMER_REFRESHER_UAC || 18956 tmp_st_ref == SESSION_TIMER_REFRESHER_UAS) { 18957 p->stimer->st_ref = tmp_st_ref; 18958 } 18959 if (tmp_st_interval) { 18960 p->stimer->st_interval = tmp_st_interval; 18961 } 18962 p->stimer->st_active = TRUE; 18963 p->stimer->st_active_peer_ua = TRUE; 18964 start_session_timer(p); 18965 } else { 18966 /* UAS doesn't support Session-Timers */ 18967 if (st_get_mode(p) == SESSION_TIMER_MODE_ORIGINATE) { 18968 p->stimer->st_ref = SESSION_TIMER_REFRESHER_UAC; 18969 p->stimer->st_active_peer_ua = FALSE; 18970 start_session_timer(p); 18971 } 18972 } 18973 } 18974 18975 18976 /* If I understand this right, the branch is different for a non-200 ACK only */ 18977 p->invitestate = INV_TERMINATED; 18978 ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED); 18979 xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, TRUE); 18980 check_pendings(p); 18981 break; 18982 18983 case 407: /* Proxy authentication */ 18984 case 401: /* Www auth */ 18985 /* First we ACK */ 18986 xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); 18987 if (p->options) 18988 p->options->auth_type = resp; 18989 18990 /* Then we AUTH */ 18991 ast_string_field_set(p, theirtag, NULL); /* forget their old tag, so we don't match tags when getting response */ 18992 if (!req->ignore) { 18993 if (p->authtries < MAX_AUTHTRIES) 18994 p->invitestate = INV_CALLING; 18995 if (p->authtries == MAX_AUTHTRIES || do_proxy_auth(p, req, resp, SIP_INVITE, 1)) { 18996 ast_log(LOG_NOTICE, "Failed to authenticate on INVITE to '%s'\n", get_header(&p->initreq, "From")); 18997 pvt_set_needdestroy(p, "failed to authenticate on INVITE"); 18998 sip_alreadygone(p); 18999 if (p->owner) 19000 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 19001 } 19002 } 19003 break; 19004 19005 case 403: /* Forbidden */ 19006 /* First we ACK */ 19007 xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); 19008 ast_log(LOG_WARNING, "Received response: \"Forbidden\" from '%s'\n", get_header(&p->initreq, "From")); 19009 if (!req->ignore && p->owner) { 19010 ast_set_hangupsource(p->owner, p->owner->name, 0); 19011 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 19012 } 19013 pvt_set_needdestroy(p, "received 403 response"); 19014 sip_alreadygone(p); 19015 break; 19016 19017 case 404: /* Not found */ 19018 xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); 19019 if (p->owner && !req->ignore) { 19020 ast_set_hangupsource(p->owner, p->owner->name, 0); 19021 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 19022 } 19023 sip_alreadygone(p); 19024 break; 19025 19026 case 408: /* Request timeout */ 19027 case 481: /* Call leg does not exist */ 19028 /* Could be REFER caused INVITE with replaces */ 19029 ast_log(LOG_WARNING, "Re-invite to non-existing call leg on other UA. SIP dialog '%s'. Giving up.\n", p->callid); 19030 xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); 19031 if (p->owner) 19032 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 19033 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 19034 break; 19035 19036 case 422: /* Session-Timers: Session interval too small */ 19037 xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); 19038 ast_string_field_set(p, theirtag, NULL); 19039 proc_422_rsp(p, req); 19040 break; 19041 19042 case 428: /* Use identity header - rfc 4474 - not supported by Asterisk yet */ 19043 xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); 19044 append_history(p, "Identity", "SIP identity is required. Not supported by Asterisk."); 19045 ast_log(LOG_WARNING, "SIP identity required by proxy. SIP dialog '%s'. Giving up.\n", p->callid); 19046 if (p->owner) 19047 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 19048 break; 19049 19050 19051 19052 case 487: /* Cancelled transaction */ 19053 /* We have sent CANCEL on an outbound INVITE 19054 This transaction is already scheduled to be killed by sip_hangup(). 19055 */ 19056 xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); 19057 if (p->owner && !req->ignore) { 19058 ast_queue_hangup_with_cause(p->owner, AST_CAUSE_NORMAL_CLEARING); 19059 append_history(p, "Hangup", "Got 487 on CANCEL request from us. Queued AST hangup request"); 19060 } else if (!req->ignore) { 19061 update_call_counter(p, DEC_CALL_LIMIT); 19062 append_history(p, "Hangup", "Got 487 on CANCEL request from us on call without owner. Killing this dialog."); 19063 pvt_set_needdestroy(p, "received 487 response"); 19064 sip_alreadygone(p); 19065 } 19066 break; 19067 case 415: /* Unsupported media type */ 19068 case 488: /* Not acceptable here */ 19069 case 606: /* Not Acceptable */ 19070 xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); 19071 if (p->udptl && p->t38.state == T38_LOCAL_REINVITE) { 19072 change_t38_state(p, T38_DISABLED); 19073 /* Try to reset RTP timers */ 19074 //ast_rtp_set_rtptimers_onhold(p->rtp); 19075 19076 /* Trigger a reinvite back to audio */ 19077 transmit_reinvite_with_sdp(p, FALSE, FALSE); 19078 } else { 19079 /* We can't set up this call, so give up */ 19080 if (p->owner && !req->ignore) 19081 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 19082 pvt_set_needdestroy(p, "received 488 response"); 19083 /* If there's no dialog to end, then mark p as already gone */ 19084 if (!reinvite) 19085 sip_alreadygone(p); 19086 } 19087 break; 19088 case 491: /* Pending */ 19089 xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); 19090 if (p->owner && !req->ignore) { 19091 if (p->owner->_state != AST_STATE_UP) { 19092 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 19093 pvt_set_needdestroy(p, "received 491 response"); 19094 } else { 19095 /* This is a re-invite that failed. */ 19096 /* Reset the flag after a while 19097 */ 19098 int wait; 19099 /* RFC 3261, if owner of call, wait between 2.1 to 4 seconds, 19100 * if not owner of call, wait 0 to 2 seconds */ 19101 if (p->outgoing_call) { 19102 wait = 2100 + ast_random() % 2000; 19103 } else { 19104 wait = ast_random() % 2000; 19105 } 19106 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.")); 19107 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); 19108 ast_debug(2, "Reinvite race. Waiting %d secs before retry\n", wait); 19109 } 19110 } 19111 break; 19112 19113 case 405: /* Not allowed */ 19114 case 501: /* Not implemented */ 19115 xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); 19116 if (p->owner) 19117 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 19118 break; 19119 } 19120 if (xmitres == XMIT_ERROR) 19121 ast_log(LOG_WARNING, "Could not transmit message in dialog %s\n", p->callid); 19122 }
| static void handle_response_notify | ( | struct sip_pvt * | p, | |
| int | resp, | |||
| const char * | rest, | |||
| struct sip_request * | req, | |||
| int | seqno | |||
| ) | [static] |
Definition at line 19127 of file chan_sip.c.
References AST_CAUSE_NORMAL_UNSPECIFIED, ast_clear_flag, ast_debug, ast_log(), ast_queue_hangup_with_cause(), ast_sockaddr_stringify(), ast_string_field_set, ast_strlen_zero(), ast_test_flag, cb_extensionstate(), do_proxy_auth(), get_header(), LOG_NOTICE, LOG_WARNING, NONE, and pvt_set_needdestroy().
Referenced by handle_response().
19128 { 19129 switch (resp) { 19130 case 200: /* Notify accepted */ 19131 /* They got the notify, this is the end */ 19132 if (p->owner) { 19133 if (!p->refer) { 19134 ast_log(LOG_WARNING, "Notify answer on an owned channel? - %s\n", p->owner->name); 19135 ast_queue_hangup_with_cause(p->owner, AST_CAUSE_NORMAL_UNSPECIFIED); 19136 } else { 19137 ast_debug(4, "Got OK on REFER Notify message\n"); 19138 } 19139 } else { 19140 if (p->subscribed == NONE) { 19141 ast_debug(4, "Got 200 accepted on NOTIFY\n"); 19142 pvt_set_needdestroy(p, "received 200 response"); 19143 } 19144 if (ast_test_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE)) { 19145 /* Ready to send the next state we have on queue */ 19146 ast_clear_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE); 19147 cb_extensionstate((char *)p->context, (char *)p->exten, p->laststate, (void *) p); 19148 } 19149 } 19150 break; 19151 case 401: /* Not www-authorized on SIP method */ 19152 case 407: /* Proxy auth */ 19153 if (!p->notify) { 19154 break; /* Only device notify can use NOTIFY auth */ 19155 } 19156 ast_string_field_set(p, theirtag, NULL); 19157 if (ast_strlen_zero(p->authname)) { 19158 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)); 19159 pvt_set_needdestroy(p, "unable to authenticate NOTIFY"); 19160 } 19161 if (p->authtries > 1 || do_proxy_auth(p, req, resp, SIP_NOTIFY, 0)) { 19162 ast_log(LOG_NOTICE, "Failed to authenticate on NOTIFY to '%s'\n", get_header(&p->initreq, "From")); 19163 pvt_set_needdestroy(p, "failed to authenticate NOTIFY"); 19164 } 19165 break; 19166 } 19167 }
| static void handle_response_peerpoke | ( | struct sip_pvt * | p, | |
| int | resp, | |||
| struct sip_request * | req | |||
| ) | [static] |
Handle qualification responses (OPTIONS).
Definition at line 19476 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(), ref_peer(), register_peer_exten(), SENTINEL, sip_cfg, sip_poke_peer_s(), TRUE, and unref_peer().
Referenced by handle_response().
19477 { 19478 struct sip_peer *peer = /* ref_peer( */ p->relatedpeer /* , "bump refcount on p, as it is being used in this function(handle_response_peerpoke)")*/ ; /* hope this is already refcounted! */ 19479 int statechanged, is_reachable, was_reachable; 19480 int pingtime = ast_tvdiff_ms(ast_tvnow(), peer->ps); 19481 19482 /* 19483 * Compute the response time to a ping (goes in peer->lastms.) 19484 * -1 means did not respond, 0 means unknown, 19485 * 1..maxms is a valid response, >maxms means late response. 19486 */ 19487 if (pingtime < 1) /* zero = unknown, so round up to 1 */ 19488 pingtime = 1; 19489 19490 /* Now determine new state and whether it has changed. 19491 * Use some helper variables to simplify the writing 19492 * of the expressions. 19493 */ 19494 was_reachable = peer->lastms > 0 && peer->lastms <= peer->maxms; 19495 is_reachable = pingtime <= peer->maxms; 19496 statechanged = peer->lastms == 0 /* yes, unknown before */ 19497 || was_reachable != is_reachable; 19498 19499 peer->lastms = pingtime; 19500 peer->call = dialog_unref(peer->call, "unref dialog peer->call"); 19501 if (statechanged) { 19502 const char *s = is_reachable ? "Reachable" : "Lagged"; 19503 char str_lastms[20]; 19504 snprintf(str_lastms, sizeof(str_lastms), "%d", pingtime); 19505 19506 ast_log(LOG_NOTICE, "Peer '%s' is now %s. (%dms / %dms)\n", 19507 peer->name, s, pingtime, peer->maxms); 19508 ast_devstate_changed(AST_DEVICE_UNKNOWN, "SIP/%s", peer->name); 19509 if (sip_cfg.peer_rtupdate) { 19510 ast_update_realtime(ast_check_realtime("sipregs") ? "sipregs" : "sippeers", "name", peer->name, "lastms", str_lastms, SENTINEL); 19511 } 19512 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", 19513 "ChannelType: SIP\r\nPeer: SIP/%s\r\nPeerStatus: %s\r\nTime: %d\r\n", 19514 peer->name, s, pingtime); 19515 if (is_reachable && sip_cfg.regextenonqualify) 19516 register_peer_exten(peer, TRUE); 19517 } 19518 19519 pvt_set_needdestroy(p, "got OPTIONS response"); 19520 19521 /* Try again eventually */ 19522 AST_SCHED_REPLACE_UNREF(peer->pokeexpire, sched, 19523 is_reachable ? peer->qualifyfreq : DEFAULT_FREQ_NOTOK, 19524 sip_poke_peer_s, peer, 19525 unref_peer(_data, "removing poke peer ref"), 19526 unref_peer(peer, "removing poke peer ref"), 19527 ref_peer(peer, "adding poke peer ref")); 19528 }
| static void handle_response_publish | ( | struct sip_pvt * | p, | |
| int | resp, | |||
| const char * | rest, | |||
| struct sip_request * | req, | |||
| int | seqno | |||
| ) | [static] |
Definition at line 18652 of file chan_sip.c.
References ast_assert, ast_copy_string(), ast_log(), ast_string_field_set, ast_strlen_zero(), do_proxy_auth(), get_header(), LOG_NOTICE, mark_method_unallowed(), pvt_set_needdestroy(), and sip_alreadygone().
Referenced by handle_response().
18653 { 18654 struct sip_epa_entry *epa_entry = p->epa_entry; 18655 const char *etag = get_header(req, "Sip-ETag"); 18656 18657 ast_assert(epa_entry != NULL); 18658 18659 if (resp == 401 || resp == 407) { 18660 ast_string_field_set(p, theirtag, NULL); 18661 if (p->options) { 18662 p->options->auth_type = (resp == 401 ? WWW_AUTH : PROXY_AUTH); 18663 } 18664 if ((p->authtries == MAX_AUTHTRIES) || do_proxy_auth(p, req, resp, SIP_PUBLISH, 0)) { 18665 ast_log(LOG_NOTICE, "Failed to authenticate on PUBLISH to '%s'\n", get_header(&p->initreq, "From")); 18666 pvt_set_needdestroy(p, "Failed to authenticate on PUBLISH"); 18667 sip_alreadygone(p); 18668 } 18669 return; 18670 } 18671 18672 if (resp == 501 || resp == 405) { 18673 mark_method_unallowed(&p->allowed_methods, SIP_PUBLISH); 18674 } 18675 18676 if (resp == 200) { 18677 p->authtries = 0; 18678 /* If I've read section 6, item 6 of RFC 3903 correctly, 18679 * an ESC will only generate a new etag when it sends a 200 OK 18680 */ 18681 if (!ast_strlen_zero(etag)) { 18682 ast_copy_string(epa_entry->entity_tag, etag, sizeof(epa_entry->entity_tag)); 18683 } 18684 /* The nominal case. Everything went well. Everybody is happy. 18685 * Each EPA will have a specific action to take as a result of this 18686 * development, so ... callbacks! 18687 */ 18688 if (epa_entry->static_data->handle_ok) { 18689 epa_entry->static_data->handle_ok(p, req, epa_entry); 18690 } 18691 } else { 18692 /* Rather than try to make individual callbacks for each error 18693 * type, there is just a single error callback. The callback 18694 * can distinguish between error messages and do what it needs to 18695 */ 18696 if (epa_entry->static_data->handle_error) { 18697 epa_entry->static_data->handle_error(p, resp, req, epa_entry); 18698 } 18699 } 18700 }
| static void handle_response_refer | ( | struct sip_pvt * | p, | |
| int | resp, | |||
| const char * | rest, | |||
| struct sip_request * | req, | |||
| int | seqno | |||
| ) | [static] |
Definition at line 19232 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(), get_header(), LOG_NOTICE, LOG_WARNING, and pvt_set_needdestroy().
Referenced by handle_response().
19233 { 19234 enum ast_control_transfer message = AST_TRANSFER_FAILED; 19235 19236 /* If no refer structure exists, then do nothing */ 19237 if (!p->refer) 19238 return; 19239 19240 switch (resp) { 19241 case 202: /* Transfer accepted */ 19242 /* We need to do something here */ 19243 /* The transferee is now sending INVITE to target */ 19244 p->refer->status = REFER_ACCEPTED; 19245 /* Now wait for next message */ 19246 ast_debug(3, "Got 202 accepted on transfer\n"); 19247 /* We should hang along, waiting for NOTIFY's here */ 19248 break; 19249 19250 case 401: /* Not www-authorized on SIP method */ 19251 case 407: /* Proxy auth */ 19252 if (ast_strlen_zero(p->authname)) { 19253 ast_log(LOG_WARNING, "Asked to authenticate REFER to %s but we have no matching peer or realm auth!\n", 19254 ast_sockaddr_stringify(&p->recv)); 19255 if (p->owner) { 19256 ast_queue_control_data(p->owner, AST_CONTROL_TRANSFER, &message, sizeof(message)); 19257 } 19258 pvt_set_needdestroy(p, "unable to authenticate REFER"); 19259 } 19260 if (p->authtries > 1 || do_proxy_auth(p, req, resp, SIP_REFER, 0)) { 19261 ast_log(LOG_NOTICE, "Failed to authenticate on REFER to '%s'\n", get_header(&p->initreq, "From")); 19262 p->refer->status = REFER_NOAUTH; 19263 if (p->owner) { 19264 ast_queue_control_data(p->owner, AST_CONTROL_TRANSFER, &message, sizeof(message)); 19265 } 19266 pvt_set_needdestroy(p, "failed to authenticate REFER"); 19267 } 19268 break; 19269 19270 case 405: /* Method not allowed */ 19271 /* Return to the current call onhold */ 19272 /* Status flag needed to be reset */ 19273 ast_log(LOG_NOTICE, "SIP transfer to %s failed, REFER not allowed. \n", p->refer->refer_to); 19274 pvt_set_needdestroy(p, "received 405 response"); 19275 p->refer->status = REFER_FAILED; 19276 if (p->owner) { 19277 ast_queue_control_data(p->owner, AST_CONTROL_TRANSFER, &message, sizeof(message)); 19278 } 19279 break; 19280 19281 case 481: /* Call leg does not exist */ 19282 19283 /* A transfer with Replaces did not work */ 19284 /* OEJ: We should Set flag, cancel the REFER, go back 19285 to original call - but right now we can't */ 19286 ast_log(LOG_WARNING, "Remote host can't match REFER request to call '%s'. Giving up.\n", p->callid); 19287 if (p->owner) 19288 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 19289 pvt_set_needdestroy(p, "received 481 response"); 19290 break; 19291 19292 case 500: /* Server error */ 19293 case 501: /* Method not implemented */ 19294 /* Return to the current call onhold */ 19295 /* Status flag needed to be reset */ 19296 ast_log(LOG_NOTICE, "SIP transfer to %s failed, call miserably fails. \n", p->refer->refer_to); 19297 pvt_set_needdestroy(p, "received 500/501 response"); 19298 p->refer->status = REFER_FAILED; 19299 if (p->owner) { 19300 ast_queue_control_data(p->owner, AST_CONTROL_TRANSFER, &message, sizeof(message)); 19301 } 19302 break; 19303 case 603: /* Transfer declined */ 19304 ast_log(LOG_NOTICE, "SIP transfer to %s declined, call miserably fails. \n", p->refer->refer_to); 19305 p->refer->status = REFER_FAILED; 19306 pvt_set_needdestroy(p, "received 603 response"); 19307 if (p->owner) { 19308 ast_queue_control_data(p->owner, AST_CONTROL_TRANSFER, &message, sizeof(message)); 19309 } 19310 break; 19311 default: 19312 /* We should treat unrecognized 9xx as 900. 400 is actually 19313 specified as a possible response, but any 4-6xx is 19314 theoretically possible. */ 19315 19316 if (resp < 299) { /* 1xx cases don't get here */ 19317 ast_log(LOG_WARNING, "SIP transfer to %s had unxpected 2xx response (%d), confusion is possible. \n", p->refer->refer_to, resp); 19318 } else { 19319 ast_log(LOG_WARNING, "SIP transfer to %s with response (%d). \n", p->refer->refer_to, resp); 19320 } 19321 19322 p->refer->status = REFER_FAILED; 19323 pvt_set_needdestroy(p, "received failure response"); 19324 if (p->owner) { 19325 ast_queue_control_data(p->owner, AST_CONTROL_TRANSFER, &message, sizeof(message)); 19326 } 19327 break; 19328 } 19329 }
| static int handle_response_register | ( | struct sip_pvt * | p, | |
| int | resp, | |||
| const char * | rest, | |||
| struct sip_request * | req, | |||
| int | seqno | |||
| ) | [static] |
Handle responses on REGISTER to services.
Definition at line 19332 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, get_header(), 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_reregister(), sip_scheddestroy(), strcasestr(), and transmit_register().
Referenced by handle_response().
19333 { 19334 int expires, expires_ms; 19335 struct sip_registry *r; 19336 r=p->registry; 19337 19338 switch (resp) { 19339 case 401: /* Unauthorized */ 19340 if (p->authtries == MAX_AUTHTRIES || do_register_auth(p, req, resp)) { 19341 ast_log(LOG_NOTICE, "Failed to authenticate on REGISTER to '%s@%s' (Tries %d)\n", p->registry->username, p->registry->hostname, p->authtries); 19342 pvt_set_needdestroy(p, "failed to authenticate REGISTER"); 19343 } 19344 break; 19345 case 403: /* Forbidden */ 19346 ast_log(LOG_WARNING, "Forbidden - wrong password on authentication for REGISTER for '%s' to '%s'\n", p->registry->username, p->registry->hostname); 19347 AST_SCHED_DEL_UNREF(sched, r->timeout, registry_unref(r, "reg ptr unref from handle_response_register 403")); 19348 r->regstate = REG_STATE_NOAUTH; 19349 pvt_set_needdestroy(p, "received 403 response"); 19350 break; 19351 case 404: /* Not found */ 19352 ast_log(LOG_WARNING, "Got 404 Not found on SIP register to service %s@%s, giving up\n", p->registry->username, p->registry->hostname); 19353 pvt_set_needdestroy(p, "received 404 response"); 19354 if (r->call) 19355 r->call = dialog_unref(r->call, "unsetting registry->call pointer-- case 404"); 19356 r->regstate = REG_STATE_REJECTED; 19357 AST_SCHED_DEL_UNREF(sched, r->timeout, registry_unref(r, "reg ptr unref from handle_response_register 404")); 19358 break; 19359 case 407: /* Proxy auth */ 19360 if (p->authtries == MAX_AUTHTRIES || do_register_auth(p, req, resp)) { 19361 ast_log(LOG_NOTICE, "Failed to authenticate on REGISTER to '%s' (tries '%d')\n", get_header(&p->initreq, "From"), p->authtries); 19362 pvt_set_needdestroy(p, "failed to authenticate REGISTER"); 19363 } 19364 break; 19365 case 408: /* Request timeout */ 19366 /* Got a timeout response, so reset the counter of failed responses */ 19367 if (r) { 19368 r->regattempts = 0; 19369 } else { 19370 ast_log(LOG_WARNING, "Got a 408 response to our REGISTER on call %s after we had destroyed the registry object\n", p->callid); 19371 } 19372 break; 19373 case 423: /* Interval too brief */ 19374 r->expiry = atoi(get_header(req, "Min-Expires")); 19375 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); 19376 AST_SCHED_DEL_UNREF(sched, r->timeout, registry_unref(r, "reg ptr unref from handle_response_register 423")); 19377 if (r->call) { 19378 r->call = dialog_unref(r->call, "unsetting registry->call pointer-- case 423"); 19379 pvt_set_needdestroy(p, "received 423 response"); 19380 } 19381 if (r->expiry > max_expiry) { 19382 ast_log(LOG_WARNING, "Required expiration time from %s@%s is too high, giving up\n", p->registry->username, p->registry->hostname); 19383 r->expiry = r->configured_expiry; 19384 r->regstate = REG_STATE_REJECTED; 19385 } else { 19386 r->regstate = REG_STATE_UNREGISTERED; 19387 transmit_register(r, SIP_REGISTER, NULL, NULL); 19388 } 19389 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)); 19390 break; 19391 case 479: /* SER: Not able to process the URI - address is wrong in register*/ 19392 ast_log(LOG_WARNING, "Got error 479 on register to %s@%s, giving up (check config)\n", p->registry->username, p->registry->hostname); 19393 pvt_set_needdestroy(p, "received 479 response"); 19394 if (r->call) 19395 r->call = dialog_unref(r->call, "unsetting registry->call pointer-- case 479"); 19396 r->regstate = REG_STATE_REJECTED; 19397 AST_SCHED_DEL_UNREF(sched, r->timeout, registry_unref(r, "reg ptr unref from handle_response_register 479")); 19398 break; 19399 case 200: /* 200 OK */ 19400 if (!r) { 19401 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)); 19402 pvt_set_needdestroy(p, "received erroneous 200 response"); 19403 return 0; 19404 } 19405 19406 r->regstate = REG_STATE_REGISTERED; 19407 r->regtime = ast_tvnow(); /* Reset time of last successful registration */ 19408 manager_event(EVENT_FLAG_SYSTEM, "Registry", "ChannelType: SIP\r\nDomain: %s\r\nStatus: %s\r\n", r->hostname, regstate2str(r->regstate)); 19409 r->regattempts = 0; 19410 ast_debug(1, "Registration successful\n"); 19411 if (r->timeout > -1) { 19412 ast_debug(1, "Cancelling timeout %d\n", r->timeout); 19413 } 19414 AST_SCHED_DEL_UNREF(sched, r->timeout, registry_unref(r, "reg ptr unref from handle_response_register 200")); 19415 if (r->call) 19416 r->call = dialog_unref(r->call, "unsetting registry->call pointer-- case 200"); 19417 p->registry = registry_unref(p->registry, "unref registry entry p->registry"); 19418 /* Let this one hang around until we have all the responses */ 19419 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 19420 /* p->needdestroy = 1; */ 19421 19422 /* set us up for re-registering 19423 * figure out how long we got registered for 19424 * according to section 6.13 of RFC, contact headers override 19425 * expires headers, so check those first */ 19426 expires = 0; 19427 19428 /* XXX todo: try to save the extra call */ 19429 if (!ast_strlen_zero(get_header(req, "Contact"))) { 19430 const char *contact = NULL; 19431 const char *tmptmp = NULL; 19432 int start = 0; 19433 for(;;) { 19434 contact = __get_header(req, "Contact", &start); 19435 /* this loop ensures we get a contact header about our register request */ 19436 if(!ast_strlen_zero(contact)) { 19437 if( (tmptmp=strstr(contact, p->our_contact))) { 19438 contact=tmptmp; 19439 break; 19440 } 19441 } else 19442 break; 19443 } 19444 tmptmp = strcasestr(contact, "expires="); 19445 if (tmptmp) { 19446 if (sscanf(tmptmp + 8, "%30d;", &expires) != 1) 19447 expires = 0; 19448 } 19449 19450 } 19451 if (!expires) 19452 expires=atoi(get_header(req, "expires")); 19453 if (!expires) 19454 expires=default_expiry; 19455 19456 expires_ms = expires * 1000; 19457 if (expires <= EXPIRY_GUARD_LIMIT) 19458 expires_ms -= MAX((expires_ms * EXPIRY_GUARD_PCT), EXPIRY_GUARD_MIN); 19459 else 19460 expires_ms -= EXPIRY_GUARD_SECS * 1000; 19461 if (sipdebug) 19462 ast_log(LOG_NOTICE, "Outbound Registration: Expiry for %s is %d sec (Scheduling reregistration in %d s)\n", r->hostname, expires, expires_ms/1000); 19463 19464 r->refresh= (int) expires_ms / 1000; 19465 19466 /* Schedule re-registration before we expire */ 19467 AST_SCHED_REPLACE_UNREF(r->expire, sched, expires_ms, sip_reregister, r, 19468 registry_unref(_data,"unref in REPLACE del fail"), 19469 registry_unref(r,"unref in REPLACE add fail"), 19470 registry_addref(r,"The Addition side of REPLACE")); 19471 } 19472 return 1; 19473 }
| static void handle_response_subscribe | ( | struct sip_pvt * | p, | |
| int | resp, | |||
| const char * | rest, | |||
| struct sip_request * | req, | |||
| int | seqno | |||
| ) | [static] |
Definition at line 19170 of file chan_sip.c.
References ast_debug, ast_free, ast_log(), ast_sched_add(), ast_string_field_set, ASTOBJ_REF, ASTOBJ_UNREF, do_proxy_auth(), get_header(), LOG_NOTICE, LOG_WARNING, pvt_set_needdestroy(), set_pvt_allowed_methods(), sip_alreadygone(), sip_subscribe_mwi_destroy(), sip_subscribe_mwi_do(), and transmit_response_with_date().
Referenced by handle_response().
19171 { 19172 if (!p->mwi) { 19173 return; 19174 } 19175 19176 switch (resp) { 19177 case 200: /* Subscription accepted */ 19178 ast_debug(3, "Got 200 OK on subscription for MWI\n"); 19179 set_pvt_allowed_methods(p, req); 19180 if (p->options) { 19181 ast_free(p->options); 19182 p->options = NULL; 19183 } 19184 p->mwi->subscribed = 1; 19185 if ((p->mwi->resub = ast_sched_add(sched, mwi_expiry * 1000, sip_subscribe_mwi_do, ASTOBJ_REF(p->mwi))) < 0) { 19186 ASTOBJ_UNREF(p->mwi, sip_subscribe_mwi_destroy); 19187 } 19188 break; 19189 case 401: 19190 case 407: 19191 ast_string_field_set(p, theirtag, NULL); 19192 if (p->authtries > 1 || do_proxy_auth(p, req, resp, SIP_SUBSCRIBE, 0)) { 19193 ast_log(LOG_NOTICE, "Failed to authenticate on SUBSCRIBE to '%s'\n", get_header(&p->initreq, "From")); 19194 p->mwi->call = NULL; 19195 ASTOBJ_UNREF(p->mwi, sip_subscribe_mwi_destroy); 19196 pvt_set_needdestroy(p, "failed to authenticate SUBSCRIBE"); 19197 } 19198 break; 19199 case 403: 19200 transmit_response_with_date(p, "200 OK", req); 19201 ast_log(LOG_WARNING, "Authentication failed while trying to subscribe for MWI.\n"); 19202 p->mwi->call = NULL; 19203 ASTOBJ_UNREF(p->mwi, sip_subscribe_mwi_destroy); 19204 pvt_set_needdestroy(p, "received 403 response"); 19205 sip_alreadygone(p); 19206 break; 19207 case 404: 19208 ast_log(LOG_WARNING, "Subscription failed for MWI. The remote side said that a mailbox may not have been configured.\n"); 19209 p->mwi->call = NULL; 19210 ASTOBJ_UNREF(p->mwi, sip_subscribe_mwi_destroy); 19211 pvt_set_needdestroy(p, "received 404 response"); 19212 break; 19213 case 481: 19214 ast_log(LOG_WARNING, "Subscription failed for MWI. The remote side said that our dialog did not exist.\n"); 19215 p->mwi->call = NULL; 19216 ASTOBJ_UNREF(p->mwi, sip_subscribe_mwi_destroy); 19217 pvt_set_needdestroy(p, "received 481 response"); 19218 break; 19219 case 500: 19220 case 501: 19221 ast_log(LOG_WARNING, "Subscription failed for MWI. The remote side may have suffered a heart attack.\n"); 19222 p->mwi->call = NULL; 19223 ASTOBJ_UNREF(p->mwi, sip_subscribe_mwi_destroy); 19224 pvt_set_needdestroy(p, "received 500/501 response"); 19225 break; 19226 } 19227 }
| static void handle_response_update | ( | struct sip_pvt * | p, | |
| int | resp, | |||
| const char * | rest, | |||
| struct sip_request * | req, | |||
| int | 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 18592 of file chan_sip.c.
References ast_log(), do_proxy_auth(), get_header(), and LOG_NOTICE.
Referenced by handle_response().
18593 { 18594 if (p->options) { 18595 p->options->auth_type = (resp == 401 ? WWW_AUTH : PROXY_AUTH); 18596 } 18597 if ((p->authtries == MAX_AUTHTRIES) || do_proxy_auth(p, req, resp, SIP_UPDATE, 1)) { 18598 ast_log(LOG_NOTICE, "Failed to authenticate on UPDATE to '%s'\n", get_header(&p->initreq, "From")); 18599 } 18600 }
| 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 22707 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().
22708 { 22709 struct sip_esc_entry *esc_entry = create_esc_entry(esc, req, expires); 22710 int res = 0; 22711 22712 if (!esc_entry) { 22713 transmit_response(p, "503 Internal Server Failure", req); 22714 return -1; 22715 } 22716 22717 if (esc->callbacks->initial_handler) { 22718 res = esc->callbacks->initial_handler(p, req, esc, esc_entry); 22719 } 22720 22721 if (!res) { 22722 transmit_response_with_sip_etag(p, "200 OK", req, esc_entry, 0); 22723 } 22724 22725 ao2_ref(esc_entry, -1); 22726 return res; 22727 }
| 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 22757 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().
22758 { 22759 struct sip_esc_entry *esc_entry = get_esc_entry(etag, esc); 22760 int expires_ms = expires * 1000; 22761 int res = 0; 22762 22763 if (!esc_entry) { 22764 transmit_response(p, "412 Conditional Request Failed", req); 22765 return -1; 22766 } 22767 22768 AST_SCHED_REPLACE_UNREF(esc_entry->sched_id, sched, expires_ms, publish_expire, esc_entry, 22769 ao2_ref(_data, -1), 22770 ao2_ref(esc_entry, -1), 22771 ao2_ref(esc_entry, +1)); 22772 22773 if (esc->callbacks->modify_handler) { 22774 res = esc->callbacks->modify_handler(p, req, esc, esc_entry); 22775 } 22776 22777 if (!res) { 22778 transmit_response_with_sip_etag(p, "200 OK", req, esc_entry, 1); 22779 } 22780 22781 ao2_ref(esc_entry, -1); 22782 return res; 22783 }
| 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 22729 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().
22730 { 22731 struct sip_esc_entry *esc_entry = get_esc_entry(etag, esc); 22732 int expires_ms = expires * 1000; 22733 int res = 0; 22734 22735 if (!esc_entry) { 22736 transmit_response(p, "412 Conditional Request Failed", req); 22737 return -1; 22738 } 22739 22740 AST_SCHED_REPLACE_UNREF(esc_entry->sched_id, sched, expires_ms, publish_expire, esc_entry, 22741 ao2_ref(_data, -1), 22742 ao2_ref(esc_entry, -1), 22743 ao2_ref(esc_entry, +1)); 22744 22745 if (esc->callbacks->refresh_handler) { 22746 res = esc->callbacks->refresh_handler(p, req, esc, esc_entry); 22747 } 22748 22749 if (!res) { 22750 transmit_response_with_sip_etag(p, "200 OK", req, esc_entry, 1); 22751 } 22752 22753 ao2_ref(esc_entry, -1); 22754 return res; 22755 }
| 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 22785 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().
22786 { 22787 struct sip_esc_entry *esc_entry = get_esc_entry(etag, esc); 22788 int res = 0; 22789 22790 if (!esc_entry) { 22791 transmit_response(p, "412 Conditional Request Failed", req); 22792 return -1; 22793 } 22794 22795 AST_SCHED_DEL(sched, esc_entry->sched_id); 22796 /* Scheduler's ref of the esc_entry */ 22797 ao2_ref(esc_entry, -1); 22798 22799 if (esc->callbacks->remove_handler) { 22800 res = esc->callbacks->remove_handler(p, req, esc, esc_entry); 22801 } 22802 22803 if (!res) { 22804 transmit_response_with_sip_etag(p, "200 OK", req, esc_entry, 1); 22805 } 22806 22807 /* Ref from finding the esc_entry earlier in function */ 22808 ao2_unlink(esc->compositor, esc_entry); 22809 ao2_ref(esc_entry, -1); 22810 return res; 22811 }
| 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 25091 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().
25093 { 25094 int res = 1; 25095 25096 if (!strcasecmp(v->name, "t38pt_udptl")) { 25097 char *buf = ast_strdupa(v->value); 25098 char *word, *next = buf; 25099 25100 ast_set_flag(&mask[1], SIP_PAGE2_T38SUPPORT); 25101 25102 while ((word = strsep(&next, ","))) { 25103 if (ast_true(word) || !strcasecmp(word, "fec")) { 25104 ast_clear_flag(&flags[1], SIP_PAGE2_T38SUPPORT); 25105 ast_set_flag(&flags[1], SIP_PAGE2_T38SUPPORT_UDPTL_FEC); 25106 } else if (!strcasecmp(word, "redundancy")) { 25107 ast_clear_flag(&flags[1], SIP_PAGE2_T38SUPPORT); 25108 ast_set_flag(&flags[1], SIP_PAGE2_T38SUPPORT_UDPTL_REDUNDANCY); 25109 } else if (!strcasecmp(word, "none")) { 25110 ast_clear_flag(&flags[1], SIP_PAGE2_T38SUPPORT); 25111 ast_set_flag(&flags[1], SIP_PAGE2_T38SUPPORT_UDPTL); 25112 } else if (!strncasecmp(word, "maxdatagram=", 12)) { 25113 if (sscanf(&word[12], "%30u", maxdatagram) != 1) { 25114 ast_log(LOG_WARNING, "Invalid maxdatagram '%s' at line %d of %s\n", v->value, v->lineno, config); 25115 *maxdatagram = global_t38_maxdatagram; 25116 } 25117 } 25118 } 25119 } else if (!strcasecmp(v->name, "t38pt_usertpsource")) { 25120 ast_set_flag(&mask[1], SIP_PAGE2_UDPTL_DESTINATION); 25121 ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_UDPTL_DESTINATION); 25122 } else { 25123 res = 0; 25124 } 25125 25126 return res; 25127 }
| 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 5692 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_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().
05693 { 05694 switch (cause) { 05695 case AST_CAUSE_UNALLOCATED: /* 1 */ 05696 case AST_CAUSE_NO_ROUTE_DESTINATION: /* 3 IAX2: Can't find extension in context */ 05697 case AST_CAUSE_NO_ROUTE_TRANSIT_NET: /* 2 */ 05698 return "404 Not Found"; 05699 case AST_CAUSE_CONGESTION: /* 34 */ 05700 case AST_CAUSE_SWITCH_CONGESTION: /* 42 */ 05701 return "503 Service Unavailable"; 05702 case AST_CAUSE_NO_USER_RESPONSE: /* 18 */ 05703 return "408 Request Timeout"; 05704 case AST_CAUSE_NO_ANSWER: /* 19 */ 05705 case AST_CAUSE_UNREGISTERED: /* 20 */ 05706 return "480 Temporarily unavailable"; 05707 case AST_CAUSE_CALL_REJECTED: /* 21 */ 05708 return "403 Forbidden"; 05709 case AST_CAUSE_NUMBER_CHANGED: /* 22 */ 05710 return "410 Gone"; 05711 case AST_CAUSE_NORMAL_UNSPECIFIED: /* 31 */ 05712 return "480 Temporarily unavailable"; 05713 case AST_CAUSE_INVALID_NUMBER_FORMAT: 05714 return "484 Address incomplete"; 05715 case AST_CAUSE_USER_BUSY: 05716 return "486 Busy here"; 05717 case AST_CAUSE_FAILURE: 05718 return "500 Server internal failure"; 05719 case AST_CAUSE_FACILITY_REJECTED: /* 29 */ 05720 return "501 Not Implemented"; 05721 case AST_CAUSE_CHAN_NOT_IMPLEMENTED: 05722 return "503 Service Unavailable"; 05723 /* Used in chan_iax2 */ 05724 case AST_CAUSE_DESTINATION_OUT_OF_ORDER: 05725 return "502 Bad Gateway"; 05726 case AST_CAUSE_BEARERCAPABILITY_NOTAVAIL: /* Can't find codec to connect to host */ 05727 return "488 Not Acceptable Here"; 05728 05729 case AST_CAUSE_NOTDEFINED: 05730 default: 05731 ast_debug(1, "AST hangup cause %d (no match found in SIP)\n", cause); 05732 return NULL; 05733 } 05734 05735 /* Never reached */ 05736 return 0; 05737 }
| int hangup_sip2cause | ( | int | cause | ) |
Convert SIP hangup causes to Asterisk hangup causes.
Definition at line 5570 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().
05571 { 05572 /* Possible values taken from causes.h */ 05573 05574 switch(cause) { 05575 case 401: /* Unauthorized */ 05576 return AST_CAUSE_CALL_REJECTED; 05577 case 403: /* Not found */ 05578 return AST_CAUSE_CALL_REJECTED; 05579 case 404: /* Not found */ 05580 return AST_CAUSE_UNALLOCATED; 05581 case 405: /* Method not allowed */ 05582 return AST_CAUSE_INTERWORKING; 05583 case 407: /* Proxy authentication required */ 05584 return AST_CAUSE_CALL_REJECTED; 05585 case 408: /* No reaction */ 05586 return AST_CAUSE_NO_USER_RESPONSE; 05587 case 409: /* Conflict */ 05588 return AST_CAUSE_NORMAL_TEMPORARY_FAILURE; 05589 case 410: /* Gone */ 05590 return AST_CAUSE_NUMBER_CHANGED; 05591 case 411: /* Length required */ 05592 return AST_CAUSE_INTERWORKING; 05593 case 413: /* Request entity too large */ 05594 return AST_CAUSE_INTERWORKING; 05595 case 414: /* Request URI too large */ 05596 return AST_CAUSE_INTERWORKING; 05597 case 415: /* Unsupported media type */ 05598 return AST_CAUSE_INTERWORKING; 05599 case 420: /* Bad extension */ 05600 return AST_CAUSE_NO_ROUTE_DESTINATION; 05601 case 480: /* No answer */ 05602 return AST_CAUSE_NO_ANSWER; 05603 case 481: /* No answer */ 05604 return AST_CAUSE_INTERWORKING; 05605 case 482: /* Loop detected */ 05606 return AST_CAUSE_INTERWORKING; 05607 case 483: /* Too many hops */ 05608 return AST_CAUSE_NO_ANSWER; 05609 case 484: /* Address incomplete */ 05610 return AST_CAUSE_INVALID_NUMBER_FORMAT; 05611 case 485: /* Ambiguous */ 05612 return AST_CAUSE_UNALLOCATED; 05613 case 486: /* Busy everywhere */ 05614 return AST_CAUSE_BUSY; 05615 case 487: /* Request terminated */ 05616 return AST_CAUSE_INTERWORKING; 05617 case 488: /* No codecs approved */ 05618 return AST_CAUSE_BEARERCAPABILITY_NOTAVAIL; 05619 case 491: /* Request pending */ 05620 return AST_CAUSE_INTERWORKING; 05621 case 493: /* Undecipherable */ 05622 return AST_CAUSE_INTERWORKING; 05623 case 500: /* Server internal failure */ 05624 return AST_CAUSE_FAILURE; 05625 case 501: /* Call rejected */ 05626 return AST_CAUSE_FACILITY_REJECTED; 05627 case 502: 05628 return AST_CAUSE_DESTINATION_OUT_OF_ORDER; 05629 case 503: /* Service unavailable */ 05630 return AST_CAUSE_CONGESTION; 05631 case 504: /* Gateway timeout */ 05632 return AST_CAUSE_RECOVERY_ON_TIMER_EXPIRE; 05633 case 505: /* SIP version not supported */ 05634 return AST_CAUSE_INTERWORKING; 05635 case 600: /* Busy everywhere */ 05636 return AST_CAUSE_USER_BUSY; 05637 case 603: /* Decline */ 05638 return AST_CAUSE_CALL_REJECTED; 05639 case 604: /* Does not exist anywhere */ 05640 return AST_CAUSE_UNALLOCATED; 05641 case 606: /* Not acceptable */ 05642 return AST_CAUSE_BEARERCAPABILITY_NOTAVAIL; 05643 default: 05644 if (cause < 500 && cause >= 400) { 05645 /* 4xx class error that is unknown - someting wrong with our request */ 05646 return AST_CAUSE_INTERWORKING; 05647 } else if (cause < 600 && cause >= 500) { 05648 /* 5xx class error - problem in the remote end */ 05649 return AST_CAUSE_CONGESTION; 05650 } else if (cause < 700 && cause >= 600) { 05651 /* 6xx - global errors in the 4xx class */ 05652 return AST_CAUSE_INTERWORKING; 05653 } 05654 return AST_CAUSE_NORMAL; 05655 } 05656 /* Never reached */ 05657 return 0; 05658 }
| static int init_req | ( | struct sip_request * | req, | |
| int | sipmethod, | |||
| const char * | recip | |||
| ) | [static] |
Initialize SIP request.
Definition at line 9347 of file chan_sip.c.
References ast_free, ast_str_create(), ast_str_set(), ast_str_strlen(), sip_methods, and cfsip_methods::text.
09348 { 09349 /* Initialize a request */ 09350 memset(req, 0, sizeof(*req)); 09351 if (!(req->data = ast_str_create(SIP_MIN_PACKET))) 09352 goto e_return; 09353 if (!(req->content = ast_str_create(SIP_MIN_PACKET))) 09354 goto e_free_data; 09355 req->method = sipmethod; 09356 req->header[0] = 0; 09357 ast_str_set(&req->data, 0, "%s %s SIP/2.0\r\n", sip_methods[sipmethod].text, recip); 09358 req->len = ast_str_strlen(req->data); 09359 req->headers++; 09360 return 0; 09361 09362 e_free_data: 09363 ast_free(req->data); 09364 req->data = NULL; 09365 e_return: 09366 return -1; 09367 }
| static int init_resp | ( | struct sip_request * | resp, | |
| const char * | msg | |||
| ) | [static] |
Initialize SIP response, based on SIP request.
Definition at line 9324 of file chan_sip.c.
References ast_free, ast_str_create(), and ast_str_set().
09325 { 09326 /* Initialize a response */ 09327 memset(resp, 0, sizeof(*resp)); 09328 resp->method = SIP_RESPONSE; 09329 if (!(resp->data = ast_str_create(SIP_MIN_PACKET))) 09330 goto e_return; 09331 if (!(resp->content = ast_str_create(SIP_MIN_PACKET))) 09332 goto e_free_data; 09333 resp->header[0] = 0; 09334 ast_str_set(&resp->data, 0, "SIP/2.0 %s\r\n", msg); 09335 resp->len = resp->data->used; 09336 resp->headers++; 09337 return 0; 09338 09339 e_free_data: 09340 ast_free(resp->data); 09341 resp->data = NULL; 09342 e_return: 09343 return -1; 09344 }
| static int initialize_escs | ( | void | ) | [static] |
Definition at line 1048 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().
01049 { 01050 int i, res = 0; 01051 for (i = 0; i < ARRAY_LEN(event_state_compositors); i++) { 01052 if (!((event_state_compositors[i].compositor) = 01053 ao2_container_alloc(ESC_MAX_BUCKETS, esc_hash_fn, esc_cmp_fn))) { 01054 res = -1; 01055 } 01056 } 01057 return res; 01058 }
| 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 2815 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_notify_with_mwi(), transmit_notify_with_sipfrag(), transmit_register(), transmit_reinvite_with_sdp(), and update_connectedline().
02816 { 02817 if (p->initreq.headers) { 02818 ast_debug(1, "Initializing already initialized SIP dialog %s (presumably reinvite)\n", p->callid); 02819 } else { 02820 ast_debug(1, "Initializing initreq for method %s - callid %s\n", sip_methods[req->method].text, p->callid); 02821 } 02822 /* Use this as the basis */ 02823 copy_request(&p->initreq, req); 02824 parse_request(&p->initreq); 02825 if (req->debug) { 02826 ast_verbose("Initreq: %d headers, %d lines\n", p->initreq.headers, p->initreq.lines); 02827 } 02828 }
| 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 11026 of file chan_sip.c.
References add_header(), add_header_max_forwards(), add_route(), AST_DIGIT_ANYNUM, ast_party_id_presentation(), AST_PRES_ALLOWED, AST_PRES_RESTRICTION, ast_sockaddr_port, ast_sockaddr_stringify_host(), ast_str_alloca, ast_str_append(), ast_str_set(), ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_uri_encode(), build_contact(), exten, init_req(), ourport, S_OR, sip_cfg, sip_methods, sip_standard_port(), and cfsip_methods::text.
Referenced by transmit_invite(), and transmit_notify_with_mwi().
11027 { 11028 struct ast_str *invite = ast_str_alloca(256); 11029 char from[256]; 11030 char to[256]; 11031 char tmp_n[SIPBUFSIZE/2]; /* build a local copy of 'n' if needed */ 11032 char tmp_l[SIPBUFSIZE/2]; /* build a local copy of 'l' if needed */ 11033 const char *l = NULL; /* XXX what is this, exactly ? */ 11034 const char *n = NULL; /* XXX what is this, exactly ? */ 11035 const char *d = NULL; /* domain in from header */ 11036 const char *urioptions = ""; 11037 int ourport; 11038 11039 if (ast_test_flag(&p->flags[0], SIP_USEREQPHONE)) { 11040 const char *s = p->username; /* being a string field, cannot be NULL */ 11041 11042 /* Test p->username against allowed characters in AST_DIGIT_ANY 11043 If it matches the allowed characters list, then sipuser = ";user=phone" 11044 If not, then sipuser = "" 11045 */ 11046 /* + is allowed in first position in a tel: uri */ 11047 if (*s == '+') 11048 s++; 11049 for (; *s; s++) { 11050 if (!strchr(AST_DIGIT_ANYNUM, *s) ) 11051 break; 11052 } 11053 /* If we have only digits, add ;user=phone to the uri */ 11054 if (!*s) 11055 urioptions = ";user=phone"; 11056 } 11057 11058 11059 snprintf(p->lastmsg, sizeof(p->lastmsg), "Init: %s", sip_methods[sipmethod].text); 11060 11061 d = S_OR(p->fromdomain, ast_sockaddr_stringify_host(&p->ourip)); 11062 if (p->owner) { 11063 if ((ast_party_id_presentation(&p->owner->connected.id) & AST_PRES_RESTRICTION) == AST_PRES_ALLOWED) { 11064 l = p->owner->connected.id.number.valid ? p->owner->connected.id.number.str : NULL; 11065 n = p->owner->connected.id.name.valid ? p->owner->connected.id.name.str : NULL; 11066 } else if (!ast_test_flag(&p->flags[0], SIP_SENDRPID)) { 11067 /* if we are not sending RPID and user wants his callerid restricted */ 11068 l = CALLERID_UNKNOWN; 11069 n = l; 11070 d = FROMDOMAIN_INVALID; 11071 } 11072 } 11073 11074 /* Hey, it's a NOTIFY! See if they've configured a mwi_from. 11075 * XXX Right now, this logic works because the only place that mwi_from 11076 * is set on the sip_pvt is in sip_send_mwi_to_peer. If things changed, then 11077 * we might end up putting the mwi_from setting into other types of NOTIFY 11078 * messages as well. 11079 */ 11080 if (sipmethod == SIP_NOTIFY && !ast_strlen_zero(p->mwi_from)) { 11081 l = p->mwi_from; 11082 } 11083 11084 if (ast_strlen_zero(l)) 11085 l = default_callerid; 11086 if (ast_strlen_zero(n)) 11087 n = l; 11088 /* Allow user to be overridden */ 11089 if (!ast_strlen_zero(p->fromuser)) 11090 l = p->fromuser; 11091 else /* Save for any further attempts */ 11092 ast_string_field_set(p, fromuser, l); 11093 11094 /* Allow user to be overridden */ 11095 if (!ast_strlen_zero(p->fromname)) 11096 n = p->fromname; 11097 else /* Save for any further attempts */ 11098 ast_string_field_set(p, fromname, n); 11099 11100 if (sip_cfg.pedanticsipchecking) { 11101 ast_uri_encode(n, tmp_n, sizeof(tmp_n), 0); 11102 n = tmp_n; 11103 ast_uri_encode(l, tmp_l, sizeof(tmp_l), 0); 11104 l = tmp_l; 11105 } 11106 11107 ourport = (p->fromdomainport) ? p->fromdomainport : ast_sockaddr_port(&p->ourip); 11108 if (!sip_standard_port(p->socket.type, ourport)) { 11109 snprintf(from, sizeof(from), "\"%s\" <sip:%s@%s:%d>;tag=%s", n, l, d, ourport, p->tag); 11110 } else { 11111 snprintf(from, sizeof(from), "\"%s\" <sip:%s@%s>;tag=%s", n, l, d, p->tag); 11112 } 11113 11114 if (!ast_strlen_zero(explicit_uri)) { 11115 ast_str_set(&invite, 0, "%s", explicit_uri); 11116 } else { 11117 /* If we're calling a registered SIP peer, use the fullcontact to dial to the peer */ 11118 if (!ast_strlen_zero(p->fullcontact)) { 11119 /* If we have full contact, trust it */ 11120 ast_str_append(&invite, 0, "%s", p->fullcontact); 11121 } else { 11122 /* Otherwise, use the username while waiting for registration */ 11123 ast_str_append(&invite, 0, "sip:"); 11124 if (!ast_strlen_zero(p->username)) { 11125 n = p->username; 11126 if (sip_cfg.pedanticsipchecking) { 11127 ast_uri_encode(n, tmp_n, sizeof(tmp_n), 0); 11128 n = tmp_n; 11129 } 11130 ast_str_append(&invite, 0, "%s@", n); 11131 } 11132 ast_str_append(&invite, 0, "%s", p->tohost); 11133 if (p->portinuri) { 11134 ast_str_append(&invite, 0, ":%d", ast_sockaddr_port(&p->sa)); 11135 } 11136 ast_str_append(&invite, 0, "%s", urioptions); 11137 } 11138 } 11139 11140 /* If custom URI options have been provided, append them */ 11141 if (p->options && !ast_strlen_zero(p->options->uri_options)) 11142 ast_str_append(&invite, 0, ";%s", p->options->uri_options); 11143 11144 /* This is the request URI, which is the next hop of the call 11145 which may or may not be the destination of the call 11146 */ 11147 ast_string_field_set(p, uri, invite->str); 11148 11149 if (!ast_strlen_zero(p->todnid)) { 11150 /*! \todo Need to add back the VXML URL here at some point, possibly use build_string for all this junk */ 11151 if (!strchr(p->todnid, '@')) { 11152 /* We have no domain in the dnid */ 11153 snprintf(to, sizeof(to), "<sip:%s@%s>%s%s", p->todnid, p->tohost, ast_strlen_zero(p->theirtag) ? "" : ";tag=", p->theirtag); 11154 } else { 11155 snprintf(to, sizeof(to), "<sip:%s>%s%s", p->todnid, ast_strlen_zero(p->theirtag) ? "" : ";tag=", p->theirtag); 11156 } 11157 } else { 11158 if (sipmethod == SIP_NOTIFY && !ast_strlen_zero(p->theirtag)) { 11159 /* If this is a NOTIFY, use the From: tag in the subscribe (RFC 3265) */ 11160 snprintf(to, sizeof(to), "<%s%s>;tag=%s", (strncasecmp(p->uri, "sip:", 4) ? "sip:" : ""), p->uri, p->theirtag); 11161 } else if (p->options && p->options->vxml_url) { 11162 /* If there is a VXML URL append it to the SIP URL */ 11163 snprintf(to, sizeof(to), "<%s>;%s", p->uri, p->options->vxml_url); 11164 } else { 11165 snprintf(to, sizeof(to), "<%s>", p->uri); 11166 } 11167 } 11168 11169 init_req(req, sipmethod, p->uri); 11170 /* now tmp_n is available so reuse it to build the CSeq */ 11171 snprintf(tmp_n, sizeof(tmp_n), "%d %s", ++p->ocseq, sip_methods[sipmethod].text); 11172 11173 add_header(req, "Via", p->via); 11174 add_header_max_forwards(p, req); 11175 /* This will be a no-op most of the time. However, under certain circumstances, 11176 * NOTIFY messages will use this function for preparing the request and should 11177 * have Route headers present. 11178 */ 11179 add_route(req, p->route); 11180 11181 add_header(req, "From", from); 11182 add_header(req, "To", to); 11183 ast_string_field_set(p, exten, l); 11184 build_contact(p); 11185 add_header(req, "Contact", p->our_contact); 11186 add_header(req, "Call-ID", p->callid); 11187 add_header(req, "CSeq", tmp_n); 11188 if (!ast_strlen_zero(global_useragent)) { 11189 add_header(req, "User-Agent", global_useragent); 11190 } 11191 }
| static const char * insecure2str | ( | int | mode | ) | [static] |
Convert Insecure setting to printable string.
Definition at line 15775 of file chan_sip.c.
References map_x_s().
Referenced by _sip_show_peer().
15776 { 15777 return map_x_s(insecurestr, mode, "<error>"); 15778 }
| 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 6222 of file chan_sip.c.
References AST_CONTROL_T38_PARAMETERS, ast_queue_control_data(), AST_SCHED_DEL, 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().
06223 { 06224 int res = 0; 06225 06226 if (!ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT) || !p->udptl) { 06227 return -1; 06228 } 06229 switch (parameters->request_response) { 06230 case AST_T38_NEGOTIATED: 06231 case AST_T38_REQUEST_NEGOTIATE: /* Request T38 */ 06232 /* Negotiation can not take place without a valid max_ifp value. */ 06233 if (!parameters->max_ifp) { 06234 change_t38_state(p, T38_DISABLED); 06235 if (p->t38.state == T38_PEER_REINVITE) { 06236 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")); 06237 transmit_response_reliable(p, "488 Not acceptable here", &p->initreq); 06238 } 06239 break; 06240 } else if (p->t38.state == T38_PEER_REINVITE) { 06241 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")); 06242 p->t38.our_parms = *parameters; 06243 /* modify our parameters to conform to the peer's parameters, 06244 * based on the rules in the ITU T.38 recommendation 06245 */ 06246 if (!p->t38.their_parms.fill_bit_removal) { 06247 p->t38.our_parms.fill_bit_removal = FALSE; 06248 } 06249 if (!p->t38.their_parms.transcoding_mmr) { 06250 p->t38.our_parms.transcoding_mmr = FALSE; 06251 } 06252 if (!p->t38.their_parms.transcoding_jbig) { 06253 p->t38.our_parms.transcoding_jbig = FALSE; 06254 } 06255 p->t38.our_parms.version = MIN(p->t38.our_parms.version, p->t38.their_parms.version); 06256 p->t38.our_parms.rate_management = p->t38.their_parms.rate_management; 06257 ast_udptl_set_local_max_ifp(p->udptl, p->t38.our_parms.max_ifp); 06258 change_t38_state(p, T38_ENABLED); 06259 transmit_response_with_t38_sdp(p, "200 OK", &p->initreq, XMIT_CRITICAL); 06260 } else if (p->t38.state != T38_ENABLED) { 06261 p->t38.our_parms = *parameters; 06262 ast_udptl_set_local_max_ifp(p->udptl, p->t38.our_parms.max_ifp); 06263 change_t38_state(p, T38_LOCAL_REINVITE); 06264 if (!p->pendinginvite) { 06265 transmit_reinvite_with_sdp(p, TRUE, FALSE); 06266 } else if (!ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) { 06267 ast_set_flag(&p->flags[0], SIP_NEEDREINVITE); 06268 } 06269 } 06270 break; 06271 case AST_T38_TERMINATED: 06272 case AST_T38_REFUSED: 06273 case AST_T38_REQUEST_TERMINATE: /* Shutdown T38 */ 06274 if (p->t38.state == T38_PEER_REINVITE) { 06275 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")); 06276 change_t38_state(p, T38_DISABLED); 06277 transmit_response_reliable(p, "488 Not acceptable here", &p->initreq); 06278 } else if (p->t38.state == T38_ENABLED) 06279 transmit_reinvite_with_sdp(p, FALSE, FALSE); 06280 break; 06281 case AST_T38_REQUEST_PARMS: { /* Application wants remote's parameters re-sent */ 06282 struct ast_control_t38_parameters parameters = p->t38.their_parms; 06283 06284 if (p->t38.state == T38_PEER_REINVITE) { 06285 AST_SCHED_DEL(sched, p->t38id); 06286 parameters.max_ifp = ast_udptl_get_far_max_ifp(p->udptl); 06287 parameters.request_response = AST_T38_REQUEST_NEGOTIATE; 06288 ast_queue_control_data(p->owner, AST_CONTROL_T38_PARAMETERS, ¶meters, sizeof(parameters)); 06289 /* we need to return a positive value here, so that applications that 06290 * send this request can determine conclusively whether it was accepted or not... 06291 * older versions of chan_sip would just silently accept it and return zero. 06292 */ 06293 res = AST_T38_REQUEST_PARMS; 06294 } 06295 break; 06296 } 06297 default: 06298 res = -1; 06299 break; 06300 } 06301 06302 return res; 06303 }
| 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 7604 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 13112 of file chan_sip.c.
References ast_verbose.
Referenced by build_route().
13113 { 13114 if (!route) { 13115 ast_verbose("list_route: no route\n"); 13116 } else { 13117 for (;route; route = route->next) 13118 ast_verbose("list_route: hop: <%s>\n", route->hop); 13119 } 13120 }
| static int load_module | ( | void | ) | [static] |
PBX load module - initialization.
Definition at line 28364 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_log(), ast_manager_register_xml, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, ast_realtime_require_field(), ast_register_application_xml, ast_rtp_glue_register, AST_TEST_REGISTER, ast_udptl_proto_register(), ast_verbose, ASTOBJ_CONTAINER_INIT, 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, sched_context_create(), sched_context_destroy(), ast_channel_tech::send_digit_begin, SENTINEL, sip_addheader(), 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_send_all_mwi_subscriptions(), sip_send_all_registers(), sip_tech_info, submwil, threadt_cmp_cb(), and threadt_hash_cb().
28365 { 28366 ast_verbose("SIP channel loading...\n"); 28367 /* the fact that ao2_containers can't resize automatically is a major worry! */ 28368 /* if the number of objects gets above MAX_XXX_BUCKETS, things will slow down */ 28369 peers = ao2_t_container_alloc(HASH_PEER_SIZE, peer_hash_cb, peer_cmp_cb, "allocate peers"); 28370 peers_by_ip = ao2_t_container_alloc(HASH_PEER_SIZE, peer_iphash_cb, peer_ipcmp_cb, "allocate peers_by_ip"); 28371 dialogs = ao2_t_container_alloc(HASH_DIALOG_SIZE, dialog_hash_cb, dialog_cmp_cb, "allocate dialogs"); 28372 threadt = ao2_t_container_alloc(HASH_DIALOG_SIZE, threadt_hash_cb, threadt_cmp_cb, "allocate threadt table"); 28373 28374 ASTOBJ_CONTAINER_INIT(®l); /* Registry object list -- not searched for anything */ 28375 ASTOBJ_CONTAINER_INIT(&submwil); /* MWI subscription object list */ 28376 28377 if (!(sched = sched_context_create())) { 28378 ast_log(LOG_ERROR, "Unable to create scheduler context\n"); 28379 return AST_MODULE_LOAD_FAILURE; 28380 } 28381 28382 if (!(io = io_context_create())) { 28383 ast_log(LOG_ERROR, "Unable to create I/O context\n"); 28384 sched_context_destroy(sched); 28385 return AST_MODULE_LOAD_FAILURE; 28386 } 28387 28388 sip_reloadreason = CHANNEL_MODULE_LOAD; 28389 28390 can_parse_xml = sip_is_xml_parsable(); 28391 if(reload_config(sip_reloadreason)) { /* Load the configuration from sip.conf */ 28392 return AST_MODULE_LOAD_DECLINE; 28393 } 28394 28395 /* Prepare the version that does not require DTMF BEGIN frames. 28396 * We need to use tricks such as memcpy and casts because the variable 28397 * has const fields. 28398 */ 28399 memcpy(&sip_tech_info, &sip_tech, sizeof(sip_tech)); 28400 memset((void *) &sip_tech_info.send_digit_begin, 0, sizeof(sip_tech_info.send_digit_begin)); 28401 28402 /* Make sure we can register our sip channel type */ 28403 if (ast_channel_register(&sip_tech)) { 28404 ast_log(LOG_ERROR, "Unable to register channel type 'SIP'\n"); 28405 io_context_destroy(io); 28406 sched_context_destroy(sched); 28407 return AST_MODULE_LOAD_FAILURE; 28408 } 28409 28410 #ifdef TEST_FRAMEWORK 28411 AST_TEST_REGISTER(test_sip_peers_get); 28412 #endif 28413 28414 /* Register AstData providers */ 28415 ast_data_register_multiple(sip_data_providers, ARRAY_LEN(sip_data_providers)); 28416 28417 /* Register all CLI functions for SIP */ 28418 ast_cli_register_multiple(cli_sip, ARRAY_LEN(cli_sip)); 28419 28420 /* Tell the UDPTL subdriver that we're here */ 28421 ast_udptl_proto_register(&sip_udptl); 28422 28423 /* Tell the RTP engine about our RTP glue */ 28424 ast_rtp_glue_register(&sip_rtp_glue); 28425 28426 /* Register dialplan applications */ 28427 ast_register_application_xml(app_dtmfmode, sip_dtmfmode); 28428 ast_register_application_xml(app_sipaddheader, sip_addheader); 28429 ast_register_application_xml(app_sipremoveheader, sip_removeheader); 28430 28431 /* Register dialplan functions */ 28432 ast_custom_function_register(&sip_header_function); 28433 ast_custom_function_register(&sippeer_function); 28434 ast_custom_function_register(&sipchaninfo_function); 28435 ast_custom_function_register(&checksipdomain_function); 28436 28437 /* Register manager commands */ 28438 ast_manager_register_xml("SIPpeers", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_sip_show_peers); 28439 ast_manager_register_xml("SIPshowpeer", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_sip_show_peer); 28440 ast_manager_register_xml("SIPqualifypeer", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_sip_qualify_peer); 28441 ast_manager_register_xml("SIPshowregistry", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_show_registry); 28442 ast_manager_register_xml("SIPnotify", EVENT_FLAG_SYSTEM, manager_sipnotify); 28443 sip_poke_all_peers(); 28444 sip_send_all_registers(); 28445 sip_send_all_mwi_subscriptions(); 28446 initialize_escs(); 28447 28448 if (sip_epa_register(&cc_epa_static_data)) { 28449 return AST_MODULE_LOAD_DECLINE; 28450 } 28451 28452 if (sip_reqresp_parser_init() == -1) { 28453 ast_log(LOG_ERROR, "Unable to initialize the SIP request and response parser\n"); 28454 return AST_MODULE_LOAD_DECLINE; 28455 } 28456 28457 if (can_parse_xml) { 28458 /* SIP CC agents require the ability to parse XML PIDF bodies 28459 * in incoming PUBLISH requests 28460 */ 28461 if (ast_cc_agent_register(&sip_cc_agent_callbacks)) { 28462 return AST_MODULE_LOAD_DECLINE; 28463 } 28464 } 28465 if (ast_cc_monitor_register(&sip_cc_monitor_callbacks)) { 28466 return AST_MODULE_LOAD_DECLINE; 28467 } 28468 if (!(sip_monitor_instances = ao2_container_alloc(37, sip_monitor_instance_hash_fn, sip_monitor_instance_cmp_fn))) { 28469 return AST_MODULE_LOAD_DECLINE; 28470 } 28471 28472 /* And start the monitor for the first time */ 28473 restart_monitor(); 28474 28475 ast_realtime_require_field(ast_check_realtime("sipregs") ? "sipregs" : "sippeers", 28476 "name", RQ_CHAR, 10, 28477 "ipaddr", RQ_CHAR, 15, 28478 "port", RQ_UINTEGER2, 5, 28479 "regseconds", RQ_INTEGER4, 11, 28480 "defaultuser", RQ_CHAR, 10, 28481 "fullcontact", RQ_CHAR, 35, 28482 "regserver", RQ_CHAR, 20, 28483 "useragent", RQ_CHAR, 20, 28484 "lastms", RQ_INTEGER4, 11, 28485 SENTINEL); 28486 28487 28488 sip_register_tests(); 28489 network_change_event_subscribe(); 28490 28491 return AST_MODULE_LOAD_SUCCESS; 28492 }
| static int local_attended_transfer | ( | struct sip_pvt * | transferer, | |
| struct sip_dual * | current, | |||
| struct sip_request * | req, | |||
| int | seqno, | |||
| int * | nounlock | |||
| ) | [static] |
Find all call legs and bridge transferee with target called from handle_request_refer.
Definition at line 21640 of file chan_sip.c.
References ao2_t_ref, append_history, ast_bridged_channel(), AST_CEL_ATTENDEDTRANSFER, ast_cel_report_event(), ast_channel_queue_connected_line_update(), ast_channel_ref, 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_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(), ast_channel::name, pbx_builtin_getvar_helper(), sip_pvt_lock, sip_pvt_unlock, ast_party_connected_line::source, transmit_notify_with_sipfrag(), transmit_response(), TRUE, and xfersound.
Referenced by handle_request_refer().
21641 { 21642 struct sip_dual target; /* Chan 1: Call from tranferer to Asterisk */ 21643 /* Chan 2: Call from Asterisk to target */ 21644 int res = 0; 21645 struct sip_pvt *targetcall_pvt; 21646 struct ast_party_connected_line connected_to_transferee; 21647 struct ast_party_connected_line connected_to_target; 21648 char transferer_linkedid[32]; 21649 struct ast_channel *chans[2]; 21650 21651 /* Check if the call ID of the replaces header does exist locally */ 21652 if (!(targetcall_pvt = get_sip_pvt_byid_locked(transferer->refer->replaces_callid, transferer->refer->replaces_callid_totag, 21653 transferer->refer->replaces_callid_fromtag))) { 21654 if (transferer->refer->localtransfer) { 21655 /* We did not find the refered call. Sorry, can't accept then */ 21656 transmit_response(transferer, "202 Accepted", req); 21657 /* Let's fake a response from someone else in order 21658 to follow the standard */ 21659 transmit_notify_with_sipfrag(transferer, seqno, "481 Call leg/transaction does not exist", TRUE); 21660 append_history(transferer, "Xfer", "Refer failed"); 21661 ast_clear_flag(&transferer->flags[0], SIP_GOTREFER); 21662 transferer->refer->status = REFER_FAILED; 21663 return -1; 21664 } 21665 /* Fall through for remote transfers that we did not find locally */ 21666 ast_debug(3, "SIP attended transfer: Not our call - generating INVITE with replaces\n"); 21667 return 0; 21668 } 21669 21670 /* Ok, we can accept this transfer */ 21671 transmit_response(transferer, "202 Accepted", req); 21672 append_history(transferer, "Xfer", "Refer accepted"); 21673 if (!targetcall_pvt->owner) { /* No active channel */ 21674 ast_debug(4, "SIP attended transfer: Error: No owner of target call\n"); 21675 /* Cancel transfer */ 21676 transmit_notify_with_sipfrag(transferer, seqno, "503 Service Unavailable", TRUE); 21677 append_history(transferer, "Xfer", "Refer failed"); 21678 ast_clear_flag(&transferer->flags[0], SIP_GOTREFER); 21679 transferer->refer->status = REFER_FAILED; 21680 sip_pvt_unlock(targetcall_pvt); 21681 if (targetcall_pvt) 21682 ao2_t_ref(targetcall_pvt, -1, "Drop targetcall_pvt pointer"); 21683 return -1; 21684 } 21685 21686 /* We have a channel, find the bridge */ 21687 target.chan1 = targetcall_pvt->owner; /* Transferer to Asterisk */ 21688 target.chan2 = ast_bridged_channel(targetcall_pvt->owner); /* Asterisk to target */ 21689 21690 if (!target.chan2 || !(target.chan2->_state == AST_STATE_UP || target.chan2->_state == AST_STATE_RINGING) ) { 21691 /* Wrong state of new channel */ 21692 if (target.chan2) 21693 ast_debug(4, "SIP attended transfer: Error: Wrong state of target call: %s\n", ast_state2str(target.chan2->_state)); 21694 else if (target.chan1->_state != AST_STATE_RING) 21695 ast_debug(4, "SIP attended transfer: Error: No target channel\n"); 21696 else 21697 ast_debug(4, "SIP attended transfer: Attempting transfer in ringing state\n"); 21698 } 21699 21700 /* Transfer */ 21701 if (sipdebug) { 21702 if (current->chan2) /* We have two bridges */ 21703 ast_debug(4, "SIP attended transfer: trying to bridge %s and %s\n", target.chan1->name, current->chan2->name); 21704 else /* One bridge, propably transfer of IVR/voicemail etc */ 21705 ast_debug(4, "SIP attended transfer: trying to make %s take over (masq) %s\n", target.chan1->name, current->chan1->name); 21706 } 21707 21708 ast_set_flag(&transferer->flags[0], SIP_DEFER_BYE_ON_TRANSFER); /* Delay hangup */ 21709 21710 ast_copy_string(transferer_linkedid, transferer->owner->linkedid, sizeof(transferer_linkedid)); 21711 21712 /* Perform the transfer */ 21713 chans[0] = transferer->owner; 21714 chans[1] = target.chan1; 21715 ast_manager_event_multichan(EVENT_FLAG_CALL, "Transfer", 2, chans, "TransferMethod: SIP\r\nTransferType: Attended\r\nChannel: %s\r\nUniqueid: %s\r\nSIP-Callid: %s\r\nTargetChannel: %s\r\nTargetUniqueid: %s\r\n", 21716 transferer->owner->name, 21717 transferer->owner->uniqueid, 21718 transferer->callid, 21719 target.chan1->name, 21720 target.chan1->uniqueid); 21721 ast_party_connected_line_init(&connected_to_transferee); 21722 ast_party_connected_line_init(&connected_to_target); 21723 /* No need to lock current->chan1 here since it was locked in sipsock_read */ 21724 ast_party_connected_line_copy(&connected_to_transferee, ¤t->chan1->connected); 21725 /* No need to lock target.chan1 here since it was locked in get_sip_pvt_byid_locked */ 21726 ast_party_connected_line_copy(&connected_to_target, &target.chan1->connected); 21727 connected_to_target.source = connected_to_transferee.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER; 21728 res = attempt_transfer(current, &target); 21729 if (res) { 21730 /* Failed transfer */ 21731 transmit_notify_with_sipfrag(transferer, seqno, "486 Busy Here", TRUE); 21732 append_history(transferer, "Xfer", "Refer failed"); 21733 ast_clear_flag(&transferer->flags[0], SIP_DEFER_BYE_ON_TRANSFER); 21734 /* if transfer failed, go ahead and unlock targetcall_pvt and it's owner channel */ 21735 sip_pvt_unlock(targetcall_pvt); 21736 ast_channel_unlock(target.chan1); 21737 } else { 21738 /* Transfer succeeded! */ 21739 const char *xfersound = pbx_builtin_getvar_helper(target.chan1, "ATTENDED_TRANSFER_COMPLETE_SOUND"); 21740 21741 /* target.chan1 was locked in get_sip_pvt_byid_locked, do not unlock target.chan1 before this */ 21742 ast_cel_report_event(target.chan1, AST_CEL_ATTENDEDTRANSFER, NULL, transferer_linkedid, target.chan2); 21743 21744 /* Tell transferer that we're done. */ 21745 transmit_notify_with_sipfrag(transferer, seqno, "200 OK", TRUE); 21746 append_history(transferer, "Xfer", "Refer succeeded"); 21747 transferer->refer->status = REFER_200OK; 21748 if (target.chan2 && !ast_strlen_zero(xfersound) && ast_streamfile(target.chan2, xfersound, target.chan2->language) >= 0) { 21749 ast_waitstream(target.chan2, ""); 21750 } 21751 21752 /* By forcing the masquerade, we know that target.chan1 and target.chan2 are bridged. We then 21753 * can queue connected line updates where they need to go. 21754 * 21755 * before a masquerade, all channel and pvt locks must be unlocked. Any recursive 21756 * channel locks held before this function invalidates channel container locking order. 21757 * Since we are unlocking both the pvt (transferer) and its owner channel (current.chan1) 21758 * it is possible for current.chan1 to be destroyed in the pbx thread. To prevent this 21759 * we must give c a reference before any unlocking takes place. 21760 */ 21761 21762 ast_channel_ref(current->chan1); 21763 ast_channel_unlock(current->chan1); /* current.chan1 is p->owner before the masq, it was locked by socket_read()*/ 21764 ast_channel_unlock(target.chan1); 21765 *nounlock = 1; /* we just unlocked the dialog's channel and have no plans of locking it again. */ 21766 sip_pvt_unlock(targetcall_pvt); 21767 sip_pvt_unlock(transferer); 21768 21769 ast_do_masquerade(target.chan1); 21770 21771 sip_pvt_lock(transferer); /* the transferer pvt is expected to remain locked on return */ 21772 21773 ast_indicate(target.chan1, AST_CONTROL_UNHOLD); 21774 21775 if (target.chan2) { 21776 ast_channel_queue_connected_line_update(target.chan1, &connected_to_transferee, NULL); 21777 ast_channel_queue_connected_line_update(target.chan2, &connected_to_target, NULL); 21778 } else { 21779 /* Since target.chan1 isn't actually connected to another channel, there is no way for us 21780 * to queue a frame so that its connected line status will be updated. 21781 * 21782 * Instead, we use the somewhat hackish approach of using a special control frame type that 21783 * instructs ast_read to perform a specific action. In this case, the frame we queue tells 21784 * ast_read to call the connected line interception macro configured for target.chan1. 21785 */ 21786 struct ast_control_read_action_payload *frame_payload; 21787 int payload_size; 21788 int frame_size; 21789 unsigned char connected_line_data[1024]; 21790 payload_size = ast_connected_line_build_data(connected_line_data, 21791 sizeof(connected_line_data), &connected_to_target, NULL); 21792 frame_size = payload_size + sizeof(*frame_payload); 21793 if (payload_size != -1 && (frame_payload = alloca(frame_size))) { 21794 frame_payload->payload_size = payload_size; 21795 memcpy(frame_payload->payload, connected_line_data, payload_size); 21796 frame_payload->action = AST_FRAME_READ_ACTION_CONNECTED_LINE_MACRO; 21797 ast_queue_control_data(target.chan1, AST_CONTROL_READ_ACTION, frame_payload, frame_size); 21798 } 21799 /* In addition to queueing the read action frame so that target.chan1's connected line info 21800 * will be updated, we also are going to queue a plain old connected line update on target.chan1. This 21801 * way, either Dial or Queue can apply this connected line update to the outgoing ringing channel. 21802 */ 21803 ast_channel_queue_connected_line_update(target.chan1, &connected_to_transferee, NULL); 21804 21805 } 21806 ast_channel_unref(current->chan1); 21807 } 21808 21809 /* at this point if the transfer is successful only the transferer pvt should be locked. */ 21810 ast_party_connected_line_free(&connected_to_target); 21811 ast_party_connected_line_free(&connected_to_transferee); 21812 if (targetcall_pvt) 21813 ao2_t_ref(targetcall_pvt, -1, "drop targetcall_pvt"); 21814 return 1; 21815 }
| static int lws2sws | ( | char * | msgbuf, | |
| int | len | |||
| ) | [static] |
Parse multiline SIP headers into one header This is enabled if pedanticsipchecking is enabled.
Definition at line 7692 of file chan_sip.c.
Referenced by handle_request_do().
07693 { 07694 int h = 0, t = 0; 07695 int lws = 0; 07696 07697 for (; h < len;) { 07698 /* Eliminate all CRs */ 07699 if (msgbuf[h] == '\r') { 07700 h++; 07701 continue; 07702 } 07703 /* Check for end-of-line */ 07704 if (msgbuf[h] == '\n') { 07705 /* Check for end-of-message */ 07706 if (h + 1 == len) 07707 break; 07708 /* Check for a continuation line */ 07709 if (msgbuf[h + 1] == ' ' || msgbuf[h + 1] == '\t') { 07710 /* Merge continuation line */ 07711 h++; 07712 continue; 07713 } 07714 /* Propagate LF and start new line */ 07715 msgbuf[t++] = msgbuf[h++]; 07716 lws = 0; 07717 continue; 07718 } 07719 if (msgbuf[h] == ' ' || msgbuf[h] == '\t') { 07720 if (lws) { 07721 h++; 07722 continue; 07723 } 07724 msgbuf[t++] = msgbuf[h++]; 07725 lws = 1; 07726 continue; 07727 } 07728 msgbuf[t++] = msgbuf[h++]; 07729 if (lws) 07730 lws = 0; 07731 } 07732 msgbuf[t] = '\0'; 07733 return t; 07734 }
| static void make_our_tag | ( | char * | tagbuf, | |
| size_t | len | |||
| ) | [static] |
Make our SIP dialog tag.
Definition at line 7004 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().
07005 { 07006 snprintf(tagbuf, len, "as%08lx", ast_random()); 07007 }
| static int manager_show_registry | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Show SIP registrations in the manager API.
Definition at line 15413 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().
15414 { 15415 const char *id = astman_get_header(m, "ActionID"); 15416 char idtext[256] = ""; 15417 int total = 0; 15418 15419 if (!ast_strlen_zero(id)) 15420 snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id); 15421 15422 astman_send_listack(s, m, "Registrations will follow", "start"); 15423 15424 ASTOBJ_CONTAINER_TRAVERSE(®l, 1, do { 15425 ASTOBJ_RDLOCK(iterator); 15426 astman_append(s, 15427 "Event: RegistryEntry\r\n" 15428 "%s" 15429 "Host: %s\r\n" 15430 "Port: %d\r\n" 15431 "Username: %s\r\n" 15432 "Domain: %s\r\n" 15433 "DomainPort: %d\r\n" 15434 "Refresh: %d\r\n" 15435 "State: %s\r\n" 15436 "RegistrationTime: %ld\r\n" 15437 "\r\n", 15438 idtext, 15439 iterator->hostname, 15440 iterator->portno ? iterator->portno : STANDARD_SIP_PORT, 15441 iterator->username, 15442 S_OR(iterator->regdomain,iterator->hostname), 15443 iterator->regdomainport ? iterator->regdomainport : STANDARD_SIP_PORT, 15444 iterator->refresh, 15445 regstate2str(iterator->regstate), 15446 (long) iterator->regtime.tv_sec); 15447 ASTOBJ_UNLOCK(iterator); 15448 total++; 15449 } while(0)); 15450 15451 astman_append(s, 15452 "Event: RegistrationsComplete\r\n" 15453 "EventList: Complete\r\n" 15454 "ListItems: %d\r\n" 15455 "%s" 15456 "\r\n", total, idtext); 15457 15458 return 0; 15459 }
| static int manager_sip_qualify_peer | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Qualify SIP peers in the manager API.
Definition at line 16133 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().
16134 { 16135 const char *a[4]; 16136 const char *peer; 16137 16138 peer = astman_get_header(m, "Peer"); 16139 if (ast_strlen_zero(peer)) { 16140 astman_send_error(s, m, "Peer: <name> missing."); 16141 return 0; 16142 } 16143 a[0] = "sip"; 16144 a[1] = "qualify"; 16145 a[2] = "peer"; 16146 a[3] = peer; 16147 16148 _sip_qualify_peer(1, -1, s, m, 4, a); 16149 astman_append(s, "\r\n\r\n" ); 16150 return 0; 16151 }
| static int manager_sip_show_peer | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Show SIP peers in the manager API.
Definition at line 16074 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().
16075 { 16076 const char *a[4]; 16077 const char *peer; 16078 16079 peer = astman_get_header(m, "Peer"); 16080 if (ast_strlen_zero(peer)) { 16081 astman_send_error(s, m, "Peer: <name> missing."); 16082 return 0; 16083 } 16084 a[0] = "sip"; 16085 a[1] = "show"; 16086 a[2] = "peer"; 16087 a[3] = peer; 16088 16089 _sip_show_peer(1, -1, s, m, 4, a); 16090 astman_append(s, "\r\n\r\n" ); 16091 return 0; 16092 }
| static int manager_sip_show_peers | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Show SIP peers in the manager API.
Definition at line 15463 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().
15464 { 15465 const char *id = astman_get_header(m, "ActionID"); 15466 const char *a[] = {"sip", "show", "peers"}; 15467 char idtext[256] = ""; 15468 int total = 0; 15469 15470 if (!ast_strlen_zero(id)) 15471 snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id); 15472 15473 astman_send_listack(s, m, "Peer status list will follow", "start"); 15474 /* List the peers in separate manager events */ 15475 _sip_show_peers(-1, &total, s, m, 3, a); 15476 /* Send final confirmation */ 15477 astman_append(s, 15478 "Event: PeerlistComplete\r\n" 15479 "EventList: Complete\r\n" 15480 "ListItems: %d\r\n" 15481 "%s" 15482 "\r\n", total, idtext); 15483 return 0; 15484 }
| static int manager_sipnotify | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 11920 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(), TRUE, ast_variable::value, and var.
Referenced by load_module().
11921 { 11922 const char *channame = astman_get_header(m, "Channel"); 11923 struct ast_variable *vars = astman_get_variables(m); 11924 struct sip_pvt *p; 11925 struct ast_variable *header, *var; 11926 11927 if (ast_strlen_zero(channame)) { 11928 astman_send_error(s, m, "SIPNotify requires a channel name"); 11929 return 0; 11930 } 11931 11932 if (!strncasecmp(channame, "sip/", 4)) { 11933 channame += 4; 11934 } 11935 11936 if (!(p = sip_alloc(NULL, NULL, 0, SIP_NOTIFY, NULL))) { 11937 astman_send_error(s, m, "Unable to build sip pvt data for notify (memory/socket error)"); 11938 return 0; 11939 } 11940 11941 if (create_addr(p, channame, NULL, 0, NULL)) { 11942 /* Maybe they're not registered, etc. */ 11943 dialog_unlink_all(p, TRUE, TRUE); 11944 dialog_unref(p, "unref dialog inside for loop" ); 11945 /* sip_destroy(p); */ 11946 astman_send_error(s, m, "Could not create address"); 11947 return 0; 11948 } 11949 11950 /* Notify is outgoing call */ 11951 ast_set_flag(&p->flags[0], SIP_OUTGOING); 11952 sip_notify_allocate(p); 11953 11954 p->notify->headers = header = ast_variable_new("Subscription-State", "terminated", ""); 11955 11956 for (var = vars; var; var = var->next) { 11957 if (!strcasecmp(var->name, "Content")) { 11958 if (ast_str_strlen(p->notify->content)) 11959 ast_str_append(&p->notify->content, 0, "\r\n"); 11960 ast_str_append(&p->notify->content, 0, "%s", var->value); 11961 } else if (!strcasecmp(var->name, "Content-Length")) { 11962 ast_log(LOG_WARNING, "it is not necessary to specify Content-Length, ignoring"); 11963 } else { 11964 header->next = ast_variable_new(var->name, var->value, ""); 11965 header = header->next; 11966 } 11967 } 11968 11969 dialog_ref(p, "bump the count of p, which transmit_sip_request will decrement."); 11970 sip_scheddestroy(p, SIP_TRANS_TIMEOUT); 11971 transmit_invite(p, SIP_NOTIFY, 0, 2, NULL); 11972 11973 astman_send_ack(s, m, "Notify Sent"); 11974 ast_variables_destroy(vars); 11975 return 0; 11976 }
| 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 2212 of file chan_sip.c.
Referenced by str2dtmfmode(), str2stmode(), and str2strefresher().
02213 { 02214 const struct _map_x_s *cur; 02215 02216 for (cur = table; cur->s; cur++) 02217 if (!strcasecmp(cur->s, s)) 02218 return cur->x; 02219 return errorvalue; 02220 }
| 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 2199 of file chan_sip.c.
Referenced by dtmfmode2str(), faxec2str(), insecure2str(), referstatus2str(), regstate2str(), stmode2str(), and strefresher2str().
02200 { 02201 const struct _map_x_s *cur; 02202 02203 for (cur = table; cur->s; cur++) 02204 if (cur->x == x) 02205 return cur->s; 02206 return errorstring; 02207 }
| static void mark_method_allowed | ( | unsigned int * | allowed_methods, | |
| enum sipmethod | method | |||
| ) | [static] |
Definition at line 7593 of file chan_sip.c.
Referenced by handle_response(), mark_parsed_methods(), and set_pvt_allowed_methods().
| static void mark_method_unallowed | ( | unsigned int * | allowed_methods, | |
| enum sipmethod | method | |||
| ) | [static] |
Definition at line 7598 of file chan_sip.c.
Referenced by handle_response(), and handle_response_publish().
| static void mark_parsed_methods | ( | unsigned int * | methods, | |
| char * | methods_str | |||
| ) | [static] |
Definition at line 7609 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().
07610 { 07611 char *method; 07612 for (method = strsep(&methods_str, ","); !ast_strlen_zero(method); method = strsep(&methods_str, ",")) { 07613 int id = find_sip_method(ast_skip_blanks(method)); 07614 if (id == SIP_UNKNOWN) { 07615 continue; 07616 } 07617 mark_method_allowed(methods, id); 07618 } 07619 }
| static enum match_req_res match_req_to_dialog | ( | struct sip_pvt * | sip_pvt_ptr, | |
| struct match_req_args * | arg | |||
| ) | [static] |
Definition at line 7204 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::ruri, match_req_args::seqno, SIP_REQ_LOOP_DETECTED, SIP_REQ_MATCH, SIP_REQ_NOT_MATCH, match_req_args::totag, match_req_args::viabranch, and match_req_args::viasentby.
Referenced by find_call().
07205 { 07206 const char *init_ruri = NULL; 07207 if (sip_pvt_ptr->initreq.headers) { 07208 init_ruri = REQ_OFFSET_TO_STR(&sip_pvt_ptr->initreq, rlPart2); 07209 } 07210 07211 /* 07212 * Match Tags and call-id to Dialog 07213 */ 07214 if (!ast_strlen_zero(arg->callid) && strcmp(sip_pvt_ptr->callid, arg->callid)) { 07215 /* call-id does not match. */ 07216 return SIP_REQ_NOT_MATCH; 07217 } 07218 if (arg->method == SIP_RESPONSE) { 07219 /* Verify totag if we have one stored for this dialog, but never be strict about this for 07220 * a response until the dialog is established */ 07221 if (!ast_strlen_zero(sip_pvt_ptr->theirtag) && ast_test_flag(&sip_pvt_ptr->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED)) { 07222 if (ast_strlen_zero(arg->totag)) { 07223 /* missing totag when they already gave us one earlier */ 07224 return SIP_REQ_NOT_MATCH; 07225 } 07226 if (strcmp(arg->totag, sip_pvt_ptr->theirtag)) { 07227 /* The totag of the response does not match the one we have stored */ 07228 return SIP_REQ_NOT_MATCH; 07229 } 07230 } 07231 /* Verify fromtag of response matches the tag we gave them. */ 07232 if (strcmp(arg->fromtag, sip_pvt_ptr->tag)) { 07233 /* fromtag from response does not match our tag */ 07234 return SIP_REQ_NOT_MATCH; 07235 } 07236 } else { 07237 /* Verify the fromtag of Request matches the tag they provided earlier. */ 07238 if (strcmp(arg->fromtag, sip_pvt_ptr->theirtag)) { 07239 /* their tag does not match the one was have stored for them */ 07240 return SIP_REQ_NOT_MATCH; 07241 } 07242 /* Verify if totag is present in Request, that it matches what we gave them as our tag earlier */ 07243 if (!ast_strlen_zero(arg->totag) && (strcmp(arg->totag, sip_pvt_ptr->tag))) { 07244 /* totag from Request does not match our tag */ 07245 return SIP_REQ_NOT_MATCH; 07246 } 07247 } 07248 07249 /* 07250 * Compare incoming request against initial transaction. 07251 * 07252 * This is a best effort attempt at distinguishing forked requests from 07253 * our initial transaction. If all the elements are NOT in place to evaluate 07254 * this, this block is ignored and the dialog match is made regardless. 07255 * Once the totag is established after the dialog is confirmed, this is not necessary. 07256 * 07257 * CRITERIA required for initial transaction matching. 07258 * 07259 * 1. Is a Request 07260 * 2. Callid and theirtag match (this is done in the dialog matching block) 07261 * 3. totag is NOT present 07262 * 4. CSeq matchs our initial transaction's cseq number 07263 * 5. pvt has init via branch parameter stored 07264 */ 07265 if ((arg->method != SIP_RESPONSE) && /* must be a Request */ 07266 ast_strlen_zero(arg->totag) && /* must not have a totag */ 07267 (sip_pvt_ptr->init_icseq == arg->seqno) && /* the cseq must be the same as this dialogs initial cseq */ 07268 !ast_strlen_zero(sip_pvt_ptr->initviabranch) && /* The dialog must have started with a RFC3261 compliant branch tag */ 07269 init_ruri) { /* the dialog must have an initial request uri associated with it */ 07270 /* This Request matches all the criteria required for Loop/Merge detection. 07271 * Now we must go down the path of comparing VIA's and RURIs. */ 07272 if (ast_strlen_zero(arg->viabranch) || 07273 strcmp(arg->viabranch, sip_pvt_ptr->initviabranch) || 07274 ast_strlen_zero(arg->viasentby) || 07275 strcmp(arg->viasentby, sip_pvt_ptr->initviasentby)) { 07276 /* At this point, this request does not match this Dialog.*/ 07277 07278 /* if methods are different this is just a mismatch */ 07279 if ((sip_pvt_ptr->method != arg->method)) { 07280 return SIP_REQ_NOT_MATCH; 07281 } 07282 07283 /* If RUIs are different, this is a forked request to a separate URI. 07284 * Returning a mismatch allows this Request to be processed separately. */ 07285 if (sip_uri_cmp(init_ruri, arg->ruri)) { 07286 /* not a match, request uris are different */ 07287 return SIP_REQ_NOT_MATCH; 07288 } 07289 07290 /* Loop/Merge Detected 07291 * 07292 * ---Current Matches to Initial Request--- 07293 * request uri 07294 * Call-id 07295 * their-tag 07296 * no totag present 07297 * method 07298 * cseq 07299 * 07300 * --- Does not Match Initial Request --- 07301 * Top Via 07302 * 07303 * Without the same Via, this can not match our initial transaction for this dialog, 07304 * but given that this Request matches everything else associated with that initial 07305 * Request this is most certainly a Forked request in which we have already received 07306 * part of the fork. 07307 */ 07308 return SIP_REQ_LOOP_DETECTED; 07309 } 07310 } /* end of Request Via check */ 07311 07312 /* Match Authentication Request. 07313 * 07314 * A Request with an Authentication header must come back with the 07315 * same Request URI. Otherwise it is not a match. 07316 */ 07317 if ((arg->method != SIP_RESPONSE) && /* Must be a Request type to even begin checking this */ 07318 ast_strlen_zero(arg->totag) && /* no totag is present to match */ 07319 arg->authentication_present && /* Authentication header is present in Request */ 07320 sip_uri_cmp(init_ruri, arg->ruri)) { /* Compare the Request URI of both the last Request and this new one */ 07321 07322 /* Authentication was provided, but the Request URI did not match the last one on this dialog. */ 07323 return SIP_REQ_NOT_MATCH; 07324 } 07325 07326 return SIP_REQ_MATCH; 07327 }
| 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 2902 of file chan_sip.c.
References len(), sip_methods, and text.
Referenced by __sip_autodestruct(), __sip_semi_ack(), and find_sip_method().
02903 { 02904 int len = strlen(sip_methods[id].text); 02905 int l_name = name ? strlen(name) : 0; 02906 /* true if the string is long enough, and ends with whitespace, and matches */ 02907 return (l_name >= len && name[len] < 33 && 02908 !strncasecmp(sip_methods[id].text, name, len)); 02909 }
| static void mwi_event_cb | ( | const struct ast_event * | event, | |
| void * | userdata | |||
| ) | [static] |
Receive MWI events that we have subscribed to.
Definition at line 13453 of file chan_sip.c.
References ao2_lock, ao2_unlock, and sip_send_mwi_to_peer().
13454 { 13455 struct sip_peer *peer = userdata; 13456 13457 ao2_lock(peer); 13458 sip_send_mwi_to_peer(peer, event, 0); 13459 ao2_unlock(peer); 13460 }
| static void network_change_event_cb | ( | const struct ast_event * | event, | |
| void * | userdata | |||
| ) | [static] |
Definition at line 13487 of file chan_sip.c.
References ast_debug, ast_sched_add(), and network_change_event_sched_cb().
13488 { 13489 ast_debug(1, "SIP, got a network change event, renewing all SIP registrations.\n"); 13490 if (network_change_event_sched_id == -1) { 13491 network_change_event_sched_id = ast_sched_add(sched, 1000, network_change_event_sched_cb, NULL); 13492 } 13493 }
| static int network_change_event_sched_cb | ( | const void * | data | ) | [static] |
Definition at line 13479 of file chan_sip.c.
References sip_send_all_mwi_subscriptions(), and sip_send_all_registers().
13480 { 13481 network_change_event_sched_id = -1; 13482 sip_send_all_registers(); 13483 sip_send_all_mwi_subscriptions(); 13484 return 0; 13485 }
| static void network_change_event_subscribe | ( | void | ) | [static] |
Definition at line 13462 of file chan_sip.c.
References AST_EVENT_IE_END, AST_EVENT_NETWORK_CHANGE, ast_event_subscribe(), and network_change_event_cb().
13463 { 13464 if (!network_change_event_subscription) { 13465 network_change_event_subscription = ast_event_subscribe(AST_EVENT_NETWORK_CHANGE, 13466 network_change_event_cb, 13467 "SIP Network Change ", 13468 NULL, AST_EVENT_IE_END); 13469 } 13470 }
| static void network_change_event_unsubscribe | ( | void | ) | [static] |
Definition at line 13472 of file chan_sip.c.
References ast_event_unsubscribe().
13473 { 13474 if (network_change_event_subscription) { 13475 network_change_event_subscription = ast_event_unsubscribe(network_change_event_subscription); 13476 } 13477 }
| 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 2874 of file chan_sip.c.
References append_history, ast_debug, and sip_cfg.
Referenced by __sip_subscribe_mwi_do(), create_addr(), and create_addr_from_peer().
02875 { 02876 if (peer && peer->outboundproxy) { 02877 if (sipdebug) { 02878 ast_debug(1, "OBPROXY: Applying peer OBproxy to this call\n"); 02879 } 02880 append_history(dialog, "OBproxy", "Using peer obproxy %s", peer->outboundproxy->name); 02881 return peer->outboundproxy; 02882 } 02883 if (sip_cfg.outboundproxy.name[0]) { 02884 if (sipdebug) { 02885 ast_debug(1, "OBPROXY: Applying global OBproxy to this call\n"); 02886 } 02887 append_history(dialog, "OBproxy", "Using global obproxy %s", sip_cfg.outboundproxy.name); 02888 return &sip_cfg.outboundproxy; 02889 } 02890 if (sipdebug) { 02891 ast_debug(1, "OBPROXY: Not applying OBproxy to this call\n"); 02892 } 02893 return NULL; 02894 }
| 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 7636 of file chan_sip.c.
References ast_strdupa, ast_strip_quoted(), ast_strlen_zero(), get_header(), and mark_parsed_methods().
Referenced by set_pvt_allowed_methods().
07637 { 07638 char *allow = ast_strdupa(get_header(req, "Allow")); 07639 unsigned int allowed_methods = SIP_UNKNOWN; 07640 07641 if (ast_strlen_zero(allow)) { 07642 /* I have witnessed that REGISTER requests from Polycom phones do not 07643 * place the phone's allowed methods in an Allow header. Instead, they place the 07644 * allowed methods in a methods= parameter in the Contact header. 07645 */ 07646 char *contact = ast_strdupa(get_header(req, "Contact")); 07647 char *methods = strstr(contact, ";methods="); 07648 07649 if (ast_strlen_zero(methods)) { 07650 /* RFC 3261 states: 07651 * 07652 * "The absence of an Allow header field MUST NOT be 07653 * interpreted to mean that the UA sending the message supports no 07654 * methods. Rather, it implies that the UA is not providing any 07655 * information on what methods it supports." 07656 * 07657 * For simplicity, we'll assume that the peer allows all known 07658 * SIP methods if they have no Allow header. We can then clear out the necessary 07659 * bits if the peer lets us know that we have sent an unsupported method. 07660 */ 07661 return UINT_MAX; 07662 } 07663 allow = ast_strip_quoted(methods + 9, "\"", "\""); 07664 } 07665 mark_parsed_methods(&allowed_methods, allow); 07666 return allowed_methods; 07667 }
| static void parse_copy | ( | struct sip_request * | dst, | |
| const struct sip_request * | src | |||
| ) | [static] |
Copy SIP request, parse it.
Definition at line 3808 of file chan_sip.c.
References copy_request(), and parse_request().
Referenced by send_request(), and send_response().
03809 { 03810 copy_request(dst, src); 03811 parse_request(dst); 03812 }
| int parse_minse | ( | const char * | p_hdrval, | |
| int *const | p_interval | |||
| ) | [static] |
Session-Timers: Function for parsing Min-SE header.
Definition at line 24464 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().
24465 { 24466 if (ast_strlen_zero(p_hdrval)) { 24467 ast_log(LOG_WARNING, "Null Min-SE header\n"); 24468 return -1; 24469 } 24470 24471 *p_interval = 0; 24472 p_hdrval = ast_skip_blanks(p_hdrval); 24473 if (!sscanf(p_hdrval, "%30d", p_interval)) { 24474 ast_log(LOG_WARNING, "Parsing of Min-SE header failed %s\n", p_hdrval); 24475 return -1; 24476 } 24477 24478 ast_debug(2, "Received Min-SE: %d\n", *p_interval); 24479 return 0; 24480 }
| 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 18414 of file chan_sip.c.
References ao2_ref, ast_copy_string(), ast_debug, ast_log(), ast_strdup, ast_string_field_build, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_uri_decode(), find_closing_quote(), get_header(), get_transport(), LOG_NOTICE, pbx_builtin_setvar_helper(), remove_uri_parameters(), set_socket_transport(), and strcasestr().
Referenced by change_redirecting_information().
18415 { 18416 char contact[SIPBUFSIZE]; 18417 char *contact_name = NULL; 18418 char *contact_number = NULL; 18419 char *separator, *trans; 18420 char *domain; 18421 enum sip_transport transport = SIP_TRANSPORT_UDP; 18422 18423 ast_copy_string(contact, get_header(req, "Contact"), sizeof(contact)); 18424 if ((separator = strchr(contact, ','))) 18425 *separator = '\0'; 18426 18427 contact_number = get_in_brackets(contact); 18428 if ((trans = strcasestr(contact_number, ";transport="))) { 18429 trans += 11; 18430 18431 if ((separator = strchr(trans, ';'))) 18432 *separator = '\0'; 18433 18434 if (!strncasecmp(trans, "tcp", 3)) 18435 transport = SIP_TRANSPORT_TCP; 18436 else if (!strncasecmp(trans, "tls", 3)) 18437 transport = SIP_TRANSPORT_TLS; 18438 else { 18439 if (strncasecmp(trans, "udp", 3)) 18440 ast_debug(1, "received contact with an invalid transport, '%s'\n", contact_number); 18441 /* This will assume UDP for all unknown transports */ 18442 transport = SIP_TRANSPORT_UDP; 18443 } 18444 } 18445 contact_number = remove_uri_parameters(contact_number); 18446 18447 if (p->socket.tcptls_session) { 18448 ao2_ref(p->socket.tcptls_session, -1); 18449 p->socket.tcptls_session = NULL; 18450 } 18451 18452 set_socket_transport(&p->socket, transport); 18453 18454 if (set_call_forward && ast_test_flag(&p->flags[0], SIP_PROMISCREDIR)) { 18455 char *host = NULL; 18456 if (!strncasecmp(contact_number, "sip:", 4)) 18457 contact_number += 4; 18458 else if (!strncasecmp(contact_number, "sips:", 5)) 18459 contact_number += 5; 18460 separator = strchr(contact_number, '/'); 18461 if (separator) 18462 *separator = '\0'; 18463 if ((host = strchr(contact_number, '@'))) { 18464 *host++ = '\0'; 18465 ast_debug(2, "Found promiscuous redirection to 'SIP/%s::::%s@%s'\n", contact_number, get_transport(transport), host); 18466 if (p->owner) 18467 ast_string_field_build(p->owner, call_forward, "SIP/%s::::%s@%s", contact_number, get_transport(transport), host); 18468 } else { 18469 ast_debug(2, "Found promiscuous redirection to 'SIP/::::%s@%s'\n", get_transport(transport), contact_number); 18470 if (p->owner) 18471 ast_string_field_build(p->owner, call_forward, "SIP/::::%s@%s", get_transport(transport), contact_number); 18472 } 18473 } else { 18474 separator = strchr(contact, '@'); 18475 if (separator) { 18476 *separator++ = '\0'; 18477 domain = separator; 18478 } else { 18479 /* No username part */ 18480 domain = contact; 18481 } 18482 separator = strchr(contact, '/'); /* WHEN do we hae a forward slash in the URI? */ 18483 if (separator) 18484 *separator = '\0'; 18485 18486 if (!strncasecmp(contact_number, "sip:", 4)) 18487 contact_number += 4; 18488 else if (!strncasecmp(contact_number, "sips:", 5)) 18489 contact_number += 5; 18490 separator = strchr(contact_number, ';'); /* And username ; parameters? */ 18491 if (separator) 18492 *separator = '\0'; 18493 ast_uri_decode(contact_number); 18494 if (set_call_forward) { 18495 ast_debug(2, "Received 302 Redirect to extension '%s' (domain %s)\n", contact_number, domain); 18496 if (p->owner) { 18497 pbx_builtin_setvar_helper(p->owner, "SIPDOMAIN", domain); 18498 ast_string_field_set(p->owner, call_forward, contact_number); 18499 } 18500 } 18501 } 18502 18503 /* We've gotten the number for the contact, now get the name */ 18504 18505 if (*contact == '\"') { 18506 contact_name = contact + 1; 18507 if (!(separator = (char *)find_closing_quote(contact_name, NULL))) { 18508 ast_log(LOG_NOTICE, "No closing quote on name in Contact header? %s\n", contact); 18509 } 18510 *separator = '\0'; 18511 } 18512 18513 if (name && !ast_strlen_zero(contact_name)) { 18514 *name = ast_strdup(contact_name); 18515 } 18516 if (number) { 18517 *number = ast_strdup(contact_number); 18518 } 18519 }
| 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 12815 of file chan_sip.c.
References ast_copy_string(), ast_string_field_set, get_header(), and TRUE.
Referenced by handle_request_invite(), handle_request_subscribe(), and handle_response_invite().
12816 { 12817 char contact[SIPBUFSIZE]; 12818 char *c; 12819 12820 /* Look for brackets */ 12821 ast_copy_string(contact, get_header(req, "Contact"), sizeof(contact)); 12822 c = get_in_brackets(contact); 12823 12824 /* Save full contact to call pvt for later bye or re-invite */ 12825 ast_string_field_set(pvt, fullcontact, c); 12826 12827 /* Save URI for later ACKs, BYE or RE-invites */ 12828 ast_string_field_set(pvt, okcontacturi, c); 12829 12830 /* We should return false for URI:s we can't handle, 12831 like tel:, mailto:,ldap: etc */ 12832 return TRUE; 12833 }
| 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 12897 of file chan_sip.c.
References 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_string_field_build, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_verb, ast_verbose, copy_socket_data(), destroy_association(), EVENT_FLAG_SYSTEM, expire_register(), FALSE, get_header(), get_transport_str2enum(), LOG_NOTICE, LOG_WARNING, manager_event, ref_peer(), register_peer_exten(), set_socket_transport(), sip_cfg, sip_poke_peer(), strcasestr(), strsep(), TRUE, unref_peer(), VERBOSE_PREFIX_3, and VERBOSITY_ATLEAST.
Referenced by register_verify().
12898 { 12899 char contact[SIPBUFSIZE]; 12900 char data[SIPBUFSIZE]; 12901 const char *expires = get_header(req, "Expires"); 12902 int expire = atoi(expires); 12903 char *curi, *domain, *transport; 12904 int transport_type; 12905 const char *useragent; 12906 struct ast_sockaddr oldsin, testsa; 12907 12908 ast_copy_string(contact, get_header(req, "Contact"), sizeof(contact)); 12909 12910 if (ast_strlen_zero(expires)) { /* No expires header, try look in Contact: */ 12911 char *s = strcasestr(contact, ";expires="); 12912 if (s) { 12913 expires = strsep(&s, ";"); /* trim ; and beyond */ 12914 if (sscanf(expires + 9, "%30d", &expire) != 1) { 12915 expire = default_expiry; 12916 } 12917 } else { 12918 /* Nothing has been specified */ 12919 expire = default_expiry; 12920 } 12921 } 12922 12923 copy_socket_data(&pvt->socket, &req->socket); 12924 12925 /* Look for brackets */ 12926 curi = contact; 12927 if (strchr(contact, '<') == NULL) /* No <, check for ; and strip it */ 12928 strsep(&curi, ";"); /* This is Header options, not URI options */ 12929 curi = get_in_brackets(contact); 12930 12931 /* if they did not specify Contact: or Expires:, they are querying 12932 what we currently have stored as their contact address, so return 12933 it 12934 */ 12935 if (ast_strlen_zero(curi) && ast_strlen_zero(expires)) { 12936 /* If we have an active registration, tell them when the registration is going to expire */ 12937 if (peer->expire > -1 && !ast_strlen_zero(peer->fullcontact)) { 12938 pvt->expiry = ast_sched_when(sched, peer->expire); 12939 } 12940 return PARSE_REGISTER_QUERY; 12941 } else if (!strcasecmp(curi, "*") || !expire) { /* Unregister this peer */ 12942 /* This means remove all registrations and return OK */ 12943 memset(&peer->addr, 0, sizeof(peer->addr)); 12944 set_socket_transport(&peer->socket, peer->default_outbound_transport); 12945 12946 AST_SCHED_DEL_UNREF(sched, peer->expire, 12947 unref_peer(peer, "remove register expire ref")); 12948 12949 destroy_association(peer); 12950 12951 register_peer_exten(peer, FALSE); /* Remove extension from regexten= setting in sip.conf */ 12952 ast_string_field_set(peer, fullcontact, ""); 12953 ast_string_field_set(peer, useragent, ""); 12954 peer->sipoptions = 0; 12955 peer->lastms = 0; 12956 peer->portinuri = 0; 12957 pvt->expiry = 0; 12958 12959 ast_verb(3, "Unregistered SIP '%s'\n", peer->name); 12960 12961 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: SIP\r\nPeer: SIP/%s\r\nPeerStatus: Unregistered\r\n", peer->name); 12962 return PARSE_REGISTER_UPDATE; 12963 } 12964 12965 /* Store whatever we got as a contact from the client */ 12966 ast_string_field_set(peer, fullcontact, curi); 12967 12968 /* For the 200 OK, we should use the received contact */ 12969 ast_string_field_build(pvt, our_contact, "<%s>", curi); 12970 12971 /* Make sure it's a SIP URL */ 12972 if (parse_uri(curi, "sip:,sips:", &curi, NULL, &domain, &transport)) { 12973 ast_log(LOG_NOTICE, "Not a valid SIP contact (missing sip:/sips:) trying to use anyway\n"); 12974 } 12975 12976 /* handle the transport type specified in Contact header. */ 12977 if (!(transport_type = get_transport_str2enum(transport))) { 12978 transport_type = pvt->socket.type; 12979 } 12980 12981 /* if the peer's socket type is different than the Registration 12982 * transport type, change it. If it got this far, it is a 12983 * supported type, but check just in case */ 12984 if ((peer->socket.type != transport_type) && (peer->transports & transport_type)) { 12985 set_socket_transport(&peer->socket, transport_type); 12986 } 12987 12988 oldsin = peer->addr; 12989 12990 /* If we were already linked into the peers_by_ip container unlink ourselves so nobody can find us */ 12991 if (!ast_sockaddr_isnull(&peer->addr)) { 12992 ao2_t_unlink(peers_by_ip, peer, "ao2_unlink of peer from peers_by_ip table"); 12993 } 12994 12995 if (!ast_test_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT) && !ast_test_flag(&peer->flags[0], SIP_NAT_RPORT_PRESENT)) { 12996 /* use the data provided in the Contact header for call routing */ 12997 ast_debug(1, "Store REGISTER's Contact header for call routing.\n"); 12998 /* XXX This could block for a long time XXX */ 12999 /*! \todo Check NAPTR/SRV if we have not got a port in the URI */ 13000 if (ast_sockaddr_resolve_first(&testsa, domain, 0)) { 13001 ast_log(LOG_WARNING, "Invalid domain '%s'\n", domain); 13002 ast_string_field_set(peer, fullcontact, ""); 13003 ast_string_field_set(pvt, our_contact, ""); 13004 return PARSE_REGISTER_FAILED; 13005 } 13006 13007 /* If we have a port number in the given URI, make sure we do remember to not check for NAPTR/SRV records. 13008 The domain part is actually a host. */ 13009 peer->portinuri = ast_sockaddr_port(&testsa) ? TRUE : FALSE; 13010 13011 if (!ast_sockaddr_port(&testsa)) { 13012 ast_sockaddr_set_port(&testsa, 13013 transport_type == SIP_TRANSPORT_TLS ? 13014 STANDARD_TLS_PORT : STANDARD_SIP_PORT); 13015 } 13016 13017 ast_sockaddr_copy(&peer->addr, &testsa); 13018 } else { 13019 /* Don't trust the contact field. Just use what they came to us 13020 with */ 13021 ast_debug(1, "Store REGISTER's src-IP:port for call routing.\n"); 13022 peer->addr = pvt->recv; 13023 } 13024 13025 /* Check that they're allowed to register at this IP */ 13026 if (ast_apply_ha(sip_cfg.contact_ha, &peer->addr) != AST_SENSE_ALLOW || 13027 ast_apply_ha(peer->contactha, &peer->addr) != AST_SENSE_ALLOW) { 13028 ast_log(LOG_WARNING, "Domain '%s' disallowed by contact ACL (violating IP %s)\n", domain, 13029 ast_sockaddr_stringify_addr(&testsa)); 13030 ast_string_field_set(peer, fullcontact, ""); 13031 ast_string_field_set(pvt, our_contact, ""); 13032 return PARSE_REGISTER_DENIED; 13033 } 13034 13035 /* if the Contact header information copied into peer->addr matches the 13036 * received address, and the transport types are the same, then copy socket 13037 * data into the peer struct */ 13038 if ((peer->socket.type == pvt->socket.type) && 13039 !ast_sockaddr_cmp(&peer->addr, &pvt->recv)) { 13040 copy_socket_data(&peer->socket, &pvt->socket); 13041 } 13042 13043 /* Now that our address has been updated put ourselves back into the container for lookups */ 13044 ao2_t_link(peers_by_ip, peer, "ao2_link into peers_by_ip table"); 13045 13046 /* Save SIP options profile */ 13047 peer->sipoptions = pvt->sipoptions; 13048 13049 if (!ast_strlen_zero(curi) && ast_strlen_zero(peer->username)) { 13050 ast_string_field_set(peer, username, curi); 13051 } 13052 13053 AST_SCHED_DEL_UNREF(sched, peer->expire, 13054 unref_peer(peer, "remove register expire ref")); 13055 13056 if (expire > max_expiry) { 13057 expire = max_expiry; 13058 } 13059 if (expire < min_expiry) { 13060 expire = min_expiry; 13061 } 13062 if (peer->is_realtime && !ast_test_flag(&peer->flags[1], SIP_PAGE2_RTCACHEFRIENDS)) { 13063 peer->expire = -1; 13064 } else { 13065 peer->expire = ast_sched_add(sched, (expire + 10) * 1000, expire_register, 13066 ref_peer(peer, "add registration ref")); 13067 if (peer->expire == -1) { 13068 unref_peer(peer, "remote registration ref"); 13069 } 13070 } 13071 pvt->expiry = expire; 13072 snprintf(data, sizeof(data), "%s:%d:%s:%s", ast_sockaddr_stringify(&peer->addr), 13073 expire, peer->username, peer->fullcontact); 13074 /* Saving TCP connections is useless, we won't be able to reconnect 13075 XXX WHY???? XXX 13076 \todo Fix this immediately. 13077 */ 13078 if (!peer->rt_fromcontact && (peer->socket.type & SIP_TRANSPORT_UDP)) 13079 ast_db_put("SIP/Registry", peer->name, data); 13080 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)); 13081 13082 /* Is this a new IP address for us? */ 13083 if (VERBOSITY_ATLEAST(2) && ast_sockaddr_cmp(&peer->addr, &oldsin)) { 13084 ast_verbose(VERBOSE_PREFIX_3 "Registered SIP '%s' at %s\n", peer->name, 13085 ast_sockaddr_stringify(&peer->addr)); 13086 } 13087 sip_poke_peer(peer, 0); 13088 register_peer_exten(peer, 1); 13089 13090 /* Save User agent */ 13091 useragent = get_header(req, "User-Agent"); 13092 if (strcasecmp(useragent, peer->useragent)) { 13093 ast_string_field_set(peer, useragent, useragent); 13094 ast_verb(4, "Saved useragent \"%s\" for peer %s\n", peer->useragent, peer->name); 13095 } 13096 return PARSE_REGISTER_UPDATE; 13097 }
| static int parse_request | ( | struct sip_request * | req | ) | [static] |
Parse a SIP message.
Definition at line 7739 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().
07740 { 07741 char *c = req->data->str; 07742 ptrdiff_t *dst = req->header; 07743 int i = 0, lim = SIP_MAX_HEADERS - 1; 07744 unsigned int skipping_headers = 0; 07745 ptrdiff_t current_header_offset = 0; 07746 char *previous_header = ""; 07747 07748 req->header[0] = 0; 07749 req->headers = -1; /* mark that we are working on the header */ 07750 for (; *c; c++) { 07751 if (*c == '\r') { /* remove \r */ 07752 *c = '\0'; 07753 } else if (*c == '\n') { /* end of this line */ 07754 *c = '\0'; 07755 current_header_offset = (c + 1) - req->data->str; 07756 previous_header = req->data->str + dst[i]; 07757 if (skipping_headers) { 07758 /* check to see if this line is blank; if so, turn off 07759 the skipping flag, so the next line will be processed 07760 as a body line */ 07761 if (ast_strlen_zero(previous_header)) { 07762 skipping_headers = 0; 07763 } 07764 dst[i] = current_header_offset; /* record start of next line */ 07765 continue; 07766 } 07767 if (sipdebug) { 07768 ast_debug(4, "%7s %2d [%3d]: %s\n", 07769 req->headers < 0 ? "Header" : "Body", 07770 i, (int) strlen(previous_header), previous_header); 07771 } 07772 if (ast_strlen_zero(previous_header) && req->headers < 0) { 07773 req->headers = i; /* record number of header lines */ 07774 dst = req->line; /* start working on the body */ 07775 i = 0; 07776 lim = SIP_MAX_LINES - 1; 07777 } else { /* move to next line, check for overflows */ 07778 if (i++ == lim) { 07779 /* if we're processing headers, then skip any remaining 07780 headers and move on to processing the body, otherwise 07781 we're done */ 07782 if (req->headers != -1) { 07783 break; 07784 } else { 07785 req->headers = i; 07786 dst = req->line; 07787 i = 0; 07788 lim = SIP_MAX_LINES - 1; 07789 skipping_headers = 1; 07790 } 07791 } 07792 } 07793 dst[i] = current_header_offset; /* record start of next line */ 07794 } 07795 } 07796 07797 /* Check for last header or body line without CRLF. The RFC for SDP requires CRLF, 07798 but since some devices send without, we'll be generous in what we accept. However, 07799 if we've already reached the maximum number of lines for portion of the message 07800 we were parsing, we can't accept any more, so just ignore it. 07801 */ 07802 previous_header = req->data->str + dst[i]; 07803 if ((i < lim) && !ast_strlen_zero(previous_header)) { 07804 if (sipdebug) { 07805 ast_debug(4, "%7s %2d [%3d]: %s\n", 07806 req->headers < 0 ? "Header" : "Body", 07807 i, (int) strlen(previous_header), previous_header ); 07808 } 07809 i++; 07810 } 07811 07812 /* update count of header or body lines */ 07813 if (req->headers >= 0) { /* we are in the body */ 07814 req->lines = i; 07815 } else { /* no body */ 07816 req->headers = i; 07817 req->lines = 0; 07818 /* req->data->used will be a NULL byte */ 07819 req->line[0] = ast_str_strlen(req->data); 07820 } 07821 07822 if (*c) { 07823 ast_log(LOG_WARNING, "Too many lines, skipping <%s>\n", c); 07824 } 07825 07826 /* Split up the first line parts */ 07827 return determine_firstline_parts(req); 07828 }
| 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 24484 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().
24485 { 24486 char *p_token; 24487 int ref_idx; 24488 char *p_se_hdr; 24489 24490 if (ast_strlen_zero(p_hdrval)) { 24491 ast_log(LOG_WARNING, "Null Session-Expires header\n"); 24492 return -1; 24493 } 24494 24495 *p_ref = SESSION_TIMER_REFRESHER_AUTO; 24496 *p_interval = 0; 24497 24498 p_se_hdr = ast_strdupa(p_hdrval); 24499 p_se_hdr = ast_skip_blanks(p_se_hdr); 24500 24501 while ((p_token = strsep(&p_se_hdr, ";"))) { 24502 p_token = ast_skip_blanks(p_token); 24503 if (!sscanf(p_token, "%30d", p_interval)) { 24504 ast_log(LOG_WARNING, "Parsing of Session-Expires failed\n"); 24505 return -1; 24506 } 24507 24508 ast_debug(2, "Session-Expires: %d\n", *p_interval); 24509 24510 if (!p_se_hdr) 24511 continue; 24512 24513 p_se_hdr = ast_skip_blanks(p_se_hdr); 24514 ref_idx = strlen("refresher="); 24515 if (!strncasecmp(p_se_hdr, "refresher=", ref_idx)) { 24516 p_se_hdr += ref_idx; 24517 p_se_hdr = ast_skip_blanks(p_se_hdr); 24518 24519 if (!strncasecmp(p_se_hdr, "uac", strlen("uac"))) { 24520 *p_ref = SESSION_TIMER_REFRESHER_UAC; 24521 ast_debug(2, "Refresher: UAC\n"); 24522 } else if (!strncasecmp(p_se_hdr, "uas", strlen("uas"))) { 24523 *p_ref = SESSION_TIMER_REFRESHER_UAS; 24524 ast_debug(2, "Refresher: UAS\n"); 24525 } else { 24526 ast_log(LOG_WARNING, "Invalid refresher value %s\n", p_se_hdr); 24527 return -1; 24528 } 24529 break; 24530 } 24531 } 24532 return 0; 24533 }
| 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 15688 of file chan_sip.c.
References ao2_t_ref, ast_cli(), and ast_cli_args::fd.
Referenced by sip_show_objects().
15689 { 15690 struct sip_peer *peer = userobj; 15691 int refc = ao2_t_ref(userobj, 0, ""); 15692 struct ast_cli_args *a = (struct ast_cli_args *) arg; 15693 15694 ast_cli(a->fd, "name: %s\ntype: peer\nobjflags: %d\nrefcount: %d\n\n", 15695 peer->name, 0, refc); 15696 return 0; 15697 }
| static int peer_hash_cb | ( | const void * | obj, | |
| const int | flags | |||
| ) | [static] |
Definition at line 27964 of file chan_sip.c.
References ast_str_case_hash().
27965 { 27966 const struct sip_peer *peer = obj; 27967 27968 return ast_str_case_hash(peer->name); 27969 }
| static int peer_ipcmp_cb | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Match Peers by IP and Port number.
This function has two modes.
This callback will be used twice when doing peer matching. There is a first pass for full IP+port matching, and a second pass in case there is a match that meets the insecure=port criteria.
the peer's addr struct provides to fields combined to make a key: the sin_addr.s_addr and sin_port fields.
Definition at line 28022 of file chan_sip.c.
References ast_sockaddr_cmp_addr(), ast_sockaddr_port, ast_test_flag, CMP_MATCH, and CMP_STOP.
Referenced by load_module().
28023 { 28024 struct sip_peer *peer = obj, *peer2 = arg; 28025 28026 if (ast_sockaddr_cmp_addr(&peer->addr, &peer2->addr)) { 28027 /* IP doesn't match */ 28028 return 0; 28029 } 28030 28031 /* We matched the IP, check to see if we need to match by port as well. */ 28032 if ((peer->transports & peer2->transports) & (SIP_TRANSPORT_TLS | SIP_TRANSPORT_TCP)) { 28033 /* peer matching on port is not possible with TCP/TLS */ 28034 return CMP_MATCH | CMP_STOP; 28035 } else if (ast_test_flag(&peer2->flags[0], SIP_INSECURE_PORT)) { 28036 /* We are allowing match without port for peers configured that 28037 * way in this pass through the peers. */ 28038 return ast_test_flag(&peer->flags[0], SIP_INSECURE_PORT) ? 28039 (CMP_MATCH | CMP_STOP) : 0; 28040 } 28041 28042 /* Now only return a match if the port matches, as well. */ 28043 return ast_sockaddr_port(&peer->addr) == ast_sockaddr_port(&peer2->addr) ? 28044 (CMP_MATCH | CMP_STOP) : 0; 28045 }
| static int peer_iphash_cb | ( | const void * | obj, | |
| const int | flags | |||
| ) | [static] |
Hash function based on the the peer's ip address. For IPv6, we use the end of the address.
Definition at line 27986 of file chan_sip.c.
References ast_log(), ast_sockaddr_hash(), ast_sockaddr_isnull(), and LOG_ERROR.
Referenced by load_module().
27987 { 27988 const struct sip_peer *peer = obj; 27989 int ret = 0; 27990 27991 if (ast_sockaddr_isnull(&peer->addr)) { 27992 ast_log(LOG_ERROR, "Empty address\n"); 27993 } 27994 27995 ret = ast_sockaddr_hash(&peer->addr); 27996 27997 if (ret < 0) { 27998 ret = -ret; 27999 } 28000 28001 return ret; 28002 }
| static int peer_is_marked | ( | void * | peerobj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 2627 of file chan_sip.c.
References CMP_MATCH.
Referenced by unlink_marked_peers_from_tables().
02628 { 02629 struct sip_peer *peer = peerobj; 02630 return peer->the_mark ? CMP_MATCH : 0; 02631 }
| static void peer_mailboxes_to_str | ( | struct ast_str ** | mailbox_str, | |
| struct sip_peer * | peer | |||
| ) | [static] |
list peer mailboxes to CLI
Definition at line 16171 of file chan_sip.c.
References AST_LIST_NEXT, AST_LIST_TRAVERSE, ast_str_append(), ast_strlen_zero(), mailbox, and S_OR.
Referenced by _sip_show_peer(), function_sippeer(), show_channels_cb(), and sip_send_mwi_to_peer().
16172 { 16173 struct sip_mailbox *mailbox; 16174 16175 AST_LIST_TRAVERSE(&peer->mailboxes, mailbox, entry) { 16176 ast_str_append(mailbox_str, 0, "%s%s%s%s", 16177 mailbox->mailbox, 16178 ast_strlen_zero(mailbox->context) ? "" : "@", 16179 S_OR(mailbox->context, ""), 16180 AST_LIST_NEXT(mailbox, entry) ? "," : ""); 16181 } 16182 }
| static int peer_markall_func | ( | void * | device, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
| static int peer_status | ( | struct sip_peer * | peer, | |
| char * | status, | |||
| int | statuslen | |||
| ) | [static] |
Definition at line 15278 of file chan_sip.c.
References ast_copy_string().
15279 { 15280 int res = 0; 15281 if (peer->maxms) { 15282 if (peer->lastms < 0) { 15283 ast_copy_string(status, "UNREACHABLE", statuslen); 15284 } else if (peer->lastms > peer->maxms) { 15285 snprintf(status, statuslen, "LAGGED (%d ms)", peer->lastms); 15286 res = 1; 15287 } else if (peer->lastms) { 15288 snprintf(status, statuslen, "OK (%d ms)", peer->lastms); 15289 res = 1; 15290 } else { 15291 ast_copy_string(status, "UNKNOWN", statuslen); 15292 } 15293 } else { 15294 ast_copy_string(status, "Unmonitored", statuslen); 15295 /* Checking if port is 0 */ 15296 res = -1; 15297 } 15298 return res; 15299 }
| int peercomparefunc | ( | const void * | a, | |
| const void * | b | |||
| ) |
Definition at line 15506 of file chan_sip.c.
Referenced by _sip_show_peers().
15507 { 15508 struct sip_peer **ap = (struct sip_peer **)a; 15509 struct sip_peer **bp = (struct sip_peer **)b; 15510 return strcmp((*ap)->name, (*bp)->name); 15511 }
| static int peers_data_provider_get | ( | const struct ast_data_search * | search, | |
| struct ast_data * | data_root | |||
| ) | [static] |
Definition at line 28252 of file chan_sip.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ARRAY_LEN, ast_cdr_flags2str(), ast_data_add_bool(), ast_data_add_codecs(), ast_data_add_int(), ast_data_add_node(), ast_data_add_str(), ast_data_add_structure, ast_data_remove_node(), ast_data_search_match(), ast_describe_caller_presentation(), AST_LIST_TRAVERSE, get_transport_list(), mailbox, text, and transfermode2str().
28254 { 28255 struct sip_peer *peer; 28256 struct ao2_iterator i; 28257 struct ast_data *data_peer, *data_peer_mailboxes = NULL, *data_peer_mailbox, *enum_node; 28258 struct ast_data *data_sip_options; 28259 int total_mailboxes, x; 28260 struct sip_mailbox *mailbox; 28261 28262 i = ao2_iterator_init(peers, 0); 28263 while ((peer = ao2_iterator_next(&i))) { 28264 ao2_lock(peer); 28265 28266 data_peer = ast_data_add_node(data_root, "peer"); 28267 if (!data_peer) { 28268 ao2_unlock(peer); 28269 ao2_ref(peer, -1); 28270 continue; 28271 } 28272 28273 ast_data_add_structure(sip_peer, data_peer, peer); 28274 28275 /* transfer mode */ 28276 enum_node = ast_data_add_node(data_peer, "allowtransfer"); 28277 if (!enum_node) { 28278 continue; 28279 } 28280 ast_data_add_str(enum_node, "text", transfermode2str(peer->allowtransfer)); 28281 ast_data_add_int(enum_node, "value", peer->allowtransfer); 28282 28283 /* transports */ 28284 ast_data_add_str(data_peer, "transports", get_transport_list(peer->transports)); 28285 28286 /* peer type */ 28287 if ((peer->type & SIP_TYPE_USER) && (peer->type & SIP_TYPE_PEER)) { 28288 ast_data_add_str(data_peer, "type", "friend"); 28289 } else if (peer->type & SIP_TYPE_PEER) { 28290 ast_data_add_str(data_peer, "type", "peer"); 28291 } else if (peer->type & SIP_TYPE_USER) { 28292 ast_data_add_str(data_peer, "type", "user"); 28293 } 28294 28295 /* mailboxes */ 28296 total_mailboxes = 0; 28297 AST_LIST_TRAVERSE(&peer->mailboxes, mailbox, entry) { 28298 if (!total_mailboxes) { 28299 data_peer_mailboxes = ast_data_add_node(data_peer, "mailboxes"); 28300 if (!data_peer_mailboxes) { 28301 break; 28302 } 28303 total_mailboxes++; 28304 } 28305 28306 data_peer_mailbox = ast_data_add_node(data_peer_mailboxes, "mailbox"); 28307 if (!data_peer_mailbox) { 28308 continue; 28309 } 28310 ast_data_add_str(data_peer_mailbox, "mailbox", mailbox->mailbox); 28311 ast_data_add_str(data_peer_mailbox, "context", mailbox->context); 28312 } 28313 28314 /* amaflags */ 28315 enum_node = ast_data_add_node(data_peer, "amaflags"); 28316 if (!enum_node) { 28317 continue; 28318 } 28319 ast_data_add_int(enum_node, "value", peer->amaflags); 28320 ast_data_add_str(enum_node, "text", ast_cdr_flags2str(peer->amaflags)); 28321 28322 /* sip options */ 28323 data_sip_options = ast_data_add_node(data_peer, "sipoptions"); 28324 if (!data_sip_options) { 28325 continue; 28326 } 28327 for (x = 0 ; x < ARRAY_LEN(sip_options); x++) { 28328 ast_data_add_bool(data_sip_options, sip_options[x].text, peer->sipoptions & sip_options[x].id); 28329 } 28330 28331 /* callingpres */ 28332 enum_node = ast_data_add_node(data_peer, "callingpres"); 28333 if (!enum_node) { 28334 continue; 28335 } 28336 ast_data_add_int(enum_node, "value", peer->callingpres); 28337 ast_data_add_str(enum_node, "text", ast_describe_caller_presentation(peer->callingpres)); 28338 28339 /* codecs */ 28340 ast_data_add_codecs(data_peer, "codecs", peer->capability); 28341 28342 if (!ast_data_search_match(search, data_peer)) { 28343 ast_data_remove_node(data_root, data_peer); 28344 } 28345 28346 ao2_unlock(peer); 28347 ao2_ref(peer, -1); 28348 } 28349 ao2_iterator_destroy(&i); 28350 28351 return 0; 28352 }
| 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.
Definition at line 2863 of file chan_sip.c.
References ast_strlen_zero().
Referenced by build_peer(), and reload_config().
02864 { 02865 int port = standard; 02866 if (ast_strlen_zero(pt) || (sscanf(pt, "%30d", &port) != 1) || (port < 1) || (port > 65535)) { 02867 port = standard; 02868 } 02869 02870 return port; 02871 }
| static void print_codec_to_cli | ( | int | fd, | |
| struct ast_codec_pref * | pref | |||
| ) | [static] |
Print codec list from preference to CLI/manager.
Definition at line 16008 of file chan_sip.c.
References ast_cli(), ast_codec_pref_index(), ast_getformatname(), and ast_codec_pref::framing.
Referenced by _sip_show_peer(), _skinny_show_line(), sip_show_settings(), and sip_show_user().
16009 { 16010 int x; 16011 format_t codec; 16012 16013 for(x = 0; x < 64 ; x++) { 16014 codec = ast_codec_pref_index(pref, x); 16015 if (!codec) 16016 break; 16017 ast_cli(fd, "%s", ast_getformatname(codec)); 16018 ast_cli(fd, ":%d", pref->framing[x]); 16019 if (x < 31 && ast_codec_pref_index(pref, x + 1)) 16020 ast_cli(fd, ","); 16021 } 16022 if (!x) 16023 ast_cli(fd, "none"); 16024 }
| static void print_group | ( | int | fd, | |
| ast_group_t | group, | |||
| int | crlf | |||
| ) | [static] |
Print call group and pickup group.
Definition at line 15738 of file chan_sip.c.
References ast_cli(), and ast_print_group().
Referenced by _sip_show_peer(), and sip_show_user().
15739 { 15740 char buf[256]; 15741 ast_cli(fd, crlf ? "%s\r\n" : "%s\n", ast_print_group(buf, sizeof(buf), group) ); 15742 }
| static void proc_422_rsp | ( | struct sip_pvt * | p, | |
| struct sip_request * | rsp | |||
| ) | [static] |
Handle 422 response to INVITE with session-timer requested.
Session-Timers: An INVITE originated by Asterisk that asks for session-timers support from the UAS can result into a 422 response. This is how a UAS or an intermediary proxy server tells Asterisk that the session refresh interval offered by Asterisk is too low for them. The proc_422_rsp() function handles a 422 response. It extracts the Min-SE header that comes back in 422 and sends a new INVITE accordingly.
Definition at line 24543 of file chan_sip.c.
References ast_log(), ast_strlen_zero(), get_header(), LOG_WARNING, parse_minse(), and transmit_invite().
Referenced by handle_response_invite().
24544 { 24545 int rtn; 24546 const char *p_hdrval; 24547 int minse; 24548 24549 p_hdrval = get_header(rsp, "Min-SE"); 24550 if (ast_strlen_zero(p_hdrval)) { 24551 ast_log(LOG_WARNING, "422 response without a Min-SE header %s\n", p_hdrval); 24552 return; 24553 } 24554 rtn = parse_minse(p_hdrval, &minse); 24555 if (rtn != 0) { 24556 ast_log(LOG_WARNING, "Parsing of Min-SE header failed %s\n", p_hdrval); 24557 return; 24558 } 24559 p->stimer->st_interval = minse; 24560 transmit_invite(p, SIP_INVITE, 1, 2, NULL); 24561 }
| static int proc_session_timer | ( | const void * | vp | ) | [static] |
Session-Timers: Process session refresh timeout event.
Definition at line 24383 of file chan_sip.c.
References ast_channel_trylock, ast_channel_unlock, ast_debug, ast_log(), AST_SOFTHANGUP_DEV, ast_softhangup_nolock(), AST_STATE_UP, FALSE, LOG_ERROR, LOG_WARNING, sip_pvt_lock, sip_pvt_unlock, stop_session_timer(), transmit_reinvite_with_sdp(), and TRUE.
Referenced by start_session_timer().
24384 { 24385 struct sip_pvt *p = (struct sip_pvt *) vp; 24386 int sendreinv = FALSE; 24387 int res = 0; 24388 24389 if (!p->stimer) { 24390 ast_log(LOG_WARNING, "Null stimer in proc_session_timer - %s\n", p->callid); 24391 goto return_unref; 24392 } 24393 24394 ast_debug(2, "Session timer expired: %d - %s\n", p->stimer->st_schedid, p->callid); 24395 24396 if (!p->owner) { 24397 goto return_unref; 24398 } 24399 24400 if ((p->stimer->st_active != TRUE) || (p->owner->_state != AST_STATE_UP)) { 24401 goto return_unref; 24402 } 24403 24404 switch (p->stimer->st_ref) { 24405 case SESSION_TIMER_REFRESHER_UAC: 24406 if (p->outgoing_call == TRUE) { 24407 sendreinv = TRUE; 24408 } 24409 break; 24410 case SESSION_TIMER_REFRESHER_UAS: 24411 if (p->outgoing_call != TRUE) { 24412 sendreinv = TRUE; 24413 } 24414 break; 24415 default: 24416 ast_log(LOG_ERROR, "Unknown session refresher %d\n", p->stimer->st_ref); 24417 goto return_unref; 24418 } 24419 24420 if (sendreinv == TRUE) { 24421 res = 1; 24422 transmit_reinvite_with_sdp(p, FALSE, TRUE); 24423 } else { 24424 p->stimer->st_expirys++; 24425 if (p->stimer->st_expirys >= 2) { 24426 if (p->stimer->quit_flag) { 24427 goto return_unref; 24428 } 24429 ast_log(LOG_WARNING, "Session-Timer expired - %s\n", p->callid); 24430 sip_pvt_lock(p); 24431 while (p->owner && ast_channel_trylock(p->owner)) { 24432 sip_pvt_unlock(p); 24433 usleep(1); 24434 if (p->stimer && p->stimer->quit_flag) { 24435 goto return_unref; 24436 } 24437 sip_pvt_lock(p); 24438 } 24439 24440 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_DEV); 24441 ast_channel_unlock(p->owner); 24442 sip_pvt_unlock(p); 24443 } 24444 } 24445 24446 return_unref: 24447 if (!res) { 24448 /* An error occurred. Stop session timer processing */ 24449 if (p->stimer) { 24450 p->stimer->st_schedid = -1; 24451 stop_session_timer(p); 24452 } 24453 24454 /* If we are not asking to be rescheduled, then we need to release our 24455 * reference to the dialog. */ 24456 dialog_unref(p, "removing session timer ref"); 24457 } 24458 24459 return res; 24460 }
| static int process_crypto | ( | struct sip_pvt * | p, | |
| struct ast_rtp_instance * | rtp, | |||
| struct sip_srtp ** | srtp, | |||
| const char * | a | |||
| ) | [static] |
Definition at line 27825 of file chan_sip.c.
References ast_debug, ast_log(), ast_set_flag, ast_test_flag, FALSE, LOG_WARNING, setup_srtp(), and TRUE.
Referenced by process_sdp().
27826 { 27827 if (strncasecmp(a, "crypto:", 7)) { 27828 return FALSE; 27829 } 27830 if (!*srtp) { 27831 if (ast_test_flag(&p->flags[0], SIP_OUTGOING)) { 27832 ast_log(LOG_WARNING, "Ignoring unexpected crypto attribute in SDP answer\n"); 27833 return FALSE; 27834 } 27835 27836 if (setup_srtp(srtp) < 0) { 27837 return FALSE; 27838 } 27839 } 27840 27841 /* For now, when we receive an INVITE just take the first successful crypto line */ 27842 if ((*srtp)->crypto && !ast_test_flag(&p->flags[0], SIP_OUTGOING)) { 27843 ast_debug(3, "We've already processed a crypto attribute, skipping '%s'\n", a); 27844 return FALSE; 27845 } 27846 27847 if (!(*srtp)->crypto && !((*srtp)->crypto = sdp_crypto_setup())) { 27848 return FALSE; 27849 } 27850 27851 if (sdp_crypto_process((*srtp)->crypto, a, rtp) < 0) { 27852 return FALSE; 27853 } 27854 27855 ast_set_flag(*srtp, SRTP_CRYPTO_OFFER_OK); 27856 27857 return TRUE; 27858 }
| static void process_request_queue | ( | struct sip_pvt * | p, | |
| int * | recount, | |||
| int * | nounlock | |||
| ) | [static] |
Definition at line 23643 of file chan_sip.c.
References ast_debug, ast_free, AST_LIST_REMOVE_HEAD, and handle_incoming().
Referenced by handle_request_do(), and scheduler_process_request_queue().
23644 { 23645 struct sip_request *req; 23646 23647 while ((req = AST_LIST_REMOVE_HEAD(&p->request_queue, next))) { 23648 if (handle_incoming(p, req, &p->recv, recount, nounlock) == -1) { 23649 /* Request failed */ 23650 ast_debug(1, "SIP message could not be handled, bad request: %-70.70s\n", p->callid[0] ? p->callid : "<no callid>"); 23651 } 23652 ast_free(req); 23653 } 23654 }
| static int process_sdp | ( | struct sip_pvt * | p, | |
| struct sip_request * | req, | |||
| int | t38action | |||
| ) | [static] |
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().
< RTP Audio host IP
< RTP video host IP
< RTP text host IP
< UDPTL host ip
< RTP Audio port number
< RTP Video port number
< RTP Text port number
< UDPTL Image port number
Definition at line 7993 of file chan_sip.c.
References append_history, ast_async_goto(), ast_channel_lock, ast_channel_unlock, ast_clear_flag, ast_codec_choose(), AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, ast_copy_string(), ast_debug, ast_exists_extension(), AST_FORMAT_AUDIO_MASK, AST_FORMAT_T140RED, ast_getformatname_multiple(), ast_log(), ast_manager_event, ast_null_frame, ast_queue_control(), ast_queue_control_data(), ast_queue_frame(), ast_rtp_codecs_payload_formats(), ast_rtp_codecs_payloads_clear(), ast_rtp_codecs_payloads_copy(), ast_rtp_codecs_payloads_set_m_type(), AST_RTP_DTMF, ast_rtp_instance_get_codecs(), ast_rtp_instance_get_remote_address(), ast_rtp_instance_set_prop(), ast_rtp_instance_set_remote_address(), ast_rtp_instance_stop(), ast_rtp_lookup_mime_multiple2(), AST_RTP_PROPERTY_DTMF, AST_RTP_PROPERTY_DTMF_COMPENSATE, ast_rtp_red_init(), ast_set_flag, ast_set_read_format(), ast_set_write_format(), ast_skip_blanks(), ast_sockaddr_isnull(), ast_sockaddr_set_port, ast_sockaddr_stringify(), ast_str_alloca, ast_strlen_zero(), ast_test_flag, ast_udptl_get_far_max_datagram(), ast_udptl_set_error_correction_scheme(), ast_udptl_set_far_max_datagram(), ast_udptl_set_peer(), ast_udptl_stop(), ast_verbose, change_t38_state(), debug, EVENT_FLAG_CALL, FALSE, get_sdp_iterate(), get_sdp_line(), len(), LOG_ERROR, LOG_NOTICE, LOG_WARNING, pbx_builtin_setvar_helper(), process_crypto(), process_sdp_a_audio(), process_sdp_a_image(), process_sdp_a_sendonly(), process_sdp_a_text(), process_sdp_a_video(), process_sdp_c(), process_sdp_o(), S_COR, S_OR, sip_cfg, sip_debug_test_pvt(), sip_peer_hold(), text, TRUE, type, UDPTL_ERROR_CORRECTION_NONE, value, and VERBOSE_PREFIX_2.
07994 { 07995 /* Iterators for SDP parsing */ 07996 int start = req->sdp_start; 07997 int next = start; 07998 int iterator = start; 07999 08000 /* Temporary vars for SDP parsing */ 08001 char type = '\0'; 08002 const char *value = NULL; 08003 const char *m = NULL; /* SDP media offer */ 08004 const char *nextm = NULL; 08005 int len = -1; 08006 08007 /* Host information */ 08008 struct ast_sockaddr sessionsa; 08009 struct ast_sockaddr audiosa; 08010 struct ast_sockaddr videosa; 08011 struct ast_sockaddr textsa; 08012 struct ast_sockaddr imagesa; 08013 struct ast_sockaddr *sa = NULL; /*!< RTP Audio host IP */ 08014 struct ast_sockaddr *vsa = NULL; /*!< RTP video host IP */ 08015 struct ast_sockaddr *tsa = NULL; /*!< RTP text host IP */ 08016 struct ast_sockaddr *isa = NULL; /*!< UDPTL host ip */ 08017 int portno = -1; /*!< RTP Audio port number */ 08018 int vportno = -1; /*!< RTP Video port number */ 08019 int tportno = -1; /*!< RTP Text port number */ 08020 int udptlportno = -1; /*!< UDPTL Image port number */ 08021 08022 /* Peer capability is the capability in the SDP, non codec is RFC2833 DTMF (101) */ 08023 format_t peercapability = 0, vpeercapability = 0, tpeercapability = 0; 08024 int peernoncodeccapability = 0, vpeernoncodeccapability = 0, tpeernoncodeccapability = 0; 08025 08026 struct ast_rtp_codecs newaudiortp, newvideortp, newtextrtp; 08027 format_t newjointcapability; /* Negotiated capability */ 08028 format_t newpeercapability; 08029 int newnoncodeccapability; 08030 08031 const char *codecs; 08032 int codec; 08033 08034 /* SRTP */ 08035 int secure_audio = FALSE; 08036 int secure_video = FALSE; 08037 08038 /* Others */ 08039 int sendonly = -1; 08040 int vsendonly = -1; 08041 int numberofports; 08042 int numberofmediastreams = 0; 08043 int last_rtpmap_codec = 0; 08044 int red_data_pt[10]; /* For T.140 red */ 08045 int red_num_gen = 0; /* For T.140 red */ 08046 char red_fmtp[100] = "empty"; /* For T.140 red */ 08047 int debug = sip_debug_test_pvt(p); 08048 08049 /* START UNKNOWN */ 08050 char buf[SIPBUFSIZE]; 08051 /* END UNKNOWN */ 08052 08053 /* Initial check */ 08054 if (!p->rtp) { 08055 ast_log(LOG_ERROR, "Got SDP but have no RTP session allocated.\n"); 08056 return -1; 08057 } 08058 08059 /* Make sure that the codec structures are all cleared out */ 08060 ast_rtp_codecs_payloads_clear(&newaudiortp, NULL); 08061 ast_rtp_codecs_payloads_clear(&newvideortp, NULL); 08062 ast_rtp_codecs_payloads_clear(&newtextrtp, NULL); 08063 08064 /* Update our last rtprx when we receive an SDP, too */ 08065 p->lastrtprx = p->lastrtptx = time(NULL); /* XXX why both ? */ 08066 08067 memset(p->offered_media, 0, sizeof(p->offered_media)); 08068 08069 08070 /* default: novideo and notext set */ 08071 p->novideo = TRUE; 08072 p->notext = TRUE; 08073 08074 if (p->vrtp) { 08075 ast_rtp_codecs_payloads_clear(&newvideortp, NULL); 08076 } 08077 08078 if (p->trtp) { 08079 ast_rtp_codecs_payloads_clear(&newtextrtp, NULL); 08080 } 08081 08082 /* Scan for the first media stream (m=) line to limit scanning of globals */ 08083 nextm = get_sdp_iterate(&next, req, "m"); 08084 if (ast_strlen_zero(nextm)) { 08085 ast_log(LOG_WARNING, "Insufficient information for SDP (m= not found)\n"); 08086 return -1; 08087 } 08088 08089 /* Scan session level SDP parameters (lines before first media stream) */ 08090 while ((type = get_sdp_line(&iterator, next - 1, req, &value)) != '\0') { 08091 int processed = FALSE; 08092 switch (type) { 08093 case 'o': 08094 /* If we end up receiving SDP that doesn't actually modify the session we don't want to treat this as a fatal 08095 * error. We just want to ignore the SDP and let the rest of the packet be handled as normal. 08096 */ 08097 if (!process_sdp_o(value, p)) 08098 return (p->session_modify == FALSE) ? 0 : -1; 08099 break; 08100 case 'c': 08101 if (process_sdp_c(value, &sessionsa)) { 08102 processed = TRUE; 08103 sa = &sessionsa; 08104 vsa = sa; 08105 tsa = sa; 08106 isa = sa; 08107 } 08108 break; 08109 case 'a': 08110 if (process_sdp_a_sendonly(value, &sendonly)) { 08111 processed = TRUE; 08112 vsendonly = sendonly; 08113 } 08114 else if (process_sdp_a_audio(value, p, &newaudiortp, &last_rtpmap_codec)) 08115 processed = TRUE; 08116 else if (process_sdp_a_video(value, p, &newvideortp, &last_rtpmap_codec)) 08117 processed = TRUE; 08118 else if (process_sdp_a_text(value, p, &newtextrtp, red_fmtp, &red_num_gen, red_data_pt, &last_rtpmap_codec)) 08119 processed = TRUE; 08120 else if (process_sdp_a_image(value, p)) 08121 processed = TRUE; 08122 break; 08123 } 08124 08125 ast_debug(3, "Processing session-level SDP %c=%s... %s\n", type, value, (processed == TRUE)? "OK." : "UNSUPPORTED."); 08126 } 08127 08128 08129 08130 /* Scan media stream (m=) specific parameters loop */ 08131 while (!ast_strlen_zero(nextm)) { 08132 int audio = FALSE; 08133 int video = FALSE; 08134 int image = FALSE; 08135 int text = FALSE; 08136 char protocol[5] = {0,}; 08137 int x; 08138 08139 numberofports = 1; 08140 len = -1; 08141 start = next; 08142 m = nextm; 08143 iterator = next; 08144 nextm = get_sdp_iterate(&next, req, "m"); 08145 08146 /* Search for audio media definition */ 08147 if ((sscanf(m, "audio %30u/%30u RTP/%4s %n", &x, &numberofports, protocol, &len) == 3 && len > 0) || 08148 (sscanf(m, "audio %30u RTP/%4s %n", &x, protocol, &len) == 2 && len > 0)) { 08149 if (!strcmp(protocol, "SAVP")) { 08150 secure_audio = 1; 08151 } else if (strcmp(protocol, "AVP")) { 08152 ast_log(LOG_WARNING, "unknown SDP media protocol in offer: %s\n", protocol); 08153 continue; 08154 } 08155 audio = TRUE; 08156 p->offered_media[SDP_AUDIO].offered = TRUE; 08157 numberofmediastreams++; 08158 portno = x; 08159 08160 /* Scan through the RTP payload types specified in a "m=" line: */ 08161 codecs = m + len; 08162 ast_copy_string(p->offered_media[SDP_AUDIO].codecs, codecs, sizeof(p->offered_media[SDP_AUDIO].codecs)); 08163 for (; !ast_strlen_zero(codecs); codecs = ast_skip_blanks(codecs + len)) { 08164 if (sscanf(codecs, "%30u%n", &codec, &len) != 1) { 08165 ast_log(LOG_WARNING, "Error in codec string '%s'\n", codecs); 08166 return -1; 08167 } 08168 if (debug) 08169 ast_verbose("Found RTP audio format %d\n", codec); 08170 08171 ast_rtp_codecs_payloads_set_m_type(&newaudiortp, NULL, codec); 08172 } 08173 /* Search for video media definition */ 08174 } else if ((sscanf(m, "video %30u/%30u RTP/%4s %n", &x, &numberofports, protocol, &len) == 3 && len > 0) || 08175 (sscanf(m, "video %30u RTP/%4s %n", &x, protocol, &len) == 2 && len >= 0)) { 08176 if (!strcmp(protocol, "SAVP")) { 08177 secure_video = 1; 08178 } else if (strcmp(protocol, "AVP")) { 08179 ast_log(LOG_WARNING, "unknown SDP media protocol in offer: %s\n", protocol); 08180 continue; 08181 } 08182 video = TRUE; 08183 p->novideo = FALSE; 08184 p->offered_media[SDP_VIDEO].offered = TRUE; 08185 numberofmediastreams++; 08186 vportno = x; 08187 08188 /* Scan through the RTP payload types specified in a "m=" line: */ 08189 codecs = m + len; 08190 ast_copy_string(p->offered_media[SDP_VIDEO].codecs, codecs, sizeof(p->offered_media[SDP_VIDEO].codecs)); 08191 for (; !ast_strlen_zero(codecs); codecs = ast_skip_blanks(codecs + len)) { 08192 if (sscanf(codecs, "%30u%n", &codec, &len) != 1) { 08193 ast_log(LOG_WARNING, "Error in codec string '%s'\n", codecs); 08194 return -1; 08195 } 08196 if (debug) 08197 ast_verbose("Found RTP video format %d\n", codec); 08198 ast_rtp_codecs_payloads_set_m_type(&newvideortp, NULL, codec); 08199 } 08200 /* Search for text media definition */ 08201 } else if ((sscanf(m, "text %30u/%30u RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) || 08202 (sscanf(m, "text %30u RTP/AVP %n", &x, &len) == 1 && len > 0)) { 08203 text = TRUE; 08204 p->notext = FALSE; 08205 p->offered_media[SDP_TEXT].offered = TRUE; 08206 numberofmediastreams++; 08207 tportno = x; 08208 08209 /* Scan through the RTP payload types specified in a "m=" line: */ 08210 codecs = m + len; 08211 ast_copy_string(p->offered_media[SDP_TEXT].codecs, codecs, sizeof(p->offered_media[SDP_TEXT].codecs)); 08212 for (; !ast_strlen_zero(codecs); codecs = ast_skip_blanks(codecs + len)) { 08213 if (sscanf(codecs, "%30u%n", &codec, &len) != 1) { 08214 ast_log(LOG_WARNING, "Error in codec string '%s'\n", codecs); 08215 return -1; 08216 } 08217 if (debug) 08218 ast_verbose("Found RTP text format %d\n", codec); 08219 ast_rtp_codecs_payloads_set_m_type(&newtextrtp, NULL, codec); 08220 } 08221 /* Search for image media definition */ 08222 } else if (p->udptl && ((sscanf(m, "image %30u udptl t38%n", &x, &len) == 1 && len > 0) || 08223 (sscanf(m, "image %30u UDPTL t38%n", &x, &len) == 1 && len > 0) )) { 08224 image = TRUE; 08225 if (debug) 08226 ast_verbose("Got T.38 offer in SDP in dialog %s\n", p->callid); 08227 p->offered_media[SDP_IMAGE].offered = TRUE; 08228 udptlportno = x; 08229 numberofmediastreams++; 08230 08231 if (p->t38.state != T38_ENABLED) { 08232 memset(&p->t38.their_parms, 0, sizeof(p->t38.their_parms)); 08233 08234 /* default EC to none, the remote end should 08235 * respond with the EC they want to use */ 08236 ast_udptl_set_error_correction_scheme(p->udptl, UDPTL_ERROR_CORRECTION_NONE); 08237 } 08238 } else { 08239 ast_log(LOG_WARNING, "Unsupported SDP media type in offer: %s\n", m); 08240 continue; 08241 } 08242 08243 /* Check for number of ports */ 08244 if (numberofports > 1) 08245 ast_log(LOG_WARNING, "SDP offered %d ports for media, not supported by Asterisk. Will try anyway...\n", numberofports); 08246 08247 /* Media stream specific parameters */ 08248 while ((type = get_sdp_line(&iterator, next - 1, req, &value)) != '\0') { 08249 int processed = FALSE; 08250 08251 switch (type) { 08252 case 'c': 08253 if (audio) { 08254 if (process_sdp_c(value, &audiosa)) { 08255 processed = TRUE; 08256 sa = &audiosa; 08257 } 08258 } else if (video) { 08259 if (process_sdp_c(value, &videosa)) { 08260 processed = TRUE; 08261 vsa = &videosa; 08262 } 08263 } else if (text) { 08264 if (process_sdp_c(value, &textsa)) { 08265 processed = TRUE; 08266 tsa = &textsa; 08267 } 08268 } else if (image) { 08269 if (process_sdp_c(value, &imagesa)) { 08270 processed = TRUE; 08271 isa = &imagesa; 08272 } 08273 } 08274 break; 08275 case 'a': 08276 /* Audio specific scanning */ 08277 if (audio) { 08278 if (process_sdp_a_sendonly(value, &sendonly)) 08279 processed = TRUE; 08280 else if (process_crypto(p, p->rtp, &p->srtp, value)) 08281 processed = TRUE; 08282 else if (process_sdp_a_audio(value, p, &newaudiortp, &last_rtpmap_codec)) 08283 processed = TRUE; 08284 } 08285 /* Video specific scanning */ 08286 else if (video) { 08287 if (process_sdp_a_sendonly(value, &vsendonly)) 08288 processed = TRUE; 08289 else if (process_crypto(p, p->vrtp, &p->vsrtp, value)) 08290 processed = TRUE; 08291 else if (process_sdp_a_video(value, p, &newvideortp, &last_rtpmap_codec)) 08292 processed = TRUE; 08293 } 08294 /* Text (T.140) specific scanning */ 08295 else if (text) { 08296 if (process_sdp_a_text(value, p, &newtextrtp, red_fmtp, &red_num_gen, red_data_pt, &last_rtpmap_codec)) 08297 processed = TRUE; 08298 else if (process_crypto(p, p->trtp, &p->tsrtp, value)) 08299 processed = TRUE; 08300 } 08301 /* Image (T.38 FAX) specific scanning */ 08302 else if (image) { 08303 if (process_sdp_a_image(value, p)) 08304 processed = TRUE; 08305 } 08306 break; 08307 } 08308 08309 ast_debug(3, "Processing media-level (%s) SDP %c=%s... %s\n", 08310 (audio == TRUE)? "audio" : (video == TRUE)? "video" : "image", 08311 type, value, 08312 (processed == TRUE)? "OK." : "UNSUPPORTED."); 08313 } 08314 } 08315 08316 08317 /* Sanity checks */ 08318 if (!sa && !vsa && !tsa && !isa) { 08319 ast_log(LOG_WARNING, "Insufficient information in SDP (c=)...\n"); 08320 return -1; 08321 } 08322 08323 if (portno == -1 && vportno == -1 && udptlportno == -1 && tportno == -1) { 08324 /* No acceptable offer found in SDP - we have no ports */ 08325 /* Do not change RTP or VRTP if this is a re-invite */ 08326 ast_log(LOG_WARNING, "Failing due to no acceptable offer found\n"); 08327 return -2; 08328 } 08329 08330 if (numberofmediastreams > 3) { 08331 /* We have too many fax, audio and/or video and/or text media streams, fail this offer */ 08332 ast_log(LOG_WARNING, "Faling due to too many media streams\n"); 08333 return -3; 08334 } 08335 08336 if (secure_audio && !(p->srtp && (ast_test_flag(p->srtp, SRTP_CRYPTO_OFFER_OK)))) { 08337 ast_log(LOG_WARNING, "Can't provide secure audio requested in SDP offer\n"); 08338 return -4; 08339 } 08340 08341 if (!secure_audio && p->srtp) { 08342 ast_log(LOG_WARNING, "We are requesting SRTP, but they responded without it!\n"); 08343 return -4; 08344 } 08345 08346 if (secure_video && !(p->vsrtp && (ast_test_flag(p->vsrtp, SRTP_CRYPTO_OFFER_OK)))) { 08347 ast_log(LOG_WARNING, "Can't provide secure video requested in SDP offer\n"); 08348 return -4; 08349 } 08350 08351 if (!p->novideo && !secure_video && p->vsrtp) { 08352 ast_log(LOG_WARNING, "We are requesting SRTP, but they responded without it!\n"); 08353 return -4; 08354 } 08355 08356 if (!(secure_audio || secure_video) && ast_test_flag(&p->flags[1], SIP_PAGE2_USE_SRTP)) { 08357 ast_log(LOG_WARNING, "Matched device setup to use SRTP, but request was not!\n"); 08358 return -4; 08359 } 08360 08361 if (udptlportno == -1) { 08362 change_t38_state(p, T38_DISABLED); 08363 } 08364 08365 /* Now gather all of the codecs that we are asked for: */ 08366 ast_rtp_codecs_payload_formats(&newaudiortp, &peercapability, &peernoncodeccapability); 08367 ast_rtp_codecs_payload_formats(&newvideortp, &vpeercapability, &vpeernoncodeccapability); 08368 ast_rtp_codecs_payload_formats(&newtextrtp, &tpeercapability, &tpeernoncodeccapability); 08369 08370 newjointcapability = p->capability & (peercapability | vpeercapability | tpeercapability); 08371 newpeercapability = (peercapability | vpeercapability | tpeercapability); 08372 newnoncodeccapability = p->noncodeccapability & peernoncodeccapability; 08373 08374 if (debug) { 08375 /* shame on whoever coded this.... */ 08376 char s1[SIPBUFSIZE], s2[SIPBUFSIZE], s3[SIPBUFSIZE], s4[SIPBUFSIZE], s5[SIPBUFSIZE]; 08377 08378 ast_verbose("Capabilities: us - %s, peer - audio=%s/video=%s/text=%s, combined - %s\n", 08379 ast_getformatname_multiple(s1, SIPBUFSIZE, p->capability), 08380 ast_getformatname_multiple(s2, SIPBUFSIZE, peercapability), 08381 ast_getformatname_multiple(s3, SIPBUFSIZE, vpeercapability), 08382 ast_getformatname_multiple(s4, SIPBUFSIZE, tpeercapability), 08383 ast_getformatname_multiple(s5, SIPBUFSIZE, newjointcapability)); 08384 } 08385 if (debug) { 08386 struct ast_str *s1 = ast_str_alloca(SIPBUFSIZE); 08387 struct ast_str *s2 = ast_str_alloca(SIPBUFSIZE); 08388 struct ast_str *s3 = ast_str_alloca(SIPBUFSIZE); 08389 08390 ast_verbose("Non-codec capabilities (dtmf): us - %s, peer - %s, combined - %s\n", 08391 ast_rtp_lookup_mime_multiple2(s1, p->noncodeccapability, 0, 0), 08392 ast_rtp_lookup_mime_multiple2(s2, peernoncodeccapability, 0, 0), 08393 ast_rtp_lookup_mime_multiple2(s3, newnoncodeccapability, 0, 0)); 08394 } 08395 if (!newjointcapability && (portno != -1)) { 08396 ast_log(LOG_NOTICE, "No compatible codecs, not accepting this offer!\n"); 08397 /* Do NOT Change current setting */ 08398 return -1; 08399 } 08400 08401 /* Setup audio address and port */ 08402 if (p->rtp) { 08403 if (portno > 0) { 08404 ast_sockaddr_set_port(sa, portno); 08405 ast_rtp_instance_set_remote_address(p->rtp, sa); 08406 if (debug) { 08407 ast_verbose("Peer audio RTP is at port %s\n", 08408 ast_sockaddr_stringify(sa)); 08409 } 08410 /* We are now ready to change the sip session and p->rtp and p->vrtp with the offered codecs, since 08411 they are acceptable */ 08412 p->jointcapability = newjointcapability; /* Our joint codec profile for this call */ 08413 p->peercapability = newpeercapability; /* The other sides capability in latest offer */ 08414 p->jointnoncodeccapability = newnoncodeccapability; /* DTMF capabilities */ 08415 08416 if (ast_test_flag(&p->flags[1], SIP_PAGE2_PREFERRED_CODEC)) { /* respond with single most preferred joint codec, limiting the other side's choice */ 08417 p->jointcapability = ast_codec_choose(&p->prefs, p->jointcapability, 1); 08418 } 08419 08420 ast_rtp_codecs_payloads_copy(&newaudiortp, ast_rtp_instance_get_codecs(p->rtp), p->rtp); 08421 08422 if (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO) { 08423 ast_clear_flag(&p->flags[0], SIP_DTMF); 08424 if (newnoncodeccapability & AST_RTP_DTMF) { 08425 /* XXX Would it be reasonable to drop the DSP at this point? XXX */ 08426 ast_set_flag(&p->flags[0], SIP_DTMF_RFC2833); 08427 /* Since RFC2833 is now negotiated we need to change some properties of the RTP stream */ 08428 ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_DTMF, 1); 08429 ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_DTMF_COMPENSATE, ast_test_flag(&p->flags[1], SIP_PAGE2_RFC2833_COMPENSATE)); 08430 } else { 08431 ast_set_flag(&p->flags[0], SIP_DTMF_INBAND); 08432 } 08433 } 08434 } else if (udptlportno > 0) { 08435 if (debug) 08436 ast_verbose("Got T.38 Re-invite without audio. Keeping RTP active during T.38 session.\n"); 08437 } else { 08438 ast_rtp_instance_stop(p->rtp); 08439 if (debug) 08440 ast_verbose("Peer doesn't provide audio\n"); 08441 } 08442 } 08443 08444 /* Setup video address and port */ 08445 if (p->vrtp) { 08446 if (vportno > 0) { 08447 ast_sockaddr_set_port(vsa, vportno); 08448 ast_rtp_instance_set_remote_address(p->vrtp, vsa); 08449 if (debug) { 08450 ast_verbose("Peer video RTP is at port %s\n", 08451 ast_sockaddr_stringify(vsa)); 08452 } 08453 ast_rtp_codecs_payloads_copy(&newvideortp, ast_rtp_instance_get_codecs(p->vrtp), p->vrtp); 08454 } else { 08455 ast_rtp_instance_stop(p->vrtp); 08456 if (debug) 08457 ast_verbose("Peer doesn't provide video\n"); 08458 } 08459 } 08460 08461 /* Setup text address and port */ 08462 if (p->trtp) { 08463 if (tportno > 0) { 08464 ast_sockaddr_set_port(tsa, tportno); 08465 ast_rtp_instance_set_remote_address(p->trtp, tsa); 08466 if (debug) { 08467 ast_verbose("Peer T.140 RTP is at port %s\n", 08468 ast_sockaddr_stringify(tsa)); 08469 } 08470 if ((p->jointcapability & AST_FORMAT_T140RED)) { 08471 p->red = 1; 08472 ast_rtp_red_init(p->trtp, 300, red_data_pt, 2); 08473 } else { 08474 p->red = 0; 08475 } 08476 ast_rtp_codecs_payloads_copy(&newtextrtp, ast_rtp_instance_get_codecs(p->trtp), p->trtp); 08477 } else { 08478 ast_rtp_instance_stop(p->trtp); 08479 if (debug) 08480 ast_verbose("Peer doesn't provide T.140\n"); 08481 } 08482 } 08483 /* Setup image address and port */ 08484 if (p->udptl) { 08485 if (udptlportno > 0) { 08486 if (ast_test_flag(&p->flags[1], SIP_PAGE2_SYMMETRICRTP) && ast_test_flag(&p->flags[1], SIP_PAGE2_UDPTL_DESTINATION)) { 08487 ast_rtp_instance_get_remote_address(p->rtp, isa); 08488 if (!ast_sockaddr_isnull(isa) && debug) { 08489 ast_debug(1, "Peer T.38 UDPTL is set behind NAT and with destination, destination address now %s\n", ast_sockaddr_stringify(isa)); 08490 } 08491 } 08492 ast_sockaddr_set_port(isa, udptlportno); 08493 ast_udptl_set_peer(p->udptl, isa); 08494 if (debug) 08495 ast_debug(1,"Peer T.38 UDPTL is at port %s\n", ast_sockaddr_stringify(isa)); 08496 08497 /* verify the far max ifp can be calculated. this requires far max datagram to be set. */ 08498 if (!ast_udptl_get_far_max_datagram(p->udptl)) { 08499 /* setting to zero will force a default if none was provided by the SDP */ 08500 ast_udptl_set_far_max_datagram(p->udptl, 0); 08501 } 08502 08503 /* Remote party offers T38, we need to update state */ 08504 if ((t38action == SDP_T38_ACCEPT) && 08505 (p->t38.state == T38_LOCAL_REINVITE)) { 08506 change_t38_state(p, T38_ENABLED); 08507 } else if ((t38action == SDP_T38_INITIATE) && 08508 p->owner && p->lastinvite) { 08509 change_t38_state(p, T38_PEER_REINVITE); /* T38 Offered in re-invite from remote party */ 08510 /* If fax detection is enabled then send us off to the fax extension */ 08511 if (ast_test_flag(&p->flags[1], SIP_PAGE2_FAX_DETECT_T38)) { 08512 ast_channel_lock(p->owner); 08513 if (strcmp(p->owner->exten, "fax")) { 08514 const char *target_context = S_OR(p->owner->macrocontext, p->owner->context); 08515 ast_channel_unlock(p->owner); 08516 if (ast_exists_extension(p->owner, target_context, "fax", 1, 08517 S_COR(p->owner->caller.id.number.valid, p->owner->caller.id.number.str, NULL))) { 08518 ast_verbose(VERBOSE_PREFIX_2 "Redirecting '%s' to fax extension due to peer T.38 re-INVITE\n", p->owner->name); 08519 pbx_builtin_setvar_helper(p->owner, "FAXEXTEN", p->owner->exten); 08520 if (ast_async_goto(p->owner, target_context, "fax", 1)) { 08521 ast_log(LOG_NOTICE, "Failed to async goto '%s' into fax of '%s'\n", p->owner->name, target_context); 08522 } 08523 } else { 08524 ast_log(LOG_NOTICE, "T.38 re-INVITE detected but no fax extension\n"); 08525 } 08526 } else { 08527 ast_channel_unlock(p->owner); 08528 } 08529 } 08530 } 08531 } else { 08532 ast_udptl_stop(p->udptl); 08533 if (debug) 08534 ast_debug(1, "Peer doesn't provide T.38 UDPTL\n"); 08535 } 08536 } 08537 08538 if ((portno == -1) && (p->t38.state != T38_DISABLED)) { 08539 ast_debug(3, "Have T.38 but no audio, accepting offer anyway\n"); 08540 return 0; 08541 } 08542 08543 /* Ok, we're going with this offer */ 08544 ast_debug(2, "We're settling with these formats: %s\n", ast_getformatname_multiple(buf, SIPBUFSIZE, p->jointcapability)); 08545 08546 if (!p->owner) /* There's no open channel owning us so we can return here. For a re-invite or so, we proceed */ 08547 return 0; 08548 08549 ast_debug(4, "We have an owner, now see if we need to change this call\n"); 08550 08551 if (!(p->owner->nativeformats & p->jointcapability) && (p->jointcapability & AST_FORMAT_AUDIO_MASK)) { 08552 if (debug) { 08553 char s1[SIPBUFSIZE], s2[SIPBUFSIZE]; 08554 ast_debug(1, "Oooh, we need to change our audio formats since our peer supports only %s and not %s\n", 08555 ast_getformatname_multiple(s1, SIPBUFSIZE, p->jointcapability), 08556 ast_getformatname_multiple(s2, SIPBUFSIZE, p->owner->nativeformats)); 08557 } 08558 p->owner->nativeformats = ast_codec_choose(&p->prefs, p->jointcapability, 1) | (p->capability & vpeercapability) | (p->capability & tpeercapability); 08559 ast_set_read_format(p->owner, p->owner->readformat); 08560 ast_set_write_format(p->owner, p->owner->writeformat); 08561 } 08562 08563 if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD) && (!ast_sockaddr_isnull(sa) || !ast_sockaddr_isnull(vsa) || !ast_sockaddr_isnull(tsa) || !ast_sockaddr_isnull(isa)) && (!sendonly || sendonly == -1)) { 08564 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 08565 /* Activate a re-invite */ 08566 ast_queue_frame(p->owner, &ast_null_frame); 08567 /* Queue Manager Unhold event */ 08568 append_history(p, "Unhold", "%s", req->data->str); 08569 if (sip_cfg.callevents) 08570 ast_manager_event(p->owner, EVENT_FLAG_CALL, "Hold", 08571 "Status: Off\r\n" 08572 "Channel: %s\r\n" 08573 "Uniqueid: %s\r\n", 08574 p->owner->name, 08575 p->owner->uniqueid); 08576 if (sip_cfg.notifyhold) 08577 sip_peer_hold(p, FALSE); 08578 ast_clear_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD); /* Clear both flags */ 08579 } else if ((ast_sockaddr_isnull(sa) && ast_sockaddr_isnull(vsa) && ast_sockaddr_isnull(tsa) && ast_sockaddr_isnull(isa)) || (sendonly && sendonly != -1)) { 08580 int already_on_hold = ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD); 08581 ast_queue_control_data(p->owner, AST_CONTROL_HOLD, 08582 S_OR(p->mohsuggest, NULL), 08583 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 08584 if (sendonly) 08585 ast_rtp_instance_stop(p->rtp); 08586 /* RTCP needs to go ahead, even if we're on hold!!! */ 08587 /* Activate a re-invite */ 08588 ast_queue_frame(p->owner, &ast_null_frame); 08589 /* Queue Manager Hold event */ 08590 append_history(p, "Hold", "%s", req->data->str); 08591 if (sip_cfg.callevents && !ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD)) { 08592 ast_manager_event(p->owner, EVENT_FLAG_CALL, "Hold", 08593 "Status: On\r\n" 08594 "Channel: %s\r\n" 08595 "Uniqueid: %s\r\n", 08596 p->owner->name, 08597 p->owner->uniqueid); 08598 } 08599 if (sendonly == 1) /* One directional hold (sendonly/recvonly) */ 08600 ast_set_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD_ONEDIR); 08601 else if (sendonly == 2) /* Inactive stream */ 08602 ast_set_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD_INACTIVE); 08603 else 08604 ast_set_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD_ACTIVE); 08605 if (sip_cfg.notifyhold && !already_on_hold) 08606 sip_peer_hold(p, TRUE); 08607 } 08608 08609 return 0; 08610 }
| static int process_sdp_a_audio | ( | const char * | a, | |
| struct sip_pvt * | p, | |||
| struct ast_rtp_codecs * | newaudiortp, | |||
| int * | last_rtpmap_codec | |||
| ) | [static] |
Definition at line 8738 of file chan_sip.c.
References ast_codec_pref_setsize(), ast_debug, AST_FORMAT_G719, AST_FORMAT_SIREN14, AST_FORMAT_SIREN7, ast_getformatname(), ast_log(), ast_rtp_codecs_packetization_set(), ast_rtp_codecs_payload_lookup(), ast_rtp_codecs_payloads_set_rtpmap_type_rate(), ast_rtp_codecs_payloads_unset(), ast_rtp_instance_get_codecs(), AST_RTP_MAX_PT, AST_RTP_OPT_G726_NONSTANDARD, ast_test_flag, ast_verbose, ast_rtp_payload_type::asterisk_format, ast_rtp_payload_type::code, debug, FALSE, format, LOG_WARNING, LONG_MAX, LONG_MIN, ast_rtp_codecs::pref, sip_debug_test_pvt(), and TRUE.
Referenced by process_sdp().
08739 { 08740 int found = FALSE; 08741 int codec; 08742 char mimeSubtype[128]; 08743 char fmtp_string[64]; 08744 unsigned int sample_rate; 08745 int debug = sip_debug_test_pvt(p); 08746 08747 if (!strncasecmp(a, "ptime", 5)) { 08748 char *tmp = strrchr(a, ':'); 08749 long int framing = 0; 08750 if (tmp) { 08751 tmp++; 08752 framing = strtol(tmp, NULL, 10); 08753 if (framing == LONG_MIN || framing == LONG_MAX) { 08754 framing = 0; 08755 ast_debug(1, "Can't read framing from SDP: %s\n", a); 08756 } 08757 } 08758 if (framing && p->autoframing) { 08759 struct ast_codec_pref *pref = &ast_rtp_instance_get_codecs(p->rtp)->pref; 08760 int codec_n; 08761 for (codec_n = 0; codec_n < AST_RTP_MAX_PT; codec_n++) { 08762 struct ast_rtp_payload_type format = ast_rtp_codecs_payload_lookup(ast_rtp_instance_get_codecs(p->rtp), codec_n); 08763 if (!format.asterisk_format || !format.code) /* non-codec or not found */ 08764 continue; 08765 ast_debug(1, "Setting framing for %s to %ld\n", ast_getformatname(format.code), framing); 08766 ast_codec_pref_setsize(pref, format.code, framing); 08767 } 08768 ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(p->rtp), p->rtp, pref); 08769 } 08770 found = TRUE; 08771 } else if (sscanf(a, "rtpmap: %30u %127[^/]/%30u", &codec, mimeSubtype, &sample_rate) == 3) { 08772 /* We have a rtpmap to handle */ 08773 if (*last_rtpmap_codec < SDP_MAX_RTPMAP_CODECS) { 08774 if (ast_rtp_codecs_payloads_set_rtpmap_type_rate(newaudiortp, NULL, codec, "audio", mimeSubtype, 08775 ast_test_flag(&p->flags[0], SIP_G726_NONSTANDARD) ? AST_RTP_OPT_G726_NONSTANDARD : 0, sample_rate) != -1) { 08776 if (debug) 08777 ast_verbose("Found audio description format %s for ID %d\n", mimeSubtype, codec); 08778 //found_rtpmap_codecs[last_rtpmap_codec] = codec; 08779 (*last_rtpmap_codec)++; 08780 found = TRUE; 08781 } else { 08782 ast_rtp_codecs_payloads_unset(newaudiortp, NULL, codec); 08783 if (debug) 08784 ast_verbose("Found unknown media description format %s for ID %d\n", mimeSubtype, codec); 08785 } 08786 } else { 08787 if (debug) 08788 ast_verbose("Discarded description format %s for ID %d\n", mimeSubtype, codec); 08789 } 08790 } else if (sscanf(a, "fmtp: %30u %63s", &codec, fmtp_string) == 2) { 08791 struct ast_rtp_payload_type payload; 08792 08793 payload = ast_rtp_codecs_payload_lookup(newaudiortp, codec); 08794 if (payload.code && payload.asterisk_format) { 08795 unsigned int bit_rate; 08796 08797 switch (payload.code) { 08798 case AST_FORMAT_SIREN7: 08799 if (sscanf(fmtp_string, "bitrate=%30u", &bit_rate) == 1) { 08800 if (bit_rate != 32000) { 08801 ast_log(LOG_WARNING, "Got Siren7 offer at %d bps, but only 32000 bps supported; ignoring.\n", bit_rate); 08802 ast_rtp_codecs_payloads_unset(newaudiortp, NULL, codec); 08803 } else { 08804 found = TRUE; 08805 } 08806 } 08807 break; 08808 case AST_FORMAT_SIREN14: 08809 if (sscanf(fmtp_string, "bitrate=%30u", &bit_rate) == 1) { 08810 if (bit_rate != 48000) { 08811 ast_log(LOG_WARNING, "Got Siren14 offer at %d bps, but only 48000 bps supported; ignoring.\n", bit_rate); 08812 ast_rtp_codecs_payloads_unset(newaudiortp, NULL, codec); 08813 } else { 08814 found = TRUE; 08815 } 08816 } 08817 break; 08818 case AST_FORMAT_G719: 08819 if (sscanf(fmtp_string, "bitrate=%30u", &bit_rate) == 1) { 08820 if (bit_rate != 64000) { 08821 ast_log(LOG_WARNING, "Got G.719 offer at %d bps, but only 64000 bps supported; ignoring.\n", bit_rate); 08822 ast_rtp_codecs_payloads_unset(newaudiortp, NULL, codec); 08823 } else { 08824 found = TRUE; 08825 } 08826 } 08827 } 08828 } 08829 } 08830 08831 return found; 08832 }
| static int process_sdp_a_image | ( | const char * | a, | |
| struct sip_pvt * | p | |||
| ) | [static] |
Definition at line 8917 of file chan_sip.c.
References ast_debug, AST_T38_RATE_12000, AST_T38_RATE_14400, AST_T38_RATE_2400, AST_T38_RATE_4800, AST_T38_RATE_7200, AST_T38_RATE_9600, AST_T38_RATE_MANAGEMENT_LOCAL_TCF, AST_T38_RATE_MANAGEMENT_TRANSFERRED_TCF, ast_udptl_set_error_correction_scheme(), ast_udptl_set_far_max_datagram(), FALSE, TRUE, UDPTL_ERROR_CORRECTION_FEC, UDPTL_ERROR_CORRECTION_NONE, and UDPTL_ERROR_CORRECTION_REDUNDANCY.
Referenced by process_sdp().
08918 { 08919 int found = FALSE; 08920 char s[256]; 08921 unsigned int x; 08922 08923 if ((sscanf(a, "T38FaxMaxBuffer:%30u", &x) == 1)) { 08924 ast_debug(3, "MaxBufferSize:%d\n", x); 08925 found = TRUE; 08926 } else if ((sscanf(a, "T38MaxBitRate:%30u", &x) == 1) || (sscanf(a, "T38FaxMaxRate:%30u", &x) == 1)) { 08927 ast_debug(3, "T38MaxBitRate: %d\n", x); 08928 switch (x) { 08929 case 14400: 08930 p->t38.their_parms.rate = AST_T38_RATE_14400; 08931 break; 08932 case 12000: 08933 p->t38.their_parms.rate = AST_T38_RATE_12000; 08934 break; 08935 case 9600: 08936 p->t38.their_parms.rate = AST_T38_RATE_9600; 08937 break; 08938 case 7200: 08939 p->t38.their_parms.rate = AST_T38_RATE_7200; 08940 break; 08941 case 4800: 08942 p->t38.their_parms.rate = AST_T38_RATE_4800; 08943 break; 08944 case 2400: 08945 p->t38.their_parms.rate = AST_T38_RATE_2400; 08946 break; 08947 } 08948 found = TRUE; 08949 } else if ((sscanf(a, "T38FaxVersion:%30u", &x) == 1)) { 08950 ast_debug(3, "FaxVersion: %u\n", x); 08951 p->t38.their_parms.version = x; 08952 found = TRUE; 08953 } else if ((sscanf(a, "T38FaxMaxDatagram:%30u", &x) == 1) || (sscanf(a, "T38MaxDatagram:%30u", &x) == 1)) { 08954 /* override the supplied value if the configuration requests it */ 08955 if (((signed int) p->t38_maxdatagram >= 0) && ((unsigned int) p->t38_maxdatagram > x)) { 08956 ast_debug(1, "Overriding T38FaxMaxDatagram '%d' with '%d'\n", x, p->t38_maxdatagram); 08957 x = p->t38_maxdatagram; 08958 } 08959 ast_debug(3, "FaxMaxDatagram: %u\n", x); 08960 ast_udptl_set_far_max_datagram(p->udptl, x); 08961 found = TRUE; 08962 } else if ((strncmp(a, "T38FaxFillBitRemoval", 20) == 0)) { 08963 if (sscanf(a, "T38FaxFillBitRemoval:%30u", &x) == 1) { 08964 ast_debug(3, "FillBitRemoval: %d\n", x); 08965 if (x == 1) { 08966 p->t38.their_parms.fill_bit_removal = TRUE; 08967 } 08968 } else { 08969 ast_debug(3, "FillBitRemoval\n"); 08970 p->t38.their_parms.fill_bit_removal = TRUE; 08971 } 08972 found = TRUE; 08973 } else if ((strncmp(a, "T38FaxTranscodingMMR", 20) == 0)) { 08974 if (sscanf(a, "T38FaxTranscodingMMR:%30u", &x) == 1) { 08975 ast_debug(3, "Transcoding MMR: %d\n", x); 08976 if (x == 1) { 08977 p->t38.their_parms.transcoding_mmr = TRUE; 08978 } 08979 } else { 08980 ast_debug(3, "Transcoding MMR\n"); 08981 p->t38.their_parms.transcoding_mmr = TRUE; 08982 } 08983 found = TRUE; 08984 } else if ((strncmp(a, "T38FaxTranscodingJBIG", 21) == 0)) { 08985 if (sscanf(a, "T38FaxTranscodingJBIG:%30u", &x) == 1) { 08986 ast_debug(3, "Transcoding JBIG: %d\n", x); 08987 if (x == 1) { 08988 p->t38.their_parms.transcoding_jbig = TRUE; 08989 } 08990 } else { 08991 ast_debug(3, "Transcoding JBIG\n"); 08992 p->t38.their_parms.transcoding_jbig = TRUE; 08993 } 08994 found = TRUE; 08995 } else if ((sscanf(a, "T38FaxRateManagement:%255s", s) == 1)) { 08996 ast_debug(3, "RateManagement: %s\n", s); 08997 if (!strcasecmp(s, "localTCF")) 08998 p->t38.their_parms.rate_management = AST_T38_RATE_MANAGEMENT_LOCAL_TCF; 08999 else if (!strcasecmp(s, "transferredTCF")) 09000 p->t38.their_parms.rate_management = AST_T38_RATE_MANAGEMENT_TRANSFERRED_TCF; 09001 found = TRUE; 09002 } else if ((sscanf(a, "T38FaxUdpEC:%255s", s) == 1)) { 09003 ast_debug(3, "UDP EC: %s\n", s); 09004 if (!strcasecmp(s, "t38UDPRedundancy")) { 09005 ast_udptl_set_error_correction_scheme(p->udptl, UDPTL_ERROR_CORRECTION_REDUNDANCY); 09006 } else if (!strcasecmp(s, "t38UDPFEC")) { 09007 ast_udptl_set_error_correction_scheme(p->udptl, UDPTL_ERROR_CORRECTION_FEC); 09008 } else { 09009 ast_udptl_set_error_correction_scheme(p->udptl, UDPTL_ERROR_CORRECTION_NONE); 09010 } 09011 found = TRUE; 09012 } 09013 09014 return found; 09015 }
| static int process_sdp_a_sendonly | ( | const char * | a, | |
| int * | sendonly | |||
| ) | [static] |
Definition at line 8718 of file chan_sip.c.
Referenced by process_sdp().
08719 { 08720 int found = FALSE; 08721 08722 if (!strcasecmp(a, "sendonly")) { 08723 if (*sendonly == -1) 08724 *sendonly = 1; 08725 found = TRUE; 08726 } else if (!strcasecmp(a, "inactive")) { 08727 if (*sendonly == -1) 08728 *sendonly = 2; 08729 found = TRUE; 08730 } else if (!strcasecmp(a, "sendrecv")) { 08731 if (*sendonly == -1) 08732 *sendonly = 0; 08733 found = TRUE; 08734 } 08735 return found; 08736 }
| 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] |
Definition at line 8868 of file chan_sip.c.
References AST_RED_MAX_GENERATION, ast_rtp_codecs_payloads_set_rtpmap_type_rate(), ast_verbose, debug, FALSE, sip_debug_test_pvt(), and TRUE.
Referenced by process_sdp().
08869 { 08870 int found = FALSE; 08871 int codec; 08872 char mimeSubtype[128]; 08873 unsigned int sample_rate; 08874 char *red_cp; 08875 int debug = sip_debug_test_pvt(p); 08876 08877 if (sscanf(a, "rtpmap: %30u %127[^/]/%30u", &codec, mimeSubtype, &sample_rate) == 3) { 08878 /* We have a rtpmap to handle */ 08879 if (*last_rtpmap_codec < SDP_MAX_RTPMAP_CODECS) { 08880 if (!strncasecmp(mimeSubtype, "T140", 4)) { /* Text */ 08881 if (p->trtp) { 08882 /* ast_verbose("Adding t140 mimeSubtype to textrtp struct\n"); */ 08883 ast_rtp_codecs_payloads_set_rtpmap_type_rate(newtextrtp, NULL, codec, "text", mimeSubtype, 0, sample_rate); 08884 found = TRUE; 08885 } 08886 } else if (!strncasecmp(mimeSubtype, "RED", 3)) { /* Text with Redudancy */ 08887 if (p->trtp) { 08888 ast_rtp_codecs_payloads_set_rtpmap_type_rate(newtextrtp, NULL, codec, "text", mimeSubtype, 0, sample_rate); 08889 sprintf(red_fmtp, "fmtp:%d ", codec); 08890 if (debug) 08891 ast_verbose("RED submimetype has payload type: %d\n", codec); 08892 found = TRUE; 08893 } 08894 } 08895 } else { 08896 if (debug) 08897 ast_verbose("Discarded description format %s for ID %d\n", mimeSubtype, codec); 08898 } 08899 } else if (!strncmp(a, red_fmtp, strlen(red_fmtp))) { 08900 /* count numbers of generations in fmtp */ 08901 red_cp = &red_fmtp[strlen(red_fmtp)]; 08902 strncpy(red_fmtp, a, 100); 08903 08904 sscanf(red_cp, "%30u", &red_data_pt[*red_num_gen]); 08905 red_cp = strtok(red_cp, "/"); 08906 while (red_cp && (*red_num_gen)++ < AST_RED_MAX_GENERATION) { 08907 sscanf(red_cp, "%30u", &red_data_pt[*red_num_gen]); 08908 red_cp = strtok(NULL, "/"); 08909 } 08910 red_cp = red_fmtp; 08911 found = TRUE; 08912 } 08913 08914 return found; 08915 }
| static int process_sdp_a_video | ( | const char * | a, | |
| struct sip_pvt * | p, | |||
| struct ast_rtp_codecs * | newvideortp, | |||
| int * | last_rtpmap_codec | |||
| ) | [static] |
Definition at line 8834 of file chan_sip.c.
References ast_rtp_codecs_payloads_set_rtpmap_type_rate(), ast_rtp_codecs_payloads_unset(), ast_verbose, debug, FALSE, sip_debug_test_pvt(), and TRUE.
Referenced by process_sdp().
08835 { 08836 int found = FALSE; 08837 int codec; 08838 char mimeSubtype[128]; 08839 unsigned int sample_rate; 08840 int debug = sip_debug_test_pvt(p); 08841 08842 if (sscanf(a, "rtpmap: %30u %127[^/]/%30u", &codec, mimeSubtype, &sample_rate) == 3) { 08843 /* We have a rtpmap to handle */ 08844 if (*last_rtpmap_codec < SDP_MAX_RTPMAP_CODECS) { 08845 /* Note: should really look at the '#chans' params too */ 08846 if (!strncasecmp(mimeSubtype, "H26", 3) || !strncasecmp(mimeSubtype, "MP4", 3)) { 08847 if (ast_rtp_codecs_payloads_set_rtpmap_type_rate(newvideortp, NULL, codec, "video", mimeSubtype, 0, sample_rate) != -1) { 08848 if (debug) 08849 ast_verbose("Found video description format %s for ID %d\n", mimeSubtype, codec); 08850 //found_rtpmap_codecs[last_rtpmap_codec] = codec; 08851 (*last_rtpmap_codec)++; 08852 found = TRUE; 08853 } else { 08854 ast_rtp_codecs_payloads_unset(newvideortp, NULL, codec); 08855 if (debug) 08856 ast_verbose("Found unknown media description format %s for ID %d\n", mimeSubtype, codec); 08857 } 08858 } 08859 } else { 08860 if (debug) 08861 ast_verbose("Discarded description format %s for ID %d\n", mimeSubtype, codec); 08862 } 08863 } 08864 08865 return found; 08866 }
| static int process_sdp_c | ( | const char * | c, | |
| struct ast_sockaddr * | addr | |||
| ) | [static] |
Definition at line 8691 of file chan_sip.c.
References ast_log(), ast_sockaddr_resolve_first_af(), FALSE, LOG_WARNING, and TRUE.
Referenced by process_sdp().
08692 { 08693 char proto[4], host[258]; 08694 int af; 08695 08696 /* Check for Media-description-level-address */ 08697 if (sscanf(c, "IN %3s %255s", proto, host) == 2) { 08698 if (!strcmp("IP4", proto)) { 08699 af = AF_INET; 08700 } else if (!strcmp("IP6", proto)) { 08701 af = AF_INET6; 08702 } else { 08703 ast_log(LOG_WARNING, "Unknown protocol '%s'.\n", proto); 08704 return FALSE; 08705 } 08706 if (ast_sockaddr_resolve_first_af(addr, host, 0, af)) { 08707 ast_log(LOG_WARNING, "Unable to lookup RTP Audio host in c= line, '%s'\n", c); 08708 return FALSE; 08709 } 08710 return TRUE; 08711 } else { 08712 ast_log(LOG_WARNING, "Invalid host in c= line, '%s'\n", c); 08713 return FALSE; 08714 } 08715 return FALSE; 08716 }
| static int process_sdp_o | ( | const char * | o, | |
| struct sip_pvt * | p | |||
| ) | [static] |
Definition at line 8612 of file chan_sip.c.
References ast_debug, ast_log(), ast_strdupa, ast_strlen_zero(), ast_test_flag, FALSE, LOG_WARNING, strsep(), and TRUE.
Referenced by process_sdp().
08613 { 08614 char *o_copy; 08615 char *token; 08616 int64_t rua_version; 08617 08618 /* Store the SDP version number of remote UA. This will allow us to 08619 distinguish between session modifications and session refreshes. If 08620 the remote UA does not send an incremented SDP version number in a 08621 subsequent RE-INVITE then that means its not changing media session. 08622 The RE-INVITE may have been sent to update connected party, remote 08623 target or to refresh the session (Session-Timers). Asterisk must not 08624 change media session and increment its own version number in answer 08625 SDP in this case. */ 08626 08627 p->session_modify = TRUE; 08628 08629 if (ast_strlen_zero(o)) { 08630 ast_log(LOG_WARNING, "SDP syntax error. SDP without an o= line\n"); 08631 return FALSE; 08632 } 08633 08634 o_copy = ast_strdupa(o); 08635 token = strsep(&o_copy, " "); /* Skip username */ 08636 if (!o_copy) { 08637 ast_log(LOG_WARNING, "SDP syntax error in o= line username\n"); 08638 return FALSE; 08639 } 08640 token = strsep(&o_copy, " "); /* Skip session-id */ 08641 if (!o_copy) { 08642 ast_log(LOG_WARNING, "SDP syntax error in o= line session-id\n"); 08643 return FALSE; 08644 } 08645 token = strsep(&o_copy, " "); /* Version */ 08646 if (!o_copy) { 08647 ast_log(LOG_WARNING, "SDP syntax error in o= line\n"); 08648 return FALSE; 08649 } 08650 if (!sscanf(token, "%30" SCNd64, &rua_version)) { 08651 ast_log(LOG_WARNING, "SDP syntax error in o= line version\n"); 08652 return FALSE; 08653 } 08654 08655 /* we need to check the SDP version number the other end sent us; 08656 * our rules for deciding what to accept are a bit complex. 08657 * 08658 * 1) if 'ignoresdpversion' has been set for this dialog, then 08659 * we will just accept whatever they sent and assume it is 08660 * a modification of the session, even if it is not 08661 * 2) otherwise, if this is the first SDP we've seen from them 08662 * we accept it 08663 * 3) otherwise, if the new SDP version number is higher than the 08664 * old one, we accept it 08665 * 4) otherwise, if this SDP is in response to us requesting a switch 08666 * to T.38, we accept the SDP, but also generate a warning message 08667 * that this peer should have the 'ignoresdpversion' option set, 08668 * because it is not following the SDP offer/answer RFC; if we did 08669 * not request a switch to T.38, then we stop parsing the SDP, as it 08670 * has not changed from the previous version 08671 */ 08672 08673 if (ast_test_flag(&p->flags[1], SIP_PAGE2_IGNORESDPVERSION) || 08674 (p->sessionversion_remote < 0) || 08675 (p->sessionversion_remote < rua_version)) { 08676 p->sessionversion_remote = rua_version; 08677 } else { 08678 if (p->t38.state == T38_LOCAL_REINVITE) { 08679 p->sessionversion_remote = rua_version; 08680 ast_log(LOG_WARNING, "Call %s responded to our T.38 reinvite without changing SDP version; 'ignoresdpversion' should be set for this peer.\n", p->callid); 08681 } else { 08682 p->session_modify = FALSE; 08683 ast_debug(2, "Call %s responded to our reinvite without changing SDP version; ignoring SDP.\n", p->callid); 08684 return FALSE; 08685 } 08686 } 08687 08688 return TRUE; 08689 }
| static int proxy_update | ( | struct sip_proxy * | proxy | ) | [static] |
Resolve DNS srv name or host name in a sip_proxy structure
Definition at line 2838 of file chan_sip.c.
References ast_get_ip_or_srv(), ast_log(), ast_sockaddr_parse(), ast_sockaddr_set_port, bindaddr, FALSE, get_address_family_filter(), LOG_WARNING, sip_cfg, and TRUE.
Referenced by build_peer(), and reload_config().
02839 { 02840 /* if it's actually an IP address and not a name, 02841 there's no need for a managed lookup */ 02842 if (!ast_sockaddr_parse(&proxy->ip, proxy->name, 0)) { 02843 /* Ok, not an IP address, then let's check if it's a domain or host */ 02844 /* XXX Todo - if we have proxy port, don't do SRV */ 02845 proxy->ip.ss.ss_family = get_address_family_filter(&bindaddr); /* Filter address family */ 02846 if (ast_get_ip_or_srv(&proxy->ip, proxy->name, sip_cfg.srvlookup ? "_sip._udp" : NULL) < 0) { 02847 ast_log(LOG_WARNING, "Unable to locate host '%s'\n", proxy->name); 02848 return FALSE; 02849 } 02850 02851 } 02852 02853 ast_sockaddr_set_port(&proxy->ip, proxy->port); 02854 02855 proxy->last_dnsupdate = time(NULL); 02856 return TRUE; 02857 }
| static int publish_expire | ( | const void * | data | ) | [static] |
Definition at line 1001 of file chan_sip.c.
References ao2_ref, ao2_unlink, ast_assert, event_state_compositor::compositor, and get_esc().
Referenced by create_esc_entry(), handle_sip_publish_modify(), and handle_sip_publish_refresh().
01002 { 01003 struct sip_esc_entry *esc_entry = (struct sip_esc_entry *) data; 01004 struct event_state_compositor *esc = get_esc(esc_entry->event); 01005 01006 ast_assert(esc != NULL); 01007 01008 ao2_unlink(esc->compositor, esc_entry); 01009 ao2_ref(esc_entry, -1); 01010 return 0; 01011 }
| static void pvt_set_needdestroy | ( | struct sip_pvt * | pvt, | |
| const char * | reason | |||
| ) | [inline, static] |
Definition at line 2803 of file chan_sip.c.
References append_history.
Referenced by __sip_autodestruct(), handle_incoming(), handle_request_refer(), handle_request_subscribe(), handle_response(), handle_response_invite(), handle_response_notify(), handle_response_peerpoke(), handle_response_publish(), handle_response_refer(), handle_response_register(), handle_response_subscribe(), retrans_pkt(), sip_hangup(), and sip_reg_timeout().
02804 { 02805 if (pvt->final_destruction_scheduled) { 02806 return; /* This is already scheduled for final destruction, let the scheduler take care of it. */ 02807 } 02808 append_history(pvt, "NeedDestroy", "Setting needdestroy because %s", reason); 02809 pvt->needdestroy = 1; 02810 }
| static int queue_request | ( | struct sip_pvt * | p, | |
| const struct sip_request * | req | |||
| ) | [static] |
Definition at line 23711 of file chan_sip.c.
References ast_calloc, AST_LIST_INSERT_TAIL, ast_sched_add(), copy_request(), and scheduler_process_request_queue().
Referenced by handle_request_do().
23712 { 23713 struct sip_request *newreq; 23714 23715 if (!(newreq = ast_calloc(1, sizeof(*newreq)))) { 23716 return -1; 23717 } 23718 23719 copy_request(newreq, req); 23720 AST_LIST_INSERT_TAIL(&p->request_queue, newreq, next); 23721 if (p->request_queue_sched_id == -1) { 23722 if ((p->request_queue_sched_id = ast_sched_add(sched, 10, scheduler_process_request_queue, dialog_ref(p, "Increment refcount to pass dialog pointer to sched callback"))) == -1) { 23723 dialog_unref(p, "Decrement refcount due to sched_add failure"); 23724 } 23725 } 23726 23727 return 0; 23728 }
| static struct sip_peer * realtime_peer | ( | const char * | peername, | |
| struct ast_sockaddr * | sin, | |||
| int | devstate_only | |||
| ) | [static, read] |
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.
Definition at line 4374 of file chan_sip.c.
References ao2_t_link, ast_check_realtime(), ast_config_destroy(), ast_copy_flags, ast_copy_string(), ast_debug, ast_free, ast_load_realtime(), ast_load_realtime_multientry(), ast_log(), AST_SCHED_REPLACE_UNREF, ast_sockaddr_cmp(), ast_sockaddr_isnull(), ast_sockaddr_resolve(), ast_sockaddr_stringify_addr(), ast_sockaddr_stringify_port(), ast_test_flag, ast_variables_destroy(), bindaddr, build_peer(), expire_register(), get_address_family_filter(), get_insecure_variable_from_config(), get_name_from_variable(), ipaddr, LOG_WARNING, ast_variable::name, ast_variable::next, PARSE_PORT_FORBID, ref_peer(), SENTINEL, sip_cfg, TRUE, unref_peer(), ast_variable::value, and var.
04375 { 04376 struct sip_peer *peer; 04377 struct ast_variable *var = NULL; 04378 struct ast_variable *varregs = NULL; 04379 struct ast_variable *tmp; 04380 struct ast_config *peerlist = NULL; 04381 char ipaddr[INET_ADDRSTRLEN]; 04382 char portstring[6]; /*up to 5 digits plus null terminator*/ 04383 char *cat = NULL; 04384 int realtimeregs = ast_check_realtime("sipregs"); 04385 04386 /* First check on peer name */ 04387 if (newpeername) { 04388 if (realtimeregs) 04389 varregs = ast_load_realtime("sipregs", "name", newpeername, SENTINEL); 04390 04391 var = ast_load_realtime("sippeers", "name", newpeername, "host", "dynamic", SENTINEL); 04392 if (!var && addr) { 04393 var = ast_load_realtime("sippeers", "name", newpeername, "host", ast_sockaddr_stringify_addr(addr), SENTINEL); 04394 } 04395 if (!var) { 04396 var = ast_load_realtime("sippeers", "name", newpeername, SENTINEL); 04397 /*!\note 04398 * If this one loaded something, then we need to ensure that the host 04399 * field matched. The only reason why we can't have this as a criteria 04400 * is because we only have the IP address and the host field might be 04401 * set as a name (and the reverse PTR might not match). 04402 */ 04403 if (var && addr) { 04404 for (tmp = var; tmp; tmp = tmp->next) { 04405 if (!strcasecmp(tmp->name, "host")) { 04406 struct ast_sockaddr *addrs = NULL; 04407 04408 if (ast_sockaddr_resolve(&addrs, 04409 tmp->value, 04410 PARSE_PORT_FORBID, 04411 get_address_family_filter(&bindaddr)) <= 0 || 04412 ast_sockaddr_cmp(&addrs[0], addr)) { 04413 /* No match */ 04414 ast_variables_destroy(var); 04415 var = NULL; 04416 } 04417 ast_free(addrs); 04418 break; 04419 } 04420 } 04421 } 04422 } 04423 } 04424 04425 if (!var && addr) { /* Then check on IP address for dynamic peers */ 04426 ast_copy_string(ipaddr, ast_sockaddr_stringify_addr(addr), sizeof(ipaddr)); 04427 ast_copy_string(portstring, ast_sockaddr_stringify_port(addr), sizeof(portstring)); 04428 var = ast_load_realtime("sippeers", "host", ipaddr, "port", portstring, SENTINEL); /* First check for fixed IP hosts */ 04429 if (var) { 04430 if (realtimeregs) { 04431 newpeername = get_name_from_variable(var, newpeername); 04432 varregs = ast_load_realtime("sipregs", "name", newpeername, SENTINEL); 04433 } 04434 } else { 04435 if (realtimeregs) 04436 varregs = ast_load_realtime("sipregs", "ipaddr", ipaddr, "port", portstring, SENTINEL); /* Then check for registered hosts */ 04437 else 04438 var = ast_load_realtime("sippeers", "ipaddr", ipaddr, "port", portstring, SENTINEL); /* Then check for registered hosts */ 04439 if (varregs) { 04440 newpeername = get_name_from_variable(varregs, newpeername); 04441 var = ast_load_realtime("sippeers", "name", newpeername, SENTINEL); 04442 } 04443 } 04444 if (!var) { /*We couldn't match on ipaddress and port, so we need to check if port is insecure*/ 04445 peerlist = ast_load_realtime_multientry("sippeers", "host", ipaddr, SENTINEL); 04446 if (peerlist) { 04447 var = get_insecure_variable_from_config(peerlist); 04448 if(var) { 04449 if (realtimeregs) { 04450 newpeername = get_name_from_variable(var, newpeername); 04451 varregs = ast_load_realtime("sipregs", "name", newpeername, SENTINEL); 04452 } 04453 } else { /*var wasn't found in the list of "hosts", so try "ipaddr"*/ 04454 peerlist = NULL; 04455 cat = NULL; 04456 peerlist = ast_load_realtime_multientry("sippeers", "ipaddr", ipaddr, SENTINEL); 04457 if(peerlist) { 04458 var = get_insecure_variable_from_config(peerlist); 04459 if(var) { 04460 if (realtimeregs) { 04461 newpeername = get_name_from_variable(var, newpeername); 04462 varregs = ast_load_realtime("sipregs", "name", newpeername, SENTINEL); 04463 } 04464 } 04465 } 04466 } 04467 } else { 04468 if (realtimeregs) { 04469 peerlist = ast_load_realtime_multientry("sipregs", "ipaddr", ipaddr, SENTINEL); 04470 if (peerlist) { 04471 varregs = get_insecure_variable_from_config(peerlist); 04472 if (varregs) { 04473 newpeername = get_name_from_variable(varregs, newpeername); 04474 var = ast_load_realtime("sippeers", "name", newpeername, SENTINEL); 04475 } 04476 } 04477 } else { 04478 peerlist = ast_load_realtime_multientry("sippeers", "ipaddr", ipaddr, SENTINEL); 04479 if (peerlist) { 04480 var = get_insecure_variable_from_config(peerlist); 04481 if (var) { 04482 newpeername = get_name_from_variable(var, newpeername); 04483 varregs = ast_load_realtime("sipregs", "name", newpeername, SENTINEL); 04484 } 04485 } 04486 } 04487 } 04488 } 04489 } 04490 04491 if (!var) { 04492 if (peerlist) 04493 ast_config_destroy(peerlist); 04494 return NULL; 04495 } 04496 04497 for (tmp = var; tmp; tmp = tmp->next) { 04498 if (!newpeername && !strcasecmp(tmp->name, "name")) { 04499 newpeername = tmp->value; 04500 } 04501 } 04502 04503 if (!newpeername) { /* Did not find peer in realtime */ 04504 ast_log(LOG_WARNING, "Cannot Determine peer name ip=%s\n", ipaddr); 04505 if(peerlist) 04506 ast_config_destroy(peerlist); 04507 else 04508 ast_variables_destroy(var); 04509 return NULL; 04510 } 04511 04512 04513 /* Peer found in realtime, now build it in memory */ 04514 peer = build_peer(newpeername, var, varregs, TRUE, devstate_only); 04515 if (!peer) { 04516 if(peerlist) 04517 ast_config_destroy(peerlist); 04518 else { 04519 ast_variables_destroy(var); 04520 ast_variables_destroy(varregs); 04521 } 04522 return NULL; 04523 } 04524 04525 ast_debug(3, "-REALTIME- loading peer from database to memory. Name: %s. Peer objects: %d\n", peer->name, rpeerobjs); 04526 04527 if (ast_test_flag(&