#include "asterisk.h"
#include <ctype.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/signal.h>
#include <regex.h>
#include <time.h>
#include "asterisk/network.h"
#include "asterisk/paths.h"
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/rtp.h"
#include "asterisk/udptl.h"
#include "asterisk/acl.h"
#include "asterisk/manager.h"
#include "asterisk/callerid.h"
#include "asterisk/cli.h"
#include "asterisk/app.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/astobj.h"
#include "asterisk/astobj2.h"
#include "asterisk/dnsmgr.h"
#include "asterisk/devicestate.h"
#include "asterisk/linkedlists.h"
#include "asterisk/stringfields.h"
#include "asterisk/monitor.h"
#include "asterisk/netsock.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/tcptls.h"
Go to the source code of this file.
Data Structures | |
| struct | __show_chan_arg |
| argument for the 'show channels|subscriptions' callback. More... | |
| struct | _map_x_s |
| generic struct to map between strings and integers. Fill it with x-s pairs, terminate with an entry with s = NULL; Then you can call map_x_s(...) to map an integer to a string, and map_s_x() for the string -> integer mapping. More... | |
| struct | ast_register_list |
| The register list: Other SIP proxies we register with and place calls to. 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 | cfsip_options |
| List of well-known SIP options. If we get this in a require, we should check the list and answer accordingly. More... | |
| struct | cfsubscription_types |
Subscription types that we support. We support
| |
| struct | domain |
| Domain data structure. More... | |
| struct | domain_list |
| struct | find_call_cb_arg |
| argument to the helper function to identify a call More... | |
| struct | invstate2stringtable |
| Readable descriptions of device states. More... | |
| struct | peer_finding_info |
| struct | sip_auth |
| sip_auth: Credentials for authentication to other SIP services More... | |
| struct | sip_dual |
| structure used in transfers More... | |
| struct | sip_history |
| sip_history: Structure for saving transactions within a SIP dialog More... | |
| struct | sip_history_head |
| struct | sip_invite_param |
| Parameters to the transmit_invite function. More... | |
| struct | sip_mailbox |
| A peer's mailbox. More... | |
| struct | sip_peer |
| Structure for SIP peer data, we place calls to peers if registered or fixed IP address (host). More... | |
| struct | sip_pkt |
| sip packet - raw format for outbound packets that are sent or scheduled for transmission Packets are linked in a list, whose head is in the struct sip_pvt they belong to. Each packet holds a reference to the parent struct sip_pvt. This structure is allocated in __sip_reliable_xmit() and only for packets that require retransmissions. More... | |
| struct | sip_proxy |
| definition of a sip proxy server More... | |
| struct | sip_pvt |
| Structure used for each SIP dialog, ie. a call, a registration, a subscribe. Created and initialized by sip_alloc(), the descriptor goes into the list of descriptors (dialoglist). More... | |
| struct | sip_pvt::request_queue |
| struct | sip_refer |
| Structure to handle SIP transfers. Dynamically allocated when needed. More... | |
| struct | sip_registry |
| Registrations with other SIP proxies. More... | |
| struct | sip_request |
| sip_request: The data grabbed from the UDP socket More... | |
| struct | sip_route |
| Structure to save routing information for a SIP session. More... | |
| struct | sip_settings |
| a place to store all global settings for the sip channel driver More... | |
| struct | sip_socket |
| The SIP socket definition. More... | |
| struct | sip_st_cfg |
| Structure that encapsulates all attributes related to configuration of SIP Session-Timers feature on a per user/peer basis. More... | |
| struct | sip_st_dlg |
| Structure that encapsulates all attributes related to running SIP Session-Timers feature on a per dialog basis. More... | |
| struct | sip_threadinfo |
| Definition of a thread that handles a socket. More... | |
| struct | t38properties |
| T.38 channel settings (at some point we need to make this alloc'ed. More... | |
| struct | threadl |
| The thread list of TCP threads. More... | |
Object counters @{ | |
| |
| #define | DEC_CALL_LIMIT 0 |
| #define | DEC_CALL_RINGING 2 |
| #define | INC_CALL_LIMIT 1 |
| #define | INC_CALL_RINGING 3 |
| #define | REQ_OFFSET_TO_STR(req, offset) ((req)->data->str + ((req)->offset)) |
| enum | domain_mode { SIP_DOMAIN_AUTO, SIP_DOMAIN_CONFIG } |
| Modes for SIP domain handling in the PBX. More... | |
| static int | apeerobjs = 0 |
| static struct ast_flags | global_flags [2] = {{0}} |
| static struct io_context * | io |
| 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 = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) |
| 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 = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) |
| static int | regobjs = 0 |
| static int | rpeerobjs = 0 |
| static struct sched_context * | sched |
| static ast_mutex_t | sip_reload_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) |
| static int | sip_reloading = FALSE |
| static enum channelreloadreason | sip_reloadreason |
| static int * | sipsock_read_id |
| static int | speerobjs = 0 |
| static char | used_context [AST_MAX_CONTEXT] |
DefaultValues Default values, set and reset in reload_config before reading configuration | |
| These are default values in the source. There are other recommended values in the sip.conf.sample for new installations. These may differ to keep backwards compatibility, yet encouraging new behaviour on new installations | |
| #define | DEFAULT_ALLOW_EXT_DOM TRUE |
| #define | DEFAULT_ALLOWGUEST TRUE |
| #define | DEFAULT_AUTOCREATEPEER FALSE |
| #define | DEFAULT_CALLCOUNTER FALSE |
| #define | DEFAULT_CALLERID "asterisk" |
| #define | DEFAULT_COMPACTHEADERS FALSE |
| #define | DEFAULT_CONTEXT "default" |
| #define | DEFAULT_COS_AUDIO 5 |
| #define | DEFAULT_COS_SIP 4 |
| #define | DEFAULT_COS_TEXT 5 |
| #define | DEFAULT_COS_VIDEO 6 |
| #define | DEFAULT_MAX_CALL_BITRATE (384) |
| #define | DEFAULT_MOHINTERPRET "default" |
| #define | DEFAULT_MOHSUGGEST "" |
| #define | DEFAULT_NOTIFYMIME "application/simple-message-summary" |
| #define | DEFAULT_NOTIFYRINGING TRUE |
| #define | DEFAULT_PEDANTIC FALSE |
| #define | DEFAULT_QUALIFY FALSE |
| #define | DEFAULT_REALM "asterisk" |
| #define | DEFAULT_REGEXTENONQUALIFY FALSE |
| #define | DEFAULT_SDPOWNER "root" |
| #define | DEFAULT_SDPSESSION "Asterisk PBX" |
| #define | DEFAULT_SRVLOOKUP TRUE |
| #define | DEFAULT_T1MIN 100 |
| #define | DEFAULT_TOS_AUDIO 0 |
| #define | DEFAULT_TOS_SIP 0 |
| #define | DEFAULT_TOS_TEXT 0 |
| #define | DEFAULT_TOS_VIDEO 0 |
| #define | DEFAULT_USERAGENT "Asterisk PBX" |
| #define | DEFAULT_VMEXTEN "asterisk" |
SIPflags | |
| Various flags for the flags field in the pvt structure Trying to sort these up (one or more of the following): D: Dialog P: Peer/user G: Global flag When flags are used by multiple structures, it is important that they have a common layout so it is easy to copy them. | |
| #define | SIP_CALL_LIMIT (1 << 7) |
| #define | SIP_CAN_REINVITE (1 << 20) |
| #define | SIP_CAN_REINVITE_NAT (2 << 20) |
| #define | SIP_DEFER_BYE_ON_TRANSFER (1 << 10) |
| #define | SIP_DTMF (7 << 15) |
| #define | SIP_DTMF_AUTO (3 << 15) |
| #define | SIP_DTMF_INBAND (1 << 15) |
| #define | SIP_DTMF_INFO (2 << 15) |
| #define | SIP_DTMF_RFC2833 (0 << 15) |
| #define | SIP_DTMF_SHORTINFO (4 << 15) |
| #define | SIP_FLAGS_TO_COPY |
| Flags to copy from peer/user to dialog. | |
| #define | SIP_G726_NONSTANDARD (1 << 31) |
| #define | SIP_GOTREFER (1 << 6) |
| #define | SIP_INC_COUNT (1 << 8) |
| #define | SIP_INC_RINGING (1 << 9) |
| #define | SIP_INSECURE (3 << 23) |
| #define | SIP_INSECURE_INVITE (1 << 24) |
| #define | SIP_INSECURE_NONE (0 << 23) |
| #define | SIP_INSECURE_PORT (1 << 23) |
| #define | SIP_NAT (3 << 18) |
| #define | SIP_NAT_ALWAYS (3 << 18) |
| #define | SIP_NAT_NEVER (0 << 18) |
| #define | SIP_NAT_RFC3581 (1 << 18) |
| #define | SIP_NAT_ROUTE (2 << 18) |
| #define | SIP_NEEDREINVITE (1 << 4) |
| #define | SIP_OUTGOING (1 << 0) |
| #define | SIP_PENDINGBYE (1 << 5) |
| #define | SIP_PROG_INBAND (3 << 25) |
| #define | SIP_PROG_INBAND_NEVER (0 << 25) |
| #define | SIP_PROG_INBAND_NO (1 << 25) |
| #define | SIP_PROG_INBAND_YES (2 << 25) |
| #define | SIP_PROGRESS_SENT (1 << 3) |
| #define | SIP_PROMISCREDIR (1 << 11) |
| #define | SIP_REINVITE (7 << 20) |
| #define | SIP_REINVITE_NONE (0 << 20) |
| #define | SIP_REINVITE_UPDATE (4 << 20) |
| #define | SIP_RINGING (1 << 2) |
| #define | SIP_SENDRPID (1 << 29) |
| #define | SIP_TRUSTRPID (1 << 12) |
| #define | SIP_USECLIENTCODE (1 << 14) |
| #define | SIP_USEREQPHONE (1 << 13) |
SIPflags2 | |
| a second page of flags (for flags[1] | |
| #define | SIP_PAGE2_ALLOWOVERLAP (1 << 17) |
| #define | SIP_PAGE2_ALLOWSUBSCRIBE (1 << 16) |
| #define | SIP_PAGE2_BUGGY_MWI (1 << 26) |
| #define | SIP_PAGE2_CALL_ONHOLD (3 << 23) |
| #define | SIP_PAGE2_CALL_ONHOLD_ACTIVE (1 << 23) |
| #define | SIP_PAGE2_CALL_ONHOLD_INACTIVE (3 << 23) |
| #define | SIP_PAGE2_CALL_ONHOLD_ONEDIR (2 << 23) |
| #define | SIP_PAGE2_DIALOG_ESTABLISHED (1 << 27) |
| #define | SIP_PAGE2_FLAGS_TO_COPY |
| #define | SIP_PAGE2_REGISTERTRYING (1 << 29) |
| #define | SIP_PAGE2_RFC2833_COMPENSATE (1 << 25) |
| #define | SIP_PAGE2_RTAUTOCLEAR (1 << 2) |
| #define | SIP_PAGE2_RTCACHEFRIENDS (1 << 0) |
| #define | SIP_PAGE2_STATECHANGEQUEUE (1 << 9) |
| #define | SIP_PAGE2_SUBSCRIBEMWIONLY (1 << 18) |
| #define | SIP_PAGE2_T38SUPPORT (7 << 20) |
| #define | SIP_PAGE2_T38SUPPORT_RTP (2 << 20) |
| #define | SIP_PAGE2_T38SUPPORT_TCP (4 << 20) |
| #define | SIP_PAGE2_T38SUPPORT_UDPTL (1 << 20) |
| #define | SIP_PAGE2_TEXTSUPPORT (1 << 15) |
| #define | SIP_PAGE2_UDPTL_DESTINATION (1 << 30) |
| #define | SIP_PAGE2_VIDEOSUPPORT (1 << 14) |
| #define | SIP_PAGE2_VIDEOSUPPORT_ALWAYS (1 << 31) |
SIPflagsT38 | |
| T.38 set of flags | |
| #define | T38FAX_FILL_BIT_REMOVAL (1 << 0) |
| #define | T38FAX_RATE_12000 (1 << 12) |
| #define | T38FAX_RATE_14400 (1 << 13) |
| #define | T38FAX_RATE_2400 (1 << 8) |
| #define | T38FAX_RATE_4800 (1 << 9) |
| #define | T38FAX_RATE_7200 (1 << 10) |
| #define | T38FAX_RATE_9600 (1 << 11) |
| #define | T38FAX_RATE_MANAGEMENT_LOCAL_TCF (1 << 3) |
| #define | T38FAX_RATE_MANAGEMENT_TRANSFERED_TCF (0 << 3) |
| #define | T38FAX_TRANSCODING_JBIG (1 << 2) |
| #define | T38FAX_TRANSCODING_MMR (1 << 1) |
| #define | T38FAX_UDP_EC_FEC (1 << 4) |
| #define | T38FAX_UDP_EC_NONE (0 << 4) |
| #define | T38FAX_UDP_EC_REDUNDANCY (2 << 4) |
| #define | T38FAX_VERSION (3 << 6) |
| #define | T38FAX_VERSION_0 (0 << 6) |
| #define | T38FAX_VERSION_1 (1 << 6) |
| static int | global_t38_capability = T38FAX_VERSION_0 | T38FAX_RATE_2400 | T38FAX_RATE_4800 | T38FAX_RATE_7200 | T38FAX_RATE_9600 |
GlobalSettings | |
| Global settings apply to the channel (often settings you can change in the general section of sip.conf | |
| static int | allow_external_domains |
| static int | autocreatepeer |
| static int | compactheaders |
| static int | dumphistory |
| static int | global_allowguest |
| static int | global_allowsubscribe |
| static enum transfermodes | global_allowtransfer |
| static int | global_alwaysauthreject |
| static int | global_authfailureevents |
| static int | global_autoframing |
| static int | global_callcounter |
| static int | global_callevents |
| static int | global_capability = AST_FORMAT_ULAW | AST_FORMAT_ALAW | AST_FORMAT_GSM | AST_FORMAT_H263 |
| Codecs that we support by default:. | |
| 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_directrtpsetup |
| static int | global_match_auth_username |
| static int | global_matchexterniplocally |
| static int | global_max_se |
| static int | global_min_se |
| static int | global_notifyhold |
| static int | global_notifyringing |
| static struct sip_proxy | global_outboundproxy |
| static int | global_qualifyfreq |
| static char | global_realm [MAXHOSTNAMELEN] |
| static int | global_reg_timeout |
| static int | global_regattempts_max |
| static char | global_regcontext [AST_MAX_CONTEXT] |
| static int | global_regextenonqualify |
| static int | global_relaxdtmf |
| static int | global_rtautoclear |
| 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_srvlookup |
| 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 int | pedanticsipchecking |
| static int | recordhistory |
DefaultSettings | |
| Default setttings are used as a channel setting and as a default when configuring devices | |
| static char | default_callerid [AST_MAX_EXTENSION] |
| static char | default_context [AST_MAX_CONTEXT] |
| static char | default_fromdomain [AST_MAX_EXTENSION] |
| 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_notifymime [AST_MAX_EXTENSION] |
| static char | default_parkinglot [AST_MAX_CONTEXT] |
| static struct ast_codec_pref | default_prefs |
| static int | default_qualify |
| static char | default_subscribecontext [AST_MAX_CONTEXT] |
| static char | default_vmexten [AST_MAX_EXTENSION] |
| static struct sip_settings | sip_cfg |
Defines | |
| #define | ALLOWED_METHODS "INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY" |
| SIP Methods we support. | |
| #define | append_history(p, event, fmt, args...) append_history_full(p, "%-15s " fmt, event, ## args) |
| Append to SIP dialog history. | |
| #define | CALLERID_UNKNOWN "Unknown" |
| #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 | DEFAULT_DEFAULT_EXPIRY 120 |
| #define | DEFAULT_EXPIRY 900 |
| #define | DEFAULT_FREQ_NOTOK 10 * 1000 |
| #define | DEFAULT_MAX_EXPIRY 3600 |
| #define | DEFAULT_MAX_FORWARDS "70" |
| #define | DEFAULT_MAX_SE 1800 |
| #define | DEFAULT_MAXMS 2000 |
| #define | DEFAULT_MIN_EXPIRY 60 |
| #define | DEFAULT_MIN_SE 90 |
| #define | DEFAULT_QUALIFYFREQ 60 * 1000 |
| #define | DEFAULT_REGISTRATION_TIMEOUT 20 |
| #define | DEFAULT_RETRANS 1000 |
| #define | DEFAULT_TRANS_TIMEOUT -1 |
| #define | EXPIRY_GUARD_LIMIT 30 |
| #define | EXPIRY_GUARD_MIN 500 |
| #define | EXPIRY_GUARD_PCT 0.20 |
| #define | EXPIRY_GUARD_SECS 15 |
| #define | FALSE 0 |
| #define | FINDALLDEVICES (FINDUSERS | FINDPEERS) |
| #define | FINDPEERS (1 << 1) |
| #define | FINDUSERS (1 << 0) |
| #define | FORMAT "%-15.15s %-10.10s %-15.15s %-15.15s %-3.3s %-3.3s %-15.15s %-10.10s\n" |
| #define | FORMAT "%-15.15s %-11.11s %-8.8s %-10.10u%-1.1s %-10.10u (%-2.2u%%) %-6.6u %-10.10u%-1.1s %-10.10u (%-2.2u%%) %-6.6u\n" |
| #define | FORMAT "%-30.30s %-6.6s %-12.12s %8d %-20.20s %-25.25s\n" |
| #define | FORMAT "%-40.40s %-20.20s %-16.16s\n" |
| #define | FORMAT "%-25.25s %-15.15s %-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 "%-30.30s %-6d %-9.9s %-6.6s\n" |
| #define | FORMAT "%-25.25s %-15.15s %-15.15s \n" |
| #define | FORMAT2 "%-15.15s %-10.10s %-15.15s %-15.15s %-7.7s %-15.15s %-6.6s\n" |
| #define | FORMAT2 "%-15.15s %-11.11s %-8.8s %-10.10s %-10.10s (%-2.2s) %-6.6s %-10.10s %-10.10s ( %%) %-6.6s\n" |
| #define | FORMAT2 "%-30.30s %-6.6s %-12.12s %8.8s %-20.20s %-25.25s\n" |
| #define | FORMAT2 "%-25.25s %-15.15s %-3.3s %-3.3s %-3.3s %-8s %-10s %s\n" |
| #define | FORMAT2 "%-30.30s %3.6s %9.9s %6.6s\n" |
| #define | FORMAT2 "%-25.25s %-15.15s %-15.15s \n" |
| #define | FORMAT3 "%-15.15s %-10.10s %-15.15s %-15.15s %-13.13s %-15.15s %-10.10s %-6.6s\n" |
| #define | FORMAT4 "%-15.15s %-10.10s %-15.15s %-15.15s %-13.13s %-15.15s %-10.10s %-6.6d\n" |
| #define | INITIAL_CSEQ 101 |
| #define | IS_SIP_TECH(t) ((t) == &sip_tech || (t) == &sip_tech_info) |
| #define | MAX(a, b) ((a) > (b) ? (a) : (b)) |
| #define | MAX_AUTHTRIES 3 |
| #define | MAX_HISTORY_ENTRIES 50 |
| #define | MAX_RETRANS 6 |
| #define | NO_RTP 0 |
| #define | NOT_SUPPORTED 0 |
| #define | RTP 1 |
| #define | SDP_MAX_RTPMAP_CODECS 32 |
| #define | SDP_SAMPLE_RATE(x) 8000 |
| #define | SIP_MAX_HEADERS 64 |
| #define | SIP_MAX_LINES 64 |
| #define | SIP_MAX_PACKET 4096 |
| #define | SIP_MIN_PACKET 1024 |
| #define | SIP_OPT_100REL (1 << 1) |
| #define | SIP_OPT_EARLY_SESSION (1 << 3) |
| #define | SIP_OPT_EVENTLIST (1 << 11) |
| #define | SIP_OPT_FROMCHANGE (1 << 17) |
| #define | SIP_OPT_GRUU (1 << 12) |
| #define | SIP_OPT_HISTINFO (1 << 15) |
| #define | SIP_OPT_JOIN (1 << 4) |
| #define | SIP_OPT_NOREFERSUB (1 << 14) |
| #define | SIP_OPT_PATH (1 << 5) |
| #define | SIP_OPT_PRECONDITION (1 << 7) |
| #define | SIP_OPT_PREF (1 << 6) |
| #define | SIP_OPT_PRIVACY (1 << 8) |
| #define | SIP_OPT_RECLISTINV (1 << 18) |
| #define | SIP_OPT_RECLISTSUB (1 << 19) |
| #define | SIP_OPT_REPLACES (1 << 0) |
| #define | SIP_OPT_RESPRIORITY (1 << 16) |
| #define | SIP_OPT_SDP_ANAT (1 << 9) |
| #define | SIP_OPT_SEC_AGREE (1 << 10) |
| #define | SIP_OPT_TARGET_DIALOG (1 << 13) |
| #define | SIP_OPT_TIMER (1 << 2) |
| #define | SIP_OPT_UNKNOWN (1 << 20) |
| #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 | SIP_RESERVED ";/?:@&=+$,# " |
| #define | SIP_TIMER_T1 500 |
| #define | SIP_TRANS_TIMEOUT 64 * SIP_TIMER_T1 |
| #define | SIPBUFSIZE 512 |
| #define | STANDARD_SIP_PORT 5060 |
| Standard SIP unsecure port for UDP and TCP from RFC 3261. DO NOT CHANGE THIS. | |
| #define | STANDARD_TLS_PORT 5061 |
| Standard SIP TLS port for sips: from RFC 3261. DO NOT CHANGE THIS. | |
| #define | SUPPORTED 1 |
| #define | SUPPORTED_EXTENSIONS "replaces, timer" |
| SIP Extensions we support. | |
| #define | TRUE 1 |
| #define | UNLINK(element, head, prev) |
| #define | XMIT_ERROR -2 |
Enumerations | |
| enum | can_create_dialog { CAN_NOT_CREATE_DIALOG, CAN_CREATE_DIALOG, CAN_CREATE_DIALOG_UNSUPPORTED_METHOD } |
| States whether a SIP message can create a dialog in Asterisk. More... | |
| enum | check_auth_result { AUTH_DONT_KNOW = -100, AUTH_SUCCESSFUL = 0, AUTH_CHALLENGE_SENT = 1, AUTH_SECRET_FAILED = -1, AUTH_USERNAME_MISMATCH = -2, AUTH_NOT_FOUND = -3, AUTH_FAKE_AUTH = -4, AUTH_UNKNOWN_DOMAIN = -5, AUTH_PEER_NOT_DYNAMIC = -6, AUTH_ACL_FAILED = -7, AUTH_BAD_TRANSPORT = -8 } |
| Authentication result from check_auth* functions. More... | |
| enum | invitestates { INV_NONE = 0, INV_CALLING = 1, INV_PROCEEDING = 2, INV_EARLY_MEDIA = 3, INV_COMPLETED = 4, INV_CONFIRMED = 5, INV_TERMINATED = 6, INV_CANCELLED = 7 } |
| States for the INVITE transaction, not the dialog. More... | |
| enum | parse_register_result { PARSE_REGISTER_FAILED, PARSE_REGISTER_UPDATE, PARSE_REGISTER_QUERY } |
| enum | referstatus { REFER_IDLE, REFER_SENT, REFER_RECEIVED, REFER_CONFIRMED, REFER_ACCEPTED, REFER_RINGING, REFER_200OK, REFER_FAILED, REFER_NOAUTH } |
| Parameters to know status of transfer. More... | |
| enum | sip_auth_type { PROXY_AUTH = 407, WWW_AUTH = 401 } |
| Authentication types - proxy or www authentication. More... | |
| enum | sip_debug_e { sip_debug_none = 0, sip_debug_config = 1, sip_debug_console = 2 } |
| debugging state We store separately the debugging requests from the config file and requests from the CLI. Debugging is enabled if either is set (which means that if sipdebug is set in the config file, we can only turn it off by reloading the config). More... | |
| enum | sip_peer_type { SIP_TYPE_PEER = (1 << 0), SIP_TYPE_USER = (1 << 1) } |
| enum | sip_result { AST_SUCCESS = 0, AST_FAILURE = -1 } |
| The result of a lot of functions. More... | |
| enum | sip_transport { SIP_TRANSPORT_UDP = 1, SIP_TRANSPORT_TCP = 1 << 1, SIP_TRANSPORT_TLS = 1 << 2 } |
| Define some implemented SIP transports. More... | |
| enum | sipmethod { SIP_UNKNOWN, SIP_RESPONSE, SIP_REGISTER, SIP_OPTIONS, SIP_NOTIFY, SIP_INVITE, SIP_ACK, SIP_PRACK, SIP_BYE, SIP_REFER, SIP_SUBSCRIBE, SIP_MESSAGE, SIP_UPDATE, SIP_INFO, SIP_CANCEL, SIP_PUBLISH, SIP_PING } |
| SIP Request methods known by Asterisk. More... | |
| enum | sipregistrystate { REG_STATE_UNREGISTERED = 0, REG_STATE_REGSENT, REG_STATE_AUTHSENT, REG_STATE_REGISTERED, REG_STATE_REJECTED, REG_STATE_TIMEOUT, REG_STATE_NOAUTH, REG_STATE_FAILED } |
| States for outbound registrations (with register= lines in sip.conf. More... | |
| enum | st_mode { SESSION_TIMER_MODE_INVALID = 0, SESSION_TIMER_MODE_ACCEPT, SESSION_TIMER_MODE_ORIGINATE, SESSION_TIMER_MODE_REFUSE } |
| Modes in which Asterisk can be configured to run SIP Session-Timers. More... | |
| enum | st_refresher { SESSION_TIMER_REFRESHER_AUTO, SESSION_TIMER_REFRESHER_UAC, SESSION_TIMER_REFRESHER_UAS } |
| The entity playing the refresher role for Session-Timers. More... | |
| enum | subscriptiontype { NONE = 0, XPIDF_XML, DIALOG_INFO_XML, CPIM_PIDF_XML, PIDF_XML, MWI_NOTIFICATION } |
| Type of subscription, based on the packages we do support. More... | |
| enum | t38_action_flag { SDP_T38_NONE = 0, SDP_T38_INITIATE, SDP_T38_ACCEPT } |
| enum | t38state { T38_DISABLED = 0, T38_LOCAL_REINVITE, T38_PEER_DIRECT, T38_PEER_REINVITE, T38_ENABLED } |
| T38 States for a call. More... | |
| enum | transfermodes { TRANSFER_OPENFORALL, TRANSFER_CLOSED } |
| Authorization scheme for call transfers. More... | |
| enum | xmittype { XMIT_CRITICAL = 2, XMIT_RELIABLE = 1, XMIT_UNRELIABLE = 0 } |
| When sending a SIP message, we can send with a few options, depending on type of SIP request. UNRELIABLE is moslty used for responses to repeated requests, where the original response would be sent RELIABLE in an INVITE transaction. More... | |
Functions | |
| 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 sockaddr_in *sin, int tcp) |
| static void | __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(). | |
| static 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. | |
| static 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. | |
| static 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_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. | |
| static int | acf_channel_read (struct ast_channel *chan, const char *funcname, char *preparse, char *buf, size_t buflen) |
| static void | add_blank (struct sip_request *req) |
| add a blank line if no body | |
| static void | add_codec_to_sdp (const struct sip_pvt *p, int codec, int sample_rate, 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_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 int | add_header (struct sip_request *req, const char *var, const char *value) |
| Add header to SIP message. | |
| static int | add_header_contentLength (struct sip_request *req, int len) |
| Add 'Content-Length' header to SIP message. | |
| static int | add_line (struct sip_request *req, const char *line) |
| Add content (not header) to SIP message. | |
| static void | add_noncodec_to_sdp (const struct sip_pvt *p, int format, int sample_rate, 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 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 void | add_tcodec_to_sdp (const struct sip_pvt *p, int codec, int sample_rate, 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, int codec, int sample_rate, 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 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 (struct in_addr *them, struct sockaddr_in *us) |
| NAT fix - decide which IP address to use for Asterisk server? | |
| 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, struct in_addr 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) |
| 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_rpid (struct sip_pvt *p) |
| Build the Remote Party-ID & From using callingpres options. | |
| 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 | 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, 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 sockaddr_in *sin, struct sip_peer **authpeer, enum xmittype reliable, char *rpid_num, 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, char *uri, enum xmittype reliable, struct sockaddr_in *sin) |
| 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, char *uri, enum xmittype reliable, struct sockaddr_in *sin, 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 externip/seternaddr/stunaddr. | |
| 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 const char * | cli_yesno (int x) |
| return Yes or No depending on the argument. This is used in many places in CLI command, having a function to generate this helps maintaining a consistent output (and possibly emitting the output in other languages, at some point). | |
| 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 | 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) |
| 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 sockaddr_in *sin, int newdialog) |
| 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 void | destroy_association (struct sip_peer *peer) |
| Remove registration data from realtime database or AST/DB when registration expires. | |
| 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 int | dialog_cmp_cb (void *obj, void *arg, int flags) |
| static int | dialog_dump_func (void *userobj, void *arg, int flags) |
| static int | dialog_hash_cb (const void *obj, const int flags) |
| static int | dialog_needdestroy (void *dialogobj, void *arg, int flags) |
| static struct sip_pvt * | dialog_ref (struct sip_pvt *p, char *tag) |
| when we create or delete references, make sure to use these functions so we keep track of the refcounts. To simplify the code, we allow a NULL to be passed to dialog_unref(). | |
| static 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. | |
| static struct sip_pvt * | dialog_unref (struct sip_pvt *p, char *tag) |
| 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, int natflags) |
| 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 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 * | find_alias (const char *name, const char *_default) |
| Find compressed SIP alias. | |
| static int | find_by_name (void *obj, void *arg, int flags) |
| static struct sip_pvt * | find_call (struct sip_request *req, struct sockaddr_in *sin, 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_call_cb (void *__pvt, void *__arg, int flags) |
| static 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 sockaddr_in *sin, int realtime, int which_objects, int devstate_only) |
| 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 int | find_sip_method (const char *msg) |
| find_sip_method: Find SIP method from header | |
| 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 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) |
| Get a specific line from the message body. | |
| static char * | get_body_by_line (const char *line, const char *name, int nameLen) |
| 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 char * | get_calleridname (const char *input, char *output, size_t outputsize) |
| Get caller id name from SIP headers. | |
| static int | get_destination (struct sip_pvt *p, struct sip_request *oreq) |
| 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 const char * | get_header (const struct sip_request *req, const char *name) |
| Get header from SIP request. | |
| static char * | get_in_brackets (char *tmp) |
| Pick out text in brackets from character string. | |
| static struct ast_variable * | get_insecure_variable_from_config (struct ast_config *config) |
| 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, struct sockaddr_in *sin, struct sockaddr_in *vsin, struct sockaddr_in *tsin, struct sockaddr_in *dest, struct sockaddr_in *vdest) |
| Set all IP media addresses for this call. | |
| static int | get_rdnis (struct sip_pvt *p, struct sip_request *oreq) |
| Get referring dnis. | |
| 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_num (const char *input, char *output, int maxlen) |
| Get caller id number from Remote-Party-ID header field Returns true if number should be restricted (privacy setting found) output is set to NULL if no number found. | |
| static const char * | get_sdp (struct sip_request *req, const char *name) |
| Get a line from an SDP message body. | |
| 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 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_transport (enum sip_transport t) |
| static const char * | get_transport_list (struct sip_peer *peer) |
| static const char * | get_transport_pvt (struct sip_pvt *p) |
| static const char * | gettag (const struct sip_request *req, const char *header, char *tagbuf, int tagbufsize) |
| Get tag from packet. | |
| 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 sockaddr_in *sin, 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 sockaddr_in *sin) |
| 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 sockaddr_in *sin) |
| 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 sockaddr_in *sin, int *recount, 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 sockaddr_in *sin, int seqno, char *e) |
| Handle incoming notifications. | |
| static int | handle_request_options (struct sip_pvt *p, struct sip_request *req) |
| Handle incoming OPTIONS request An OPTIONS request should be answered like an INVITE from the same UA, including SDP. | |
| 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 sockaddr_in *sin, char *e) |
| Handle incoming REGISTER request. | |
| static int | handle_request_subscribe (struct sip_pvt *p, struct sip_request *req, struct sockaddr_in *sin, int seqno, char *e) |
| Handle incoming SUBSCRIBE request. | |
| static void | handle_response (struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int seqno) |
| Handle SIP response in dialogue. | |
| static void | handle_response_invite (struct sip_pvt *p, int resp, 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, 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_refer (struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int seqno) |
| static int | handle_response_register (struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int seqno) |
| Handle responses on REGISTER to services. | |
| static const char * | hangup_cause2sip (int cause) |
| Convert Asterisk hangup causes to SIP codes. | |
| static 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 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) |
| Initiate new SIP request to peer/user. | |
| static const char * | insecure2str (int mode) |
| Convert Insecure setting to printable string. | |
| 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) |
| 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 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 const char * | nat2str (int nat) |
| Convert NAT setting to text string. | |
| static struct sip_proxy * | obproxy_get (struct sip_pvt *dialog, struct sip_peer *peer) |
| Get default outbound proxy or global proxy. | |
| 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) |
| 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 unsigned int | parse_sip_options (struct sip_pvt *pvt, const char *supported) |
| Parse supported header in incoming packet. | |
| static int | parse_uri (char *uri, char *scheme, char **ret_name, char **pass, char **domain, char **port, char **options) |
| * parses a URI in its components. | |
| 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 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 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 struct sip_proxy * | proxy_allocate (char *name, char *port, int force) |
| Allocate and initialize sip proxy. | |
| static int | proxy_update (struct sip_proxy *proxy) |
| static int | queue_request (struct sip_pvt *p, const struct sip_request *req) |
| static struct sip_peer * | realtime_peer (const char *newpeername, struct sockaddr_in *sin, 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 sockaddr_in *sin, const char *defaultuser, const char *fullcontact, const char *useragent, int expirey, int 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 struct sip_proxy * | 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 sockaddr_in *sin, struct sip_request *req, 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 void | replace_cid (struct sip_pvt *p, const char *rpid_num, const char *calleridname) |
| helper function for check_{user|peer}_ok() | |
| 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_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 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_peer_defaults (struct sip_peer *peer) |
| Set peer defaults before configuring specific configurations. | |
| static void | set_t38_capabilities (struct sip_pvt *p) |
| Set the global T38 capabilities on a SIP dialog structure. | |
| 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, void *data) |
| Add a SIP header to an outbound INVITE. | |
| static struct sip_pvt * | sip_alloc (ast_string_field callid, struct sockaddr_in *sin, int useglobal_nat, const int intended_method) |
| 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. | |
| static 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 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 sockaddr_in *addr) |
| See if we pass debug IP filter. | |
| static int | sip_debug_test_pvt (struct sip_pvt *p) |
| Test PVT for debugging output. | |
| static 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, char *arg) |
| Enable SIP Debugging for a single IP. | |
| static char * | sip_do_debug_peer (int fd, char *arg) |
| Turn on SIP debugging for a given peer. | |
| static char * | sip_do_history_deprecated (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| Enable/Disable SIP History logging (CLI) - deprecated. use sip_set_history instead. | |
| static int | sip_do_reload (enum channelreloadreason reason) |
| Reload module. | |
| static int | sip_dtmfmode (struct ast_channel *chan, void *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_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_codec (struct ast_channel *chan) |
| Return SIP UA's codec (part of the RTP interface). | |
| static enum ast_rtp_get_result | sip_get_rtp_peer (struct ast_channel *chan, struct ast_rtp **rtp) |
| Returns null if we can't reinvite audio (part of RTP interface). | |
| static enum ast_rtp_get_result | sip_get_trtp_peer (struct ast_channel *chan, struct ast_rtp **rtp) |
| Returns null if we can't reinvite text (part of RTP interface). | |
| static struct ast_udptl * | sip_get_udptl_peer (struct ast_channel *chan) |
| static enum ast_rtp_get_result | sip_get_vrtp_peer (struct ast_channel *chan, struct ast_rtp **rtp) |
| Returns null if we can't reinvite video (part of RTP interface). | |
| 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 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) |
| 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_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 int | sip_parse_host (char *line, int lineno, char **hostname, int *portnum, enum sip_transport *transport) |
| Small function to parse a config line for a host with a transport i.e. tls://www.google.com:8056. | |
| 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 Space them out 100 ms apart XXX We might have a cool algorithm for this or use random - any suggestions? | |
| 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 sockaddr_in * | sip_real_dst (const struct sip_pvt *p) |
| The real destination address for a write. | |
| 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) |
| Parse register=> line in sip.conf and add to registry. | |
| 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 struct ast_channel * | sip_request_call (const char *type, int format, 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. | |
| static void | sip_scheddestroy (struct sip_pvt *p, int ms) |
| Schedule destruction of SIP dialog. | |
| 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 *rtp, struct ast_rtp *vrtp, struct ast_rtp *trtp, int codecs, int nat_active) |
| Set the RTP peer for this call. | |
| static int | sip_set_udptl_peer (struct ast_channel *chan, struct ast_udptl *udptl) |
| 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_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_t38_abort (const void *data) |
| static struct ast_tcptls_session_instance * | sip_tcp_locate (struct sockaddr_in *s) |
| Find thread for TCP/TLS session (based on IP/Port. | |
| static void * | sip_tcp_worker_fn (void *data) |
| SIP TCP connection handler. | |
| 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 int | sip_uri_cmp (const char *input1, const char *input2) |
| static int | sip_uri_headers_cmp (const char *input1, const char *input2) |
| helper routine for sip_uri_cmp | |
| static int | sip_uri_params_cmp (const char *input1, const char *input2) |
| helper routine for sip_uri_cmp | |
| 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 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 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 int | t38_get_rate (int t38cap) |
| Get Max T.38 Transmission rate from T38 capabilities. | |
| 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 char * | transfermode2str (enum transfermodes mode) |
| Convert transfer mode to text string. | |
| 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_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) |
| Build REFER/INVITE/OPTIONS 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_custom (struct sip_pvt *p, struct ast_variable *vars) |
| Notify device with custom headers from sip_notify.conf. | |
| static int | transmit_notify_with_mwi (struct sip_pvt *p, int newmsgs, int oldmsgs, 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_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 sockaddr_in *sin, 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_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) |
| Used for 200 OK and 183 early media. | |
| 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 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_peer (struct sip_peer *p, int expire) |
| Update peer data in database (if used). | |
Variables | |
| static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, } |
| static char * | app_dtmfmode = "SIPDtmfMode" |
| static char * | app_sipaddheader = "SIPAddHeader" |
| static struct ast_module_info * | ast_module_info = &__mod_info |
| static struct sip_auth * | authl = NULL |
| Authentication list for realm authentication. | |
| static struct sockaddr_in | bindaddr |
| 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_cli_entry | cli_sip_do_history_deprecated = { .handler = sip_do_history_deprecated , .summary = "Enable/Disable SIP history" ,__VA_ARGS__ } |
| static const char | config [] = "sip.conf" |
| static struct sockaddr_in | debugaddr |
| static int | default_expiry = DEFAULT_DEFAULT_EXPIRY |
| static struct ast_jb_conf | default_jbconf |
| Global jitterbuffer configuration - by default, jb is disabled. | |
| static struct ast_tls_config | default_tls_cfg |
| Default TLS connection configuration. | |
| static char * | descrip_dtmfmode = " SIPDtmfMode(inband|info|rfc2833): Changes the dtmfmode for a SIP call\n" |
| static char * | descrip_sipaddheader |
| 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 time_t | externexpire |
| static char | externhost [MAXHOSTNAMELEN] |
| static struct sockaddr_in | externip |
| our external IP address/port for SIP sessions. externip.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 int | externrefresh = 10 |
| static struct ast_ha * | global_contact_ha = NULL |
| Global list of addresses dynamic peers are not allowed to use. | |
| static int | global_dynamic_exclude_static = 0 |
| static struct ast_jb_conf | global_jbconf |
| static int | hash_dialog_size = 563 |
| static int | hash_peer_size = 563 |
| static int | hash_user_size = 563 |
| static struct _map_x_s | insecurestr [] |
| static struct sockaddr_in | 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 invstate2stringtable | invitestate2string [] |
| Readable descriptions of device states. | |
| 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 char | mandescr_show_peer [] |
| static char | mandescr_show_peers [] |
| static char | mandescr_show_registry [] |
| Manager Action SIPShowRegistry description. | |
| static char | mandescr_sipnotify [] |
| static int | max_expiry = DEFAULT_MAX_EXPIRY |
| static int | min_expiry = DEFAULT_MIN_EXPIRY |
| static struct _map_x_s | natmodes [] |
| static const char | notify_config [] = "sip_notify.conf" |
| static struct ast_config * | notify_types |
| static int | ourport_tcp |
| static int | ourport_tls |
| ao2_container * | peers |
| The peer list: Users, Peers and Friends. | |
| ao2_container * | peers_by_ip |
| static struct _map_x_s | referstatusstrings [] |
| static struct ast_register_list | regl |
| The register list: Other SIP proxies we register with and place calls to. | |
| static struct _map_x_s | regstatestrings [] |
| static struct ast_custom_function | sip_header_function |
| 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 cfsip_options | sip_options [] |
| List of well-known SIP options. If we get this in a require, we should check the list and answer accordingly. | |
| static struct ast_rtp_protocol | sip_rtp |
| Interface structure with callbacks used to connect to RTP module. | |
| static struct ast_tcptls_session_args | sip_tcp_desc |
| The TCP server definition. | |
| static struct ast_channel_tech | sip_tech |
| Definition of this channel for PBX channel registration. | |
| static 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. | |
| ast_custom_function | sippeer_function |
| Structure to declare a dialplan function: SIPPEER. | |
| static int | sipsock = -1 |
| Main socket for SIP communication. | |
| static struct _map_x_s | stmodes [] |
| Report Peer status in character string. | |
| static struct _map_x_s | strefreshers [] |
| static struct sockaddr_in | stunaddr |
| static struct cfsubscription_types | subscription_types [] |
Subscription types that we support. We support
| |
| static char * | synopsis_dtmfmode = "Change the dtmfmode for a SIP call" |
| static char * | synopsis_sipaddheader = "Add a SIP header to the outbound call" |
| static struct ast_threadstorage | ts_temp_pvt = { .once = PTHREAD_ONCE_INIT, .key_init = __init_ts_temp_pvt , .custom_init = temp_pvt_init , } |
********** IMPORTANT *
VIA branch tag transaction checking
Transaction support
We need to test TCP sessions with SIP proxies and in regards to the SIP outbound specs.
Fix TCP/TLS handling in dialplan, SRV records, transfers and much more
Save TCP/TLS sessions in registry
Add TCP/TLS information to function SIPPEER and SIPCHANINFO
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 ALLOWED_METHODS "INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY" |
SIP Methods we support.
Definition at line 654 of file chan_sip.c.
Referenced by respprep(), transmit_invite(), transmit_notify_with_sipfrag(), transmit_refer(), and transmit_reinvite_with_sdp().
| #define append_history | ( | p, | |||
| event, | |||||
| fmt, | |||||
| args... | ) | append_history_full(p, "%-15s " fmt, event, ## args) |
Append to SIP dialog history.
Definition at line 2096 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_incoming(), handle_invite_replaces(), handle_request_bye(), handle_request_do(), handle_request_invite(), handle_request_refer(), handle_request_register(), handle_request_subscribe(), handle_response_invite(), local_attended_transfer(), obproxy_get(), process_sdp(), 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(), and transmit_response_with_auth().
| #define CALLERID_UNKNOWN "Unknown" |
| #define CHECK_AUTH_BUF_INITLEN 256 |
Definition at line 10883 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 2003 of file chan_sip.c.
Referenced by create_addr_from_peer(), and register_verify().
| #define DEC_CALL_LIMIT 0 |
Definition at line 850 of file chan_sip.c.
Referenced by __sip_destroy(), handle_request_cancel(), handle_request_invite(), handle_response_invite(), sip_hangup(), and update_call_counter().
| #define DEC_CALL_RINGING 2 |
Definition at line 852 of file chan_sip.c.
Referenced by handle_response_invite(), and update_call_counter().
| #define DEFAULT_ALLOW_EXT_DOM TRUE |
Allow external domains
Definition at line 702 of file chan_sip.c.
| #define DEFAULT_ALLOWGUEST TRUE |
Definition at line 690 of file chan_sip.c.
| #define DEFAULT_AUTOCREATEPEER FALSE |
Definition at line 706 of file chan_sip.c.
| #define DEFAULT_CALLCOUNTER FALSE |
Definition at line 691 of file chan_sip.c.
| #define DEFAULT_CALLERID "asterisk" |
Definition at line 688 of file chan_sip.c.
| #define DEFAULT_COMPACTHEADERS FALSE |
Definition at line 693 of file chan_sip.c.
| #define DEFAULT_CONTEXT "default" |
Definition at line 684 of file chan_sip.c.
| #define DEFAULT_COS_AUDIO 5 |
Level 2 class of service for audio media
Definition at line 699 of file chan_sip.c.
| #define DEFAULT_COS_SIP 4 |
Level 2 class of service for SIP signalling
Definition at line 698 of file chan_sip.c.
| #define DEFAULT_COS_TEXT 5 |
Level 2 class of service for text media (T.140)
Definition at line 701 of file chan_sip.c.
| #define DEFAULT_COS_VIDEO 6 |
Level 2 class of service for video media
Definition at line 700 of file chan_sip.c.
| #define DEFAULT_DEFAULT_EXPIRY 120 |
Definition at line 223 of file chan_sip.c.
| #define DEFAULT_EXPIRY 900 |
Expire slowly
Definition at line 240 of file chan_sip.c.
| #define DEFAULT_FREQ_NOTOK 10 * 1000 |
Qualification: How often to check, if the host is down...
Definition at line 254 of file chan_sip.c.
| #define DEFAULT_MAX_CALL_BITRATE (384) |
Max bitrate for video
Definition at line 710 of file chan_sip.c.
| #define DEFAULT_MAX_EXPIRY 3600 |
Definition at line 225 of file chan_sip.c.
| #define DEFAULT_MAX_FORWARDS "70" |
Definition at line 227 of file chan_sip.c.
Referenced by initreqprep(), reqprep(), and transmit_register().
| #define DEFAULT_MAX_SE 1800 |
Session-Timer Default Session-Expires period (RFC 4028)
Definition at line 272 of file chan_sip.c.
| #define DEFAULT_MAXMS 2000 |
Qualification: Must be faster than 2 seconds by default
Definition at line 252 of file chan_sip.c.
| #define DEFAULT_MIN_EXPIRY 60 |
Definition at line 224 of file chan_sip.c.
| #define DEFAULT_MIN_SE 90 |
Session-Timer Default Min-SE period (RFC 4028)
Definition at line 273 of file chan_sip.c.
| #define DEFAULT_MOHINTERPRET "default" |
Definition at line 685 of file chan_sip.c.
| #define DEFAULT_MOHSUGGEST "" |
Definition at line 686 of file chan_sip.c.
| #define DEFAULT_NOTIFYMIME "application/simple-message-summary" |
Definition at line 689 of file chan_sip.c.
| #define DEFAULT_NOTIFYRINGING TRUE |
Definition at line 704 of file chan_sip.c.
| #define DEFAULT_PEDANTIC FALSE |
Definition at line 705 of file chan_sip.c.
| #define DEFAULT_QUALIFY FALSE |
Definition at line 707 of file chan_sip.c.
| #define DEFAULT_QUALIFYFREQ 60 * 1000 |
Qualification: How often to check for the host to be up
Definition at line 253 of file chan_sip.c.
| #define DEFAULT_REALM "asterisk" |
Realm for HTTP digest authentication
Definition at line 703 of file chan_sip.c.
| #define DEFAULT_REGEXTENONQUALIFY FALSE |
Definition at line 708 of file chan_sip.c.
| #define DEFAULT_REGISTRATION_TIMEOUT 20 |
Definition at line 226 of file chan_sip.c.
| #define DEFAULT_RETRANS 1000 |
How frequently to retransmit Default: 2 * 500 ms in RFC 3261
Definition at line 256 of file chan_sip.c.
| #define DEFAULT_SDPOWNER "root" |
Default SDP username field in (o=) header unless re-defined in sip.conf
Definition at line 714 of file chan_sip.c.
| #define DEFAULT_SDPSESSION "Asterisk PBX" |
Default SDP session name, (s=) header unless re-defined in sip.conf
Definition at line 713 of file chan_sip.c.
| #define DEFAULT_SRVLOOKUP TRUE |
Recommended setting is ON
Definition at line 692 of file chan_sip.c.
| #define DEFAULT_T1MIN 100 |
100 MS for minimal roundtrip time
Definition at line 709 of file chan_sip.c.
| #define DEFAULT_TOS_AUDIO 0 |
Audio packets should be marked as DSCP EF (Expedited Forwarding), but the default is 0 to be compatible with previous versions.
Definition at line 695 of file chan_sip.c.
| #define DEFAULT_TOS_SIP 0 |
Call signalling packets should be marked as DSCP CS3, but the default is 0 to be compatible with previous versions.
Definition at line 694 of file chan_sip.c.
| #define DEFAULT_TOS_TEXT 0 |
Text packets should be marked as XXXX XXXX, but the default is 0 to be compatible with previous versions.
Definition at line 697 of file chan_sip.c.
| #define DEFAULT_TOS_VIDEO 0 |
Video packets should be marked as DSCP AF41, but the default is 0 to be compatible with previous versions.
Definition at line 696 of file chan_sip.c.
| #define DEFAULT_TRANS_TIMEOUT -1 |
Definition at line 262 of file chan_sip.c.
Referenced by __sip_autodestruct(), cb_extensionstate(), check_auth(), check_pendings(), handle_incoming(), handle_invite_replaces(), handle_request_bye(), handle_request_cancel(), handle_request_info(), handle_request_invite(), handle_request_notify(), handle_request_options(), handle_request_register(), handle_response_invite(), handle_response_register(), receive_message(), sip_hangup(), sip_send_mwi_to_peer(), and transmit_fake_auth_response().
| #define DEFAULT_USERAGENT "Asterisk PBX" |
Default Useragent: header unless re-defined in sip.conf
Definition at line 712 of file chan_sip.c.
| #define DEFAULT_VMEXTEN "asterisk" |
Definition at line 687 of file chan_sip.c.
| #define EXPIRY_GUARD_LIMIT 30 |
Below here, we use EXPIRY_GUARD_PCT instead of EXPIRY_GUARD_SECS
Definition at line 232 of file chan_sip.c.
Referenced by handle_response_register().
| #define EXPIRY_GUARD_MIN 500 |
This is the minimum guard time applied. If GUARD_PCT turns out to be lower than this, it will use this time instead. This is in milliseconds.
Definition at line 234 of file chan_sip.c.
Referenced by handle_response_register().
| #define EXPIRY_GUARD_PCT 0.20 |
Percentage of expires timeout to use when below EXPIRY_GUARD_LIMIT
Definition at line 238 of file chan_sip.c.
Referenced by handle_response_register().
| #define EXPIRY_GUARD_SECS 15 |
How long before expiry do we reregister
Definition at line 231 of file chan_sip.c.
Referenced by handle_response_register().
| #define FALSE 0 |
Definition at line 203 of file chan_sip.c.
| #define FINDALLDEVICES (FINDUSERS | FINDPEERS) |
Definition at line 215 of file chan_sip.c.
Referenced by check_peer_ok(), find_by_name(), sip_devicestate(), sip_peer_hold(), and update_call_counter().
| #define FINDPEERS (1 << 1) |
Definition at line 214 of file chan_sip.c.
Referenced by _sip_qualify_peer(), _sip_show_peer(), check_peer_ok(), create_addr(), find_by_name(), function_sippeer(), register_verify(), sip_do_debug_peer(), sip_unregister(), st_get_mode(), st_get_refresher(), and st_get_se().
| #define FINDUSERS (1 << 0) |
Definition at line 213 of file chan_sip.c.
Referenced by check_peer_ok(), find_by_name(), and sip_show_user().
| #define FORMAT "%-15.15s %-10.10s %-15.15s %-15.15s %-3.3s %-3.3s %-15.15s %-10.10s\n" |
Definition at line 14408 of file chan_sip.c.
| #define FORMAT "%-15.15s %-11.11s %-8.8s %-10.10u%-1.1s %-10.10u (%-2.2u%%) %-6.6u %-10.10u%-1.1s %-10.10u (%-2.2u%%) %-6.6u\n" |
Definition at line 14408 of file chan_sip.c.
| #define FORMAT "%-30.30s %-6.6s %-12.12s %8d %-20.20s %-25.25s\n" |
Definition at line 14408 of file chan_sip.c.
| #define FORMAT "%-40.40s %-20.20s %-16.16s\n" |
Definition at line 14408 of file chan_sip.c.
| #define FORMAT "%-25.25s %-15.15s %-3.3s %-3.3s %-3.3s %-8d %-10s %s\n" |
Definition at line 14408 of file chan_sip.c.
| #define FORMAT "%-25.25s %-15.15s %-15.15s %-15.15s %-5.5s%-10.10s\n" |
Definition at line 14408 of file chan_sip.c.
| #define FORMAT "%-30.30s %-6d %-9.9s %-6.6s\n" |
Definition at line 14408 of file chan_sip.c.
| #define FORMAT "%-25.25s %-15.15s %-15.15s \n" |
Definition at line 14408 of file chan_sip.c.
| #define FORMAT2 "%-15.15s %-10.10s %-15.15s %-15.15s %-7.7s %-15.15s %-6.6s\n" |
Definition at line 14407 of file chan_sip.c.
| #define FORMAT2 "%-15.15s %-11.11s %-8.8s %-10.10s %-10.10s (%-2.2s) %-6.6s %-10.10s %-10.10s ( %%) %-6.6s\n" |
Definition at line 14407 of file chan_sip.c.
| #define FORMAT2 "%-30.30s %-6.6s %-12.12s %8.8s %-20.20s %-25.25s\n" |
Definition at line 14407 of file chan_sip.c.
| #define FORMAT2 "%-25.25s %-15.15s %-3.3s %-3.3s %-3.3s %-8s %-10s %s\n" |
Definition at line 14407 of file chan_sip.c.
| #define FORMAT2 "%-30.30s %3.6s %9.9s %6.6s\n" |
Definition at line 14407 of file chan_sip.c.
| #define FORMAT2 "%-25.25s %-15.15s %-15.15s \n" |
Definition at line 14407 of file chan_sip.c.
| #define FORMAT3 "%-15.15s %-10.10s %-15.15s %-15.15s %-13.13s %-15.15s %-10.10s %-6.6s\n" |
| #define FORMAT4 "%-15.15s %-10.10s %-15.15s %-15.15s %-13.13s %-15.15s %-10.10s %-6.6d\n" |
| #define INC_CALL_LIMIT 1 |
Definition at line 851 of file chan_sip.c.
Referenced by handle_request_invite(), and update_call_counter().
| #define INC_CALL_RINGING 3 |
| #define INITIAL_CSEQ 101 |
our initial sip sequence number
Definition at line 270 of file chan_sip.c.
Referenced by sip_alloc(), sip_register(), and transmit_response_using_temp().
| #define IS_SIP_TECH | ( | t | ) | ((t) == &sip_tech || (t) == &sip_tech_info) |
Definition at line 2319 of file chan_sip.c.
Referenced by acf_channel_read(), func_header_read(), function_sipchaninfo_read(), handle_request_bye(), sip_dtmfmode(), and sip_hangup().
| #define MAX | ( | a, | |||
| b | ) | ((a) > (b) ? (a) : (b)) |
Definition at line 247 of file chan_sip.c.
| #define MAX_AUTHTRIES 3 |
Try authentication three times, then fail
Definition at line 263 of file chan_sip.c.
Referenced by handle_response(), handle_response_invite(), and handle_response_register().
| #define MAX_HISTORY_ENTRIES 50 |
Max entires in the history list for a sip_pvt
Definition at line 1409 of file chan_sip.c.
Referenced by append_history_va().
| #define MAX_RETRANS 6 |
Try only 6 times for retransmissions, a total of 7 transmissions
Definition at line 257 of file chan_sip.c.
| #define NO_RTP 0 |
Definition at line 291 of file chan_sip.c.
| #define NOT_SUPPORTED 0 |
Definition at line 572 of file chan_sip.c.
| #define REQ_OFFSET_TO_STR | ( | req, | |||
| offset | ) | ((req)->data->str + ((req)->offset)) |
Definition at line 916 of file chan_sip.c.
Referenced by __get_header(), _sip_tcp_helper_thread(), find_sdp(), get_body(), get_destination(), get_msg_text(), get_sdp_iterate(), handle_incoming(), handle_request_do(), handle_request_invite(), reqprep(), and send_response().
| #define RTP 1 |
Definition at line 290 of file chan_sip.c.
| #define SDP_MAX_RTPMAP_CODECS 32 |
Maximum number of codecs allowed in received SDP
Definition at line 275 of file chan_sip.c.
Referenced by process_sdp().
| #define SDP_SAMPLE_RATE | ( | x | ) | 8000 |
Definition at line 8596 of file chan_sip.c.
Referenced by add_sdp().
| #define SIP_CALL_LIMIT (1 << 7) |
D: Call limit enforced for this call
Definition at line 999 of file chan_sip.c.
Referenced by check_peer_ok(), create_addr_from_peer(), and update_call_counter().
| #define SIP_CAN_REINVITE (1 << 20) |
DP: allow peers to be reinvited to send media directly p2p
Definition at line 1027 of file chan_sip.c.
Referenced by _sip_show_peer(), handle_common_options(), sip_get_rtp_peer(), sip_get_trtp_peer(), sip_get_udptl_peer(), and sip_get_vrtp_peer().
| #define SIP_CAN_REINVITE_NAT (2 << 20) |
DP: allow media reinvite when new peer is behind NAT
Definition at line 1028 of file chan_sip.c.
Referenced by handle_common_options(), sip_get_rtp_peer(), and sip_set_rtp_peer().
| #define SIP_DEFER_BYE_ON_TRANSFER (1 << 10) |
D: Do not hangup at first ast_hangup
Definition at line 1002 of file chan_sip.c.
Referenced by handle_invite_replaces(), handle_request_refer(), local_attended_transfer(), sip_hangup(), and sip_set_rtp_peer().
| #define SIP_DTMF (7 << 15) |
DP: DTMF Support: five settings, uses three bits
Definition at line 1010 of file chan_sip.c.
Referenced by _sip_show_peer(), check_peer_ok(), create_addr_from_peer(), handle_common_options(), handle_request_invite(), process_sdp(), sip_alloc(), sip_dtmfmode(), sip_new(), sip_rtp_read(), sip_senddigit_begin(), sip_senddigit_end(), sip_show_channel(), sip_show_settings(), and transmit_info_with_digit().
| #define SIP_DTMF_AUTO (3 << 15) |
DP: DTMF Support: AUTO switch between rfc2833 and in-band DTMF
Definition at line 1014 of file chan_sip.c.
Referenced by check_peer_ok(), create_addr_from_peer(), handle_common_options(), process_sdp(), sip_alloc(), and sip_new().
| #define SIP_DTMF_INBAND (1 << 15) |
DP: DTMF Support: Inband audio, only for ULAW/ALAW - "inband"
Definition at line 1012 of file chan_sip.c.
Referenced by handle_common_options(), process_sdp(), sip_dtmfmode(), sip_new(), sip_rtp_read(), sip_senddigit_begin(), and sip_senddigit_end().
| #define SIP_DTMF_INFO (2 << 15) |
DP: DTMF Support: SIP Info messages - "info"
Definition at line 1013 of file chan_sip.c.
Referenced by handle_common_options(), sip_dtmfmode(), sip_new(), and sip_senddigit_end().
| #define SIP_DTMF_RFC2833 (0 << 15) |
DP: DTMF Support: RTP DTMF - "rfc2833"
Definition at line 1011 of file chan_sip.c.
Referenced by check_peer_ok(), create_addr_from_peer(), handle_common_options(), handle_request_invite(), process_sdp(), sip_alloc(), sip_dtmfmode(), sip_rtp_read(), sip_senddigit_begin(), and sip_senddigit_end().
| #define SIP_DTMF_SHORTINFO (4 << 15) |
DP: DTMF Support: SIP Info messages - "info" - short variant
Definition at line 1015 of file chan_sip.c.
Referenced by handle_common_options(), sip_dtmfmode(), sip_new(), sip_senddigit_end(), and transmit_info_with_digit().
| #define SIP_FLAGS_TO_COPY |
Value:
(SIP_PROMISCREDIR | SIP_TRUSTRPID | SIP_SENDRPID | SIP_DTMF | SIP_REINVITE | \ SIP_PROG_INBAND | SIP_USECLIENTCODE | SIP_NAT | SIP_G726_NONSTANDARD | \ SIP_USEREQPHONE | SIP_INSECURE)
Definition at line 1047 of file chan_sip.c.
Referenced by check_peer_ok(), create_addr_from_peer(), set_peer_defaults(), sip_alloc(), and sip_poke_peer().
| #define SIP_G726_NONSTANDARD (1 << 31) |
DP: Use non-standard packing for G726-32 data
Definition at line 1044 of file chan_sip.c.
Referenced by add_codec_to_sdp(), handle_common_options(), and process_sdp().
| #define SIP_GOTREFER (1 << 6) |
D: Got a refer?
Definition at line 998 of file chan_sip.c.
Referenced by handle_request_refer(), local_attended_transfer(), sip_read(), sip_set_rtp_peer(), and sip_set_udptl_peer().
| #define SIP_INC_COUNT (1 << 8) |
D: Did this dialog increment the counter of in-use calls?
Definition at line 1000 of file chan_sip.c.
Referenced by __sip_destroy(), handle_request_cancel(), sip_hangup(), and update_call_counter().
| #define SIP_INC_RINGING (1 << 9) |
D: Did this connection increment the counter of in-use calls?
Definition at line 1001 of file chan_sip.c.
Referenced by update_call_counter().
| #define SIP_INSECURE (3 << 23) |
DP: three settings, uses two bits
Definition at line 1032 of file chan_sip.c.
Referenced by _sip_show_peer(), and handle_common_options().
| #define SIP_INSECURE_INVITE (1 << 24) |
DP: don't require authentication for incoming INVITEs
Definition at line 1035 of file chan_sip.c.
Referenced by check_peer_ok(), and set_insecure_flags().
| #define SIP_INSECURE_NONE (0 << 23) |
DP: secure mode
Definition at line 1033 of file chan_sip.c.
| #define SIP_INSECURE_PORT (1 << 23) |
DP: don't require matching port for incoming requests
Definition at line 1034 of file chan_sip.c.
Referenced by find_peer(), get_insecure_variable_from_config(), peer_ipcmp_cb(), peer_iphash_cb(), and set_insecure_flags().
| #define SIP_MAX_HEADERS 64 |
Max amount of SIP headers to read
Definition at line 265 of file chan_sip.c.
Referenced by add_header(), and parse_request().
| #define SIP_MAX_LINES 64 |
Max amount of lines in SIP attachment (like SDP)
Definition at line 266 of file chan_sip.c.
Referenced by add_line(), and parse_request().
| #define SIP_MAX_PACKET 4096 |
Also from RFC 3261 (2543), should sub headers tho
Definition at line 267 of file chan_sip.c.
| #define SIP_MIN_PACKET 1024 |
Initialize size of memory to allocate for packets
Definition at line 268 of file chan_sip.c.
Referenced by _sip_tcp_helper_thread(), init_req(), init_resp(), and sipsock_read().
| #define SIP_NAT (3 << 18) |
DP: four settings, uses two bits
Definition at line 1018 of file chan_sip.c.
Referenced by _sip_show_peer(), build_via(), copy_via_headers(), create_addr(), create_addr_from_peer(), handle_common_options(), process_sdp(), register_verify(), sip_alloc(), sip_nat_mode(), sip_real_dst(), sip_show_channel(), sip_show_settings(), sip_show_users(), and transmit_response_using_temp().
| #define SIP_NAT_ALWAYS (3 << 18) |
DP: NAT Both ROUTE and RFC3581
Definition at line 1022 of file chan_sip.c.
Referenced by copy_via_headers(), and handle_common_options().
| #define SIP_NAT_NEVER (0 << 18) |
DP: No nat support
Definition at line 1019 of file chan_sip.c.
Referenced by handle_common_options().
| #define SIP_NAT_RFC3581 (1 << 18) |
DP: NAT RFC3581
Definition at line 1020 of file chan_sip.c.
Referenced by build_via(), copy_via_headers(), and handle_common_options().
| #define SIP_NAT_ROUTE (2 << 18) |
DP: NAT Only ROUTE
Definition at line 1021 of file chan_sip.c.
Referenced by _sip_show_peers(), check_peer_ok(), check_via(), create_addr(), create_addr_from_peer(), handle_common_options(), parse_register_contact(), send_request(), set_address_from_contact(), sip_alloc(), sip_nat_mode(), sip_real_dst(), and transmit_response_using_temp().
| #define SIP_NEEDREINVITE (1 << 4) |
D: Do we need to send another reinvite?
Definition at line 996 of file chan_sip.c.
Referenced by check_pendings(), sip_hangup(), sip_indicate(), sip_read(), sip_reinvite_retry(), sip_sendhtml(), sip_set_rtp_peer(), and sip_set_udptl_peer().
| #define SIP_OPT_100REL (1 << 1) |
Definition at line 576 of file chan_sip.c.
| #define SIP_OPT_EARLY_SESSION (1 << 3) |
Definition at line 578 of file chan_sip.c.
| #define SIP_OPT_EVENTLIST (1 << 11) |
Definition at line 586 of file chan_sip.c.
| #define SIP_OPT_FROMCHANGE (1 << 17) |
Definition at line 592 of file chan_sip.c.
| #define SIP_OPT_GRUU (1 << 12) |
Definition at line 587 of file chan_sip.c.
| #define SIP_OPT_HISTINFO (1 << 15) |
Definition at line 590 of file chan_sip.c.
| #define SIP_OPT_JOIN (1 << 4) |
Definition at line 579 of file chan_sip.c.
| #define SIP_OPT_NOREFERSUB (1 << 14) |
Definition at line 589 of file chan_sip.c.
| #define SIP_OPT_PATH (1 << 5) |
Definition at line 580 of file chan_sip.c.
| #define SIP_OPT_PRECONDITION (1 << 7) |
Definition at line 582 of file chan_sip.c.
| #define SIP_OPT_PREF (1 << 6) |
Definition at line 581 of file chan_sip.c.
| #define SIP_OPT_PRIVACY (1 << 8) |
Definition at line 583 of file chan_sip.c.
| #define SIP_OPT_RECLISTINV (1 << 18) |
Definition at line 593 of file chan_sip.c.
| #define SIP_OPT_RECLISTSUB (1 << 19) |
Definition at line 594 of file chan_sip.c.
| #define SIP_OPT_REPLACES (1 << 0) |
| #define SIP_OPT_RESPRIORITY (1 << 16) |
Definition at line 591 of file chan_sip.c.
| #define SIP_OPT_SDP_ANAT (1 << 9) |
Definition at line 584 of file chan_sip.c.
| #define SIP_OPT_SEC_AGREE (1 << 10) |
Definition at line 585 of file chan_sip.c.
| #define SIP_OPT_TARGET_DIALOG (1 << 13) |
Definition at line 588 of file chan_sip.c.
| #define SIP_OPT_TIMER (1 << 2) |
| #define SIP_OPT_UNKNOWN (1 << 20) |
| #define SIP_OUTGOING (1 << 0) |
D: Direction of the last transaction in this dialog
Definition at line 993 of file chan_sip.c.
Referenced by handle_request_bye(), handle_request_invite(), handle_request_refer(), handle_response(), handle_response_invite(), manager_sipnotify(), reqprep(), respprep(), sip_call(), sip_cli_notify(), sip_hangup(), sip_indicate(), sip_poke_peer(), sip_send_mwi_to_peer(), sip_show_channel(), sip_write(), transmit_refer(), transmit_register(), transmit_reinvite_with_sdp(), and transmit_response_with_sdp().
| #define SIP_PAGE2_ALLOWOVERLAP (1 << 17) |
DP: Allow overlap dialing ?
Definition at line 1065 of file chan_sip.c.
Referenced by _sip_show_peer(), get_destination(), handle_common_options(), handle_request_invite(), and sip_show_settings().
| #define SIP_PAGE2_ALLOWSUBSCRIBE (1 << 16) |
GP: Allow subscriptions from this peer?
Definition at line 1064 of file chan_sip.c.
Referenced by _sip_show_peer(), build_peer(), handle_common_options(), handle_request_subscribe(), and sip_show_settings().
| #define SIP_PAGE2_BUGGY_MWI (1 << 26) |
DP: Buggy CISCO MWI fix
Definition at line 1079 of file chan_sip.c.
Referenced by handle_common_options(), and transmit_notify_with_mwi().
| #define SIP_PAGE2_CALL_ONHOLD (3 << 23) |
D: Call hold states:
Definition at line 1073 of file chan_sip.c.
Referenced by __sip_destroy(), add_sdp(), check_rtp_timeout(), handle_request_cancel(), process_sdp(), show_channels_cb(), sip_hangup(), and update_call_counter().
| #define SIP_PAGE2_CALL_ONHOLD_ACTIVE (1 << 23) |
| #define SIP_PAGE2_CALL_ONHOLD_INACTIVE (3 << 23) |
D: Inactive hold
Definition at line 1076 of file chan_sip.c.
Referenced by add_sdp(), and process_sdp().
| #define SIP_PAGE2_CALL_ONHOLD_ONEDIR (2 << 23) |
D: One directional hold
Definition at line 1075 of file chan_sip.c.
Referenced by add_sdp(), and process_sdp().
| #define SIP_PAGE2_DIALOG_ESTABLISHED (1 << 27) |
29: Has a dialog been established?
Definition at line 1080 of file chan_sip.c.
Referenced by find_call_cb(), handle_request_bye(), handle_request_invite(), handle_request_subscribe(), handle_response(), handle_response_invite(), and sip_answer().
| #define SIP_PAGE2_FLAGS_TO_COPY |
Value:
(SIP_PAGE2_ALLOWSUBSCRIBE | SIP_PAGE2_ALLOWOVERLAP | SIP_PAGE2_VIDEOSUPPORT | \ SIP_PAGE2_T38SUPPORT | SIP_PAGE2_RFC2833_COMPENSATE | SIP_PAGE2_BUGGY_MWI | \ SIP_PAGE2_TEXTSUPPORT | SIP_PAGE2_UDPTL_DESTINATION | \ SIP_PAGE2_VIDEOSUPPORT_ALWAYS)
Definition at line 1085 of file chan_sip.c.
Referenced by check_peer_ok(), create_addr_from_peer(), set_peer_defaults(), sip_alloc(), and sip_poke_peer().
| #define SIP_PAGE2_REGISTERTRYING (1 << 29) |
DP: Send 100 Trying on REGISTER attempts
Definition at line 1081 of file chan_sip.c.
Referenced by _sip_show_peer(), build_peer(), and register_verify().
| #define SIP_PAGE2_RFC2833_COMPENSATE (1 << 25) |
DP: Compensate for buggy RFC2833 implementations
Definition at line 1078 of file chan_sip.c.
Referenced by create_addr_from_peer(), handle_common_options(), handle_request_invite(), process_sdp(), sip_alloc(), and sip_show_settings().
| #define SIP_PAGE2_RTAUTOCLEAR (1 << 2) |
GP: Should we clean memory from peers after expiry?
Definition at line 1058 of file chan_sip.c.
Referenced by expire_register().
| #define SIP_PAGE2_RTCACHEFRIENDS (1 << 0) |
GP: Should we keep RT objects in memory for extended time?
Definition at line 1057 of file chan_sip.c.
Referenced by build_peer(), parse_register_contact(), sip_prune_realtime(), sip_show_settings(), and update_peer().
| #define SIP_PAGE2_STATECHANGEQUEUE (1 << 9) |
D: Unsent state pending change exists
Definition at line 1060 of file chan_sip.c.
Referenced by cb_extensionstate(), handle_response(), and handle_response_notify().
| #define SIP_PAGE2_SUBSCRIBEMWIONLY (1 << 18) |
GP: Only issue MWI notification if subscribed to
Definition at line 1066 of file chan_sip.c.
Referenced by build_peer(), handle_request_subscribe(), register_verify(), and sip_send_mwi_to_peer().
| #define SIP_PAGE2_T38SUPPORT (7 << 20) |
GDP: T38 Fax Passthrough Support
Definition at line 1068 of file chan_sip.c.
Referenced by create_addr_from_peer(), sip_alloc(), sip_indicate(), sip_queryoption(), and sip_write().
| #define SIP_PAGE2_T38SUPPORT_RTP (2 << 20) |
GDP: T38 Fax Passthrough Support (not implemented)
Definition at line 1070 of file chan_sip.c.
Referenced by _sip_show_peer(), add_sdp(), handle_common_options(), and sip_show_settings().
| #define SIP_PAGE2_T38SUPPORT_TCP (4 << 20) |
GDP: T38 Fax Passthrough Support (not implemented)
Definition at line 1071 of file chan_sip.c.
Referenced by _sip_show_peer(), handle_common_options(), and sip_show_settings().
| #define SIP_PAGE2_T38SUPPORT_UDPTL (1 << 20) |
GDP: T38 Fax Passthrough Support
Definition at line 1069 of file chan_sip.c.
Referenced by _sip_show_peer(), handle_common_options(), sip_read(), sip_rtp_read(), and sip_show_settings().
| #define SIP_PAGE2_TEXTSUPPORT (1 << 15) |
GDP: Global text enable
Definition at line 1063 of file chan_sip.c.
Referenced by _sip_show_peer(), _sip_show_peers(), check_peer_ok(), create_addr_from_peer(), handle_common_options(), sip_alloc(), and sip_show_settings().
| #define SIP_PAGE2_UDPTL_DESTINATION (1 << 30) |
DP: Use source IP of RTP as destination if NAT is enabled
Definition at line 1082 of file chan_sip.c.
Referenced by handle_common_options(), and process_sdp().
| #define SIP_PAGE2_VIDEOSUPPORT (1 << 14) |
DP: Video supported if offered?
Definition at line 1062 of file chan_sip.c.
Referenced by _sip_show_peer(), _sip_show_peers(), check_peer_ok(), create_addr_from_peer(), handle_common_options(), sip_alloc(), sip_new(), and sip_show_settings().
| #define SIP_PAGE2_VIDEOSUPPORT_ALWAYS (1 << 31) |
DP: Always set up video, even if endpoints don't support it
Definition at line 1083 of file chan_sip.c.
Referenced by check_peer_ok(), create_addr_from_peer(), and handle_common_options().
| #define SIP_PENDINGBYE (1 << 5) |
D: Need to send bye after we ack?
Definition at line 997 of file chan_sip.c.
Referenced by check_pendings(), handle_response_invite(), register_verify(), sip_hangup(), sip_indicate(), sip_read(), sip_sendhtml(), sip_set_rtp_peer(), and sip_set_udptl_peer().
| #define SIP_PROG_INBAND (3 << 25) |
DP: three settings, uses two bits
Definition at line 1038 of file chan_sip.c.
Referenced by handle_common_options(), sip_indicate(), and sip_show_settings().
| #define SIP_PROG_INBAND_NEVER (0 << 25) |
| #define SIP_PROG_INBAND_NO (1 << 25) |
Definition at line 1040 of file chan_sip.c.
Referenced by handle_common_options(), and sip_show_settings().
| #define SIP_PROG_INBAND_YES (2 << 25) |
Definition at line 1041 of file chan_sip.c.
Referenced by handle_common_options(), and sip_indicate().
| #define SIP_PROGRESS_SENT (1 << 3) |
D: Have sent 183 message progress
Definition at line 995 of file chan_sip.c.
Referenced by sip_indicate(), and sip_write().
| #define SIP_PROMISCREDIR (1 << 11) |
DP: Promiscuous redirection
Definition at line 1004 of file chan_sip.c.
Referenced by _sip_show_peer(), handle_common_options(), parse_moved_contact(), sip_show_channel(), and sip_show_settings().
| #define sip_pvt_lock | ( | x | ) | ao2_lock(x) |
Definition at line 1421 of file chan_sip.c.
Referenced by __sip_ack(), auto_congest(), cb_extensionstate(), check_rtp_timeout(), complete_sipch(), find_call(), get_sip_pvt_byid_locked(), handle_request_invite(), handle_request_subscribe(), proc_session_timer(), retrans_pkt(), scheduler_process_request_queue(), sip_answer(), 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_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_transfer(), sip_write(), and update_call_counter().
| #define sip_pvt_trylock | ( | x | ) | ao2_trylock(x) |
| #define sip_pvt_unlock | ( | x | ) | ao2_unlock(x) |
Definition at line 1423 of file chan_sip.c.
Referenced by __sip_ack(), auto_congest(), cb_extensionstate(), check_rtp_timeout(), complete_sipch(), dialog_needdestroy(), get_sip_pvt_byid_locked(), handle_invite_replaces(), handle_request_do(), handle_request_invite(), handle_request_subscribe(), local_attended_transfer(), proc_session_timer(), retrans_pkt(), scheduler_process_request_queue(), sip_answer(), 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_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_transfer(), sip_write(), and update_call_counter().
| #define SIP_REINVITE (7 << 20) |
DP: four settings, uses three bits
Definition at line 1025 of file chan_sip.c.
Referenced by handle_common_options().
| #define SIP_REINVITE_NONE (0 << 20) |
DP: no reinvite allowed
Definition at line 1026 of file chan_sip.c.
| #define SIP_REINVITE_UPDATE (4 << 20) |
DP: use UPDATE (RFC3311) when reinviting this peer
Definition at line 1029 of file chan_sip.c.
Referenced by handle_common_options(), and transmit_reinvite_with_sdp().
| #define SIP_RESERVED ";/?:@&=+$,# " |
Definition at line 219 of file chan_sip.c.
| #define SIP_RINGING (1 << 2) |
| #define SIP_SENDRPID (1 << 29) |
DP: Remote Party-ID Support
Definition at line 1043 of file chan_sip.c.
Referenced by _sip_show_peer(), handle_common_options(), and initreqprep().
| #define SIP_TIMER_T1 500 |
Definition at line 258 of file chan_sip.c.
| #define SIP_TRANS_TIMEOUT 64 * SIP_TIMER_T1 |
SIP request timeout (rfc 3261) 64*T1
Definition at line 259 of file chan_sip.c.
Referenced by manager_sipnotify(), sip_cli_notify(), and sip_sipredirect().
| #define SIP_TRUSTRPID (1 << 12) |
DP: Trust RPID headers?
Definition at line 1005 of file chan_sip.c.
Referenced by _sip_show_peer(), handle_common_options(), and replace_cid().
| #define SIP_USECLIENTCODE (1 << 14) |
DP: Trust X-ClientCode info message
Definition at line 1007 of file chan_sip.c.
Referenced by handle_common_options(), handle_request_info(), and sip_show_settings().
| #define SIP_USEREQPHONE (1 << 13) |
DP: Add user=phone to numeric URI. Default off
Definition at line 1006 of file chan_sip.c.
Referenced by _sip_show_peer(), build_peer(), initreqprep(), and sip_show_settings().
| #define SIPBUFSIZE 512 |
Definition at line 210 of file chan_sip.c.
Referenced by add_route(), add_sdp(), extract_uri(), handle_request_refer(), initreqprep(), parse_moved_contact(), parse_ok_contact(), parse_register_contact(), process_sdp(), respprep(), show_channels_cb(), sip_call(), sip_new(), sip_show_channel(), sip_show_settings(), transmit_invite(), and transmit_notify_with_sipfrag().
| #define STANDARD_SIP_PORT 5060 |
Standard SIP unsecure port for UDP and TCP from RFC 3261. DO NOT CHANGE THIS.
Definition at line 664 of file chan_sip.c.
Referenced by __set_address_from_contact(), build_peer(), check_via(), create_addr(), initreqprep(), manager_show_registry(), parse_register_contact(), proxy_allocate(), reload_config(), set_destination(), set_peer_defaults(), sip_parse_host(), sip_show_registry(), sip_standard_port(), and transmit_register().
| #define STANDARD_TLS_PORT 5061 |
Standard SIP TLS port for sips: from RFC 3261. DO NOT CHANGE THIS.
Definition at line 666 of file chan_sip.c.
Referenced by __set_address_from_contact(), build_peer(), create_addr(), parse_register_contact(), reload_config(), sip_parse_host(), and sip_standard_port().
| #define SUPPORTED 1 |
Define SIP option tags, used in Require: and Supported: headers We need to be aware of these properties in the phones to use the replace: header. We should not do that without knowing that the other end supports it... This is nothing we can configure, we learn by the dialog Supported: header on the REGISTER (peer) or the INVITE (other devices) We are not using many of these today, but will in the future. This is documented in RFC 3261
Definition at line 571 of file chan_sip.c.
| #define SUPPORTED_EXTENSIONS "replaces, timer" |
SIP Extensions we support.
Definition at line 661 of file chan_sip.c.
Referenced by respprep(), transmit_invite(), transmit_notify_with_sipfrag(), transmit_refer(), and transmit_reinvite_with_sdp().
| #define T38FAX_FILL_BIT_REMOVAL (1 << 0) |
Default: 0 (unset)
Definition at line 1097 of file chan_sip.c.
Referenced by add_sdp(), and process_sdp().
| #define T38FAX_RATE_12000 (1 << 12) |
12000 bps t38FaxRate
Definition at line 1116 of file chan_sip.c.
Referenced by process_sdp(), and t38_get_rate().
| #define T38FAX_RATE_14400 (1 << 13) |
14400 bps t38FaxRate This is default: NO MMR and JBIG transcoding, NO fill bit removal, transferredTCF TCF, UDP FEC, Version 0 and 9600 max fax rate
Definition at line 1117 of file chan_sip.c.
Referenced by process_sdp(), and t38_get_rate().
| #define T38FAX_RATE_2400 (1 << 8) |
2400 bps t38FaxRate
Definition at line 1112 of file chan_sip.c.
Referenced by process_sdp(), and t38_get_rate().
| #define T38FAX_RATE_4800 (1 << 9) |
4800 bps t38FaxRate
Definition at line 1113 of file chan_sip.c.
Referenced by process_sdp(), and t38_get_rate().
| #define T38FAX_RATE_7200 (1 << 10) |
7200 bps t38FaxRate
Definition at line 1114 of file chan_sip.c.
Referenced by process_sdp(), and t38_get_rate().
| #define T38FAX_RATE_9600 (1 << 11) |
9600 bps t38FaxRate
Definition at line 1115 of file chan_sip.c.
Referenced by process_sdp(), and t38_get_rate().
| #define T38FAX_RATE_MANAGEMENT_LOCAL_TCF (1 << 3) |
Unset for transferredTCF (UDPTL), set for localTCF (TPKT)
Definition at line 1102 of file chan_sip.c.
Referenced by add_sdp(), and process_sdp().
| #define T38FAX_RATE_MANAGEMENT_TRANSFERED_TCF (0 << 3) |
Definition at line 1101 of file chan_sip.c.
Referenced by process_sdp(), and set_t38_capabilities().
| #define T38FAX_TRANSCODING_JBIG (1 << 2) |
Default: 0 (unset)
Definition at line 1099 of file chan_sip.c.
Referenced by add_sdp(), and process_sdp().
| #define T38FAX_TRANSCODING_MMR (1 << 1) |
Default: 0 (unset)
Definition at line 1098 of file chan_sip.c.
Referenced by add_sdp(), and process_sdp().
| #define T38FAX_UDP_EC_FEC (1 << 4) |
Set for t38UDPFEC
Definition at line 1105 of file chan_sip.c.
Referenced by process_sdp(), and set_t38_capabilities().
| #define T38FAX_UDP_EC_NONE (0 << 4) |
two bits, if unset NO t38UDPEC field in T38 SDP
Definition at line 1104 of file chan_sip.c.
Referenced by add_sdp(), process_sdp(), and set_t38_capabilities().
| #define T38FAX_UDP_EC_REDUNDANCY (2 << 4) |
Set for t38UDPRedundancy
Definition at line 1106 of file chan_sip.c.
Referenced by add_sdp(), process_sdp(), and set_t38_capabilities().
| #define T38FAX_VERSION (3 << 6) |
two bits, 2 values so far, up to 4 values max
Definition at line 1108 of file chan_sip.c.
Referenced by add_sdp().
| #define T38FAX_VERSION_0 (0 << 6) |
| #define T38FAX_VERSION_1 (1 << 6) |
| #define TRUE 1 |
Definition at line 207 of file chan_sip.c.
| #define UNLINK | ( | element, | |||
| head, | |||||
| prev | ) |
some list management macros.
Definition at line 1844 of file chan_sip.c.
Referenced by __sip_ack(), and retrans_pkt().
| #define XMIT_ERROR -2 |
Definition at line 217 of file chan_sip.c.
Referenced by __sip_reliable_xmit(), __sip_xmit(), handle_response_invite(), retrans_pkt(), sip_call(), and sip_poke_peer().
| enum can_create_dialog |
States whether a SIP message can create a dialog in Asterisk.
Definition at line 496 of file chan_sip.c.
00496 { 00497 CAN_NOT_CREATE_DIALOG, 00498 CAN_CREATE_DIALOG, 00499 CAN_CREATE_DIALOG_UNSUPPORTED_METHOD, 00500 };
| enum check_auth_result |
Authentication result from check_auth* functions.
Definition at line 397 of file chan_sip.c.
00397 { 00398 AUTH_DONT_KNOW = -100, /*!< no result, need to check further */ 00399 /* XXX maybe this is the same as AUTH_NOT_FOUND */ 00400 00401 AUTH_SUCCESSFUL = 0, 00402 AUTH_CHALLENGE_SENT = 1, 00403 AUTH_SECRET_FAILED = -1, 00404 AUTH_USERNAME_MISMATCH = -2, 00405 AUTH_NOT_FOUND = -3, /*!< returned by register_verify */ 00406 AUTH_FAKE_AUTH = -4, 00407 AUTH_UNKNOWN_DOMAIN = -5, 00408 AUTH_PEER_NOT_DYNAMIC = -6, 00409 AUTH_ACL_FAILED = -7, 00410 AUTH_BAD_TRANSPORT = -8, 00411 };
| enum domain_mode |
Modes for SIP domain handling in the PBX.
| SIP_DOMAIN_AUTO | This domain is auto-configured |
| SIP_DOMAIN_CONFIG | This domain is from configuration |
Definition at line 947 of file chan_sip.c.
00947 { 00948 SIP_DOMAIN_AUTO, /*!< This domain is auto-configured */ 00949 SIP_DOMAIN_CONFIG, /*!< This domain is from configuration */ 00950 };
| enum invitestates |
States for the INVITE transaction, not the dialog.
Definition at line 311 of file chan_sip.c.
00311 { 00312 INV_NONE = 0, /*!< No state at all, maybe not an INVITE dialog */ 00313 INV_CALLING = 1, /*!< Invite sent, no answer */ 00314 INV_PROCEEDING = 2, /*!< We got/sent 1xx message */ 00315 INV_EARLY_MEDIA = 3, /*!< We got 18x message with to-tag back */ 00316 INV_COMPLETED = 4, /*!< Got final response with error. Wait for ACK, then CONFIRMED */ 00317 INV_CONFIRMED = 5, /*!< Confirmed response - we've got an ack (Incoming calls only) */ 00318 INV_TERMINATED = 6, /*!< Transaction done - either successful (AST_STATE_UP) or failed, but done 00319 The only way out of this is a BYE from one side */ 00320 INV_CANCELLED = 7, /*!< Transaction cancelled by client or server in non-terminated state */ 00321 };
Definition at line 349 of file chan_sip.c.
00349 { 00350 PARSE_REGISTER_FAILED, 00351 PARSE_REGISTER_UPDATE, 00352 PARSE_REGISTER_QUERY, 00353 };
| enum referstatus |
Parameters to know status of transfer.
Definition at line 1163 of file chan_sip.c.
01163 { 01164 REFER_IDLE, /*!< No REFER is in progress */ 01165 REFER_SENT, /*!< Sent REFER to transferee */ 01166 REFER_RECEIVED, /*!< Received REFER from transferrer */ 01167 REFER_CONFIRMED, /*!< Refer confirmed with a 100 TRYING (unused) */ 01168 REFER_ACCEPTED, /*!< Accepted by transferee */ 01169 REFER_RINGING, /*!< Target Ringing */ 01170 REFER_200OK, /*!< Answered by transfer target */ 01171 REFER_FAILED, /*!< REFER declined - go on */ 01172 REFER_NOAUTH /*!< We had no auth for REFER */ 01173 };
| enum sip_auth_type |
Authentication types - proxy or www authentication.
Definition at line 391 of file chan_sip.c.
00391 { 00392 PROXY_AUTH = 407, 00393 WWW_AUTH = 401, 00394 };
| enum sip_debug_e |
debugging state We store separately the debugging requests from the config file and requests from the CLI. Debugging is enabled if either is set (which means that if sipdebug is set in the config file, we can only turn it off by reloading the config).
Definition at line 1129 of file chan_sip.c.
01129 { 01130 sip_debug_none = 0, 01131 sip_debug_config = 1, 01132 sip_debug_console = 2, 01133 };
| enum sip_peer_type |
Definition at line 1502 of file chan_sip.c.
01502 { 01503 SIP_TYPE_PEER = (1 << 0), 01504 SIP_TYPE_USER = (1 << 1), 01505 };
| enum sip_result |
The result of a lot of functions.
Definition at line 303 of file chan_sip.c.
00303 { 00304 AST_SUCCESS = 0, /*! FALSE means success, funny enough */ 00305 AST_FAILURE = -1, 00306 };
| enum sip_transport |
Define some implemented SIP transports.
| SIP_TRANSPORT_UDP | Unreliable transport for SIP, needs retransmissions |
| SIP_TRANSPORT_TCP | Reliable, but unsecure |
| SIP_TRANSPORT_TLS | TCP/TLS - reliable and secure transport for signalling |
Definition at line 466 of file chan_sip.c.
00466 { 00467 SIP_TRANSPORT_UDP = 1, /*!< Unreliable transport for SIP, needs retransmissions */ 00468 SIP_TRANSPORT_TCP = 1 << 1, /*!< Reliable, but unsecure */ 00469 SIP_TRANSPORT_TLS = 1 << 2, /*!< TCP/TLS - reliable and secure transport for signalling */ 00470 };
| enum sipmethod |
SIP Request methods known by Asterisk.
Definition at line 512 of file chan_sip.c.
00512 { 00513 SIP_UNKNOWN, /*!< Unknown response */ 00514 SIP_RESPONSE, /*!< Not request, response to outbound request */ 00515 SIP_REGISTER, /*!< Registration to the mothership, tell us where you are located */ 00516 SIP_OPTIONS, /*!< Check capabilities of a device, used for "ping" too */ 00517 SIP_NOTIFY, /*!< Status update, Part of the event package standard, result of a SUBSCRIBE or a REFER */ 00518 SIP_INVITE, /*!< Set up a session */ 00519 SIP_ACK, /*!< End of a three-way handshake started with INVITE. */ 00520 SIP_PRACK, /*!< Reliable pre-call signalling. Not supported in Asterisk. */ 00521 SIP_BYE, /*!< End of a session */ 00522 SIP_REFER, /*!< Refer to another URI (transfer) */ 00523 SIP_SUBSCRIBE, /*!< Subscribe for updates (voicemail, session status, device status, presence) */ 00524 SIP_MESSAGE, /*!< Text messaging */ 00525 SIP_UPDATE, /*!< Update a dialog. We can send UPDATE; but not accept it */ 00526 SIP_INFO, /*!< Information updates during a session */ 00527 SIP_CANCEL, /*!< Cancel an INVITE */ 00528 SIP_PUBLISH, /*!< Not supported in Asterisk */ 00529 SIP_PING, /*!< Not supported at all, no standard but still implemented out there */ 00530 };
| enum sipregistrystate |
States for outbound registrations (with register= lines in sip.conf.
Definition at line 414 of file chan_sip.c.
00414 { 00415 REG_STATE_UNREGISTERED = 0, /*!< We are not registered 00416 * \note Initial state. We should have a timeout scheduled for the initial 00417 * (or next) registration transmission, calling sip_reregister 00418 */ 00419 00420 REG_STATE_REGSENT, /*!< Registration request sent 00421 * \note sent initial request, waiting for an ack or a timeout to 00422 * retransmit the initial request. 00423 */ 00424 00425 REG_STATE_AUTHSENT, /*!< We have tried to authenticate 00426 * \note entered after transmit_register with auth info, 00427 * waiting for an ack. 00428 */ 00429 00430 REG_STATE_REGISTERED, /*!< Registered and done */ 00431 00432 REG_STATE_REJECTED, /*!< Registration rejected * 00433 * \note only used when the remote party has an expire larger than 00434 * our max-expire. This is a final state from which we do not 00435 * recover (not sure how correctly). 00436 */ 00437 00438 REG_STATE_TIMEOUT, /*!< Registration timed out * 00439 * \note XXX unused */ 00440 00441 REG_STATE_NOAUTH, /*!< We have no accepted credentials 00442 * \note fatal - no chance to proceed */ 00443 00444 REG_STATE_FAILED, /*!< Registration failed after several tries 00445 * \note fatal - no chance to proceed */ 00446 };
| enum st_mode |
Modes in which Asterisk can be configured to run SIP Session-Timers.
Definition at line 449 of file chan_sip.c.
00449 { 00450 SESSION_TIMER_MODE_INVALID = 0, /*!< Invalid value */ 00451 SESSION_TIMER_MODE_ACCEPT, /*!< Honor inbound Session-Timer requests */ 00452 SESSION_TIMER_MODE_ORIGINATE, /*!< Originate outbound and honor inbound requests */ 00453 SESSION_TIMER_MODE_REFUSE /*!< Ignore inbound Session-Timers requests */ 00454 };
| enum st_refresher |
The entity playing the refresher role for Session-Timers.
| SESSION_TIMER_REFRESHER_AUTO | Negotiated |
| SESSION_TIMER_REFRESHER_UAC | Session is refreshed by the UAC |
| SESSION_TIMER_REFRESHER_UAS | Session is refreshed by the UAS |
Definition at line 457 of file chan_sip.c.
00457 { 00458 SESSION_TIMER_REFRESHER_AUTO, /*!< Negotiated */ 00459 SESSION_TIMER_REFRESHER_UAC, /*!< Session is refreshed by the UAC */ 00460 SESSION_TIMER_REFRESHER_UAS /*!< Session is refreshed by the UAS */ 00461 };
| enum subscriptiontype |
Type of subscription, based on the packages we do support.
Definition at line 356 of file chan_sip.c.
00356 { 00357 NONE = 0, 00358 XPIDF_XML, 00359 DIALOG_INFO_XML, 00360 CPIM_PIDF_XML, 00361 PIDF_XML, 00362 MWI_NOTIFICATION 00363 };
| enum t38_action_flag |
| SDP_T38_NONE | Do not modify T38 information at all |
| SDP_T38_INITIATE | Remote side has requested T38 with us |
| SDP_T38_ACCEPT | Remote side accepted our T38 request |
Definition at line 1851 of file chan_sip.c.
01851 { 01852 SDP_T38_NONE = 0, /*!< Do not modify T38 information at all */ 01853 SDP_T38_INITIATE, /*!< Remote side has requested T38 with us */ 01854 SDP_T38_ACCEPT, /*!< Remote side accepted our T38 request */ 01855 };
| enum t38state |
T38 States for a call.
| T38_DISABLED | Not enabled |
| T38_LOCAL_REINVITE | Offered from local - REINVITE |
| T38_PEER_DIRECT | Offered from peer |
| T38_PEER_REINVITE | Offered from peer - REINVITE |
| T38_ENABLED | Negotiated (enabled) |
Definition at line 1144 of file chan_sip.c.
01144 { 01145 T38_DISABLED = 0, /*!< Not enabled */ 01146 T38_LOCAL_REINVITE, /*!< Offered from local - REINVITE */ 01147 T38_PEER_DIRECT, /*!< Offered from peer */ 01148 T38_PEER_REINVITE, /*!< Offered from peer - REINVITE */ 01149 T38_ENABLED /*!< Negotiated (enabled) */ 01150 };
| enum transfermodes |
Authorization scheme for call transfers.
Definition at line 296 of file chan_sip.c.
00296 { 00297 TRANSFER_OPENFORALL, /*!< Allow all SIP transfers */ 00298 TRANSFER_CLOSED, /*!< Allow no SIP transfers */ 00299 };
| enum xmittype |
When sending a SIP message, we can send with a few options, depending on type of SIP request. UNRELIABLE is moslty used for responses to repeated requests, where the original response would be sent RELIABLE in an INVITE transaction.
Definition at line 342 of file chan_sip.c.
00342 { 00343 XMIT_CRITICAL = 2, /*!< Transmit critical SIP message reliably, with re-transmits. 00344 If it fails, it's critical and will cause a teardown of the session */ 00345 XMIT_RELIABLE = 1, /*!< Transmit SIP message reliably, with re-transmits */ 00346 XMIT_UNRELIABLE = 0, /*!< Transmit SIP message without bothering with re-transmits */ 00347 };
| static const char * __get_header | ( | const struct sip_request * | req, | |
| const char * | name, | |||
| int * | start | |||
| ) | [static] |
Definition at line 5987 of file chan_sip.c.
References ast_skip_blanks(), find_alias(), sip_request::header, sip_request::headers, sip_request::len, pass, and REQ_OFFSET_TO_STR.
05988 { 05989 int pass; 05990 05991 /* 05992 * Technically you can place arbitrary whitespace both before and after the ':' in 05993 * a header, although RFC3261 clearly says you shouldn't before, and place just 05994 * one afterwards. If you shouldn't do it, what absolute idiot decided it was 05995 * a good idea to say you can do it, and if you can do it, why in the hell would. 05996 * you say you shouldn't. 05997 * Anyways, pedanticsipchecking controls whether we allow spaces before ':', 05998 * and we always allow spaces after that for compatibility. 05999 */ 06000 for (pass = 0; name && pass < 2;pass++) { 06001 int x, len = strlen(name); 06002 for (x = *start; x < req->headers; x++) { 06003 char *header = REQ_OFFSET_TO_STR(req, header[x]); 06004 if (!strncasecmp(header, name, len)) { 06005 char *r = header + len; /* skip name */ 06006 if (pedanticsipchecking) 06007 r = ast_skip_blanks(r); 06008 06009 if (*r == ':') { 06010 *start = x+1; 06011 return ast_skip_blanks(r+1); 06012 } 06013 } 06014 } 06015 if (pass == 0) /* Try aliases */ 06016 name = find_alias(name, NULL); 06017 } 06018 06019 /* Don't return NULL, so get_header is always a valid pointer */ 06020 return ""; 06021 }
| 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 23599 of file chan_sip.c.
| static int __set_address_from_contact | ( | const char * | fullcontact, | |
| struct sockaddr_in * | sin, | |||
| int | tcp | |||
| ) | [static] |
Definition at line 10524 of file chan_sip.c.
References ahp, ast_copy_string(), ast_gethostbyname(), ast_log(), ast_strlen_zero(), hp, LOG_NOTICE, LOG_WARNING, parse_uri(), STANDARD_SIP_PORT, and STANDARD_TLS_PORT.
Referenced by build_peer(), and set_address_from_contact().
10525 { 10526 struct hostent *hp; 10527 struct ast_hostent ahp; 10528 int port; 10529 char *host, *pt; 10530 char contact_buf[256]; 10531 char contact2_buf[256]; 10532 char *contact, *contact2; 10533 10534 /* Work on a copy */ 10535 ast_copy_string(contact_buf, fullcontact, sizeof(contact_buf)); 10536 ast_copy_string(contact2_buf, fullcontact, sizeof(contact2_buf)); 10537 contact = contact_buf; 10538 contact2 = contact2_buf; 10539 10540 /* We have only the part in <brackets> here so we just need to parse a SIP URI.*/ 10541 if (tcp) { 10542 if (parse_uri(contact, "sips:", &contact, NULL, &host, &pt, NULL)) { 10543 if (parse_uri(contact2, "sip:", &contact, NULL, &host, &pt, NULL)) 10544 ast_log(LOG_NOTICE, "'%s' is not a valid SIP contact (missing sip:) trying to use anyway\n", contact); 10545 } 10546 port = !ast_strlen_zero(pt) ? atoi(pt) : STANDARD_TLS_PORT; 10547 } else { 10548 if (parse_uri(contact, "sip:", &contact, NULL, &host, &pt, NULL)) 10549 ast_log(LOG_NOTICE, "'%s' is not a valid SIP contact (missing sip:) trying to use anyway\n", contact); 10550 port = !ast_strlen_zero(pt) ? atoi(pt) : STANDARD_SIP_PORT; 10551 } 10552 10553 /* XXX This could block for a long time XXX */ 10554 /* We should only do this if it's a name, not an IP */ 10555 hp = ast_gethostbyname(host, &ahp); 10556 if (!hp) { 10557 ast_log(LOG_WARNING, "Invalid host name in Contact: (can't resolve in DNS) : '%s'\n", host); 10558 return -1; 10559 } 10560 sin->sin_family = AF_INET; 10561 memcpy(&sin->sin_addr, hp->h_addr, sizeof(sin->sin_addr)); 10562 sin->sin_port = htons(port); 10563 10564 return 0; 10565 }
| static void __sip_ack | ( | struct sip_pvt * | p, | |
| int | seqno, | |||
| int | resp, | |||
| int | sipmethod | |||
| ) | [static] |
Acknowledges receipt of a packet and stops retransmission called with p locked.
Definition at line 3310 of file chan_sip.c.
References ast_debug, ast_free, ast_sched_del(), sip_pvt::callid, sip_pkt::data, dialog_unref(), sip_proxy::force, sip_pkt::is_resp, sip_pkt::method, msg, sip_pkt::next, sip_pvt::outboundproxy, sip_pkt::owner, sip_pvt::packets, sip_pvt::pendinginvite, ref_proxy(), sip_pkt::retransid, sched, sip_pkt::seqno, sip_pvt_lock, sip_pvt_unlock, and UNLINK.
Referenced by __sip_pretend_ack(), handle_incoming(), handle_request_invite(), and handle_response().
03311 { 03312 struct sip_pkt *cur, *prev = NULL; 03313 const char *msg = "Not Found"; /* used only for debugging */ 03314 03315 /* If we have an outbound proxy for this dialog, then delete it now since 03316 the rest of the requests in this dialog needs to follow the routing. 03317 If obforcing is set, we will keep the outbound proxy during the whole 03318 dialog, regardless of what the SIP rfc says 03319 */ 03320 if (p->outboundproxy && !p->outboundproxy->force){ 03321 ref_proxy(p, NULL); 03322 } 03323 03324 for (cur = p->packets; cur; prev = cur, cur = cur->next) { 03325 if (cur->seqno != seqno || cur->is_resp != resp) 03326 continue; 03327 if (cur->is_resp || cur->method == sipmethod) { 03328 msg = "Found"; 03329 if (!resp && (seqno == p->pendinginvite)) { 03330 ast_debug(1, "Acked pending invite %d\n", p->pendinginvite); 03331 p->pendinginvite = 0; 03332 } 03333 if (cur->retransid > -1) { 03334 if (sipdebug) 03335 ast_debug(4, "** SIP TIMER: Cancelling retransmit of packet (reply received) Retransid #%d\n", cur->retransid); 03336 } 03337 /* This odd section is designed to thwart a 03338 * race condition in the packet scheduler. There are 03339 * two conditions under which deleting the packet from the 03340 * scheduler can fail. 03341 * 03342 * 1. The packet has been removed from the scheduler because retransmission 03343 * is being attempted. The problem is that if the packet is currently attempting 03344 * retransmission and we are at this point in the code, then that MUST mean 03345 * that retrans_pkt is waiting on p's lock. Therefore we will relinquish the 03346 * lock temporarily to allow retransmission. 03347 * 03348 * 2. The packet has reached its maximum number of retransmissions and has 03349 * been permanently removed from the packet scheduler. If this is the case, then 03350 * the packet's retransid will be set to -1. The atomicity of the setting and checking 03351 * of the retransid to -1 is ensured since in both cases p's lock is held. 03352 */ 03353 while (cur->retransid > -1 && ast_sched_del(sched, cur->retransid)) { 03354 sip_pvt_unlock(p); 03355 usleep(1); 03356 sip_pvt_lock(p); 03357 } 03358 UNLINK(cur, p->packets, prev); 03359 dialog_unref(cur->owner, "unref pkt cur->owner dialog from sip ack before freeing pkt"); 03360 if (cur->data) 03361 ast_free(cur->data); 03362 ast_free(cur); 03363 break; 03364 } 03365 } 03366 ast_debug(1, "Stopping retransmission on '%s' of %s %d: Match %s\n", 03367 p->callid, resp ? "Response" : "Request", seqno, msg); 03368 }
| 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 3219 of file chan_sip.c.
References sip_pvt::alreadygone, append_history, AST_CAUSE_PROTOCOL_ERROR, ast_debug, AST_EXTENSION_DEACTIVATED, ast_log(), ast_queue_hangup_with_cause(), sip_pvt::autokillid, sip_pvt::callid, DEFAULT_TRANS_TIMEOUT, dialog_unlink_all(), dialog_unref(), LOG_WARNING, sip_pvt::method, NONE, sip_pvt::owner, sip_pvt::packets, sip_pvt::refer, sip_pvt::relatedpeer, SIP_BYE, sip_methods, sip_scheddestroy(), sip_pvt::subscribed, transmit_request_with_auth(), transmit_state_notify(), TRUE, unref_peer(), and XMIT_RELIABLE.
Referenced by sip_scheddestroy(), and sip_show_sched().
03220 { 03221 struct sip_pvt *p = (struct sip_pvt *)data; 03222 03223 /* If this is a subscription, tell the phone that we got a timeout */ 03224 if (p->subscribed) { 03225 transmit_state_notify(p, AST_EXTENSION_DEACTIVATED, 1, TRUE); /* Send last notification */ 03226 p->subscribed = NONE; 03227 append_history(p, "Subscribestatus", "timeout"); 03228 ast_debug(3, "Re-scheduled destruction of SIP subscription %s\n", p->callid ? p->callid : "<unknown>"); 03229 return 10000; /* Reschedule this destruction so that we know that it's gone */ 03230 } 03231 03232 /* If there are packets still waiting for delivery, delay the destruction */ 03233 if (p->packets) { 03234 ast_debug(3, "Re-scheduled destruction of SIP call %s\n", p->callid ? p->callid : "<unknown>"); 03235 append_history(p, "ReliableXmit", "timeout"); 03236 return 10000; 03237 } 03238 03239 if (p->subscribed == MWI_NOTIFICATION) 03240 if (p->relatedpeer) 03241 p->relatedpeer = unref_peer(p->relatedpeer, "__sip_autodestruct: unref peer p->relatedpeer"); /* Remove link to peer. If it's realtime, make sure it's gone from memory) */ 03242 03243 /* Reset schedule ID */ 03244 p->autokillid = -1; 03245 03246 if (p->owner) { 03247 ast_log(LOG_WARNING, "Autodestruct on dialog '%s' with owner in place (Method: %s)\n", p->callid, sip_methods[p->method].text); 03248 ast_queue_hangup_with_cause(p->owner, AST_CAUSE_PROTOCOL_ERROR); 03249 } else if (p->refer && !p->alreadygone) { 03250 ast_debug(3, "Finally hanging up channel after transfer: %s\n", p->callid); 03251 transmit_request_with_auth(p, SIP_BYE, 0, XMIT_RELIABLE, 1); 03252 append_history(p, "ReferBYE", "Sending BYE on transferer call leg %s", p->callid); 03253 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 03254 } else { 03255 append_history(p, "AutoDestroy", "%s", p->callid); 03256 ast_debug(3, "Auto destroying SIP dialog '%s'\n", p->callid); 03257 dialog_unlink_all(p, TRUE, TRUE); /* once it's unlinked and unrefd everywhere, it'll be freed automagically */ 03258 /* dialog_unref(p, "unref dialog-- no other matching conditions"); -- unlink all now should finish off the dialog's references and free it. */ 03259 /* sip_destroy(p); */ /* Go ahead and destroy dialog. All attempts to recover is done */ 03260 /* sip_destroy also absorbs the reference */ 03261 } 03262 dialog_unref(p, "The ref to a dialog passed to this sched callback is going out of scope; unref it."); 03263 return 0; 03264 }
| static void __sip_destroy | ( | struct sip_pvt * | p, | |
| int | lockowner, | |||
| int | lockdialoglist | |||
| ) | [static] |
Execute destruction of SIP dialog structure, release memory.
Definition at line 4678 of file chan_sip.c.
References ast_channel::_softhangup, ao2_ref, ast_channel_lock, ast_channel_unlock, ast_debug, ast_free, AST_LIST_REMOVE_HEAD, ast_log(), ast_rtp_destroy(), ast_rtp_get_bridged(), AST_SCHED_DEL_UNREF, AST_SOFTHANGUP_DEV, ast_string_field_free_memory, ast_test_flag, ast_udptl_destroy(), ast_variables_destroy(), ast_verbose, sip_registry::call, sip_peer::call, sip_pvt::callid, DEC_CALL_LIMIT, dialog_unref(), sip_pvt::flags, free_old_route(), sip_history::list, LOG_DEBUG, sip_pvt::method, sip_peer::mwipvt, ast_channel::name, sip_request::next, option_debug, sip_pvt::owner, sip_pvt::registry, registry_unref(), sip_pvt::relatedpeer, sched, sip_debug_test_pvt(), sip_dump_history(), SIP_INC_COUNT, sip_methods, SIP_PAGE2_CALL_ONHOLD, ast_channel::tech_pvt, TRUE, unref_peer(), and update_call_counter().
Referenced by sip_destroy().
04679 { 04680 struct sip_request *req; 04681 04682 if (sip_debug_test_pvt(p)) 04683 ast_verbose("Really destroying SIP dialog '%s' Method: %s\n", p->callid, sip_methods[p->method].text); 04684 04685 if (ast_test_flag(&p->flags[0], SIP_INC_COUNT) || ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD)) { 04686 update_call_counter(p, DEC_CALL_LIMIT); 04687 ast_debug(2, "This call did not properly clean up call limits. Call ID %s\n", p->callid); 04688 } 04689 04690 /* Unlink us from the owner if we have one */ 04691 if (p->owner) { 04692 if (lockowner) 04693 ast_channel_lock(p->owner); 04694 if (option_debug) 04695 ast_log(LOG_DEBUG, "Detaching from %s\n", p->owner->name); 04696 p->owner->tech_pvt = NULL; 04697 /* Make sure that the channel knows its backend is going away */ 04698 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 04699 if (lockowner) 04700 ast_channel_unlock(p->owner); 04701 /* Give the channel a chance to react before deallocation */ 04702 usleep(1); 04703 } 04704 04705 /* Remove link from peer to subscription of MWI */ 04706 if (p->relatedpeer && p->relatedpeer->mwipvt) 04707 p->relatedpeer->mwipvt = dialog_unref(p->relatedpeer->mwipvt, "delete ->relatedpeer->mwipvt"); 04708 if (p->relatedpeer && p->relatedpeer->call == p) 04709 p->relatedpeer->call = dialog_unref(p->relatedpeer->call, "unset the relatedpeer->call field in tandem with relatedpeer field itself"); 04710 04711 if (p->relatedpeer) 04712 p->relatedpeer = unref_peer(p->relatedpeer,"unsetting a dialog relatedpeer field in sip_destroy"); 04713 04714 if (p->registry) { 04715 if (p->registry->call == p) 04716 p->registry->call = dialog_unref(p->registry->call, "nulling out the registry's call dialog field in unlink_all"); 04717 p->registry = registry_unref(p->registry, "delete p->registry"); 04718 } 04719 04720 if (dumphistory) 04721 sip_dump_history(p); 04722 04723 if (p->options) 04724 ast_free(p->options); 04725 04726 if (p->notify_headers) { 04727 ast_variables_destroy(p->notify_headers); 04728 p->notify_headers = NULL; 04729 } 04730 if (p->rtp) { 04731 ast_rtp_destroy(p->rtp); 04732 } 04733 if (p->vrtp) { 04734 ast_rtp_destroy(p->vrtp); 04735 } 04736 if (p->trtp) { 04737 while (ast_rtp_get_bridged(p->trtp)) 04738 usleep(1); 04739 ast_rtp_destroy(p->trtp); 04740 } 04741 if (p->udptl) 04742 ast_udptl_destroy(p->udptl); 04743 if (p->refer) 04744 ast_free(p->refer); 04745 if (p->route) { 04746 free_old_route(p->route); 04747 p->route = NULL; 04748 } 04749 if (p->initreq.data) 04750 ast_free(p->initreq.data); 04751 04752 /* Destroy Session-Timers if allocated */ 04753 if (p->stimer) { 04754 if (p->stimer->st_active == TRUE && p->stimer->st_schedid > -1) { 04755 AST_SCHED_DEL_UNREF(sched, p->stimer->st_schedid, 04756 dialog_unref(p, "removing session timer ref")); 04757 } 04758 ast_free(p->stimer); 04759 p->stimer = NULL; 04760 } 04761 04762 /* Clear history */ 04763 if (p->history) { 04764 struct sip_history *hist; 04765 while ( (hist = AST_LIST_REMOVE_HEAD(p->history, list)) ) { 04766 ast_free(hist); 04767 p->history_entries--; 04768 } 04769 ast_free(p->history); 04770 p->history = NULL; 04771 } 04772 04773 while ((req = AST_LIST_REMOVE_HEAD(&p->request_queue, next))) { 04774 ast_free(req); 04775 } 04776 04777 if (p->chanvars) { 04778 ast_variables_destroy(p->chanvars); 04779 p->chanvars = NULL; 04780 } 04781 04782 ast_string_field_free_memory(p); 04783 04784 if (p->socket.tcptls_session) { 04785 ao2_ref(p->socket.tcptls_session, -1); 04786 p->socket.tcptls_session = NULL; 04787 } 04788 }
| static int __sip_do_register | ( | struct sip_registry * | r | ) | [static] |
Register with SIP proxy.
Definition at line 9892 of file chan_sip.c.
References SIP_REGISTER, and transmit_register().
Referenced by sip_reregister().
09893 { 09894 int res; 09895 09896 res = transmit_register(r, SIP_REGISTER, NULL, NULL); 09897 return res; 09898 }
| static void __sip_pretend_ack | ( | struct sip_pvt * | p | ) | [static] |
Pretend to ack all packets called with p locked.
Definition at line 3372 of file chan_sip.c.
References __sip_ack(), ast_log(), sip_pkt::data, find_sip_method(), sip_pkt::is_resp, LOG_WARNING, sip_pkt::method, sip_request::method, sip_pvt::packets, sip_pkt::seqno, sip_methods, and ast_str::str.
Referenced by handle_request_bye(), handle_request_cancel(), sip_hangup(), and sip_reg_timeout().
03373 { 03374 struct sip_pkt *cur = NULL; 03375 03376 while (p->packets) { 03377 int method; 03378 if (cur == p->packets) { 03379 ast_log(LOG_WARNING, "Have a packet that doesn't want to give up! %s\n", sip_methods[cur->method].text); 03380 return; 03381 } 03382 cur = p->packets; 03383 method = (cur->method) ? cur->method : find_sip_method(cur->data->str); 03384 __sip_ack(p, cur->seqno, cur->is_resp, method); 03385 } 03386 }
| 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 3148 of file chan_sip.c.
References __sip_xmit(), append_history, ast_calloc, ast_debug, AST_FAILURE, ast_free, ast_log(), AST_SCHED_DEL, AST_SCHED_REPLACE_VARIABLE, ast_str_create(), ast_str_set(), AST_SUCCESS, sip_request::data, DEFAULT_RETRANS, dialog_ref(), dialog_unref(), LOG_ERROR, sip_pkt::next, sip_pkt::owner, sip_pvt::packets, sip_pvt::pendinginvite, retrans_pkt(), sched, SIP_INVITE, SIP_TRANSPORT_UDP, sip_pvt::socket, ast_str::str, sip_pvt::timer_t1, sip_pkt::timer_t1, sip_socket::type, and XMIT_ERROR.
Referenced by send_request(), and send_response().
03149 { 03150 struct sip_pkt *pkt = NULL; 03151 int siptimer_a = DEFAULT_RETRANS; 03152 int xmitres = 0; 03153 03154 if (sipmethod == SIP_INVITE) { 03155 /* Note this is a pending invite */ 03156 p->pendinginvite = seqno; 03157 } 03158 03159 /* If the transport is something reliable (TCP or TLS) then don't really send this reliably */ 03160 /* I removed the code from retrans_pkt that does the same thing so it doesn't get loaded into the scheduler */ 03161 /* According to the RFC some packets need to be retransmitted even if its TCP, so this needs to get revisited */ 03162 if (!(p->socket.type & SIP_TRANSPORT_UDP)) { 03163 xmitres = __sip_xmit(p, data, len); /* Send packet */ 03164 if (xmitres == XMIT_ERROR) { /* Serious network trouble, no need to try again */ 03165 append_history(p, "XmitErr", "%s", fatal ? "(Critical)" : "(Non-critical)"); 03166 return AST_FAILURE; 03167 } else 03168 return AST_SUCCESS; 03169 } 03170 03171 if (!(pkt = ast_calloc(1, sizeof(*pkt) + len + 1))) 03172 return AST_FAILURE; 03173 /* copy data, add a terminator and save length */ 03174 if (!(pkt->data = ast_str_create(len))) { 03175 ast_free(pkt); 03176 return AST_FAILURE; 03177 } 03178 ast_str_set(&pkt->data, 0, "%s%s", data->str, "\0"); 03179 pkt->packetlen = len; 03180 /* copy other parameters from the caller */ 03181 pkt->method = sipmethod; 03182 pkt->seqno = seqno; 03183 pkt->is_resp = resp; 03184 pkt->is_fatal = fatal; 03185 pkt->owner = dialog_ref(p, "__sip_reliable_xmit: setting pkt->owner"); 03186 pkt->next = p->packets; 03187 p->packets = pkt; /* Add it to the queue */ 03188 pkt->timer_t1 = p->timer_t1; /* Set SIP timer T1 */ 03189 pkt->retransid = -1; 03190 if (pkt->timer_t1) 03191 siptimer_a = pkt->timer_t1 * 2; 03192 03193 /* Schedule retransmission */ 03194 AST_SCHED_REPLACE_VARIABLE(pkt->retransid, sched, siptimer_a, retrans_pkt, pkt, 1); 03195 if (sipdebug) 03196 ast_debug(4, "*** SIP TIMER: Initializing retransmit timer on packet: Id #%d\n", pkt->retransid); 03197 03198 xmitres = __sip_xmit(pkt->owner, pkt->data, pkt->packetlen); /* Send packet */ 03199 03200 if (xmitres == XMIT_ERROR) { /* Serious network trouble, no need to try again */ 03201 append_history(pkt->owner, "XmitErr", "%s", pkt->is_fatal ? "(Critical)" : "(Non-critical)"); 03202 ast_log(LOG_ERROR, "Serious Network Trouble; __sip_xmit returns error for pkt data\n"); 03203 AST_SCHED_DEL(sched, pkt->retransid); 03204 p->packets = pkt->next; 03205 pkt->owner = dialog_unref(pkt->owner,"pkt is being freed, its dialog ref is dead now"); 03206 ast_free(pkt->data); 03207 ast_free(pkt); 03208 return AST_FAILURE; 03209 } else { 03210 return AST_SUCCESS; 03211 } 03212 }
| static int __sip_semi_ack | ( | struct sip_pvt * | p, | |
| int | seqno, | |||
| int | resp, | |||
| int | sipmethod | |||
| ) | [static] |
Acks receipt of packet, keep it around (used for provisional responses).
Definition at line 3389 of file chan_sip.c.
References ast_debug, AST_SCHED_DEL, sip_pvt::callid, sip_pkt::data, sip_pkt::is_resp, method_match(), sip_pkt::next, sip_pvt::packets, sip_pkt::retransid, sched, sip_pkt::seqno, sip_methods, ast_str::str, and cfsip_methods::text.
Referenced by handle_response().
03390 { 03391 struct sip_pkt *cur; 03392 int res = -1; 03393 03394 for (cur = p->packets; cur; cur = cur->next) { 03395 if (cur->seqno == seqno && cur->is_resp == resp && 03396 (cur->is_resp || method_match(sipmethod, cur->data->str))) { 03397 /* this is our baby */ 03398 if (cur->retransid > -1) { 03399 if (sipdebug) 03400 ast_debug(4, "*** SIP TIMER: Cancelling retransmission #%d - %s (got response)\n", cur->retransid, sip_methods[sipmethod].text); 03401 } 03402 AST_SCHED_DEL(sched, cur->retransid); 03403 res = 0; 03404 break; 03405 } 03406 } 03407 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"); 03408 return res; 03409 }
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 2865 of file chan_sip.c.
References ast_debug, ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_tcptls_server_write(), sip_request::data, errno, ast_tcptls_session_instance::f, sip_socket::fd, get_transport_pvt(), ast_tcptls_session_instance::lock, LOG_WARNING, sip_prepare_socket(), sip_real_dst(), SIP_TRANSPORT_UDP, sip_pvt::socket, ast_str::str, sip_socket::tcptls_session, sip_socket::type, and XMIT_ERROR.
Referenced by __sip_reliable_xmit(), retrans_pkt(), send_request(), and send_response().
02866 { 02867 int res = 0; 02868 const struct sockaddr_in *dst = sip_real_dst(p); 02869 02870 ast_debug(1, "Trying to put '%.10s' onto %s socket destined for %s:%d\n", data->str, get_transport_pvt(p), ast_inet_ntoa(dst->sin_addr), htons(dst->sin_port)); 02871 02872 if (sip_prepare_socket(p) < 0) 02873 return XMIT_ERROR; 02874 02875 if (p->socket.tcptls_session) 02876 ast_mutex_lock(&p->socket.tcptls_session->lock); 02877 02878 if (p->socket.type & SIP_TRANSPORT_UDP) 02879 res = sendto(p->socket.fd, data->str, len, 0, (const struct sockaddr *)dst, sizeof(struct sockaddr_in)); 02880 else { 02881 if (p->socket.tcptls_session->f) 02882 res = ast_tcptls_server_write(p->socket.tcptls_session, data->str, len); 02883 else 02884 ast_debug(2, "No p->socket.tcptls_session->f len=%d\n", len); 02885 } 02886 02887 if (p->socket.tcptls_session) 02888 ast_mutex_unlock(&p->socket.tcptls_session->lock); 02889 02890 if (res == -1) { 02891 switch (errno) { 02892 case EBADF: /* Bad file descriptor - seems like this is generated when the host exist, but doesn't accept the UDP packet */ 02893 case EHOSTUNREACH: /* Host can't be reached */ 02894 case ENETDOWN: /* Inteface down */ 02895 case ENETUNREACH: /* Network failure */ 02896 case ECONNREFUSED: /* ICMP port unreachable */ 02897 res = XMIT_ERROR; /* Don't bother with trying to transmit again */ 02898 } 02899 } 02900 if (res != len) 02901 ast_log(LOG_WARNING, "sip_xmit of %p (len %d) to %s:%d returned %d: %s\n", data, len, ast_inet_ntoa(dst->sin_addr), ntohs(dst->sin_port), res, strerror(errno)); 02902 02903 return res; 02904 }
| 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 8160 of file chan_sip.c.
References add_header(), add_header_contentLength(), ast_cause2str(), ast_log(), buf, get_header(), ast_channel::hangupcause, LOG_WARNING, sip_pvt::method, sip_pvt::owner, respprep(), send_response(), and SIP_INVITE.
Referenced by transmit_response(), transmit_response_reliable(), and transmit_response_using_temp().
08161 { 08162 struct sip_request resp; 08163 int seqno = 0; 08164 08165 if (reliable && (sscanf(get_header(req, "CSeq"), "%d ", &seqno) != 1)) { 08166 ast_log(LOG_WARNING, "Unable to determine sequence number from '%s'\n", get_header(req, "CSeq")); 08167 return -1; 08168 } 08169 respprep(&resp, p, msg, req); 08170 add_header_contentLength(&resp, 0); 08171 /* If we are cancelling an incoming invite for some reason, add information 08172 about the reason why we are doing this in clear text */ 08173 if (p->method == SIP_INVITE && msg[0] != '1' && p->owner && p->owner->hangupcause) { 08174 char buf[10]; 08175 08176 add_header(&resp, "X-Asterisk-HangupCause", ast_cause2str(p->owner->hangupcause)); 08177 snprintf(buf, sizeof(buf), "%d", p->owner->hangupcause); 08178 add_header(&resp, "X-Asterisk-HangupCauseCode", buf); 08179 } 08180 return send_response(p, &resp, reliable, seqno); 08181 }
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 23599 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 13548 of file chan_sip.c.
References ast_cli(), astman_send_error(), CLI_SHOWUSAGE, CLI_SUCCESS, FALSE, find_peer(), FINDPEERS, s, sip_poke_peer(), TRUE, and unref_peer().
Referenced by manager_sip_qualify_peer(), and sip_qualify_peer().
13549 { 13550 struct sip_peer *peer; 13551 int load_realtime; 13552 13553 if (argc < 4) 13554 return CLI_SHOWUSAGE; 13555 13556 load_realtime = (argc == 5 && !strcmp(argv[4], "load")) ? TRUE : FALSE; 13557 if ((peer = find_peer(argv[3], NULL, load_realtime, FINDPEERS, FALSE))) { 13558 sip_poke_peer(peer, 1); 13559 unref_peer(peer, "qualify: done with peer"); 13560 } else if (type == 0) { 13561 ast_cli(fd, "Peer '%s' not found\n", argv[3]); 13562 } else { 13563 astman_send_error(s, m, "Peer not found"); 13564 } 13565 return CLI_SUCCESS; 13566 }
| 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 13621 of file chan_sip.c.
References sip_peer::accountcode, sip_peer::addr, sip_peer::allowtransfer, sip_peer::amaflags, ARRAY_LEN, ast_callerid_merge(), ast_cdr_flags2str(), ast_check_realtime(), ast_cli(), ast_codec_pref_index(), ast_describe_caller_presentation(), ast_getformatname(), ast_getformatname_multiple(), ast_inet_ntoa(), ast_print_group(), ast_sched_when(), ast_str_alloca, ast_strlen_zero(), ast_test_flag, astman_append(), astman_get_header(), astman_send_error(), sip_peer::auth, sip_peer::autoframing, sip_peer::busy_level, sip_peer::call_limit, sip_peer::callgroup, sip_peer::callingpres, sip_peer::capability, sip_peer::chanvars, sip_peer::cid_name, sip_peer::cid_num, CLI_SHOWUSAGE, CLI_SUCCESS, cli_yesno(), sip_peer::context, sip_peer::defaddr, dtmfmode2str(), sip_peer::expire, FALSE, find_peer(), FINDPEERS, sip_peer::flags, sip_proxy::force, sip_peer::fromdomain, sip_peer::fromuser, sip_peer::fullcontact, get_transport(), sip_peer::ha, sip_peer::host_dynamic, cfsip_options::id, insecure2str(), sip_peer::is_realtime, sip_peer::language, sip_peer::lastmsgssent, sip_peer::maxcallbitrate, sip_auth::md5secret, sip_peer::md5secret, ast_variable::name, sip_proxy::name, sip_peer::name, nat2str(), ast_variable::next, sip_auth::next, sip_peer::outboundproxy, peer_mailboxes_to_str(), peer_status(), sip_peer::pickupgroup, sip_peer::prefs, print_codec_to_cli(), print_group(), sip_peer::qualifyfreq, sip_auth::realm, sip_peer::regexten, s, S_OR, sched, sip_auth::secret, sip_peer::secret, SIP_CAN_REINVITE, SIP_DTMF, SIP_INSECURE, SIP_NAT, sip_options, SIP_PAGE2_ALLOWOVERLAP, SIP_PAGE2_ALLOWSUBSCRIBE, SIP_PAGE2_REGISTERTRYING, SIP_PAGE2_T38SUPPORT_RTP, SIP_PAGE2_T38SUPPORT_TCP, SIP_PAGE2_T38SUPPORT_UDPTL, SIP_PAGE2_TEXTSUPPORT, SIP_PAGE2_VIDEOSUPPORT, SIP_PROMISCREDIR, SIP_SENDRPID, SIP_TRUSTRPID, SIP_USEREQPHONE, sip_peer::sipoptions, sip_peer::socket, sip_st_cfg::st_max_se, sip_st_cfg::st_min_se, sip_st_cfg::st_mode_oper, sip_st_cfg::st_ref, status, sip_peer::stimer, stmode2str(), ast_str::str, strefresher2str(), sip_peer::subscribecontext, text, sip_peer::timer_b, sip_peer::timer_t1, sip_peer::tohost, transfermode2str(), TRUE, sip_socket::type, unref_peer(), sip_peer::useragent, sip_peer::username, sip_auth::username, ast_variable::value, and sip_peer::vmexten.
Referenced by manager_sip_show_peer(), and sip_show_peer().
13622 { 13623 char status[30] = ""; 13624 char cbuf[256]; 13625 struct sip_peer *peer; 13626 char codec_buf[512]; 13627 struct ast_codec_pref *pref; 13628 struct ast_variable *v; 13629 struct sip_auth *auth; 13630 int x = 0, codec = 0, load_realtime; 13631 int realtimepeers; 13632 13633 realtimepeers = ast_check_realtime("sippeers"); 13634 13635 if (argc < 4) 13636 return CLI_SHOWUSAGE; 13637 13638 load_realtime = (argc == 5 && !strcmp(argv[4], "load")) ? TRUE : FALSE; 13639 peer = find_peer(argv[3], NULL, load_realtime, FINDPEERS, FALSE); 13640 13641 if (s) { /* Manager */ 13642 if (peer) { 13643 const char *id = astman_get_header(m, "ActionID"); 13644 13645 astman_append(s, "Response: Success\r\n"); 13646 if (!ast_strlen_zero(id)) 13647 astman_append(s, "ActionID: %s\r\n", id); 13648 } else { 13649 snprintf (cbuf, sizeof(cbuf), "Peer %s not found.", argv[3]); 13650 astman_send_error(s, m, cbuf); 13651 return CLI_SUCCESS; 13652 } 13653 } 13654 if (peer && type==0 ) { /* Normal listing */ 13655 struct ast_str *mailbox_str = ast_str_alloca(512); 13656 ast_cli(fd, "\n\n"); 13657 ast_cli(fd, " * Name : %s\n", peer->name); 13658 if (realtimepeers) { /* Realtime is enabled */ 13659 ast_cli(fd, " Realtime peer: %s\n", peer->is_realtime ? "Yes, cached" : "No"); 13660 } 13661 ast_cli(fd, " Secret : %s\n", ast_strlen_zero(peer->secret)?"<Not set>":"<Set>"); 13662 ast_cli(fd, " MD5Secret : %s\n", ast_strlen_zero(peer->md5secret)?"<Not set>":"<Set>"); 13663 for (auth = peer->auth; auth; auth = auth->next) { 13664 ast_cli(fd, " Realm-auth : Realm %-15.15s User %-10.20s ", auth->realm, auth->username); 13665 ast_cli(fd, "%s\n", !ast_strlen_zero(auth->secret)?"<Secret set>":(!ast_strlen_zero(auth->md5secret)?"<MD5secret set>" : "<Not set>")); 13666 } 13667 ast_cli(fd, " Context : %s\n", peer->context); 13668 ast_cli(fd, " Subscr.Cont. : %s\n", S_OR(peer->subscribecontext, "<Not set>") ); 13669 ast_cli(fd, " Language : %s\n", peer->language); 13670 if (!ast_strlen_zero(peer->accountcode)) 13671 ast_cli(fd, " Accountcode : %s\n", peer->accountcode); 13672 ast_cli(fd, " AMA flags : %s\n", ast_cdr_flags2str(peer->amaflags)); 13673 ast_cli(fd, " Transfer mode: %s\n", transfermode2str(peer->allowtransfer)); 13674 ast_cli(fd, " CallingPres : %s\n", ast_describe_caller_presentation(peer->callingpres)); 13675 if (!ast_strlen_zero(peer->fromuser)) 13676 ast_cli(fd, " FromUser : %s\n", peer->fromuser); 13677 if (!ast_strlen_zero(peer->fromdomain)) 13678 ast_cli(fd, " FromDomain : %s\n", peer->fromdomain); 13679 ast_cli(fd, " Callgroup : "); 13680 print_group(fd, peer->callgroup, 0); 13681 ast_cli(fd, " Pickupgroup : "); 13682 print_group(fd, peer->pickupgroup, 0); 13683 peer_mailboxes_to_str(&mailbox_str, peer); 13684 ast_cli(fd, " Mailbox : %s\n", mailbox_str->str); 13685 ast_cli(fd, " VM Extension : %s\n", peer->vmexten); 13686 ast_cli(fd, " LastMsgsSent : %d/%d\n", (peer->lastmsgssent & 0x7fff0000) >> 16, peer->lastmsgssent & 0xffff); 13687 ast_cli(fd, " Call limit : %d\n", peer->call_limit); 13688 if (peer->busy_level) 13689 ast_cli(fd, " Busy level : %d\n", peer->busy_level); 13690 ast_cli(fd, " Dynamic : %s\n", cli_yesno(peer->host_dynamic)); 13691 ast_cli(fd, " Callerid : %s\n", ast_callerid_merge(cbuf, sizeof(cbuf), peer->cid_name, peer->cid_num, "<unspecified>")); 13692 ast_cli(fd, " MaxCallBR : %d kbps\n", peer->maxcallbitrate); 13693 ast_cli(fd, " Expire : %ld\n", ast_sched_when(sched, peer->expire)); 13694 ast_cli(fd, " Insecure : %s\n", insecure2str(ast_test_flag(&peer->flags[0], SIP_INSECURE))); 13695 ast_cli(fd, " Nat : %s\n", nat2str(ast_test_flag(&peer->flags[0], SIP_NAT))); 13696 ast_cli(fd, " ACL : %s\n", cli_yesno(peer->ha != NULL)); 13697 ast_cli(fd, " T38 pt UDPTL : %s\n", cli_yesno(ast_test_flag(&peer->flags[1], SIP_PAGE2_T38SUPPORT_UDPTL))); 13698 #ifdef WHEN_WE_HAVE_T38_FOR_OTHER_TRANSPORTS 13699 ast_cli(fd, " T38 pt RTP : %s\n", cli_yesno(ast_test_flag(&peer->flags[1], SIP_PAGE2_T38SUPPORT_RTP))); 13700 ast_cli(fd, " T38 pt TCP : %s\n", cli_yesno(ast_test_flag(&peer->flags[1], SIP_PAGE2_T38SUPPORT_TCP))); 13701 #endif 13702 ast_cli(fd, " CanReinvite : %s\n", cli_yesno(ast_test_flag(&peer->flags[0], SIP_CAN_REINVITE))); 13703 ast_cli(fd, " PromiscRedir : %s\n", cli_yesno(ast_test_flag(&peer->flags[0], SIP_PROMISCREDIR))); 13704 ast_cli(fd, " User=Phone : %s\n", cli_yesno(ast_test_flag(&peer->flags[0], SIP_USEREQPHONE))); 13705 ast_cli(fd, " Video Support: %s\n", cli_yesno(ast_test_flag(&peer->flags[1], SIP_PAGE2_VIDEOSUPPORT))); 13706 ast_cli(fd, " Text Support : %s\n", cli_yesno(ast_test_flag(&peer->flags[1], SIP_PAGE2_TEXTSUPPORT))); 13707 ast_cli(fd, " Trust RPID : %s\n", cli_yesno(ast_test_flag(&peer->flags[0], SIP_TRUSTRPID))); 13708 ast_cli(fd, " Send RPID : %s\n", cli_yesno(ast_test_flag(&peer->flags[0], SIP_SENDRPID))); 13709 ast_cli(fd, " Subscriptions: %s\n", cli_yesno(ast_test_flag(&peer->flags[1], SIP_PAGE2_ALLOWSUBSCRIBE))); 13710 ast_cli(fd, " Overlap dial : %s\n", cli_yesno(ast_test_flag(&peer->flags[1], SIP_PAGE2_ALLOWOVERLAP))); 13711 if (peer->outboundproxy) 13712 ast_cli(fd, " Outb. proxy : %s %s\n", ast_strlen_zero(peer->outboundproxy->name) ? "<not set>" : peer->outboundproxy->name, 13713 peer->outboundproxy->force ? "(forced)" : ""); 13714 13715 /* - is enumerated */ 13716 ast_cli(fd, " DTMFmode : %s\n", dtmfmode2str(ast_test_flag(&peer->flags[0], SIP_DTMF))); 13717 ast_cli(fd, " Timer T1 : %d\n", peer->timer_t1); 13718 ast_cli(fd, " Timer B : %d\n", peer->timer_b); 13719 ast_cli(fd, " ToHost : %s\n", peer->tohost); 13720 ast_cli(fd, " Addr->IP : %s Port %d\n", peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)", ntohs(peer->addr.sin_port)); 13721 ast_cli(fd, " Defaddr->IP : %s Port %d\n", ast_inet_ntoa(peer->defaddr.sin_addr), ntohs(peer->defaddr.sin_port)); 13722 ast_cli(fd, " Transport : %s\n", get_transport(peer->socket.type)); 13723 if (!ast_strlen_zero(global_regcontext)) 13724 ast_cli(fd, " Reg. exten : %s\n", peer->regexten); 13725 ast_cli(fd, " Def. Username: %s\n", peer->username); 13726 ast_cli(fd, " SIP Options : "); 13727 if (peer->sipoptions) { 13728 int lastoption = -1; 13729 for (x = 0 ; x < ARRAY_LEN(sip_options); x++) { 13730 if (sip_options[x].id != lastoption) { 13731 if (peer->sipoptions & sip_options[x].id) 13732 ast_cli(fd, "%s ", sip_options[x].text); 13733 lastoption = x; 13734 } 13735 } 13736 } else 13737 ast_cli(fd, "(none)"); 13738 13739 ast_cli(fd, "\n"); 13740 ast_cli(fd, " Codecs : "); 13741 ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, peer->capability); 13742 ast_cli(fd, "%s\n", codec_buf); 13743 ast_cli(fd, " Codec Order : ("); 13744 print_codec_to_cli(fd, &peer->prefs); 13745 ast_cli(fd, ")\n"); 13746 13747 ast_cli(fd, " Auto-Framing : %s \n", cli_yesno(peer->autoframing)); 13748 ast_cli(fd, " 100 on REG : %s\n", ast_test_flag(&peer->flags[1], SIP_PAGE2_REGISTERTRYING) ? "Yes" : "No"); 13749 ast_cli(fd, " Status : "); 13750 peer_status(peer, status, sizeof(status)); 13751 ast_cli(fd, "%s\n", status); 13752 ast_cli(fd, " Useragent : %s\n", peer->useragent); 13753 ast_cli(fd, " Reg. Contact : %s\n", peer->fullcontact); 13754 ast_cli(fd, " Qualify Freq : %d ms\n", peer->qualifyfreq); 13755 if (peer->chanvars) { 13756 ast_cli(fd, " Variables :\n"); 13757 for (v = peer->chanvars ; v ; v = v->next) 13758 ast_cli(fd, " %s = %s\n", v->name, v->value); 13759 } 13760 13761 ast_cli(fd, " Sess-Timers : %s\n", stmode2str(peer->stimer.st_mode_oper)); 13762 ast_cli(fd, " Sess-Refresh : %s\n", strefresher2str(peer->stimer.st_ref)); 13763 ast_cli(fd, " Sess-Expires : %d secs\n", peer->stimer.st_max_se); 13764 ast_cli(fd, " Min-Sess : %d secs\n", peer->stimer.st_min_se); 13765 ast_cli(fd, "\n"); 13766 peer = unref_peer(peer, "sip_show_peer: unref_peer: done with peer ptr"); 13767 } else if (peer && type == 1) { /* manager listing */ 13768 char buffer[256]; 13769 struct ast_str *mailbox_str = ast_str_alloca(512); 13770 astman_append(s, "Channeltype: SIP\r\n"); 13771 astman_append(s, "ObjectName: %s\r\n", peer->name); 13772 astman_append(s, "ChanObjectType: peer\r\n"); 13773 astman_append(s, "SecretExist: %s\r\n", ast_strlen_zero(peer->secret)?"N":"Y"); 13774 astman_append(s, "MD5SecretExist: %s\r\n", ast_strlen_zero(peer->md5secret)?"N":"Y"); 13775 astman_append(s, "Context: %s\r\n", peer->context); 13776 astman_append(s, "Language: %s\r\n", peer->language); 13777 if (!ast_strlen_zero(peer->accountcode)) 13778 astman_append(s, "Accountcode: %s\r\n", peer->accountcode); 13779 astman_append(s, "AMAflags: %s\r\n", ast_cdr_flags2str(peer->amaflags)); 13780 astman_append(s, "CID-CallingPres: %s\r\n", ast_describe_caller_presentation(peer->callingpres)); 13781 if (!ast_strlen_zero(peer->fromuser)) 13782 astman_append(s, "SIP-FromUser: %s\r\n", peer->fromuser); 13783 if (!ast_strlen_zero(peer->fromdomain)) 13784 astman_append(s, "SIP-FromDomain: %s\r\n", peer->fromdomain); 13785 astman_append(s, "Callgroup: "); 13786 astman_append(s, "%s\r\n", ast_print_group(buffer, sizeof(buffer), peer->callgroup)); 13787 astman_append(s, "Pickupgroup: "); 13788 astman_append(s, "%s\r\n", ast_print_group(buffer, sizeof(buffer), peer->pickupgroup)); 13789 peer_mailboxes_to_str(&mailbox_str, peer); 13790 astman_append(s, "VoiceMailbox: %s\r\n", mailbox_str->str); 13791 astman_append(s, "TransferMode: %s\r\n", transfermode2str(peer->allowtransfer)); 13792 astman_append(s, "LastMsgsSent: %d\r\n", peer->lastmsgssent); 13793 astman_append(s, "Call-limit: %d\r\n", peer->call_limit); 13794 astman_append(s, "Busy-level: %d\r\n", peer->busy_level); 13795 astman_append(s, "MaxCallBR: %d kbps\r\n", peer->maxcallbitrate); 13796 astman_append(s, "Dynamic: %s\r\n", peer->host_dynamic?"Y":"N"); 13797 astman_append(s, "Callerid: %s\r\n", ast_callerid_merge(cbuf, sizeof(cbuf), peer->cid_name, peer->cid_num, "")); 13798 astman_append(s, "RegExpire: %ld seconds\r\n", ast_sched_when(sched, peer->expire)); 13799 astman_append(s, "SIP-AuthInsecure: %s\r\n", insecure2str(ast_test_flag(&peer->flags[0], SIP_INSECURE))); 13800 astman_append(s, "SIP-NatSupport: %s\r\n", nat2str(ast_test_flag(&peer->flags[0], SIP_NAT))); 13801 astman_append(s, "ACL: %s\r\n", (peer->ha?"Y":"N")); 13802 astman_append(s, "SIP-CanReinvite: %s\r\n", (ast_test_flag(&peer->flags[0], SIP_CAN_REINVITE)?"Y":"N")); 13803 astman_append(s, "SIP-PromiscRedir: %s\r\n", (ast_test_flag(&peer->flags[0], SIP_PROMISCREDIR)?"Y":"N")); 13804 astman_append(s, "SIP-UserPhone: %s\r\n", (ast_test_flag(&peer->flags[0], SIP_USEREQPHONE)?"Y":"N")); 13805 astman_append(s, "SIP-VideoSupport: %s\r\n", (ast_test_flag(&peer->flags[1], SIP_PAGE2_VIDEOSUPPORT)?"Y":"N")); 13806 astman_append(s, "SIP-TextSupport: %s\r\n", (ast_test_flag(&peer->flags[1], SIP_PAGE2_TEXTSUPPORT)?"Y":"N")); 13807 astman_append(s, "SIP-Sess-Timers: %s\r\n", stmode2str(peer->stimer.st_mode_oper)); 13808 astman_append(s, "SIP-Sess-Refresh: %s\r\n", strefresher2str(peer->stimer.st_ref)); 13809 astman_append(s, "SIP-Sess-Expires: %d\r\n", peer->stimer.st_max_se); 13810 astman_append(s, "SIP-Sess-Min: %d\r\n", peer->stimer.st_min_se); 13811 13812 /* - is enumerated */ 13813 astman_append(s, "SIP-DTMFmode: %s\r\n", dtmfmode2str(ast_test_flag(&peer->flags[0], SIP_DTMF))); 13814 astman_append(s, "ToHost: %s\r\n", peer->tohost); 13815 astman_append(s, "Address-IP: %s\r\nAddress-Port: %d\r\n", peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "", ntohs(peer->addr.sin_port)); 13816 astman_append(s, "Default-addr-IP: %s\r\nDefault-addr-port: %d\r\n", ast_inet_ntoa(peer->defaddr.sin_addr), ntohs(peer->defaddr.sin_port)); 13817 astman_append(s, "Default-Username: %s\r\n", peer->username); 13818 if (!ast_strlen_zero(global_regcontext)) 13819 astman_append(s, "RegExtension: %s\r\n", peer->regexten); 13820 astman_append(s, "Codecs: "); 13821 ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, peer->capability); 13822 astman_append(s, "%s\r\n", codec_buf); 13823 astman_append(s, "CodecOrder: "); 13824 pref = &peer->prefs; 13825 for(x = 0; x < 32 ; x++) { 13826 codec = ast_codec_pref_index(pref, x); 13827 if (!codec) 13828 break; 13829 astman_append(s, "%s", ast_getformatname(codec)); 13830 if (x < 31 && ast_codec_pref_index(pref, x+1)) 13831 astman_append(s, ","); 13832 } 13833 13834 astman_append(s, "\r\n"); 13835 astman_append(s, "Status: "); 13836 peer_status(peer, status, sizeof(status)); 13837 astman_append(s, "%s\r\n", status); 13838 astman_append(s, "SIP-Useragent: %s\r\n", peer->useragent); 13839 astman_append(s, "Reg-Contact: %s\r\n", peer->fullcontact); 13840 astman_append(s, "QualifyFreq: %d ms\r\n", peer->qualifyfreq); 13841 if (peer->chanvars) { 13842 for (v = peer->chanvars ; v ; v = v->next) { 13843 astman_append(s, "ChanVariable: %s=%s\r\n", v->name, v->value); 13844 } 13845 } 13846 13847 peer = unref_peer(peer, "sip_show_peer: unref_peer: done with peer"); 13848 13849 } else { 13850 ast_cli(fd, "Peer %s not found.\n", argv[3]); 13851 ast_cli(fd, "\n"); 13852 } 13853 13854 return CLI_SUCCESS; 13855 }
| 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 12943 of file chan_sip.c.
References sip_peer::addr, ao2_container_count(), ao2_iterator_init(), ao2_lock(), ao2_t_iterator_next, ao2_unlock(), ast_calloc, ast_check_realtime(), ast_cli(), ast_copy_string(), ast_free, ast_inet_ntoa(), ast_strlen_zero(), ast_test_flag, astman_append(), astman_get_header(), CLI_SHOWUSAGE, CLI_SUCCESS, FALSE, sip_peer::flags, FORMAT, FORMAT2, sip_peer::ha, sip_peer::host_dynamic, id, sip_peer::is_realtime, sip_peer::name, name, peer_status(), peercomparefunc(), s, SIP_NAT_ROUTE, SIP_PAGE2_TEXTSUPPORT, SIP_PAGE2_VIDEOSUPPORT, SIP_TYPE_PEER, status, TRUE, sip_peer::type, unref_peer(), and sip_peer::username.
Referenced by manager_sip_show_peers(), and sip_show_peers().
12944 { 12945 regex_t regexbuf; 12946 int havepattern = FALSE; 12947 struct sip_peer *peer; 12948 struct ao2_iterator i; 12949 12950 /* the last argument is left-aligned, so we don't need a size anyways */ 12951 #define FORMAT2 "%-25.25s %-15.15s %-3.3s %-3.3s %-3.3s %-8s %-10s %s\n" 12952 #define FORMAT "%-25.25s %-15.15s %-3.3s %-3.3s %-3.3s %-8d %-10s %s\n" 12953 12954 char name[256]; 12955 int total_peers = 0; 12956 int peers_mon_online = 0; 12957 int peers_mon_offline = 0; 12958 int peers_unmon_offline = 0; 12959 int peers_unmon_online = 0; 12960 const char *id; 12961 char idtext[256] = ""; 12962 int realtimepeers; 12963 int objcount = ao2_container_count(peers); 12964 struct sip_peer **peerarray; 12965 int k; 12966 12967 12968 realtimepeers = ast_check_realtime("sippeers"); 12969 peerarray = ast_calloc(sizeof(struct sip_peer *), objcount); 12970 12971 if (s) { /* Manager - get ActionID */ 12972 id = astman_get_header(m, "ActionID"); 12973 if (!ast_strlen_zero(id)) 12974 snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id); 12975 } 12976 12977 switch (argc) { 12978 case 5: 12979 if (!strcasecmp(argv[3], "like")) { 12980 if (regcomp(®exbuf, argv[4], REG_EXTENDED | REG_NOSUB)) 12981 return CLI_SHOWUSAGE; 12982 havepattern = TRUE; 12983 } else 12984 return CLI_SHOWUSAGE; 12985 case 3: 12986 break; 12987 default: 12988 return CLI_SHOWUSAGE; 12989 } 12990 12991 if (!s) /* Normal list */ 12992 ast_cli(fd, FORMAT2, "Name/username", "Host", "Dyn", "Nat", "ACL", "Port", "Status", (realtimepeers ? "Realtime" : "")); 12993 12994 12995 i = ao2_iterator_init(peers, 0); 12996 while ((peer = ao2_t_iterator_next(&i, "iterate thru peers table"))) { 12997 ao2_lock(peer); 12998 12999 if (!(peer->type & SIP_TYPE_PEER)) { 13000 ao2_unlock(peer); 13001 unref_peer(peer, "unref peer because it's actually a user"); 13002 continue; 13003 } 13004 13005 if (havepattern && regexec(®exbuf, peer->name, 0, NULL, 0)) { 13006 objcount--; 13007 ao2_unlock(peer); 13008 unref_peer(peer, "toss iterator peer ptr before continue"); 13009 continue; 13010 } 13011 13012 peerarray[total_peers++] = peer; 13013 ao2_unlock(peer); 13014 } 13015 13016 qsort(peerarray, total_peers, sizeof(struct sip_peer *), peercomparefunc); 13017 13018 for(k=0; k < total_peers; k++) { 13019 char status[20] = ""; 13020 char srch[2000]; 13021 char pstatus; 13022 peer = peerarray[k]; 13023 13024 ao2_lock(peer); 13025 if (havepattern && regexec(®exbuf, peer->name, 0, NULL, 0)) { 13026 ao2_unlock(peer); 13027 unref_peer(peer, "toss iterator peer ptr before continue"); 13028 continue; 13029 } 13030 13031 if (!ast_strlen_zero(peer->username) && !s) 13032 snprintf(name, sizeof(name), "%s/%s", peer->name, peer->username); 13033 else 13034 ast_copy_string(name, peer->name, sizeof(name)); 13035 13036 pstatus = peer_status(peer, status, sizeof(status)); 13037 if (pstatus == 1) 13038 peers_mon_online++; 13039 else if (pstatus == 0) 13040 peers_mon_offline++; 13041 else { 13042 if (peer->addr.sin_port == 0) 13043 peers_unmon_offline++; 13044 else 13045 peers_unmon_online++; 13046 } 13047 13048 snprintf(srch, sizeof(srch), FORMAT, name, 13049 peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)", 13050 peer->host_dynamic ? " D " : " ", /* Dynamic or not? */ 13051 ast_test_flag(&peer->flags[0], SIP_NAT_ROUTE) ? " N " : " ", /* NAT=yes? */ 13052 peer->ha ? " A " : " ", /* permit/deny */ 13053 ntohs(peer->addr.sin_port), status, 13054 realtimepeers ? (peer->is_realtime ? "Cached RT":"") : ""); 13055 13056 if (!s) {/* Normal CLI list */ 13057 ast_cli(fd, FORMAT, name, 13058 peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)", 13059 peer->host_dynamic ? " D " : " ", /* Dynamic or not? */ 13060 ast_test_flag(&peer->flags[0], SIP_NAT_ROUTE) ? " N " : " ", /* NAT=yes? */ 13061 peer->ha ? " A " : " ", /* permit/deny */ 13062 13063 ntohs(peer->addr.sin_port), status, 13064 realtimepeers ? (peer->is_realtime ? "Cached RT":"") : ""); 13065 } else { /* Manager format */ 13066 /* The names here need to be the same as other channels */ 13067 astman_append(s, 13068 "Event: PeerEntry\r\n%s" 13069 "Channeltype: SIP\r\n" 13070 "ObjectName: %s\r\n" 13071 "ChanObjectType: peer\r\n" /* "peer" or "user" */ 13072 "IPaddress: %s\r\n" 13073 "IPport: %d\r\n" 13074 "Dynamic: %s\r\n" 13075 "Natsupport: %s\r\n" 13076 "VideoSupport: %s\r\n" 13077 "TextSupport: %s\r\n" 13078 "ACL: %s\r\n" 13079 "Status: %s\r\n" 13080 "RealtimeDevice: %s\r\n\r\n", 13081 idtext, 13082 peer->name, 13083 peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "-none-", 13084 ntohs(peer->addr.sin_port), 13085 peer->host_dynamic ? "yes" : "no", /* Dynamic or not? */ 13086 ast_test_flag(&peer->flags[0], SIP_NAT_ROUTE) ? "yes" : "no", /* NAT=yes? */ 13087 ast_test_flag(&peer->flags[1], SIP_PAGE2_VIDEOSUPPORT) ? "yes" : "no", /* VIDEOSUPPORT=yes? */ 13088 ast_test_flag(&peer->flags[1], SIP_PAGE2_TEXTSUPPORT) ? "yes" : "no", /* TEXTSUPPORT=yes? */ 13089 peer->ha ? "yes" : "no", /* permit/deny */ 13090 status, 13091 realtimepeers ? (peer->is_realtime ? "yes":"no") : "no"); 13092 } 13093 ao2_unlock(peer); 13094 unref_peer(peer, "toss iterator peer ptr"); 13095 } 13096 13097 if (!s) 13098 ast_cli(fd, "%d sip peers [Monitored: %d online, %d offline Unmonitored: %d online, %d offline]\n", 13099 total_peers, peers_mon_online, peers_mon_offline, peers_unmon_online, peers_unmon_offline); 13100 13101 if (havepattern) 13102 regfree(®exbuf); 13103 13104 if (total) 13105 *total = total_peers; 13106 13107 ast_free(peerarray); 13108 13109 return CLI_SUCCESS; 13110 #undef FORMAT 13111 #undef FORMAT2 13112 }
| static void * _sip_tcp_helper_thread | ( | struct sip_pvt * | pvt, | |
| struct ast_tcptls_session_instance * | tcptls_session | |||
| ) | [static] |
SIP TCP thread management function.
Definition at line 2368 of file chan_sip.c.
References ao2_ref, ast_calloc, ast_debug, ast_free, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), ast_str_append(), ast_str_create(), ast_str_reset(), ast_wait_for_input(), buf, cleanup(), copy_request(), sip_request::data, ast_tcptls_session_instance::f, ast_tcptls_session_instance::fd, get_header(), handle_request_do(), sip_request::len, sip_threadinfo::list, ast_tcptls_session_instance::lock, me, ourport_tcp, ourport_tls, parse_request(), ast_tcptls_session_instance::remote_address, REQ_OFFSET_TO_STR, SIP_MIN_PACKET, SIP_TRANSPORT_TCP, SIP_TRANSPORT_TLS, ast_tcptls_session_instance::ssl, and sip_threadinfo::tcptls_session.
Referenced by sip_tcp_worker_fn().
02369 { 02370 int res, cl; 02371 struct sip_request req = { 0, } , reqcpy = { 0, }; 02372 struct sip_threadinfo *me; 02373 char buf[1024] = ""; 02374 02375 me = ast_calloc(1, sizeof(*me)); 02376 02377 if (!me) 02378 goto cleanup2; 02379 02380 me->threadid = pthread_self(); 02381 me->tcptls_session = tcptls_session; 02382 if (tcptls_session->ssl) 02383 me->type = SIP_TRANSPORT_TLS; 02384 else 02385 me->type = SIP_TRANSPORT_TCP; 02386 02387 ast_debug(2, "Starting thread for %s server\n", tcptls_session->ssl ? "SSL" : "TCP"); 02388 02389 AST_LIST_LOCK(&threadl); 02390 AST_LIST_INSERT_TAIL(&threadl, me, list); 02391 AST_LIST_UNLOCK(&threadl); 02392 02393 if (!(req.data = ast_str_create(SIP_MIN_PACKET))) 02394 goto cleanup; 02395 if (!(reqcpy.data = ast_str_create(SIP_MIN_PACKET))) 02396 goto cleanup; 02397 02398 for (;;) { 02399 struct ast_str *str_save; 02400 02401 str_save = req.data; 02402 memset(&req, 0, sizeof(req)); 02403 req.data = str_save; 02404 ast_str_reset(req.data); 02405 02406 str_save = reqcpy.data; 02407 memset(&reqcpy, 0, sizeof(reqcpy)); 02408 reqcpy.data = str_save; 02409 ast_str_reset(reqcpy.data); 02410 02411 req.socket.fd = tcptls_session->fd; 02412 if (tcptls_session->ssl) { 02413 req.socket.type = SIP_TRANSPORT_TLS; 02414 req.socket.port = htons(ourport_tls); 02415 } else { 02416 req.socket.type = SIP_TRANSPORT_TCP; 02417 req.socket.port = htons(ourport_tcp); 02418 } 02419 res = ast_wait_for_input(tcptls_session->fd, -1); 02420 if (res < 0) { 02421 ast_debug(2, "SIP %s server :: ast_wait_for_input returned %d\n", tcptls_session->ssl ? "SSL": "TCP", res); 02422 goto cleanup; 02423 } 02424 02425 /* Read in headers one line at a time */ 02426 while (req.len < 4 || strncmp(REQ_OFFSET_TO_STR(&req, len - 4), "\r\n\r\n", 4)) { 02427 ast_mutex_lock(&tcptls_session->lock); 02428 if (!fgets(buf, sizeof(buf), tcptls_session->f)) { 02429 ast_mutex_unlock(&tcptls_session->lock); 02430 goto cleanup; 02431 } 02432 ast_mutex_unlock(&tcptls_session->lock); 02433 if (me->stop) 02434 goto cleanup; 02435 ast_str_append(&req.data, 0, "%s", buf); 02436 req.len = req.data->used; 02437 } 02438 copy_request(&reqcpy, &req); 02439 parse_request(&reqcpy); 02440 if (sscanf(get_header(&reqcpy, "Content-Length"), "%d", &cl)) { 02441 while (cl > 0) { 02442 ast_mutex_lock(&tcptls_session->lock); 02443 if (!fread(buf, (cl < sizeof(buf)) ? cl : sizeof(buf), 1, tcptls_session->f)) { 02444 ast_mutex_unlock(&tcptls_session->lock); 02445 goto cleanup; 02446 } 02447 ast_mutex_unlock(&tcptls_session->lock); 02448 if (me->stop) 02449 goto cleanup; 02450 cl -= strlen(buf); 02451 ast_str_append(&req.data, 0, "%s", buf); 02452 req.len = req.data->used; 02453 } 02454 } 02455 req.socket.tcptls_session = tcptls_session; 02456 handle_request_do(&req, &tcptls_session->remote_address); 02457 } 02458 02459 cleanup: 02460 AST_LIST_LOCK(&threadl); 02461 AST_LIST_REMOVE(&threadl, me, list); 02462 AST_LIST_UNLOCK(&threadl); 02463 ast_free(me); 02464 cleanup2: 02465 fclose(tcptls_session->f); 02466 tcptls_session->f = NULL; 02467 tcptls_session->fd = -1; 02468 if (reqcpy.data) { 02469 ast_free(reqcpy.data); 02470 } 02471 02472 if (req.data) { 02473 ast_free(req.data); 02474 req.data = NULL; 02475 } 02476 02477 ast_debug(2, "Shutting down thread for %s server\n", tcptls_session->ssl ? "SSL" : "TCP"); 02478 02479 ao2_ref(tcptls_session, -1); 02480 tcptls_session = NULL; 02481 02482 return NULL; 02483 }
| static int acf_channel_read | ( | struct ast_channel * | chan, | |
| const char * | funcname, | |||
| char * | preparse, | |||
| char * | buf, | |||
| size_t | buflen | |||
| ) | [static] |
Definition at line 18939 of file chan_sip.c.
References AST_APP_ARG, ast_copy_string(), AST_DECLARE_APP_ARGS, ast_inet_ntoa(), ast_log(), ast_rtp_get_peer(), ast_rtp_get_qos(), ast_rtp_get_quality(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), chan, sip_pvt::from, IS_SIP_TECH, LOG_ERROR, LOG_WARNING, parse(), sip_pvt::peername, qos, sip_pvt::recv, sip_pvt::rtp, RTPQOS_SUMMARY, sip_pvt::sa, t38properties::state, sip_pvt::t38, T38_DISABLED, ast_channel::tech, ast_channel::tech_pvt, sip_pvt::trtp, sip_pvt::uri, sip_pvt::useragent, and sip_pvt::vrtp.
18940 { 18941 struct sip_pvt *p = chan->tech_pvt; 18942 char *all = "", *parse = ast_strdupa(preparse); 18943 int res = 0; 18944 AST_DECLARE_APP_ARGS(args, 18945 AST_APP_ARG(param); 18946 AST_APP_ARG(type); 18947 AST_APP_ARG(field); 18948 ); 18949 AST_STANDARD_APP_ARGS(args, parse); 18950 18951 /* Sanity check */ 18952 if (!IS_SIP_TECH(chan->tech)) { 18953 ast_log(LOG_ERROR, "Cannot call %s on a non-SIP channel\n", funcname); 18954 return 0; 18955 } 18956 18957 memset(buf, 0, buflen); 18958 18959 if (!strcasecmp(args.param, "peerip")) { 18960 ast_copy_string(buf, p->sa.sin_addr.s_addr ? ast_inet_ntoa(p->sa.sin_addr) : "", buflen); 18961 } else if (!strcasecmp(args.param, "recvip")) { 18962 ast_copy_string(buf, p->recv.sin_addr.s_addr ? ast_inet_ntoa(p->recv.sin_addr) : "", buflen); 18963 } else if (!strcasecmp(args.param, "from")) { 18964 ast_copy_string(buf, p->from, buflen); 18965 } else if (!strcasecmp(args.param, "uri")) { 18966 ast_copy_string(buf, p->uri, buflen); 18967 } else if (!strcasecmp(args.param, "useragent")) { 18968 ast_copy_string(buf, p->useragent, buflen); 18969 } else if (!strcasecmp(args.param, "peername")) { 18970 ast_copy_string(buf, p->peername, buflen); 18971 } else if (!strcasecmp(args.param, "t38passthrough")) { 18972 ast_copy_string(buf, (p->t38.state == T38_DISABLED) ? "0" : "1", buflen); 18973 } else if (!strcasecmp(args.param, "rtpdest")) { 18974 struct sockaddr_in sin; 18975 18976 if (ast_strlen_zero(args.type)) 18977 args.type = "audio"; 18978 18979 if (!strcasecmp(args.type, "audio")) 18980 ast_rtp_get_peer(p->rtp, &sin); 18981 else if (!strcasecmp(args.type, "video")) 18982 ast_rtp_get_peer(p->vrtp, &sin); 18983 else if (!strcasecmp(args.type, "text")) 18984 ast_rtp_get_peer(p->trtp, &sin); 18985 else 18986 return -1; 18987 18988 snprintf(buf, buflen, "%s:%d", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 18989 } else if (!strcasecmp(args.param, "rtpqos")) { 18990 struct ast_rtp_quality qos; 18991 struct ast_rtp *rtp = p->rtp; 18992 18993 memset(&qos, 0, sizeof(qos)); 18994 18995 if (ast_strlen_zero(args.type)) 18996 args.type = "audio"; 18997 if (ast_strlen_zero(args.field)) 18998 args.field = "all"; 18999 19000 if (!strcasecmp(args.type, "AUDIO")) { 19001 all = ast_rtp_get_quality(rtp = p->rtp, &qos, RTPQOS_SUMMARY); 19002 } else if (!strcasecmp(args.type, "VIDEO")) { 19003 all = ast_rtp_get_quality(rtp = p->vrtp, &qos, RTPQOS_SUMMARY); 19004 } else if (!strcasecmp(args.type, "TEXT")) { 19005 all = ast_rtp_get_quality(rtp = p->trtp, &qos, RTPQOS_SUMMARY); 19006 } else { 19007 return -1; 19008 } 19009 19010 if (!strcasecmp(args.field, "local_ssrc")) 19011 snprintf(buf, buflen, "%u", qos.local_ssrc); 19012 else if (!strcasecmp(args.field, "local_lostpackets")) 19013 snprintf(buf, buflen, "%u", qos.local_lostpackets); 19014 else if (!strcasecmp(args.field, "local_jitter")) 19015 snprintf(buf, buflen, "%.0f", qos.local_jitter * 1000.0); 19016 else if (!strcasecmp(args.field, "local_count")) 19017 snprintf(buf, buflen, "%u", qos.local_count); 19018 else if (!strcasecmp(args.field, "remote_ssrc")) 19019 snprintf(buf, buflen, "%u", qos.remote_ssrc); 19020 else if (!strcasecmp(args.field, "remote_lostpackets")) 19021 snprintf(buf, buflen, "%u", qos.remote_lostpackets); 19022 else if (!strcasecmp(args.field, "remote_jitter")) 19023 snprintf(buf, buflen, "%.0f", qos.remote_jitter * 1000.0); 19024 else if (!strcasecmp(args.field, "remote_count")) 19025 snprintf(buf, buflen, "%u", qos.remote_count); 19026 else if (!strcasecmp(args.field, "rtt")) 19027 snprintf(buf, buflen, "%.0f", qos.rtt * 1000.0); 19028 else if (!strcasecmp(args.field, "all")) 19029 ast_copy_string(buf, all, buflen); 19030 else if (!ast_rtp_get_qos(rtp, args.field, buf, buflen)) 19031 ; 19032 else { 19033 ast_log(LOG_WARNING, "Unrecognized argument '%s' to %s\n", preparse, funcname); 19034 return -1; 19035 } 19036 } else { 19037 res = -1; 19038 } 19039 return res; 19040 }
| static void add_blank | ( | struct sip_request * | req | ) | [static] |
add a blank line if no body
Definition at line 3420 of file chan_sip.c.
References ast_str_append(), sip_request::data, sip_request::len, sip_request::lines, and ast_str::used.
Referenced by send_request(), and send_response().
03421 { 03422 if (!req->lines) { 03423 /* Add extra empty return. add_header() reserves 4 bytes so cannot be truncated */ 03424 ast_str_append(&req->data, 0, "\r\n"); 03425 req->len = req->data->used; 03426 } 03427 }
| static void add_codec_to_sdp | ( | const struct sip_pvt * | p, | |
| int | codec, | |||
| int | sample_rate, | |||
| 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 8410 of file chan_sip.c.
References ast_codec_pref_getsize(), AST_FORMAT_G723_1, AST_FORMAT_G729A, AST_FORMAT_ILBC, ast_getformatname(), ast_rtp_codec_getpref(), ast_rtp_lookup_code(), ast_rtp_lookup_mime_subtype(), AST_RTP_OPT_G726_NONSTANDARD, ast_str_append(), ast_test_flag, ast_verbose, ast_format_list::cur_ms, sip_pvt::flags, sip_pvt::rtp, and SIP_G726_NONSTANDARD.
Referenced by add_sdp().
08413 { 08414 int rtp_code; 08415 struct ast_format_list fmt; 08416 08417 08418 if (debug) 08419 ast_verbose("Adding codec 0x%x (%s) to SDP\n", codec, ast_getformatname(codec)); 08420 if ((rtp_code = ast_rtp_lookup_code(p->rtp, 1, codec)) == -1) 08421 return; 08422 08423 if (p->rtp) { 08424 struct ast_codec_pref *pref = ast_rtp_codec_getpref(p->rtp); 08425 fmt = ast_codec_pref_getsize(pref, codec); 08426 } else /* I dont see how you couldn't have p->rtp, but good to check for and error out if not there like earlier code */ 08427 return; 08428 ast_str_append(m_buf, 0, " %d", rtp_code); 08429 ast_str_append(a_buf, 0, "a=rtpmap:%d %s/%d\r\n", rtp_code, 08430 ast_rtp_lookup_mime_subtype(1, codec, 08431 ast_test_flag(&p->flags[0], SIP_G726_NONSTANDARD) ? AST_RTP_OPT_G726_NONSTANDARD : 0), 08432 sample_rate); 08433 if (codec == AST_FORMAT_G729A) { 08434 /* Indicate that we don't support VAD (G.729 annex B) */ 08435 ast_str_append(a_buf, 0, "a=fmtp:%d annexb=no\r\n", rtp_code); 08436 } else if (codec == AST_FORMAT_G723_1) { 08437 /* Indicate that we don't support VAD (G.723.1 annex A) */ 08438 ast_str_append(a_buf, 0, "a=fmtp:%d annexa=no\r\n", rtp_code); 08439 } else if (codec == AST_FORMAT_ILBC) { 08440 /* Add information about us using only 20/30 ms packetization */ 08441 ast_str_append(a_buf, 0, "a=fmtp:%d mode=%d\r\n", rtp_code, fmt.cur_ms); 08442 } 08443 08444 if (fmt.cur_ms && (fmt.cur_ms < *min_packet_size)) 08445 *min_packet_size = fmt.cur_ms; 08446 08447 /* Our first codec packetization processed cannot be zero */ 08448 if ((*min_packet_size)==0 && fmt.cur_ms) 08449 *min_packet_size = fmt.cur_ms; 08450 }
| 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 8361 of file chan_sip.c.
References add_header(), add_header_contentLength(), and add_line().
Referenced by transmit_info_with_digit().
08362 { 08363 char tmp[256]; 08364 int event; 08365 if (mode) { 08366 /* Application/dtmf short version used by some implementations */ 08367 if (digit == '*') 08368 event = 10; 08369 else if (digit == '#') 08370 event = 11; 08371 else if ((digit >= 'A') && (digit <= 'D')) 08372 event = 12 + digit - 'A'; 08373 else 08374 event = atoi(&digit); 08375 snprintf(tmp, sizeof(tmp), "%d\r\n", event); 08376 add_header(req, "Content-Type", "application/dtmf"); 08377 add_header_contentLength(req, strlen(tmp)); 08378 add_line(req, tmp); 08379 } else { 08380 /* Application/dtmf-relay as documented by Cisco */ 08381 snprintf(tmp, sizeof(tmp), "Signal=%c\r\nDuration=%u\r\n", digit, duration); 08382 add_header(req, "Content-Type", "application/dtmf-relay"); 08383 add_header_contentLength(req, strlen(tmp)); 08384 add_line(req, tmp); 08385 } 08386 return 0; 08387 }
| static int add_header | ( | struct sip_request * | req, | |
| const char * | var, | |||
| const char * | value | |||
| ) | [static] |
Add header to SIP message.
Definition at line 7631 of file chan_sip.c.
References ast_log(), ast_str_append(), sip_request::data, find_alias(), sip_request::header, sip_request::headers, sip_request::len, sip_request::lines, LOG_WARNING, SIP_MAX_HEADERS, and ast_str::used.
07632 { 07633 if (req->headers == SIP_MAX_HEADERS) { 07634 ast_log(LOG_WARNING, "Out of SIP header space\n"); 07635 return -1; 07636 } 07637 07638 if (req->lines) { 07639 ast_log(LOG_WARNING, "Can't add more headers when lines have been added\n"); 07640 return -1; 07641 } 07642 07643 if (compactheaders) 07644 var = find_alias(var, var); 07645 07646 ast_str_append(&req->data, 0, "%s: %s\r\n", var, value); 07647 req->header[req->headers] = req->len; 07648 07649 req->len = req->data->used; 07650 req->headers++; 07651 07652 return 0; 07653 }
| static int add_header_contentLength | ( | struct sip_request * | req, | |
| int | len | |||
| ) | [static] |
Add 'Content-Length' header to SIP message.
Definition at line 7656 of file chan_sip.c.
References add_header().
Referenced by __transmit_response(), add_digit(), add_sdp(), add_text(), add_vidupdate(), transmit_invite(), transmit_notify_with_mwi(), transmit_notify_with_sipfrag(), transmit_register(), transmit_request(), transmit_request_with_auth(), transmit_response_with_allow(), transmit_response_with_auth(), transmit_response_with_date(), transmit_response_with_minse(), transmit_response_with_unsupported(), and transmit_state_notify().
07657 { 07658 char clen[10]; 07659 07660 snprintf(clen, sizeof(clen), "%d", len); 07661 return add_header(req, "Content-Length", clen); 07662 }
| static int add_line | ( | struct sip_request * | req, | |
| const char * | line | |||
| ) | [static] |
Add content (not header) to SIP message.
Definition at line 7665 of file chan_sip.c.
References ast_log(), ast_str_append(), sip_request::data, sip_request::len, sip_request::line, sip_request::lines, LOG_WARNING, SIP_MAX_LINES, and ast_str::used.
07666 { 07667 if (req->lines == SIP_MAX_LINES) { 07668 ast_log(LOG_WARNING, "Out of SIP line space\n"); 07669 return -1; 07670 } 07671 if (!req->lines) 07672 /* Add extra empty return */ 07673 req->len += ast_str_append(&req->data, 0, "\r\n"); 07674 req->line[req->lines] = req->len; 07675 ast_str_append(&req->data, 0, "%s", line); 07676 req->len = req->data->used; 07677 req->lines++; 07678 return 0; 07679 }
| static void add_noncodec_to_sdp | ( | const struct sip_pvt * | p, | |
| int | format, | |||
| int | sample_rate, | |||
| struct ast_str ** | m_buf, | |||
| struct ast_str ** | a_buf, | |||
| int | debug | |||
| ) | [static] |
Add RFC 2833 DTMF offer to SDP.
Definition at line 8536 of file chan_sip.c.
References AST_RTP_DTMF, ast_rtp_lookup_code(), ast_rtp_lookup_mime_subtype(), ast_str_append(), ast_verbose, and sip_pvt::rtp.
Referenced by add_sdp().
08539 { 08540 int rtp_code; 08541 08542 if (debug) 08543 ast_verbose("Adding non-codec 0x%x (%s) to SDP\n", format, ast_rtp_lookup_mime_subtype(0, format, 0)); 08544 if ((rtp_code = ast_rtp_lookup_code(p->rtp, 0, format)) == -1) 08545 return; 08546 08547 ast_str_append(m_buf, 0, " %d", rtp_code); 08548 ast_str_append(a_buf, 0, "a=rtpmap:%d %s/%d\r\n", rtp_code, 08549 ast_rtp_lookup_mime_subtype(0, format, 0), 08550 sample_rate); 08551 if (format == AST_RTP_DTMF) /* Indicate we support DTMF and FLASH... */ 08552 ast_str_append(a_buf, 0, "a=fmtp:%d 0-16\r\n", rtp_code); 08553 }
| static void add_peer_mailboxes | ( | struct sip_peer * | peer, | |
| const char * | value | |||
| ) | [static] |
Definition at line 21547 of file chan_sip.c.
References ast_calloc, ast_free, AST_LIST_INSERT_TAIL, ast_strdup, ast_strdupa, ast_strlen_zero(), context, sip_mailbox::entry, mailbox, sip_peer::mailboxes, mbox(), and strsep().
Referenced by build_peer().
21548 { 21549 char *next, *mbox, *context; 21550 21551 next = ast_strdupa(value); 21552 21553 while ((mbox = context = strsep(&next, ","))) { 21554 struct sip_mailbox *mailbox; 21555 21556 if (!(mailbox = ast_calloc(1, sizeof(*mailbox)))) 21557 continue; 21558 21559 strsep(&context, "@"); 21560 if (ast_strlen_zero(mbox)) { 21561 ast_free(mailbox); 21562 continue; 21563 } 21564 mailbox->mailbox = ast_strdup(mbox); 21565 mailbox->context = ast_strdup(context); 21566 21567 AST_LIST_INSERT_TAIL(&peer->mailboxes, mailbox, entry); 21568 } 21569 }
| static void add_peer_mwi_subs | ( | struct sip_peer * | peer | ) | [static] |
Definition at line 19166 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, sip_mailbox::entry, mailbox, sip_peer::mailboxes, mwi_event_cb(), and S_OR.
Referenced by build_peer(), and handle_request_subscribe().
19167 { 19168 struct sip_mailbox *mailbox; 19169 19170 AST_LIST_TRAVERSE(&peer->mailboxes, mailbox, entry) { 19171 mailbox->event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, peer, 19172 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox->mailbox, 19173 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, S_OR(mailbox->context, "default"), 19174 AST_EVENT_IE_END); 19175 } 19176 }
| static struct sip_auth * add_realm_authentication | ( | struct sip_auth * | authlist, | |
| const char * | configuration, | |||
| int | lineno | |||
| ) | [static] |
Add realm authentication in list.
Definition at line 21369 of file chan_sip.c.
References ast_calloc, ast_copy_string(), ast_debug, ast_log(), ast_strlen_zero(), ast_verb, LOG_WARNING, sip_auth::md5secret, sip_auth::next, sip_auth::realm, secret, strsep(), and sip_auth::username.
Referenced by build_peer().
21370 { 21371 char authcopy[256]; 21372 char *username=NULL, *realm=NULL, *secret=NULL, *md5secret=NULL; 21373 char *stringp; 21374 struct sip_auth *a, *b, *auth; 21375 21376 if (ast_strlen_zero(configuration)) 21377 return authlist; 21378 21379 ast_debug(1, "Auth config :: %s\n", configuration); 21380 21381 ast_copy_string(authcopy, configuration, sizeof(authcopy)); 21382 stringp = authcopy; 21383 21384 username = stringp; 21385 realm = strrchr(stringp, '@'); 21386 if (realm) 21387 *realm++ = '\0'; 21388 if (ast_strlen_zero(username) || ast_strlen_zero(realm)) { 21389 ast_log(LOG_WARNING, "Format for authentication entry is user[:secret]@realm at line %d\n", lineno); 21390 return authlist; 21391 } 21392 stringp = username; 21393 username = strsep(&stringp, ":"); 21394 if (username) { 21395 secret = strsep(&stringp, ":"); 21396 if (!secret) { 21397 stringp = username; 21398 md5secret = strsep(&stringp, "#"); 21399 } 21400 } 21401 if (!(auth = ast_calloc(1, sizeof(*auth)))) 21402 return authlist; 21403 21404 ast_copy_string(auth->realm, realm, sizeof(auth->realm)); 21405 ast_copy_string(auth->username, username, sizeof(auth->username)); 21406 if (secret) 21407 ast_copy_string(auth->secret, secret, sizeof(auth->secret)); 21408 if (md5secret) 21409 ast_copy_string(auth->md5secret, md5secret, sizeof(auth->md5secret)); 21410 21411 /* find the end of the list */ 21412 for (b = NULL, a = authlist; a ; b = a, a = a->next) 21413 ; 21414 if (b) 21415 b->next = auth; /* Add structure add end of list */ 21416 else 21417 authlist = auth; 21418 21419 ast_verb(3, "Added authentication for realm %s\n", realm); 21420 21421 return authlist; 21422 21423 }
| static void add_route | ( | struct sip_request * | req, | |
| struct sip_route * | route | |||
| ) | [static] |
Add route header into request per learned route.
Definition at line 7782 of file chan_sip.c.
References add_header(), ast_copy_string(), sip_route::hop, sip_route::next, and SIPBUFSIZE.
Referenced by reqprep().
07783 { 07784 char r[SIPBUFSIZE*2], *p; 07785 int n, rem = sizeof(r); 07786 07787 if (!route) 07788 return; 07789 07790 p = r; 07791 for (;route ; route = route->next) { 07792 n = strlen(route->hop); 07793 if (rem < n+3) /* we need room for ",<route>" */ 07794 break; 07795 if (p != r) { /* add a separator after fist route */ 07796 *p++ = ','; 07797 --rem; 07798 } 07799 *p++ = '<'; 07800 ast_copy_string(p, route->hop, rem); /* cannot fail */ 07801 p += n; 07802 *p++ = '>'; 07803 rem -= (n+2); 07804 } 07805 *p = '\0'; 07806 add_header(req, "Route", r); 07807 }
| 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 8604 of file chan_sip.c.
References add_codec_to_sdp(), add_header(), add_header_contentLength(), add_line(), add_noncodec_to_sdp(), add_tcodec_to_sdp(), add_vcodec_to_sdp(), ast_codec_pref_index(), ast_debug, AST_FAILURE, AST_FORMAT_AUDIO_MASK, AST_FORMAT_TEXT_MASK, AST_FORMAT_VIDEO_MASK, ast_getformatname_multiple(), ast_inet_ntoa(), ast_internal_timing_enabled(), ast_log(), ast_random(), AST_RTP_MAX, ast_str_alloca, ast_str_append(), ast_strlen_zero(), AST_SUCCESS, ast_test_flag, ast_udptl_get_local_max_datagram(), ast_udptl_get_us(), ast_verbose, buf, t38properties::capability, sip_request::debug, FALSE, sip_pvt::flags, get_our_media_address(), t38properties::jointcapability, sip_pvt::jointcapability, sip_pvt::jointnoncodeccapability, sip_pvt::lastrtprx, sip_pvt::lastrtptx, ast_str::len, sip_request::len, LOG_WARNING, sip_pvt::maxcallbitrate, sip_pvt::notext, sip_pvt::novideo, sip_pvt::ourip, sip_pvt::owner, t38properties::peercapability, sip_pvt::prefcodec, sip_pvt::prefs, sip_pvt::rtp, SDP_SAMPLE_RATE, sip_pvt::sessionid, sip_pvt::sessionversion, sip_debug_test_pvt(), SIP_PAGE2_CALL_ONHOLD, SIP_PAGE2_CALL_ONHOLD_INACTIVE, SIP_PAGE2_CALL_ONHOLD_ONEDIR, SIP_PAGE2_T38SUPPORT_RTP, SIPBUFSIZE, ast_str::str, sip_pvt::t38, t38_get_rate(), T38FAX_FILL_BIT_REMOVAL, T38FAX_RATE_MANAGEMENT_LOCAL_TCF, T38FAX_TRANSCODING_JBIG, T38FAX_TRANSCODING_MMR, T38FAX_UDP_EC_NONE, T38FAX_UDP_EC_REDUNDANCY, T38FAX_VERSION, T38FAX_VERSION_0, T38FAX_VERSION_1, t38properties::t38support, sip_pvt::tredirip, sip_pvt::trtp, TRUE, sip_pvt::udptl, sip_pvt::udptlredirip, ast_str::used, version, and sip_pvt::vrtp.
08605 { 08606 int len = 0; 08607 int alreadysent = 0; 08608 08609 struct sockaddr_in sin; 08610 struct sockaddr_in vsin; 08611 struct sockaddr_in tsin; 08612 struct sockaddr_in dest; 08613 struct sockaddr_in udptlsin; 08614 struct sockaddr_in vdest = { 0, }; 08615 struct sockaddr_in tdest = { 0, }; 08616 struct sockaddr_in udptldest = { 0, }; 08617 08618 /* SDP fields */ 08619 char *version = "v=0\r\n"; /* Protocol version */ 08620 char subject[256]; /* Subject of the session */ 08621 char owner[256]; /* Session owner/creator */ 08622 char connection[256]; /* Connection data */ 08623 char *session_time = "t=0 0\r\n"; /* Time the session is active */ 08624 char bandwidth[256] = ""; /* Max bitrate */ 08625 char *hold = ""; 08626 struct ast_str *m_audio = ast_str_alloca(256); /* Media declaration line for audio */ 08627 struct ast_str *m_video = ast_str_alloca(256); /* Media declaration line for video */ 08628 struct ast_str *m_text = ast_str_alloca(256); /* Media declaration line for text */ 08629 struct ast_str *m_modem = ast_str_alloca(256); /* Media declaration line for modem */ 08630 struct ast_str *a_audio = ast_str_alloca(1024); /* Attributes for audio */ 08631 struct ast_str *a_video = ast_str_alloca(1024); /* Attributes for video */ 08632 struct ast_str *a_text = ast_str_alloca(1024); /* Attributes for text */ 08633 struct ast_str *a_modem = ast_str_alloca(1024); /* Attributes for modem */ 08634 08635 int x; 08636 int capability = 0; 08637 int needaudio = FALSE; 08638 int needvideo = FALSE; 08639 int needtext = FALSE; 08640 int debug = sip_debug_test_pvt(p); 08641 int min_audio_packet_size = 0; 08642 int min_video_packet_size = 0; 08643 int min_text_packet_size = 0; 08644 08645 char codecbuf[SIPBUFSIZE]; 08646 char buf[SIPBUFSIZE]; 08647 08648 /* Set the SDP session name */ 08649 snprintf(subject, sizeof(subject), "s=%s\r\n", ast_strlen_zero(global_sdpsession) ? "-" : global_sdpsession); 08650 08651 if (!p->rtp) { 08652 ast_log(LOG_WARNING, "No way to add SDP without an RTP structure\n"); 08653 return AST_FAILURE; 08654 } 08655 /* XXX We should not change properties in the SIP dialog until 08656 we have acceptance of the offer if this is a re-invite */ 08657 08658 /* Set RTP Session ID and version */ 08659 if (!p->sessionid) { 08660 p->sessionid = (int)ast_random(); 08661 p->sessionversion = p->sessionid; 08662 } else { 08663 if (oldsdp == FALSE) 08664 p->sessionversion++; 08665 } 08666 08667 get_our_media_address(p, needvideo, &sin, &vsin, &tsin, &dest, &vdest); 08668 08669 snprintf(owner, sizeof(owner), "o=%s %d %d IN IP4 %s\r\n", ast_strlen_zero(global_sdpowner) ? "-" : global_sdpowner, p->sessionid, p->sessionversion, ast_inet_ntoa(dest.sin_addr)); 08670 snprintf(connection, sizeof(connection), "c=IN IP4 %s\r\n", ast_inet_ntoa(dest.sin_addr)); 08671 08672 if (add_audio) { 08673 capability = p->jointcapability; 08674 08675 /* XXX note, Video and Text are negated - 'true' means 'no' */ 08676 ast_debug(1, "** Our capability: %s Video flag: %s Text flag: %s\n", ast_getformatname_multiple(codecbuf, sizeof(codecbuf), capability), 08677 p->novideo ? "True" : "False", p->notext ? "True" : "False"); 08678 ast_debug(1, "** Our prefcodec: %s \n", ast_getformatname_multiple(codecbuf, sizeof(codecbuf), p->prefcodec)); 08679 08680 #ifdef WHEN_WE_HAVE_T38_FOR_OTHER_TRANSPORTS 08681 if (ast_test_flag(&p->t38.t38support, SIP_PAGE2_T38SUPPORT_RTP)) { 08682 ast_str_append(&m_audio, 0, " %d", 191); 08683 ast_str_append(&a_audio, 0, "a=rtpmap:%d %s/%d\r\n", 191, "t38", 8000); 08684 } 08685 #endif 08686 08687 /* Check if we need audio */ 08688 if (capability & AST_FORMAT_AUDIO_MASK) 08689 needaudio = TRUE; 08690 08691 /* Check if we need video in this call */ 08692 if ((capability & AST_FORMAT_VIDEO_MASK) && !p->novideo) { 08693 if (p->vrtp) { 08694 needvideo = TRUE; 08695 ast_debug(2, "This call needs video offers!\n"); 08696 } else 08697 ast_debug(2, "This call needs video offers, but there's no video support enabled!\n"); 08698 } 08699 08700 if (debug) 08701 ast_verbose("Audio is at %s port %d\n", ast_inet_ntoa(p->ourip.sin_addr), ntohs(sin.sin_port)); 08702 08703 /* Ok, we need video. Let's add what we need for video and set codecs. 08704 Video is handled differently than audio since we can not transcode. */ 08705 if (needvideo) { 08706 ast_str_append(&m_video, 0, "m=video %d RTP/AVP", ntohs(vdest.sin_port)); 08707 08708 /* Build max bitrate string */ 08709 if (p->maxcallbitrate) 08710 snprintf(bandwidth, sizeof(bandwidth), "b=CT:%d\r\n", p->maxcallbitrate); 08711 if (debug) 08712 ast_verbose("Video is at %s port %d\n", ast_inet_ntoa(p->ourip.sin_addr), ntohs(vsin.sin_port)); 08713 } 08714 08715 /* Check if we need text in this call */ 08716 if((capability & AST_FORMAT_TEXT_MASK) && !p->notext) { 08717 if (sipdebug_text) 08718 ast_verbose("We think we can do text\n"); 08719 if (p->trtp) { 08720 if (sipdebug_text) 08721 ast_verbose("And we have a text rtp object\n"); 08722 needtext = TRUE; 08723 ast_debug(2, "This call needs text offers! \n"); 08724 } else 08725 ast_debug(2, "This call needs text offers, but there's no text support enabled ! \n"); 08726 } 08727 08728 /* Ok, we need text. Let's add what we need for text and set codecs. 08729 Text is handled differently than audio since we can not transcode. */ 08730 if (needtext) { 08731 if (sipdebug_text) 08732 ast_verbose("Lets set up the text sdp\n"); 08733 /* Determine text destination */ 08734 if (p->tredirip.sin_addr.s_addr) { 08735 tdest.sin_addr = p->tredirip.sin_addr; 08736 tdest.sin_port = p->tredirip.sin_port; 08737 } else { 08738 tdest.sin_addr = p->ourip.sin_addr; 08739 tdest.sin_port = tsin.sin_port; 08740 } 08741 ast_str_append(&m_text, 0, "m=text %d RTP/AVP", ntohs(tdest.sin_port)); 08742 08743 if (debug) /* XXX should I use tdest below ? */ 08744 ast_verbose("Text is at %s port %d\n", ast_inet_ntoa(p->ourip.sin_addr), ntohs(tsin.sin_port)); 08745 08746 } 08747 08748 /* Start building generic SDP headers */ 08749 08750 /* We break with the "recommendation" and send our IP, in order that our 08751 peer doesn't have to ast_gethostbyname() us */ 08752 08753 ast_str_append(&m_audio, 0, "m=audio %d RTP/AVP", ntohs(dest.sin_port)); 08754 08755 if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD) == SIP_PAGE2_CALL_ONHOLD_ONEDIR) 08756 hold = "a=recvonly\r\n"; 08757 else if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD) == SIP_PAGE2_CALL_ONHOLD_INACTIVE) 08758 hold = "a=inactive\r\n"; 08759 else 08760 hold = "a=sendrecv\r\n"; 08761 08762 /* Now, start adding audio codecs. These are added in this order: 08763 - First what was requested by the calling channel 08764 - Then preferences in order from sip.conf device config for this peer/user 08765 - Then other codecs in capabilities, including video 08766 */ 08767 08768 /* Prefer the audio codec we were requested to use, first, no matter what 08769 Note that p->prefcodec can include video codecs, so mask them out 08770 */ 08771 if (capability & p->prefcodec) { 08772 int codec = p->prefcodec & AST_FORMAT_AUDIO_MASK; 08773 08774 add_codec_to_sdp(p, codec, SDP_SAMPLE_RATE(codec), 08775 &m_audio, &a_audio, 08776 debug, &min_audio_packet_size); 08777 alreadysent |= codec; 08778 } 08779 08780 /* Start by sending our preferred audio/video codecs */ 08781 for (x = 0; x < 32; x++) { 08782 int codec; 08783 08784 if (!(codec = ast_codec_pref_index(&p->prefs, x))) 08785 break; 08786 08787 if (!(capability & codec)) 08788 continue; 08789 08790 if (alreadysent & codec) 08791 continue; 08792 08793 add_codec_to_sdp(p, codec, SDP_SAMPLE_RATE(codec), 08794 &m_audio, &a_audio, 08795 debug, &min_audio_packet_size); 08796 alreadysent |= codec; 08797 } 08798 08799 /* Now send any other common audio and video codecs, and non-codec formats: */ 08800 for (x = 1; x <= (needtext ? AST_FORMAT_TEXT_MASK : (needvideo ? AST_FORMAT_VIDEO_MASK : AST_FORMAT_AUDIO_MASK)); x <<= 1) { 08801 if (!(capability & x)) /* Codec not requested */ 08802 continue; 08803 08804 if (alreadysent & x) /* Already added to SDP */ 08805 continue; 08806 08807 if (x & AST_FORMAT_AUDIO_MASK) 08808 add_codec_to_sdp(p, x, SDP_SAMPLE_RATE(x), 08809 &m_audio, &a_audio, debug, &min_audio_packet_size); 08810 else if (x & AST_FORMAT_VIDEO_MASK) 08811 add_vcodec_to_sdp(p, x, 90000, 08812 &m_video, &a_video, debug, &min_video_packet_size); 08813 else if (x & AST_FORMAT_TEXT_MASK) 08814 add_tcodec_to_sdp(p, x, 1000, 08815 &m_text, &a_text, debug, &min_text_packet_size); 08816 } 08817 08818 /* Now add DTMF RFC2833 telephony-event as a codec */ 08819 for (x = 1; x <= AST_RTP_MAX; x <<= 1) { 08820 if (!(p->jointnoncodeccapability & x)) 08821 continue; 08822 08823 add_noncodec_to_sdp(p, x, 8000, &m_audio, &a_audio, debug); 08824 } 08825 08826 ast_debug(3, "-- Done with adding codecs to SDP\n"); 08827 08828 if (!p->owner || !ast_internal_timing_enabled(p->owner)) 08829 ast_str_append(&a_audio, 0, "a=silenceSupp:off - - - -\r\n"); 08830 08831 if (min_audio_packet_size) 08832 ast_str_append(&a_audio, 0, "a=ptime:%d\r\n", min_audio_packet_size); 08833 08834 /* XXX don't think you can have ptime for video */ 08835 if (min_video_packet_size) 08836 ast_str_append(&a_video, 0, "a=ptime:%d\r\n", min_video_packet_size); 08837 08838 /* XXX don't think you can have ptime for text */ 08839 if (min_text_packet_size) 08840 ast_str_append(&a_text, 0, "a=ptime:%d\r\n", min_text_packet_size); 08841 } 08842 08843 if (add_t38) { 08844 ast_udptl_get_us(p->udptl, &udptlsin); 08845 08846 /* Determine T.38 UDPTL destination */ 08847 if (p->udptlredirip.sin_addr.s_addr) { 08848 udptldest.sin_port = p->udptlredirip.sin_port; 08849 udptldest.sin_addr = p->udptlredirip.sin_addr; 08850 } else { 08851 udptldest.sin_addr = p->ourip.sin_addr; 08852 udptldest.sin_port = udptlsin.sin_port; 08853 } 08854 08855 if (debug) 08856 ast_debug(1, "T.38 UDPTL is at %s port %d\n", ast_inet_ntoa(p->ourip.sin_addr), ntohs(udptlsin.sin_port)); 08857 08858 /* We break with the "recommendation" and send our IP, in order that our 08859 peer doesn't have to ast_gethostbyname() us */ 08860 08861 if (debug) { 08862 ast_debug(1, "Our T38 capability (%d), peer T38 capability (%d), joint capability (%d)\n", 08863 p->t38.capability, 08864 p->t38.peercapability, 08865 p->t38.jointcapability); 08866 } 08867 08868 ast_str_append(&m_modem, 0, "m=image %d udptl t38\r\n", ntohs(udptldest.sin_port)); 08869 08870 if ((p->t38.jointcapability & T38FAX_VERSION) == T38FAX_VERSION_0) 08871 ast_str_append(&a_modem, 0, "a=T38FaxVersion:0\r\n"); 08872 if ((p->t38.jointcapability & T38FAX_VERSION) == T38FAX_VERSION_1) 08873 ast_str_append(&a_modem, 0, "a=T38FaxVersion:1\r\n"); 08874 if ((x = t38_get_rate(p->t38.jointcapability))) 08875 ast_str_append(&a_modem, 0, "a=T38MaxBitRate:%d\r\n", x); 08876 if ((p->t38.jointcapability & T38FAX_FILL_BIT_REMOVAL) == T38FAX_FILL_BIT_REMOVAL) 08877 ast_str_append(&a_modem, 0, "a=T38FaxFillBitRemoval\r\n"); 08878 if ((p->t38.jointcapability & T38FAX_TRANSCODING_MMR) == T38FAX_TRANSCODING_MMR) 08879 ast_str_append(&a_modem, 0, "a=T38FaxTranscodingMMR\r\n"); 08880 if ((p->t38.jointcapability & T38FAX_TRANSCODING_JBIG) == T38FAX_TRANSCODING_JBIG) 08881 ast_str_append(&a_modem, 0, "a=T38FaxTranscodingJBIG\r\n"); 08882 ast_str_append(&a_modem, 0, "a=T38FaxRateManagement:%s\r\n", (p->t38.jointcapability & T38FAX_RATE_MANAGEMENT_LOCAL_TCF) ? "localTCF" : "transferredTCF"); 08883 x = ast_udptl_get_local_max_datagram(p->udptl); 08884 ast_str_append(&a_modem, 0, "a=T38FaxMaxBuffer:%d\r\n", x); 08885 ast_str_append(&a_modem, 0, "a=T38FaxMaxDatagram:%d\r\n", x); 08886 if (p->t38.jointcapability != T38FAX_UDP_EC_NONE) 08887 ast_str_append(&a_modem, 0, "a=T38FaxUdpEC:%s\r\n", (p->t38.jointcapability & T38FAX_UDP_EC_REDUNDANCY) ? "t38UDPRedundancy" : "t38UDPFEC"); 08888 } 08889 08890 if (m_audio->len - m_audio->used < 2 || m_video->len - m_video->used < 2 || 08891 m_text->len - m_text->used < 2 || a_text->len - a_text->used < 2 || 08892 a_audio->len - a_audio->used < 2 || a_video->len - a_video->used < 2) 08893 ast_log(LOG_WARNING, "SIP SDP may be truncated due to undersized buffer!!\n"); 08894 08895 if (needaudio) 08896 ast_str_append(&m_audio, 0, "\r\n"); 08897 if (needvideo) 08898 ast_str_append(&m_video, 0, "\r\n"); 08899 if (needtext) 08900 ast_str_append(&m_text, 0, "\r\n"); 08901 08902 len = strlen(version) + strlen(subject) + strlen(owner) + 08903 strlen(connection) + strlen(session_time); 08904 if (needaudio) 08905 len += m_audio->used + a_audio->used + strlen(hold); 08906 if (needvideo) /* only if video response is appropriate */ 08907 len += m_video->used + a_video->used + strlen(bandwidth) + strlen(hold); 08908 if (needtext) /* only if text response is appropriate */ 08909 len += m_text->used + a_text->used + strlen(hold); 08910 if (add_t38) 08911 len += m_modem->used + a_modem->used; 08912 08913 add_header(resp, "Content-Type", "application/sdp"); 08914 add_header_contentLength(resp, len); 08915 add_line(resp, version); 08916 add_line(resp, owner); 08917 add_line(resp, subject); 08918 add_line(resp, connection); 08919 if (needvideo) /* only if video response is appropriate */ 08920 add_line(resp, bandwidth); 08921 add_line(resp, session_time); 08922 if (needaudio) { 08923 add_line(resp, m_audio->str); 08924 add_line(resp, a_audio->str); 08925 add_line(resp, hold); 08926 } 08927 if (needvideo) { /* only if video response is appropriate */ 08928 add_line(resp, m_video->str); 08929 add_line(resp, a_video->str); 08930 add_line(resp, hold); /* Repeat hold for the video stream */ 08931 } 08932 if (needtext) { /* only if text response is appropriate */ 08933 add_line(resp, m_text->str); 08934 add_line(resp, a_text->str); 08935 add_line(resp, hold); /* Repeat hold for the text stream */ 08936 } 08937 if (add_t38) { 08938 add_line(resp, m_modem->str); 08939 add_line(resp, a_modem->str); 08940 } 08941 08942 /* Update lastrtprx when we send our SDP */ 08943 p->lastrtprx = p->lastrtptx = time(NULL); /* XXX why both ? */ 08944 08945 ast_debug(3, "Done building SDP. Settling with this capability: %s\n", ast_getformatname_multiple(buf, SIPBUFSIZE, capability)); 08946 08947 return AST_SUCCESS; 08948 }
| 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 21305 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(), domain::list, and LOG_WARNING.
21306 { 21307 struct domain *d; 21308 21309 if (ast_strlen_zero(domain)) { 21310 ast_log(LOG_WARNING, "Zero length domain.\n"); 21311 return 1; 21312 } 21313 21314 if (!(d = ast_calloc(1, sizeof(*d)))) 21315 return 0; 21316 21317 ast_copy_string(d->domain, domain, sizeof(d->domain)); 21318 21319 if (!ast_strlen_zero(context)) 21320 ast_copy_string(d->context, context, sizeof(d->context)); 21321 21322 d->mode = mode; 21323 21324 AST_LIST_LOCK(&domain_list); 21325 AST_LIST_INSERT_TAIL(&domain_list, d, list); 21326 AST_LIST_UNLOCK(&domain_list); 21327 21328 if (sipdebug) 21329 ast_debug(1, "Added local SIP domain '%s'\n", domain); 21330 21331 return 1; 21332 }
| static void add_tcodec_to_sdp | ( | const struct sip_pvt * | p, | |
| int | codec, | |||
| int | sample_rate, | |||
| 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 8476 of file chan_sip.c.
References AST_FORMAT_T140, AST_FORMAT_T140RED, ast_getformatname(), ast_rtp_lookup_code(), ast_rtp_lookup_mime_subtype(), ast_str_append(), ast_verbose, and sip_pvt::trtp.
Referenced by add_sdp().
08479 { 08480 int rtp_code; 08481 08482 if (!p->trtp) 08483 return; 08484 08485 if (debug) 08486 ast_verbose("Adding text codec 0x%x (%s) to SDP\n", codec, ast_getformatname(codec)); 08487 08488 if ((rtp_code = ast_rtp_lookup_code(p->trtp, 1, codec)) == -1) 08489 return; 08490 08491 ast_str_append(m_buf, 0, " %d", rtp_code); 08492 ast_str_append(a_buf, 0, "a=rtpmap:%d %s/%d\r\n", rtp_code, 08493 ast_rtp_lookup_mime_subtype(1, codec, 0), sample_rate); 08494 /* Add fmtp code here */ 08495 08496 if (codec == AST_FORMAT_T140RED) { 08497 ast_str_append(a_buf, 0, "a=fmtp:%d %d/%d/%d\r\n", rtp_code, 08498 ast_rtp_lookup_code(p->trtp, 1, AST_FORMAT_T140), 08499 ast_rtp_lookup_code(p->trtp, 1, AST_FORMAT_T140), 08500 ast_rtp_lookup_code(p->trtp, 1, AST_FORMAT_T140)); 08501 08502 } 08503 }
| static int add_text | ( | struct sip_request * | req, | |
| const char * | text | |||
| ) | [static] |
Add text body to SIP message.
Definition at line 8348 of file chan_sip.c.
References add_header(), add_header_contentLength(), and add_line().
Referenced by transmit_message_with_text().
08349 { 08350 /* XXX Convert \n's to \r\n's XXX */ 08351 add_header(req, "Content-Type", "text/plain;charset=UTF-8"); 08352 add_header_contentLength(req, strlen(text)); 08353 add_line(req, text); 08354 return 0; 08355 }
| static struct ast_variable* add_var | ( | const char * | buf, | |
| struct ast_variable * | list | |||
| ) | [static] |
implement the setvar config line
Definition at line 21456 of file chan_sip.c.
References ast_strdupa, ast_variable_new(), and ast_variable::next.
Referenced by build_device(), and build_peer().
21457 { 21458 struct ast_variable *tmpvar = NULL; 21459 char *varname = ast_strdupa(buf), *varval = NULL; 21460 21461 if ((varval = strchr(varname, '='))) { 21462 *varval++ = '\0'; 21463 if ((tmpvar = ast_variable_new(varname, varval, ""))) { 21464 tmpvar->next = list; 21465 list = tmpvar; 21466 } 21467 } 21468 return list; 21469 }
| static void add_vcodec_to_sdp | ( | const struct sip_pvt * | p, | |
| int | codec, | |||
| int | sample_rate, | |||
| 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 8454 of file chan_sip.c.
References ast_getformatname(), ast_rtp_lookup_code(), ast_rtp_lookup_mime_subtype(), ast_str_append(), ast_verbose, and sip_pvt::vrtp.
Referenced by add_sdp().
08457 { 08458 int rtp_code; 08459 08460 if (!p->vrtp) 08461 return; 08462 08463 if (debug) 08464 ast_verbose("Adding video codec 0x%x (%s) to SDP\n", codec, ast_getformatname(codec)); 08465 08466 if ((rtp_code = ast_rtp_lookup_code(p->vrtp, 1, codec)) == -1) 08467 return; 08468 08469 ast_str_append(m_buf, 0, " %d", rtp_code); 08470 ast_str_append(a_buf, 0, "a=rtpmap:%d %s/%d\r\n", rtp_code, 08471 ast_rtp_lookup_mime_subtype(1, codec, 0), sample_rate); 08472 /* Add fmtp code here */ 08473 }
| static int add_vidupdate | ( | struct sip_request * | req | ) | [static] |
add XML encoded media control with update
Definition at line 8391 of file chan_sip.c.
References add_header(), add_header_contentLength(), and add_line().
Referenced by transmit_info_with_vidupdate().
08392 { 08393 const char *xml_is_a_huge_waste_of_space = 08394 "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\r\n" 08395 " <media_control>\r\n" 08396 " <vc_primitive>\r\n" 08397 " <to_encoder>\r\n" 08398 " <picture_fast_update>\r\n" 08399 " </picture_fast_update>\r\n" 08400 " </to_encoder>\r\n" 08401 " </vc_primitive>\r\n" 08402 " </media_control>\r\n"; 08403 add_header(req, "Content-Type", "application/media_control+xml"); 08404 add_header_contentLength(req, strlen(xml_is_a_huge_waste_of_space)); 08405 add_line(req, xml_is_a_huge_waste_of_space); 08406 return 0; 08407 }
| static void append_date | ( | struct sip_request * | req | ) | [static] |
Append date to SIP message.
Definition at line 8295 of file chan_sip.c.
References add_header().
Referenced by build_csv_record(), transmit_invite(), transmit_response_with_date(), transmit_response_with_minse(), and transmit_response_with_unsupported().
08296 { 08297 char tmpdat[256]; 08298 struct tm tm; 08299 time_t t = time(NULL); 08300 08301 gmtime_r(&t, &tm); 08302 strftime(tmpdat, sizeof(tmpdat), "%a, %d %b %Y %T GMT", &tm); 08303 add_header(req, "Date", tmpdat); 08304 }
| static void append_history_full | ( | struct sip_pvt * | p, | |
| const char * | fmt, | |||
| ... | ||||
| ) | [static] |
Append to SIP dialog history with arg list.
Definition at line 3004 of file chan_sip.c.
References append_history_va(), and sip_pvt::do_history.
03005 { 03006 va_list ap; 03007 03008 if (!p) 03009 return; 03010 03011 if (!p->do_history && !recordhistory && !dumphistory) 03012 return; 03013 03014 va_start(ap, fmt); 03015 append_history_va(p, fmt, ap); 03016 va_end(ap); 03017 03018 return; 03019 }
| 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 2977 of file chan_sip.c.
References ast_calloc, ast_free, AST_LIST_INSERT_TAIL, AST_LIST_REMOVE_HEAD, buf, sip_history::list, MAX_HISTORY_ENTRIES, and strsep().
Referenced by append_history_full().
02978 { 02979 char buf[80], *c = buf; /* max history length */ 02980 struct sip_history *hist; 02981 int l; 02982 02983 vsnprintf(buf, sizeof(buf), fmt, ap); 02984 strsep(&c, "\r\n"); /* Trim up everything after \r or \n */ 02985 l = strlen(buf) + 1; 02986 if (!(hist = ast_calloc(1, sizeof(*hist) + l))) 02987 return; 02988 if (!p->history && !(p->history = ast_calloc(1, sizeof(*p->history)))) { 02989 ast_free(hist); 02990 return; 02991 } 02992 memcpy(hist->event, buf, l); 02993 if (p->history_entries == MAX_HISTORY_ENTRIES) { 02994 struct sip_history *oldest; 02995 oldest = AST_LIST_REMOVE_HEAD(p->history, list); 02996 p->history_entries--; 02997 ast_free(oldest); 02998 } 02999 AST_LIST_INSERT_TAIL(p->history, hist, list); 03000 p->history_entries++; 03001 }
| 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 17075 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 chan.
Referenced by attempt_transfer(), and handle_invite_replaces().
17076 { 17077 if (chan && chan->_state == AST_STATE_UP) { 17078 if (ast_test_flag(chan, AST_FLAG_MOH)) 17079 ast_moh_stop(chan); 17080 else if (chan->generatordata) 17081 ast_deactivate_generator(chan); 17082 } 17083 }
| static void ast_sip_ouraddrfor | ( | struct in_addr * | them, | |
| struct sockaddr_in * | us | |||
| ) | [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 externip or can get away with our internal bindaddr 'us' is always overwritten.
Definition at line 2926 of file chan_sip.c.
References ast_apply_ha(), ast_debug, ast_inet_ntoa(), ast_log(), ast_ouraddrfor(), ast_parse_arg(), AST_SENSE_ALLOW, ast_stun_request(), externexpire, externhost, externrefresh, localaddr, LOG_NOTICE, LOG_WARNING, PARSE_INADDR, and sipsock.
Referenced by manager_sipnotify(), sip_alloc(), sip_cli_notify(), sip_poke_peer(), sip_request_call(), sip_send_mwi_to_peer(), transmit_register(), and transmit_response_using_temp().
02927 { 02928 struct sockaddr_in theirs; 02929 /* Set want_remap to non-zero if we want to remap 'us' to an externally 02930 * reachable IP address and port. This is done if: 02931 * 1. we have a localaddr list (containing 'internal' addresses marked 02932 * as 'deny', so ast_apply_ha() will return AST_SENSE_DENY on them, 02933 * and AST_SENSE_ALLOW on 'external' ones); 02934 * 2. either stunaddr or externip is set, so we know what to use as the 02935 * externally visible address; 02936 * 3. the remote address, 'them', is external; 02937 * 4. the address returned by ast_ouraddrfor() is 'internal' (AST_SENSE_DENY 02938 * when passed to ast_apply_ha() so it does need to be remapped. 02939 * This fourth condition is checked later. 02940 */ 02941 int want_remap; 02942 02943 *us = internip; /* starting guess for the internal address */ 02944 /* now ask the system what would it use to talk to 'them' */ 02945 ast_ouraddrfor(them, &us->sin_addr); 02946 theirs.sin_addr = *them; 02947 02948 want_remap = localaddr && 02949 (externip.sin_addr.s_addr || stunaddr.sin_addr.s_addr) && 02950 ast_apply_ha(localaddr, &theirs) == AST_SENSE_ALLOW ; 02951 02952 if (want_remap && 02953 (!global_matchexterniplocally || !ast_apply_ha(localaddr, us)) ) { 02954 /* if we used externhost or stun, see if it is time to refresh the info */ 02955 if (externexpire && time(NULL) >= externexpire) { 02956 if (stunaddr.sin_addr.s_addr) { 02957 ast_stun_request(sipsock, &stunaddr, NULL, &externip); 02958 } else { 02959 if (ast_parse_arg(externhost, PARSE_INADDR, &externip)) 02960 ast_log(LOG_NOTICE, "Warning: Re-lookup of '%s' failed!\n", externhost); 02961 } 02962 externexpire = time(NULL) + externrefresh; 02963 } 02964 if (externip.sin_addr.s_addr) 02965 *us = externip; 02966 else 02967 ast_log(LOG_WARNING, "stun failed\n"); 02968 ast_debug(1, "Target address %s is not local, substituting externip\n", 02969 ast_inet_ntoa(*(struct in_addr *)&them->s_addr)); 02970 } else if (bindaddr.sin_addr.s_addr) { 02971 /* no remapping, but we bind to a specific address, so use it. */ 02972 *us = bindaddr; 02973 } 02974 }
Attempt transfer of SIP call This fix for attended transfers on a local PBX.
Definition at line 17087 of file chan_sip.c.
References ast_channel::_state, ast_channel_masquerade(), ast_debug, ast_log(), ast_quiet_chan(), AST_SOFTHANGUP_DEV, ast_softhangup_nolock(), ast_state2str(), sip_dual::chan1, sip_dual::chan2, LOG_NOTICE, LOG_WARNING, and ast_channel::name.
17088 { 17089 int res = 0; 17090 struct ast_channel *peera = NULL, 17091 *peerb = NULL, 17092 *peerc = NULL, 17093 *peerd = NULL; 17094 17095 17096 /* We will try to connect the transferee with the target and hangup 17097 all channels to the transferer */ 17098 ast_debug(4, "Sip transfer:--------------------\n"); 17099 if (transferer->chan1) 17100 ast_debug(4, "-- Transferer to PBX channel: %s State %s\n", transferer->chan1->name, ast_state2str(transferer->chan1->_state)); 17101 else 17102 ast_debug(4, "-- No transferer first channel - odd??? \n"); 17103 if (target->chan1) 17104 ast_debug(4, "-- Transferer to PBX second channel (target): %s State %s\n", target->chan1->name, ast_state2str(target->chan1->_state)); 17105 else 17106 ast_debug(4, "-- No target first channel ---\n"); 17107 if (transferer->chan2) 17108 ast_debug(4, "-- Bridged call to transferee: %s State %s\n", transferer->chan2->name, ast_state2str(transferer->chan2->_state)); 17109 else 17110 ast_debug(4, "-- No bridged call to transferee\n"); 17111 if (target->chan2) 17112 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)"); 17113 else 17114 ast_debug(4, "-- No target second channel ---\n"); 17115 ast_debug(4, "-- END Sip transfer:--------------------\n"); 17116 if (transferer->chan2) { /* We have a bridge on the transferer's channel */ 17117 peera = transferer->chan1; /* Transferer - PBX -> transferee channel * the one we hangup */ 17118 peerb = target->chan1; /* Transferer - PBX -> target channel - This will get lost in masq */ 17119 peerc = transferer->chan2; /* Asterisk to Transferee */ 17120 peerd = target->chan2; /* Asterisk to Target */ 17121 ast_debug(3, "SIP transfer: Four channels to handle\n"); 17122 } else if (target->chan2) { /* Transferer has no bridge (IVR), but transferee */ 17123 peera = target->chan1; /* Transferer to PBX -> target channel */ 17124 peerb = transferer->chan1; /* Transferer to IVR*/ 17125 peerc = target->chan2; /* Asterisk to Target */ 17126 peerd = transferer->chan2; /* Nothing */ 17127 ast_debug(3, "SIP transfer: Three channels to handle\n"); 17128 } 17129 17130 if (peera && peerb && peerc && (peerb != peerc)) { 17131 ast_quiet_chan(peera); /* Stop generators */ 17132 ast_quiet_chan(peerb); 17133 ast_quiet_chan(peerc); 17134 if (peerd) 17135 ast_quiet_chan(peerd); 17136 17137 ast_debug(4, "SIP transfer: trying to masquerade %s into %s\n", peerc->name, peerb->name); 17138 if (ast_channel_masquerade(peerb, peerc)) { 17139 ast_log(LOG_WARNING, "Failed to masquerade %s into %s\n", peerb->name, peerc->name); 17140 res = -1; 17141 } else 17142 ast_debug(4, "SIP transfer: Succeeded to masquerade channels.\n"); 17143 return res; 17144 } else { 17145 ast_log(LOG_NOTICE, "SIP Transfer attempted with no appropriate bridged calls to transfer\n"); 17146 if (transferer->chan1) 17147 ast_softhangup_nolock(transferer->chan1, AST_SOFTHANGUP_DEV); 17148 if (target->chan1) 17149 ast_softhangup_nolock(target->chan1, AST_SOFTHANGUP_DEV); 17150 return -1; 17151 } 17152 return 0; 17153 }
| 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 10330 of file chan_sip.c.
References ast_verbose, PROXY_AUTH, and WWW_AUTH.
Referenced by check_auth(), do_proxy_auth(), do_register_auth(), and transmit_request_with_auth().
10331 { 10332 if (code == WWW_AUTH) { /* 401 */ 10333 *header = "WWW-Authenticate"; 10334 *respheader = "Authorization"; 10335 } else if (code == PROXY_AUTH) { /* 407 */ 10336 *header = "Proxy-Authenticate"; 10337 *respheader = "Proxy-Authorization"; 10338 } else { 10339 ast_verbose("-- wrong response code %d\n", code); 10340 *header = *respheader = "Invalid"; 10341 } 10342 }
| 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 4544 of file chan_sip.c.
References append_history, ast_channel_trylock, ast_channel_unlock, AST_CONTROL_CONGESTION, ast_queue_control(), dialog_unref(), sip_pvt_lock, and sip_pvt_unlock.
04545 { 04546 struct sip_pvt *p = (struct sip_pvt *)arg; 04547 04548 sip_pvt_lock(p); 04549 p->initid = -1; /* event gone, will not be rescheduled */ 04550 if (p->owner) { 04551 /* XXX fails on possible deadlock */ 04552 if (!ast_channel_trylock(p->owner)) { 04553 append_history(p, "Cong", "Auto-congesting (timer)"); 04554 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 04555 ast_channel_unlock(p->owner); 04556 } 04557 } 04558 sip_pvt_unlock(p); 04559 dialog_unref(p, "unreffing arg passed into auto_congest callback (p->initid)"); 04560 return 0; 04561 }
| static void build_callid_pvt | ( | struct sip_pvt * | pvt | ) | [static] |
Build SIP Call-ID value for a non-REGISTER transaction.
Definition at line 6163 of file chan_sip.c.
References ast_inet_ntoa(), ast_string_field_build, buf, sip_pvt::callid, sip_pvt::fromdomain, generate_random_string(), sip_pvt::ourip, and S_OR.
Referenced by manager_sipnotify(), sip_alloc(), sip_cli_notify(), sip_poke_peer(), sip_request_call(), and sip_send_mwi_to_peer().
06164 { 06165 char buf[33]; 06166 06167 const char *host = S_OR(pvt->fromdomain, ast_inet_ntoa(pvt->ourip.sin_addr)); 06168 06169 ast_string_field_build(pvt, callid, "%s@%s", generate_random_string(buf, sizeof(buf)), host); 06170 06171 }
| static void build_callid_registry | ( | struct sip_registry * | reg, | |
| struct in_addr | ourip, | |||
| const char * | fromdomain | |||
| ) | [static] |
Build SIP Call-ID value for a REGISTER transaction.
Definition at line 6174 of file chan_sip.c.
References ast_inet_ntoa(), ast_string_field_build, buf, sip_pvt::callid, generate_random_string(), and S_OR.
Referenced by transmit_register().
06175 { 06176 char buf[33]; 06177 06178 const char *host = S_OR(fromdomain, ast_inet_ntoa(ourip)); 06179 06180 ast_string_field_build(reg, callid, "%s@%s", generate_random_string(buf, sizeof(buf)), host); 06181 }
| static void build_contact | ( | struct sip_pvt * | p | ) | [static] |
Build contact header - the contact header we send out.
Definition at line 9140 of file chan_sip.c.
References ast_inet_ntoa(), ast_string_field_build, ast_strlen_zero(), sip_pvt::exten, get_transport(), sip_pvt::ourip, ourport, sip_standard_port(), SIP_TRANSPORT_UDP, sip_pvt::socket, and sip_socket::type.
Referenced by check_user_full(), handle_request_invite(), handle_request_options(), handle_request_subscribe(), initreqprep(), register_verify(), and transmit_register().
09141 { 09142 09143 int ourport = ntohs(p->ourip.sin_port); 09144 09145 if (p->socket.type & SIP_TRANSPORT_UDP) { 09146 if (!sip_standard_port(p->socket.type, ourport)) 09147 ast_string_field_build(p, our_contact, "<sip:%s%s%s:%d>", p->exten, ast_strlen_zero(p->exten) ? "" : "@", ast_inet_ntoa(p->ourip.sin_addr), ourport); 09148 else 09149 ast_string_field_build(p, our_contact, "<sip:%s%s%s>", p->exten, ast_strlen_zero(p->exten) ? "" : "@", ast_inet_ntoa(p->ourip.sin_addr)); 09150 } else 09151 ast_string_field_build(p, our_contact, "<sip:%s%s%s:%d;transport=%s>", p->exten, ast_strlen_zero(p->exten) ? "" : "@", ast_inet_ntoa(p->ourip.sin_addr), ourport, get_transport(p->socket.type)); 09152 }
| static struct sip_peer * build_peer | ( | const char * | name, | |
| struct ast_variable * | v, | |||
| struct ast_variable * | alt, | |||
| int | realtime | |||
| ) | [static] |
Build peer from configuration (file or realtime static/dynamic).
< The first transport listed should be used for outgoing
Definition at line 21572 of file chan_sip.c.
References __set_address_from_contact(), sip_peer::accountcode, add_peer_mailboxes(), add_peer_mwi_subs(), add_realm_authentication(), add_var(), sip_peer::addr, sip_peer::allowtransfer, sip_peer::amaflags, ao2_t_alloc, ao2_t_find, asprintf, ast_append_ha(), ast_atomic_fetchadd_int(), ast_callerid_split(), ast_cdr_amaflags2int(), ast_copy_flags, ast_copy_string(), ast_debug, ast_dnsmgr_lookup(), ast_free, ast_free_ha(), ast_get_group(), ast_get_ip(), ast_get_time_t(), ast_inet_ntoa(), AST_LIST_EMPTY, ast_log(), ast_parse_allow_disallow(), ast_parse_caller_presentation(), AST_SCHED_DEL_UNREF, ast_set2_flag, ast_skip_blanks(), ast_str_alloca, ast_str_append(), ast_str_set(), ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_true(), ast_variables_destroy(), sip_peer::auth, sip_peer::autoframing, sip_peer::busy_level, sip_peer::call_limit, sip_peer::callgroup, sip_peer::callingpres, sip_peer::capability, sip_peer::chanvars, sip_peer::cid_name, sip_peer::cid_num, clear_realm_authentication(), sip_peer::contactha, sip_peer::context, sip_peer::defaddr, DEFAULT_MAXMS, sip_peer::deprecated_username, destroy_association(), sip_peer::dnsmgr, errno, sip_peer::expire, FALSE, ast_flags::flags, sip_peer::flags, format, sip_peer::fromdomain, sip_peer::fromuser, sip_peer::fullcontact, get_transport(), global_contact_ha, global_flags, sip_peer::ha, handle_common_options(), sip_peer::host_dynamic, sip_settings::ignore_regexpire, inet_aton(), sip_peer::is_realtime, sip_peer::language, sip_peer::lastms, sip_peer::lastmsgssent, ast_variable::lineno, LOG_ERROR, LOG_NOTICE, LOG_WARNING, sip_peer::mailboxes, sip_peer::maxcallbitrate, MAXHOSTNAMELEN, sip_peer::maxms, sip_peer::md5secret, sip_peer::mohinterpret, sip_peer::mohsuggest, ast_variable::name, sip_peer::name, ast_variable::next, OBJ_POINTER, OBJ_UNLINK, sip_peer::outboundproxy, sip_peer::parkinglot, sip_peer::pickupgroup, sip_socket::port, sip_peer::prefs, proxy_allocate(), sip_peer::qualifyfreq, ref_peer(), reg_source_db(), sip_peer::regexten, sip_peer::rt_fromcontact, sip_peer::rtpholdtimeout, sip_peer::rtpkeepalive, sip_peer::rtptimeout, sched, sip_peer::secret, set_peer_defaults(), sip_cfg, sip_destroy_peer_fn(), SIP_PAGE2_ALLOWSUBSCRIBE, SIP_PAGE2_REGISTERTRYING, SIP_PAGE2_RTCACHEFRIENDS, SIP_PAGE2_SUBSCRIBEMWIONLY, sip_poke_peer(), sip_register(), sip_send_mwi_to_peer(), SIP_TRANSPORT_TCP, SIP_TRANSPORT_TLS, SIP_TRANSPORT_UDP, SIP_TYPE_PEER, SIP_TYPE_USER, SIP_USEREQPHONE, sip_peer::socket, srvlookup, sip_st_cfg::st_max_se, sip_st_cfg::st_min_se, sip_st_cfg::st_mode_oper, sip_st_cfg::st_ref, STANDARD_SIP_PORT, STANDARD_TLS_PORT, sip_peer::stimer, ast_str::str, str2stmode(), str2strefresher(), strsep(), sip_peer::subscribecontext, sip_peer::the_mark, sip_peer::timer_b, sip_peer::timer_t1, sip_peer::tohost, TRANSFER_CLOSED, TRANSFER_OPENFORALL, sip_peer::transports, TRUE, sip_socket::type, sip_peer::type, unref_peer(), ast_str::used, sip_peer::username, ast_variable::value, and sip_peer::vmexten.
21573 { 21574 struct sip_peer *peer = NULL; 21575 struct ast_ha *oldha = NULL; 21576 int found=0; 21577 int firstpass=1; 21578 int format=0; /* Ama flags */ 21579 time_t regseconds = 0; 21580 struct ast_flags peerflags[2] = {{(0)}}; 21581 struct ast_flags mask[2] = {{(0)}}; 21582 char callback[256] = ""; 21583 struct sip_peer tmp_peer; 21584 const char *srvlookup = NULL; 21585 static int deprecation_warning = 1; 21586 struct ast_str *fullcontact = ast_str_alloca(512); 21587 21588 if (!realtime || ast_test_flag(&global_flags[1], SIP_PAGE2_RTCACHEFRIENDS)) { 21589 /* Note we do NOT use find_peer here, to avoid realtime recursion */ 21590 /* We also use a case-sensitive comparison (unlike find_peer) so 21591 that case changes made to the peer name will be properly handled 21592 during reload 21593 */ 21594 ast_copy_string(tmp_peer.name, name, sizeof(tmp_peer.name)); 21595 peer = ao2_t_find(peers, &tmp_peer, OBJ_POINTER | OBJ_UNLINK, "find and unlink peer from peers table"); 21596 } 21597 21598 if (peer) { 21599 /* Already in the list, remove it and it will be added back (or FREE'd) */ 21600 found++; 21601 if (!(peer->the_mark)) 21602 firstpass = 0; 21603 } else { 21604 if (!(peer = ao2_t_alloc(sizeof(*peer), sip_destroy_peer_fn, "allocate a peer struct"))) 21605 return NULL; 21606 21607 if (realtime && !ast_test_flag(&global_flags[1], SIP_PAGE2_RTCACHEFRIENDS)) { 21608 ast_atomic_fetchadd_int(&rpeerobjs, 1); 21609 ast_debug(3, "-REALTIME- peer built. Name: %s. Peer objects: %d\n", name, rpeerobjs); 21610 } else 21611 ast_atomic_fetchadd_int(&speerobjs, 1); 21612 } 21613 21614 /* Note that our peer HAS had its reference count increased */ 21615 if (firstpass) { 21616 peer->lastmsgssent = -1; 21617 oldha = peer->ha; 21618 peer->ha = NULL; 21619 set_peer_defaults(peer); /* Set peer defaults */ 21620 peer->type = 0; 21621 } 21622 if (!found && name) 21623 ast_copy_string(peer->name, name, sizeof(peer->name)); 21624 21625 /* If we have channel variables, remove them (reload) */ 21626 if (peer->chanvars) { 21627 ast_variables_destroy(peer->chanvars); 21628 peer->chanvars = NULL; 21629 /* XXX should unregister ? */ 21630 } 21631 21632 /* If we have realm authentication information, remove them (reload) */ 21633 clear_realm_authentication(peer->auth); 21634 peer->auth = NULL; 21635 peer->transports = 0; 21636 peer->socket.type = 0; 21637 21638 for (; v || ((v = alt) && !(alt=NULL)); v = v->next) { 21639 if (handle_common_options(&peerflags[0], &mask[0], v)) 21640 continue; 21641 if (!strcasecmp(v->name, "transport") && !ast_strlen_zero(v->value)) { 21642 char *val = ast_strdupa(v->value); 21643 char *trans; 21644 21645 while ((trans = strsep(&val, ","))) { 21646 trans = ast_skip_blanks(trans); 21647 21648 if (!strncasecmp(trans, "udp", 3)) 21649 peer->transports |= SIP_TRANSPORT_UDP; 21650 else if (!strncasecmp(trans, "tcp", 3)) 21651 peer->transports |= SIP_TRANSPORT_TCP; 21652 else if (!strncasecmp(trans, "tls", 3)) 21653 peer->transports |= SIP_TRANSPORT_TLS; 21654 else 21655 ast_log(LOG_NOTICE, "'%s' is not a valid transport type. if no other is specified, udp will be used.\n", trans); 21656 21657 if (!peer->socket.type) /*!< The first transport listed should be used for outgoing */ 21658 peer->socket.type = peer->transports; 21659 } 21660 } else if (realtime && !strcasecmp(v->name, "regseconds")) { 21661 ast_get_time_t(v->value, ®seconds, 0, NULL); 21662 } else if (realtime && !strcasecmp(v->name, "lastms")) { 21663 sscanf(v->value, "%d", &peer->lastms); 21664 } else if (realtime && !strcasecmp(v->name, "ipaddr") && !ast_strlen_zero(v->value) ) { 21665 inet_aton(v->value, &(peer->addr.sin_addr)); 21666 } else if (realtime && !strcasecmp(v->name, "name")) 21667 ast_copy_string(peer->name, v->value, sizeof(peer->name)); 21668 else if (realtime && !strcasecmp(v->name, "fullcontact")) { 21669 /* Reconstruct field, because realtime separates our value at the ';' */ 21670 if (fullcontact->used > 0) { 21671 ast_str_append(&fullcontact, 0, ";%s", v->value); 21672 } else { 21673 ast_str_set(&fullcontact, 0, "%s", v->value); 21674 } 21675 } else if (!strcasecmp(v->name, "type")) { 21676 if (!strcasecmp(v->value, "peer")) { 21677 peer->type |= SIP_TYPE_PEER; 21678 } else if (!strcasecmp(v->value, "user")) { 21679 peer->type |= SIP_TYPE_USER; 21680 } else if (!strcasecmp(v->value, "friend")) { 21681 peer->type = SIP_TYPE_USER | SIP_TYPE_PEER; 21682 } 21683 } else if (!strcasecmp(v->name, "secret")) 21684 ast_copy_string(peer->secret, v->value, sizeof(peer->secret)); 21685 else if (!strcasecmp(v->name, "md5secret")) 21686 ast_copy_string(peer->md5secret, v->value, sizeof(peer->md5secret)); 21687 else if (!strcasecmp(v->name, "auth")) 21688 peer->auth = add_realm_authentication(peer->auth, v->value, v->lineno); 21689 else if (!strcasecmp(v->name, "callerid")) { 21690 ast_callerid_split(v->value, peer->cid_name, sizeof(peer->cid_name), peer->cid_num, sizeof(peer->cid_num)); 21691 } else if (!strcasecmp(v->name, "fullname")) { 21692 ast_copy_string(peer->cid_name, v->value, sizeof(peer->cid_name)); 21693 } else if (!strcasecmp(v->name, "cid_number")) { 21694 ast_copy_string(peer->cid_num, v->value, sizeof(peer->cid_num)); 21695 } else if (!strcasecmp(v->name, "context")) { 21696 ast_copy_string(peer->context, v->value, sizeof(peer->context)); 21697 } else if (!strcasecmp(v->name, "subscribecontext")) { 21698 ast_copy_string(peer->subscribecontext, v->value, sizeof(peer->subscribecontext)); 21699 } else if (!strcasecmp(v->name, "fromdomain")) { 21700 ast_copy_string(peer->fromdomain, v->value, sizeof(peer->fromdomain)); 21701 } else if (!strcasecmp(v->name, "usereqphone")) { 21702 ast_set2_flag(&peer->flags[0], ast_true(v->value), SIP_USEREQPHONE); 21703 } else if (!strcasecmp(v->name, "fromuser")) { 21704 ast_copy_string(peer->fromuser, v->value, sizeof(peer->fromuser)); 21705 } else if (!strcasecmp(v->name, "outboundproxy")) { 21706 char *port, *next, *force, *proxyname; 21707 int forceopt = FALSE; 21708 /* Set peer channel variable */ 21709 next = proxyname = ast_strdupa(v->value); 21710 if ((port = strchr(proxyname, ':'))) { 21711 *port++ = '\0'; 21712 next = port; 21713 } 21714 if ((force = strchr(next, ','))) { 21715 *force++ = '\0'; 21716 forceopt = strcmp(force, "force"); 21717 } 21718 /* Allocate proxy object */ 21719 peer->outboundproxy = proxy_allocate(proxyname, port, forceopt); 21720 } else if (!strcasecmp(v->name, "host")) { 21721 if (!strcasecmp(v->value, "dynamic")) { 21722 /* They'll register with us */ 21723 if (!found || !peer->host_dynamic) { 21724 /* Initialize stuff if this is a new peer, or if it used to 21725 * not be dynamic before the reload. */ 21726 memset(&peer->addr.sin_addr, 0, 4); 21727 if (peer->addr.sin_port) { 21728 /* If we've already got a port, make it the default rather than absolute */ 21729 peer->defaddr.sin_port = peer->addr.sin_port; 21730 peer->addr.sin_port = 0; 21731 } 21732 } 21733 peer->host_dynamic = TRUE; 21734 } else { 21735 /* Non-dynamic. Make sure we become that way if we're not */ 21736 AST_SCHED_DEL_UNREF(sched, peer->expire, 21737 unref_peer(peer, "removing register expire ref")); 21738 peer->host_dynamic = FALSE; 21739 srvlookup = v->value; 21740 if (global_dynamic_exclude_static) { 21741 int err = 0; 21742 global_contact_ha = ast_append_ha("deny", (char *)ast_inet_ntoa(peer->addr.sin_addr), global_contact_ha, &err); 21743 if (err) { 21744 ast_log(LOG_ERROR, "Bad ACL entry in configuration line %d : %s\n", v->lineno, v->value); 21745 } 21746 } 21747 } 21748 } else if (!strcasecmp(v->name, "defaultip")) { 21749 if (ast_get_ip(&peer->defaddr, v->value)) { 21750 unref_peer(peer, "unref_peer: from build_peer defaultip"); 21751 return NULL; 21752 } 21753 } else if (!strcasecmp(v->name, "permit") || !strcasecmp(v->name, "deny")) { 21754 int ha_error = 0; 21755 21756 peer->ha = ast_append_ha(v->name, v->value, peer->ha, &ha_error); 21757 if (ha_error) 21758 ast_log(LOG_ERROR, "Bad ACL entry in configuration line %d : %s\n", v->lineno, v->value); 21759 } else if (!strcasecmp(v->name, "contactpermit") || !strcasecmp(v->name, "contactdeny")) { 21760 int ha_error = 0; 21761 peer->contactha = ast_append_ha(v->name + 7, v->value, peer->contactha, &ha_error); 21762 if (ha_error) { 21763 ast_log(LOG_ERROR, "Bad ACL entry in configuration line %d : %s\n", v->lineno, v->value); 21764 } 21765 } else if (!strcasecmp(v->name, "port")) { 21766 if (!realtime && peer->host_dynamic) 21767 peer->defaddr.sin_port = htons(atoi(v->value)); 21768 else 21769 peer->addr.sin_port = htons(atoi(v->value)); 21770 } else if (!strcasecmp(v->name, "callingpres")) { 21771 peer->callingpres = ast_parse_caller_presentation(v->value); 21772 if (peer->callingpres == -1) 21773 peer->callingpres = atoi(v->value); 21774 } else if (!strcasecmp(v->name, "username") || !strcmp(v->name, "defaultuser")) { /* "username" is deprecated */ 21775 ast_copy_string(peer->username, v->value, sizeof(peer->username)); 21776 if (!strcasecmp(v->name, "username")) { 21777 if (deprecation_warning) { 21778 ast_log(LOG_NOTICE, "The 'username' field for sip peers has been deprecated in favor of the term 'defaultuser'\n"); 21779 deprecation_warning = 0; 21780 } 21781 peer->deprecated_username = 1; 21782 } 21783 } else if (!strcasecmp(v->name, "language")) { 21784 ast_copy_string(peer->language, v->value, sizeof(peer->language)); 21785 } else if (!strcasecmp(v->name, "regexten")) { 21786 ast_copy_string(peer->regexten, v->value, sizeof(peer->regexten)); 21787 } else if (!strcasecmp(v->name, "callbackextension")) { 21788 ast_copy_string(callback, v->value, sizeof(callback)); 21789 } else if (!strcasecmp(v->name, "callcounter")) { 21790 peer->call_limit = ast_true(v->value) ? 999 : 0; 21791 } else if (!strcasecmp(v->name, "call-limit")) { 21792 peer->call_limit = atoi(v->value); 21793 if (peer->call_limit < 0) 21794 peer->call_limit = 0; 21795 } else if (!strcasecmp(v->name, "busylevel")) { 21796 peer->busy_level = atoi(v->value); 21797 if (peer->busy_level < 0) 21798 peer->busy_level = 0; 21799 } else if (!strcasecmp(v->name, "amaflags")) { 21800 format = ast_cdr_amaflags2int(v->value); 21801 if (format < 0) { 21802 ast_log(LOG_WARNING, "Invalid AMA Flags for peer: %s at line %d\n", v->value, v->lineno); 21803 } else { 21804 peer->amaflags = format; 21805 } 21806 } else if (!strcasecmp(v->name, "accountcode")) { 21807 ast_copy_string(peer->accountcode, v->value, sizeof(peer->accountcode)); 21808 } else if (!strcasecmp(v->name, "mohinterpret")) { 21809 ast_copy_string(peer->mohinterpret, v->value, sizeof(peer->mohinterpret)); 21810 } else if (!strcasecmp(v->name, "mohsuggest")) { 21811 ast_copy_string(peer->mohsuggest, v->value, sizeof(peer->mohsuggest)); 21812 } else if (!strcasecmp(v->name, "parkinglot")) { 21813 ast_copy_string(peer->parkinglot, v->value, sizeof(peer->parkinglot)); 21814 } else if (!strcasecmp(v->name, "mailbox")) { 21815 add_peer_mailboxes(peer, v->value); 21816 } else if (!strcasecmp(v->name, "hasvoicemail")) { 21817 /* People expect that if 'hasvoicemail' is set, that the mailbox will 21818 * be also set, even if not explicitly specified. */ 21819 if (ast_true(v->value) && AST_LIST_EMPTY(&peer->mailboxes)) { 21820 add_peer_mailboxes(peer, name); 21821 } 21822 } else if (!strcasecmp(v->name, "subscribemwi")) { 21823 ast_set2_flag(&peer->flags[1], ast_true(v->value), SIP_PAGE2_SUBSCRIBEMWIONLY); 21824 } else if (!strcasecmp(v->name, "vmexten")) { 21825 ast_copy_string(peer->vmexten, v->value, sizeof(peer->vmexten)); 21826 } else if (!strcasecmp(v->name, "callgroup")) { 21827 peer->callgroup = ast_get_group(v->value); 21828 } else if (!strcasecmp(v->name, "allowtransfer")) { 21829 peer->allowtransfer = ast_true(v->value) ? TRANSFER_OPENFORALL : TRANSFER_CLOSED; 21830 } else if (!strcasecmp(v->name, "pickupgroup")) { 21831 peer->pickupgroup = ast_get_group(v->value); 21832 } else if (!strcasecmp(v->name, "allow")) { 21833 int error = ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, TRUE); 21834 if (error) 21835 ast_log(LOG_WARNING, "Codec configuration errors found in line %d : %s = %s\n", v->lineno, v->name, v->value); 21836 } else if (!strcasecmp(v->name, "disallow")) { 21837 int error = ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, FALSE); 21838 if (error) 21839 ast_log(LOG_WARNING, "Codec configuration errors found in line %d : %s = %s\n", v->lineno, v->name, v->value); 21840 } else if (!strcasecmp(v->name, "registertrying")) { 21841 ast_set2_flag(&peer->flags[1], ast_true(v->value), SIP_PAGE2_REGISTERTRYING); 21842 } else if (!strcasecmp(v->name, "autoframing")) { 21843 peer->autoframing = ast_true(v->value); 21844 } else if (!strcasecmp(v->name, "rtptimeout")) { 21845 if ((sscanf(v->value, "%d", &peer->rtptimeout) != 1) || (peer->rtptimeout < 0)) { 21846 ast_log(LOG_WARNING, "'%s' is not a valid RTP hold time at line %d. Using default.\n", v->value, v->lineno); 21847 peer->rtptimeout = global_rtptimeout; 21848 } 21849 } else if (!strcasecmp(v->name, "rtpholdtimeout")) { 21850 if ((sscanf(v->value, "%d", &peer->rtpholdtimeout) != 1) || (peer->rtpholdtimeout < 0)) { 21851 ast_log(LOG_WARNING, "'%s' is not a valid RTP hold time at line %d. Using default.\n", v->value, v->lineno); 21852 peer->rtpholdtimeout = global_rtpholdtimeout; 21853 } 21854 } else if (!strcasecmp(v->name, "rtpkeepalive")) { 21855 if ((sscanf(v->value, "%d", &peer->rtpkeepalive) != 1) || (peer->rtpkeepalive < 0)) { 21856 ast_log(LOG_WARNING, "'%s' is not a valid RTP keepalive time at line %d. Using default.\n", v->value, v->lineno); 21857 peer->rtpkeepalive = global_rtpkeepalive; 21858 } 21859 } else if (!strcasecmp(v->name, "timert1")) { 21860 if ((sscanf(v->value, "%d", &peer->timer_t1) != 1) || (peer->timer_t1 < 0)) { 21861 ast_log(LOG_WARNING, "'%s' is not a valid T1 time at line %d. Using default.\n", v->value, v->lineno); 21862 peer->timer_t1 = global_t1; 21863 } 21864 /* Note that Timer B is dependent upon T1 and MUST NOT be lower 21865 * than T1 * 64, according to RFC 3261, Section 17.1.1.2 */ 21866 if (peer->timer_b < peer->timer_t1 * 64) { 21867 peer->timer_b = peer->timer_t1 * 64; 21868 } 21869 } else if (!strcasecmp(v->name, "timerb")) { 21870 if ((sscanf(v->value, "%d", &peer->timer_b) != 1) || (peer->timer_b < 0)) { 21871 ast_log(LOG_WARNING, "'%s' is not a valid Timer B time at line %d. Using default.\n", v->value, v->lineno); 21872 peer->timer_b = global_timer_b; 21873 } 21874 if (peer->timer_b < peer->timer_t1 * 64) { 21875 static int warning = 0; 21876 if (warning++ % 20 == 0) { 21877 ast_log(LOG_WARNING, "Timer B has been set lower than recommended. (RFC 3261, 17.1.1.2)\n"); 21878 } 21879 } 21880 } else if (!strcasecmp(v->name, "setvar")) { 21881 peer->chanvars = add_var(v->value, peer->chanvars); 21882 } else if (!strcasecmp(v->name, "qualify")) { 21883 if (!strcasecmp(v->value, "no")) { 21884 peer->maxms = 0; 21885 } else if (!strcasecmp(v->value, "yes")) { 21886 peer->maxms = default_qualify ? default_qualify : DEFAULT_MAXMS; 21887 } else if (sscanf(v->value, "%d", &peer->maxms) != 1) { 21888 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); 21889 peer->maxms = 0; 21890 } 21891 if (realtime && !ast_test_flag(&global_flags[1], SIP_PAGE2_RTCACHEFRIENDS) && peer->maxms > 0) { 21892 /* This would otherwise cause a network storm, where the 21893 * qualify response refreshes the peer from the database, 21894 * which in turn causes another qualify to be sent, ad 21895 * infinitum. */ 21896 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); 21897 peer->maxms = 0; 21898 } 21899 } else if (!strcasecmp(v->name, "qualifyfreq")) { 21900 int i; 21901 if (sscanf(v->value, "%d", &i) == 1) 21902 peer->qualifyfreq = i * 1000; 21903 else { 21904 ast_log(LOG_WARNING, "Invalid qualifyfreq number '%s' at line %d of %s\n", v->value, v->lineno, config); 21905 peer->qualifyfreq = global_qualifyfreq; 21906 } 21907 } else if (!strcasecmp(v->name, "maxcallbitrate")) { 21908 peer->maxcallbitrate = atoi(v->value); 21909 if (peer->maxcallbitrate < 0) 21910 peer->maxcallbitrate = default_maxcallbitrate; 21911 } else if (!strcasecmp(v->name, "session-timers")) { 21912 int i = (int) str2stmode(v->value); 21913 if (i < 0) { 21914 ast_log(LOG_WARNING, "Invalid session-timers '%s' at line %d of %s\n", v->value, v->lineno, config); 21915 peer->stimer.st_mode_oper = global_st_mode; 21916 } else { 21917 peer->stimer.st_mode_oper = i; 21918 } 21919 } else if (!strcasecmp(v->name, "session-expires")) { 21920 if (sscanf(v->value, "%d", &peer->stimer.st_max_se) != 1) { 21921 ast_log(LOG_WARNING, "Invalid session-expires '%s' at line %d of %s\n", v->value, v->lineno, config); 21922 peer->stimer.st_max_se = global_max_se; 21923 } 21924 } else if (!strcasecmp(v->name, "session-minse")) { 21925 if (sscanf(v->value, "%d", &peer->stimer.st_min_se) != 1) { 21926 ast_log(LOG_WARNING, "Invalid session-minse '%s' at line %d of %s\n", v->value, v->lineno, config); 21927 peer->stimer.st_min_se = global_min_se; 21928 } 21929 if (peer->stimer.st_min_se < 90) { 21930 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); 21931 peer->stimer.st_min_se = global_min_se; 21932 } 21933 } else if (!strcasecmp(v->name, "session-refresher")) { 21934 int i = (int) str2strefresher(v->value); 21935 if (i < 0) { 21936 ast_log(LOG_WARNING, "Invalid session-refresher '%s' at line %d of %s\n", v->value, v->lineno, config); 21937 peer->stimer.st_ref = global_st_refresher; 21938 } else { 21939 peer->stimer.st_ref = i; 21940 } 21941 } 21942 } 21943 21944 if (!peer->socket.type) { 21945 peer->transports = SIP_TRANSPORT_UDP; 21946 peer->socket.type = SIP_TRANSPORT_UDP; 21947 } 21948 21949 if (fullcontact->used > 0) { 21950 ast_copy_string(peer->fullcontact, fullcontact->str, sizeof(peer->fullcontact)); 21951 peer->rt_fromcontact = TRUE; 21952 /* We have a hostname in the fullcontact, but if we don't have an 21953 * address listed on the entry (or if it's 'dynamic'), then we need to 21954 * parse the entry to obtain the IP address, so a dynamic host can be 21955 * contacted immediately after reload (as opposed to waiting for it to 21956 * register once again). */ 21957 /* XXX May need to revisit the final argument; does the realtime DB store whether 21958 * the original contact was over TLS or not? XXX */ 21959 __set_address_from_contact(fullcontact->str, &peer->addr, 0); 21960 } 21961 21962 if (srvlookup && peer->dnsmgr == NULL) { 21963 char transport[MAXHOSTNAMELEN]; 21964 char _srvlookup[MAXHOSTNAMELEN]; 21965 char *params; 21966 21967 ast_copy_string(_srvlookup, srvlookup, sizeof(_srvlookup)); 21968 if ((params = strchr(_srvlookup, ';'))) { 21969 *params++ = '\0'; 21970 } 21971 21972 snprintf(transport, sizeof(transport), "_sip._%s", get_transport(peer->socket.type)); 21973 21974 if (ast_dnsmgr_lookup(_srvlookup, &peer->addr, &peer->dnsmgr, global_srvlookup ? transport : NULL)) { 21975 unref_peer(peer, "getting rid of a peer pointer"); 21976 return NULL; 21977 } 21978 21979 ast_copy_string(peer->tohost, srvlookup, sizeof(peer->tohost)); 21980 } 21981 21982 if (!peer->addr.sin_port) 21983 peer->addr.sin_port = htons(((peer->socket.type & SIP_TRANSPORT_TLS) ? STANDARD_TLS_PORT : STANDARD_SIP_PORT)); 21984 21985 if (!peer->socket.port) 21986 peer->socket.port = htons(((peer->socket.type & SIP_TRANSPORT_TLS) ? STANDARD_TLS_PORT : STANDARD_SIP_PORT)); 21987 21988 if (!sip_cfg.ignore_regexpire && peer->host_dynamic && realtime) { 21989 time_t nowtime = time(NULL); 21990 21991 if ((nowtime - regseconds) > 0) { 21992 destroy_association(peer); 21993 memset(&peer->addr, 0, sizeof(peer->addr)); 21994 peer->lastms = -1; 21995 ast_debug(1, "Bah, we're expired (%d/%d/%d)!\n", (int)(nowtime - regseconds), (int)regseconds, (int)nowtime); 21996 } 21997 } 21998 21999 /* Startup regular pokes */ 22000 if (realtime && peer->lastms > 0) { 22001 ref_peer(peer, "schedule qualify"); 22002 sip_poke_peer(peer, 0); 22003 } 22004 22005 ast_copy_flags(&peer->flags[0], &peerflags[0], mask[0].flags); 22006 ast_copy_flags(&peer->flags[1], &peerflags[1], mask[1].flags); 22007 if (ast_test_flag(&peer->flags[1], SIP_PAGE2_ALLOWSUBSCRIBE)) 22008 global_allowsubscribe = TRUE; /* No global ban any more */ 22009 if (!found && peer->host_dynamic && !peer->is_realtime) 22010 reg_source_db(peer); 22011 22012 /* If they didn't request that MWI is sent *only* on subscribe, go ahead and 22013 * subscribe to it now. */ 22014 if (!ast_test_flag(&peer->flags[1], SIP_PAGE2_SUBSCRIBEMWIONLY) && 22015 !AST_LIST_EMPTY(&peer->mailboxes)) { 22016 add_peer_mwi_subs(peer); 22017 /* Send MWI from the event cache only. This is so we can send initial 22018 * MWI if app_voicemail got loaded before chan_sip. If it is the other 22019 * way, then we will get events when app_voicemail gets loaded. */ 22020 sip_send_mwi_to_peer(peer, NULL, 1); 22021 } 22022 peer->the_mark = 0; 22023 22024 ast_free_ha(oldha); 22025 if (!ast_strlen_zero(callback)) { /* build string from peer info */ 22026 char *reg_string; 22027 22028 if (asprintf(®_string, "%s:%s@%s/%s", peer->username, peer->secret, peer->tohost, callback) < 0) { 22029 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno)); 22030 } else if (reg_string) { 22031 sip_register(reg_string, 0); /* XXX TODO: count in registry_count */ 22032 ast_free(reg_string); 22033 } 22034 } 22035 return peer; 22036 }
| static int build_reply_digest | ( | struct sip_pvt * | p, | |
| int | method, | |||
| char * | digest, | |||
| int | digest_len | |||
| ) | [static] |
Build reply digest.
Definition at line 15362 of file chan_sip.c.
References append_history, ast_copy_string(), ast_debug, ast_inet_ntoa(), ast_log(), ast_md5_hash(), ast_random(), ast_strlen_zero(), authl, sip_pvt::authname, sip_pvt::callid, sip_pvt::domain, find_realm_authentication(), LOG_DEBUG, sip_auth::md5secret, sip_registry::md5secret, sip_pvt::nonce, sip_pvt::noncecount, sip_pvt::opaque, sip_registry::opaque, sip_pvt::peerauth, sip_pvt::peermd5secret, sip_pvt::peername, sip_pvt::peersecret, sip_pvt::qop, sip_pvt::realm, sip_pvt::sa, sip_auth::secret, secret, sip_methods, text, sip_pvt::uri, sip_auth::username, sip_pvt::username, and sip_registry::username.
Referenced by reply_digest(), transmit_register(), and transmit_request_with_auth().
15363 { 15364 char a1[256]; 15365 char a2[256]; 15366 char a1_hash[256]; 15367 char a2_hash[256]; 15368 char resp[256]; 15369 char resp_hash[256]; 15370 char uri[256]; 15371 char opaque[256] = ""; 15372 char cnonce[80]; 15373 const char *username; 15374 const char *secret; 15375 const char *md5secret; 15376 struct sip_auth *auth = NULL; /* Realm authentication */ 15377 15378 if (!ast_strlen_zero(p->domain)) 15379 ast_copy_string(uri, p->domain, sizeof(uri)); 15380 else if (!ast_strlen_zero(p->uri)) 15381 ast_copy_string(uri, p->uri, sizeof(uri)); 15382 else 15383 snprintf(uri, sizeof(uri), "sip:%s@%s", p->username, ast_inet_ntoa(p->sa.sin_addr)); 15384 15385 snprintf(cnonce, sizeof(cnonce), "%08lx", ast_random()); 15386 15387 /* Check if we have separate auth credentials */ 15388 if(!(auth = find_realm_authentication(p->peerauth, p->realm))) /* Start with peer list */ 15389 auth = find_realm_authentication(authl, p->realm); /* If not, global list */ 15390 15391 if (auth) { 15392 ast_log(LOG_DEBUG, "use realm [%s] from peer [%s][%s]\n", auth->username, p->peername, p->username); 15393 username = auth->username; 15394 secret = auth->secret; 15395 md5secret = auth->md5secret; 15396 if (sipdebug) 15397 ast_debug(1, "Using realm %s authentication for call %s\n", p->realm, p->callid); 15398 } else { 15399 /* No authentication, use peer or register= config */ 15400 username = p->authname; 15401 secret = p->peersecret; 15402 md5secret = p->peermd5secret; 15403 } 15404 if (ast_strlen_zero(username)) /* We have no authentication */ 15405 return -1; 15406 15407 /* Calculate SIP digest response */ 15408 snprintf(a1, sizeof(a1), "%s:%s:%s", username, p->realm, secret); 15409 snprintf(a2, sizeof(a2), "%s:%s", sip_methods[method].text, uri); 15410 if (!ast_strlen_zero(md5secret)) 15411 ast_copy_string(a1_hash, md5secret, sizeof(a1_hash)); 15412 else 15413 ast_md5_hash(a1_hash, a1); 15414 ast_md5_hash(a2_hash, a2); 15415 15416 p->noncecount++; 15417 if (!ast_strlen_zero(p->qop)) 15418 snprintf(resp, sizeof(resp), "%s:%s:%08x:%s:%s:%s", a1_hash, p->nonce, p->noncecount, cnonce, "auth", a2_hash); 15419 else 15420 snprintf(resp, sizeof(resp), "%s:%s:%s", a1_hash, p->nonce, a2_hash); 15421 ast_md5_hash(resp_hash, resp); 15422 15423 /* only include the opaque string if it's set */ 15424 if (!ast_strlen_zero(p->opaque)) { 15425 snprintf(opaque, sizeof(opaque), ", opaque=\"%s\"", p->opaque); 15426 } 15427 15428 /* XXX We hard code our qop to "auth" for now. XXX */ 15429 if (!ast_strlen_zero(p->qop)) 15430 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); 15431 else 15432 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); 15433 15434 append_history(p, "AuthResp", "Auth response sent for %s in realm %s - nc %d", username, p->realm, p->noncecount); 15435 15436 return 0; 15437 }
| 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 10780 of file chan_sip.c.
References __get_header(), ast_copy_string(), ast_debug, ast_malloc, ast_strlen_zero(), free_old_route(), get_header(), sip_route::hop, sip_request::len, list_route(), sip_route::next, sip_pvt::route, sip_pvt::route_persistant, and sip_debug_test_pvt().
Referenced by build_user_routes(), handle_request_invite(), and handle_response_invite().
10781 { 10782 struct sip_route *thishop, *head, *tail; 10783 int start = 0; 10784 int len; 10785 const char *rr, *contact, *c; 10786 10787 /* Once a persistant route is set, don't fool with it */ 10788 if (p->route && p->route_persistant) { 10789 ast_debug(1, "build_route: Retaining previous route: <%s>\n", p->route->hop); 10790 return; 10791 } 10792 10793 if (p->route) { 10794 free_old_route(p->route); 10795 p->route = NULL; 10796 } 10797 10798 /* We only want to create the route set the first time this is called */ 10799 p->route_persistant = 1; 10800 10801 /* Build a tailq, then assign it to p->route when done. 10802 * If backwards, we add entries from the head so they end up 10803 * in reverse order. However, we do need to maintain a correct 10804 * tail pointer because the contact is always at the end. 10805 */ 10806 head = NULL; 10807 tail = head; 10808 /* 1st we pass through all the hops in any Record-Route headers */ 10809 for (;;) { 10810 /* Each Record-Route header */ 10811 rr = __get_header(req, "Record-Route", &start); 10812 if (*rr == '\0') 10813 break; 10814 for (; (rr = strchr(rr, '<')) ; rr += len) { /* Each route entry */ 10815 ++rr; 10816 len = strcspn(rr, ">") + 1; 10817 /* Make a struct route */ 10818 if ((thishop = ast_malloc(sizeof(*thishop) + len))) { 10819 /* ast_calloc is not needed because all fields are initialized in this block */ 10820 ast_copy_string(thishop->hop, rr, len); 10821 ast_debug(2, "build_route: Record-Route hop: <%s>\n", thishop->hop); 10822 /* Link in */ 10823 if (backwards) { 10824 /* Link in at head so they end up in reverse order */ 10825 thishop->next = head; 10826 head = thishop; 10827 /* If this was the first then it'll be the tail */ 10828 if (!tail) 10829 tail = thishop; 10830 } else { 10831 thishop->next = NULL; 10832 /* Link in at the end */ 10833 if (tail) 10834 tail->next = thishop; 10835 else 10836 head = thishop; 10837 tail = thishop; 10838 } 10839 } 10840 } 10841 } 10842 10843 /* Only append the contact if we are dealing with a strict router */ 10844 if (!head || (!ast_strlen_zero(head->hop) && strstr(head->hop, ";lr") == NULL) ) { 10845 /* 2nd append the Contact: if there is one */ 10846 /* Can be multiple Contact headers, comma separated values - we just take the first */ 10847 contact = get_header(req, "Contact"); 10848 if (!ast_strlen_zero(contact)) { 10849 ast_debug(2, "build_route: Contact hop: %s\n", contact); 10850 /* Look for <: delimited address */ 10851 c = strchr(contact, '<'); 10852 if (c) { 10853 /* Take to > */ 10854 ++c; 10855 len = strcspn(c, ">") + 1; 10856 } else { 10857 /* No <> - just take the lot */ 10858 c = contact; 10859 len = strlen(contact) + 1; 10860 } 10861 if ((thishop = ast_malloc(sizeof(*thishop) + len))) { 10862 /* ast_calloc is not needed because all fields are initialized in this block */ 10863 ast_copy_string(thishop->hop, c, len); 10864 thishop->next = NULL; 10865 /* Goes at the end */ 10866 if (tail) 10867 tail->next = thishop; 10868 else 10869 head = thishop; 10870 } 10871 } 10872 } 10873 10874 /* Store as new route */ 10875 p->route = head; 10876 10877 /* For debugging dump what we ended up with */ 10878 if (sip_debug_test_pvt(p)) 10879 list_route(p->route); 10880 }
| static void build_rpid | ( | struct sip_pvt * | p | ) | [static] |
Build the Remote Party-ID & From using callingpres options.
Definition at line 9155 of file chan_sip.c.
References ast_inet_ntoa(), ast_log(), 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_string_field_build, ast_string_field_set, ast_strlen_zero(), buf, sip_pvt::callingpres, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, FALSE, sip_pvt::fromdomain, sip_pvt::fromuser, LOG_WARNING, sip_pvt::ourip, sip_pvt::owner, sip_pvt::rpid, sip_pvt::rpid_from, S_OR, sip_pvt::tag, and TRUE.
Referenced by initreqprep().
09156 { 09157 int send_pres_tags = TRUE; 09158 const char *privacy=NULL; 09159 const char *screen=NULL; 09160 char buf[256]; 09161 const char *clid = default_callerid; 09162 const char *clin = NULL; 09163 const char *fromdomain; 09164 09165 if (!ast_strlen_zero(p->rpid) || !ast_strlen_zero(p->rpid_from)) 09166 return; 09167 09168 if (p->owner && p->owner->cid.cid_num) 09169 clid = p->owner->cid.cid_num; 09170 if (p->owner && p->owner->cid.cid_name) 09171 clin = p->owner->cid.cid_name; 09172 if (ast_strlen_zero(clin)) 09173 clin = clid; 09174 09175 switch (p->callingpres) { 09176 case AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED: 09177 privacy = "off"; 09178 screen = "no"; 09179 break; 09180 case AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN: 09181 privacy = "off"; 09182 screen = "yes"; 09183 break; 09184 case AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN: 09185 privacy = "off"; 09186 screen = "no"; 09187 break; 09188 case AST_PRES_ALLOWED_NETWORK_NUMBER: 09189 privacy = "off"; 09190 screen = "yes"; 09191 break; 09192 case AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED: 09193 privacy = "full"; 09194 screen = "no"; 09195 break; 09196 case AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN: 09197 privacy = "full"; 09198 screen = "yes"; 09199 break; 09200 case AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN: 09201 privacy = "full"; 09202 screen = "no"; 09203 break; 09204 case AST_PRES_PROHIB_NETWORK_NUMBER: 09205 privacy = "full"; 09206 screen = "yes"; 09207 break; 09208 case AST_PRES_NUMBER_NOT_AVAILABLE: 09209 send_pres_tags = FALSE; 09210 break; 09211 default: 09212 ast_log(LOG_WARNING, "Unsupported callingpres (%d)\n", p->callingpres); 09213 if ((p->callingpres & AST_PRES_RESTRICTION) != AST_PRES_ALLOWED) 09214 privacy = "full"; 09215 else 09216 privacy = "off"; 09217 screen = "no"; 09218 break; 09219 } 09220 09221 fromdomain = S_OR(p->fromdomain, ast_inet_ntoa(p->ourip.sin_addr)); 09222 09223 snprintf(buf, sizeof(buf), "\"%s\" <sip:%s@%s>", clin, clid, fromdomain); 09224 if (send_pres_tags) 09225 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ";privacy=%s;screen=%s", privacy, screen); 09226 ast_string_field_set(p, rpid, buf); 09227 09228 ast_string_field_build(p, rpid_from, "\"%s\" <sip:%s@%s>;tag=%s", clin, 09229 S_OR(p->fromuser, clid), 09230 fromdomain, p->tag); 09231 }
| static void build_via | ( | struct sip_pvt * | p | ) | [static] |
Build a Via header for a request.
Definition at line 2907 of file chan_sip.c.
References ast_inet_ntoa(), ast_test_flag, sip_pvt::branch, sip_pvt::flags, get_transport_pvt(), sip_pvt::ourip, SIP_NAT, SIP_NAT_RFC3581, and sip_pvt::via.
Referenced by manager_sipnotify(), reqprep(), sip_alloc(), sip_cli_notify(), sip_poke_peer(), sip_request_call(), sip_send_mwi_to_peer(), transmit_invite(), transmit_register(), and transmit_response_using_temp().
02908 { 02909 /* Work around buggy UNIDEN UIP200 firmware */ 02910 const char *rport = ast_test_flag(&p->flags[0], SIP_NAT) & SIP_NAT_RFC3581 ? ";rport" : ""; 02911 02912 /* z9hG4bK is a magic cookie. See RFC 3261 section 8.1.1.7 */ 02913 snprintf(p->via, sizeof(p->via), "SIP/2.0/%s %s:%d;branch=z9hG4bK%08x%s", 02914 get_transport_pvt(p), 02915 ast_inet_ntoa(p->ourip.sin_addr), 02916 ntohs(p->ourip.sin_port), (int) p->branch, rport); 02917 }
| static int cb_extensionstate | ( | char * | context, | |
| char * | exten, | |||
| int | state, | |||
| void * | data | |||
| ) | [static] |
Callback for the devicestate notification (SUBSCRIBE) support subsystem.
Definition at line 11095 of file chan_sip.c.
References append_history, AST_EXTENSION_DEACTIVATED, AST_EXTENSION_REMOVED, ast_extension_state2str(), ast_log(), ast_set_flag, ast_test_flag, ast_verb, sip_pvt::autokillid, DEFAULT_TRANS_TIMEOUT, FALSE, sip_pvt::flags, sip_pvt::laststate, LOG_WARNING, NONE, sip_pvt::pendinginvite, sip_cancel_destroy(), SIP_PAGE2_STATECHANGEQUEUE, sip_pvt_lock, sip_pvt_unlock, sip_scheddestroy(), sip_pvt::stateid, sip_pvt::subscribed, transmit_state_notify(), and sip_pvt::username.
Referenced by handle_request_subscribe(), handle_response(), and handle_response_notify().
11096 { 11097 struct sip_pvt *p = data; 11098 11099 sip_pvt_lock(p); 11100 11101 switch(state) { 11102 case AST_EXTENSION_DEACTIVATED: /* Retry after a while */ 11103 case AST_EXTENSION_REMOVED: /* Extension is gone */ 11104 if (p->autokillid > -1 && sip_cancel_destroy(p)) /* Remove subscription expiry for renewals */ 11105 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 11106 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); /* Delete subscription in 32 secs */ 11107 ast_verb(2, "Extension state: Watcher for hint %s %s. Notify User %s\n", exten, state == AST_EXTENSION_DEACTIVATED ? "deactivated" : "removed", p->username); 11108 p->stateid = -1; 11109 p->subscribed = NONE; 11110 append_history(p, "Subscribestatus", "%s", state == AST_EXTENSION_REMOVED ? "HintRemoved" : "Deactivated"); 11111 break; 11112 default: /* Tell user */ 11113 p->laststate = state; 11114 break; 11115 } 11116 if (p->subscribed != NONE) { /* Only send state NOTIFY if we know the format */ 11117 if (!p->pendinginvite) { 11118 transmit_state_notify(p, state, 1, FALSE); 11119 } else { 11120 /* We already have a NOTIFY sent that is not answered. Queue the state up. 11121 if many state changes happen meanwhile, we will only send a notification of the last one */ 11122 ast_set_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE); 11123 } 11124 } 11125 ast_verb(2, "Extension Changed %s[%s] new state %s for Notify User %s %s\n", exten, context, ast_extension_state2str(state), p->username, 11126 ast_test_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE) ? "(queued)" : ""); 11127 11128 sip_pvt_unlock(p); 11129 11130 return 0; 11131 }
| static void change_t38_state | ( | struct sip_pvt * | p, | |
| int | state | |||
| ) | [static] |
Change the T38 state on a SIP dialog.
Definition at line 4236 of file chan_sip.c.
References AST_CONTROL_T38, ast_debug, ast_queue_control_data(), AST_T38_NEGOTIATED, AST_T38_REFUSED, AST_T38_REQUEST_NEGOTIATE, AST_T38_TERMINATED, chan, t38properties::direct, ast_channel::name, sip_pvt::owner, t38properties::state, sip_pvt::t38, T38_DISABLED, T38_ENABLED, T38_LOCAL_REINVITE, T38_PEER_DIRECT, and T38_PEER_REINVITE.
Referenced by handle_response_invite(), process_sdp(), sip_answer(), sip_indicate(), sip_read(), sip_t38_abort(), and sip_write().
04237 { 04238 int old = p->t38.state; 04239 struct ast_channel *chan = p->owner; 04240 enum ast_control_t38 message = 0; 04241 04242 /* Don't bother changing if we are already in the state wanted */ 04243 if (old == state) 04244 return; 04245 04246 if (state == T38_PEER_DIRECT) { 04247 p->t38.direct = 1; 04248 } 04249 04250 p->t38.state = state; 04251 ast_debug(2, "T38 state changed to %d on channel %s\n", p->t38.state, chan ? chan->name : "<none>"); 04252 04253 /* If no channel was provided we can't send off a control frame */ 04254 if (!chan) 04255 return; 04256 04257 /* Given the state requested and old state determine what control frame we want to queue up */ 04258 if (state == T38_PEER_REINVITE) 04259 message = AST_T38_REQUEST_NEGOTIATE; 04260 else if (state == T38_ENABLED) 04261 message = AST_T38_NEGOTIATED; 04262 else if (state == T38_DISABLED && old == T38_ENABLED) 04263 message = AST_T38_TERMINATED; 04264 else if (state == T38_DISABLED && old == T38_LOCAL_REINVITE) 04265 message = AST_T38_REFUSED; 04266 04267 /* Woot we got a message, create a control frame and send it on! */ 04268 if (message) 04269 ast_queue_control_data(chan, AST_CONTROL_T38, &message, sizeof(message)); 04270 }
| 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, | |||
| 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 10890 of file chan_sip.c.
References append_history, ast_copy_string(), AST_DYNSTR_BUILD_FAILED, ast_log(), ast_md5_hash(), ast_random(), ast_skip_blanks(), ast_str_set(), ast_str_thread_get(), ast_string_field_build, ast_strlen_zero(), AUTH_CHALLENGE_SENT, auth_headers(), AUTH_SECRET_FAILED, AUTH_SUCCESSFUL, AUTH_USERNAME_MISMATCH, buf, check_auth_buf, CHECK_AUTH_BUF_INITLEN, DEFAULT_TRANS_TIMEOUT, FALSE, get_header(), sip_request::ignore, LOG_NOTICE, LOG_WARNING, sip_pvt::randdata, s, S_OR, sip_methods, sip_scheddestroy(), strsep(), text, transmit_response_with_auth(), TRUE, and WWW_AUTH.
Referenced by check_peer_ok(), and register_verify().
10893 { 10894 const char *response; 10895 char *reqheader, *respheader; 10896 const char *authtoken; 10897 char a1_hash[256]; 10898 char resp_hash[256]=""; 10899 char *c; 10900 int wrongnonce = FALSE; 10901 int good_response; 10902 const char *usednonce = p->randdata; 10903 struct ast_str *buf; 10904 int res; 10905 10906 /* table of recognised keywords, and their value in the digest */ 10907 enum keys { K_RESP, K_URI, K_USER, K_NONCE, K_LAST }; 10908 struct x { 10909 const char *key; 10910 const char *s; 10911 } *i, keys[] = { 10912 [K_RESP] = { "response=", "" }, 10913 [K_URI] = { "uri=", "" }, 10914 [K_USER] = { "username=", "" }, 10915 [K_NONCE] = { "nonce=", "" }, 10916 [K_LAST] = { NULL, NULL} 10917 }; 10918 10919 /* Always OK if no secret */ 10920 if (ast_strlen_zero(secret) && ast_strlen_zero(md5secret)) 10921 return AUTH_SUCCESSFUL; 10922 10923 /* Always auth with WWW-auth since we're NOT a proxy */ 10924 /* Using proxy-auth in a B2BUA may block proxy authorization in the same transaction */ 10925 response = "401 Unauthorized"; 10926 10927 /* 10928 * Note the apparent swap of arguments below, compared to other 10929 * usages of auth_headers(). 10930 */ 10931 auth_headers(WWW_AUTH, &respheader, &reqheader); 10932 10933 authtoken = get_header(req, reqheader); 10934 if (ignore && !ast_strlen_zero(p->randdata) && ast_strlen_zero(authtoken)) { 10935 /* This is a retransmitted invite/register/etc, don't reconstruct authentication 10936 information */ 10937 if (!reliable) { 10938 /* Resend message if this was NOT a reliable delivery. Otherwise the 10939 retransmission should get it */ 10940 transmit_response_with_auth(p, response, req, p->randdata, reliable, respheader, 0); 10941 /* Schedule auto destroy in 32 seconds (according to RFC 3261) */ 10942 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 10943 } 10944 return AUTH_CHALLENGE_SENT; 10945 } else if (ast_strlen_zero(p->randdata) || ast_strlen_zero(authtoken)) { 10946 /* We have no auth, so issue challenge and request authentication */ 10947 ast_string_field_build(p, randdata, "%08lx", ast_random()); /* Create nonce for challenge */ 10948 transmit_response_with_auth(p, response, req, p->randdata, reliable, respheader, 0); 10949 /* Schedule auto destroy in 32 seconds */ 10950 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 10951 return AUTH_CHALLENGE_SENT; 10952 } 10953 10954 /* --- We have auth, so check it */ 10955 10956 /* Whoever came up with the authentication section of SIP can suck my %&#$&* for not putting 10957 an example in the spec of just what it is you're doing a hash on. */ 10958 10959 if (!(buf = ast_str_thread_get(&check_auth_buf, CHECK_AUTH_BUF_INITLEN))) 10960 return AUTH_SECRET_FAILED; /*! XXX \todo need a better return code here */ 10961 10962 /* Make a copy of the response and parse it */ 10963 res = ast_str_set(&buf, 0, "%s", authtoken); 10964 10965 if (res == AST_DYNSTR_BUILD_FAILED) 10966 return AUTH_SECRET_FAILED; /*! XXX \todo need a better return code here */ 10967 10968 c = buf->str; 10969 10970 while(c && *(c = ast_skip_blanks(c)) ) { /* lookup for keys */ 10971 for (i = keys; i->key != NULL; i++) { 10972 const char *separator = ","; /* default */ 10973 10974 if (strncasecmp(c, i->key, strlen(i->key)) != 0) 10975 continue; 10976 /* Found. Skip keyword, take text in quotes or up to the separator. */ 10977 c += strlen(i->key); 10978 if (*c == '"') { /* in quotes. Skip first and look for last */ 10979 c++; 10980 separator = "\""; 10981 } 10982 i->s = c; 10983 strsep(&c, separator); 10984 break; 10985 } 10986 if (i->key == NULL) /* not found, jump after space or comma */ 10987 strsep(&c, " ,"); 10988 } 10989 10990 /* Verify that digest username matches the username we auth as */ 10991 if (strcmp(username, keys[K_USER].s)) { 10992 ast_log(LOG_WARNING, "username mismatch, have <%s>, digest has <%s>\n", 10993 username, keys[K_USER].s); 10994 /* Oops, we're trying something here */ 10995 return AUTH_USERNAME_MISMATCH; 10996 } 10997 10998 /* Verify nonce from request matches our nonce. If not, send 401 with new nonce */ 10999 if (strcasecmp(p->randdata, keys[K_NONCE].s)) { /* XXX it was 'n'casecmp ? */ 11000 wrongnonce = TRUE; 11001 usednonce = keys[K_NONCE].s; 11002 } 11003 11004 if (!ast_strlen_zero(md5secret)) 11005 ast_copy_string(a1_hash, md5secret, sizeof(a1_hash)); 11006 else { 11007 char a1[256]; 11008 snprintf(a1, sizeof(a1), "%s:%s:%s", username, global_realm, secret); 11009 ast_md5_hash(a1_hash, a1); 11010 } 11011 11012 /* compute the expected response to compare with what we received */ 11013 { 11014 char a2[256]; 11015 char a2_hash[256]; 11016 char resp[256]; 11017 11018 snprintf(a2, sizeof(a2), "%s:%s", sip_methods[sipmethod].text, 11019 S_OR(keys[K_URI].s, uri)); 11020 ast_md5_hash(a2_hash, a2); 11021 snprintf(resp, sizeof(resp), "%s:%s:%s", a1_hash, usednonce, a2_hash); 11022 ast_md5_hash(resp_hash, resp); 11023 } 11024 11025 good_response = keys[K_RESP].s && 11026 !strncasecmp(keys[K_RESP].s, resp_hash, strlen(resp_hash)); 11027 if (wrongnonce) { 11028 if (good_response) { 11029 if (sipdebug) 11030 ast_log(LOG_NOTICE, "Correct auth, but based on stale nonce received from '%s'\n", get_header(req, "To")); 11031 /* We got working auth token, based on stale nonce . */ 11032 ast_string_field_build(p, randdata, "%08lx", ast_random()); 11033 transmit_response_with_auth(p, response, req, p->randdata, reliable, respheader, TRUE); 11034 } else { 11035 /* Everything was wrong, so give the device one more try with a new challenge */ 11036 if (!req->ignore) { 11037 if (sipdebug) 11038 ast_log(LOG_NOTICE, "Bad authentication received from '%s'\n", get_header(req, "To")); 11039 ast_string_field_build(p, randdata, "%08lx", ast_random()); 11040 } else { 11041 if (sipdebug) 11042 ast_log(LOG_NOTICE, "Duplicate authentication received from '%s'\n", get_header(req, "To")); 11043 } 11044 transmit_response_with_auth(p, response, req, p->randdata, reliable, respheader, FALSE); 11045 } 11046 11047 /* Schedule auto destroy in 32 seconds */ 11048 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 11049 return AUTH_CHALLENGE_SENT; 11050 } 11051 if (good_response) { 11052 append_history(p, "AuthOK", "Auth challenge succesful for %s", username); 11053 return AUTH_SUCCESSFUL; 11054 } 11055 11056 /* Ok, we have a bad username/secret pair */ 11057 /* Tell the UAS not to re-send this authentication data, because 11058 it will continue to fail 11059 */ 11060 11061 return AUTH_SECRET_FAILED; 11062 }
| static enum check_auth_result check_peer_ok | ( | struct sip_pvt * | p, | |
| char * | of, | |||
| struct sip_request * | req, | |||
| int | sipmethod, | |||
| struct sockaddr_in * | sin, | |||
| struct sip_peer ** | authpeer, | |||
| enum xmittype | reliable, | |||
| char * | rpid_num, | |||
| char * | calleridname, | |||
| char * | uri2 | |||
| ) | [static] |
Validate device authentication.
Definition at line 12206 of file chan_sip.c.
References sip_peer::accountcode, accountcode, sip_peer::amaflags, sip_pvt::amaflags, ao2_t_ref, ast_copy_flags, AST_FORMAT_TEXT_MASK, AST_FORMAT_VIDEO_MASK, ast_inet_ntoa(), ast_is_shrinkable_phonenumber(), ast_rtp_codec_setpref(), ast_rtp_destroy(), AST_RTP_DTMF, ast_set_flag, ast_shrink_phone_number(), ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_verbose, AUTH_DONT_KNOW, sip_peer::autoframing, sip_pvt::autoframing, sip_peer::call_limit, sip_peer::callgroup, sip_pvt::callgroup, sip_pvt::callingpres, sip_peer::callingpres, sip_peer::capability, sip_pvt::capability, sip_peer::chanvars, sip_pvt::chanvars, check_auth(), cid_name, sip_peer::cid_name, cid_num, sip_peer::cid_num, context, sip_peer::context, copy_vars(), debug, do_setnat(), FALSE, find_peer(), FINDALLDEVICES, FINDPEERS, FINDUSERS, sip_peer::flags, sip_pvt::flags, sip_peer::fullcontact, sip_request::ignore, t38properties::jointcapability, sip_pvt::jointcapability, sip_pvt::jointnoncodeccapability, sip_peer::language, language, sip_peer::lastms, sip_peer::maxcallbitrate, sip_pvt::maxcallbitrate, sip_peer::maxms, sip_peer::md5secret, sip_peer::mohinterpret, mohinterpret, sip_peer::mohsuggest, mohsuggest, sip_peer::name, sip_pvt::noncodeccapability, sip_peer::parkinglot, parkinglot, t38properties::peercapability, sip_pvt::peercapability, sip_pvt::peermd5secret, sip_pvt::peersecret, sip_peer::pickupgroup, sip_pvt::pickupgroup, sip_pvt::prefs, sip_peer::prefs, sip_pvt::recv, replace_cid(), sip_pvt::rtp, sip_peer::secret, SIP_CALL_LIMIT, sip_debug_test_addr(), SIP_DTMF, SIP_DTMF_AUTO, SIP_DTMF_RFC2833, SIP_FLAGS_TO_COPY, SIP_INSECURE_INVITE, SIP_INVITE, SIP_NAT_ROUTE, SIP_PAGE2_FLAGS_TO_COPY, SIP_PAGE2_TEXTSUPPORT, SIP_PAGE2_VIDEOSUPPORT, SIP_PAGE2_VIDEOSUPPORT_ALWAYS, SIP_SUBSCRIBE, sip_peer::sipoptions, sip_pvt::sipoptions, sip_peer::subscribecontext, sip_pvt::t38, sip_pvt::timer_b, sip_peer::timer_b, sip_peer::timer_t1, sip_pvt::timer_t1, sip_pvt::trtp, TRUE, unref_peer(), sip_peer::username, and sip_pvt::vrtp.
Referenced by check_user_full().
12211 { 12212 enum check_auth_result res; 12213 int debug=sip_debug_test_addr(sin); 12214 struct sip_peer *peer; 12215 12216 if (sipmethod == SIP_SUBSCRIBE) { 12217 /* For subscribes, match on device name only; for other methods, 12218 * match on IP address-port of the incoming request. 12219 */ 12220 peer = find_peer(of, NULL, TRUE, FINDALLDEVICES, FALSE); 12221 } else { 12222 /* First find devices based on username (avoid all type=peer's) */ 12223 peer = find_peer(of, NULL, TRUE, FINDUSERS, FALSE); 12224 12225 /* Then find devices based on IP */ 12226 if (!peer) { 12227 peer = find_peer(NULL, &p->recv, TRUE, FINDPEERS, FALSE); 12228 } 12229 } 12230 12231 if (!peer) { 12232 if (debug) 12233 ast_verbose("No matching peer for '%s' from '%s:%d'\n", 12234 of, ast_inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port)); 12235 return AUTH_DONT_KNOW; 12236 } 12237 12238 if (debug) 12239 ast_verbose("Found peer '%s' for '%s' from %s:%d\n", 12240 peer->name, of, ast_inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port)); 12241 12242 /* XXX what about p->prefs = peer->prefs; ? */ 12243 /* Set Frame packetization */ 12244 if (p->rtp) { 12245 ast_rtp_codec_setpref(p->rtp, &peer->prefs); 12246 p->autoframing = peer->autoframing; 12247 } 12248 12249 /* Take the peer */ 12250 ast_copy_flags(&p->flags[0], &peer->flags[0], SIP_FLAGS_TO_COPY); 12251 ast_copy_flags(&p->flags[1], &peer->flags[1], SIP_PAGE2_FLAGS_TO_COPY); 12252 12253 /* Copy SIP extensions profile to peer */ 12254 /* XXX is this correct before a successful auth ? */ 12255 if (p->sipoptions) 12256 peer->sipoptions = p->sipoptions; 12257 12258 replace_cid(p, rpid_num, calleridname); 12259 do_setnat(p, ast_test_flag(&p->flags[0], SIP_NAT_ROUTE)); 12260 12261 ast_string_field_set(p, peersecret, peer->secret); 12262 ast_string_field_set(p, peermd5secret, peer->md5secret); 12263 ast_string_field_set(p, subscribecontext, peer->subscribecontext); 12264 ast_string_field_set(p, mohinterpret, peer->mohinterpret); 12265 ast_string_field_set(p, mohsuggest, peer->mohsuggest); 12266 ast_string_field_set(p, parkinglot, peer->parkinglot); 12267 if (peer->callingpres) /* Peer calling pres setting will override RPID */ 12268 p->callingpres = peer->callingpres; 12269 if (peer->maxms && peer->lastms) 12270 p->timer_t1 = peer->lastms < global_t1min ? global_t1min : peer->lastms; 12271 else 12272 p->timer_t1 = peer->timer_t1; 12273 12274 /* Set timer B to control transaction timeouts */ 12275 if (peer->timer_b) 12276 p->timer_b = peer->timer_b; 12277 else 12278 p->timer_b = 64 * p->timer_t1; 12279 12280 if (ast_test_flag(&peer->flags[0], SIP_INSECURE_INVITE)) { 12281 /* Pretend there is no required authentication */ 12282 ast_string_field_set(p, peersecret, NULL); 12283 ast_string_field_set(p, peermd5secret, NULL); 12284 } 12285 if (!(res = check_auth(p, req, peer->name, p->peersecret, p->peermd5secret, sipmethod, uri2, reliable, req->ignore))) { 12286 ast_copy_flags(&p->flags[0], &peer->flags[0], SIP_FLAGS_TO_COPY); 12287 ast_copy_flags(&p->flags[1], &peer->flags[1], SIP_PAGE2_FLAGS_TO_COPY); 12288 /* If we have a call limit, set flag */ 12289 if (peer->call_limit) 12290 ast_set_flag(&p->flags[0], SIP_CALL_LIMIT); 12291 ast_string_field_set(p, peername, peer->name); 12292 ast_string_field_set(p, authname, peer->name); 12293 12294 if (sipmethod == SIP_INVITE) { 12295 /* copy channel vars */ 12296 p->chanvars = copy_vars(peer->chanvars); 12297 } 12298 12299 if (authpeer) { 12300 ao2_t_ref(peer, 1, "copy pointer into (*authpeer)"); 12301 (*authpeer) = peer; /* Add a ref to the object here, to keep it in memory a bit longer if it is realtime */ 12302 } 12303 12304 if (!ast_strlen_zero(peer->username)) { 12305 ast_string_field_set(p, username, peer->username); 12306 /* Use the default username for authentication on outbound calls */ 12307 /* XXX this takes the name from the caller... can we override ? */ 12308 ast_string_field_set(p, authname, peer->username); 12309 } 12310 if (!ast_strlen_zero(peer->cid_num)) { 12311 char *tmp = ast_strdupa(peer->cid_num); 12312 if (ast_is_shrinkable_phonenumber(tmp)) 12313 ast_shrink_phone_number(tmp); 12314 ast_string_field_set(p, cid_num, tmp); 12315 } 12316 if (!ast_strlen_zero(peer->cid_name)) 12317 ast_string_field_set(p, cid_name, peer->cid_name); 12318 ast_string_field_set(p, fullcontact, peer->fullcontact); 12319 if (!ast_strlen_zero(peer->context)) 12320 ast_string_field_set(p, context, peer->context); 12321 ast_string_field_set(p, peersecret, peer->secret); 12322 ast_string_field_set(p, peermd5secret, peer->md5secret); 12323 ast_string_field_set(p, language, peer->language); 12324 ast_string_field_set(p, accountcode, peer->accountcode); 12325 p->amaflags = peer->amaflags; 12326 p->callgroup = peer->callgroup; 12327 p->pickupgroup = peer->pickupgroup; 12328 p->capability = peer->capability; 12329 p->prefs = peer->prefs; 12330 p->jointcapability = peer->capability; 12331 if (p->peercapability) 12332 p->jointcapability &= p->peercapability; 12333 p->maxcallbitrate = peer->maxcallbitrate; 12334 if (!ast_test_flag(&p->flags[1], SIP_PAGE2_VIDEOSUPPORT_ALWAYS) && 12335 (!ast_test_flag(&p->flags[1], SIP_PAGE2_VIDEOSUPPORT) || 12336 !(p->capability & AST_FORMAT_VIDEO_MASK)) && 12337 p->vrtp) { 12338 ast_rtp_destroy(p->vrtp); 12339 p->vrtp = NULL; 12340 } 12341 if ((!ast_test_flag(&p->flags[1], SIP_PAGE2_TEXTSUPPORT) || !(p->capability & AST_FORMAT_TEXT_MASK)) && p->trtp) { 12342 ast_rtp_destroy(p->trtp); 12343 p->trtp = NULL; 12344 } 12345 if ((ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833) || 12346 (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO)) 12347 p->noncodeccapability |= AST_RTP_DTMF; 12348 else 12349 p->noncodeccapability &= ~AST_RTP_DTMF; 12350 p->jointnoncodeccapability = p->noncodeccapability; 12351 if (p->t38.peercapability) 12352 p->t38.jointcapability &= p->t38.peercapability; 12353 } 12354 unref_peer(peer, "check_peer_ok: unref_peer: tossing temp ptr to peer from find_peer"); 12355 return res; 12356 }
| static void check_pendings | ( | struct sip_pvt * | p | ) | [static] |
Check pending actions on SIP call.
Definition at line 15809 of file chan_sip.c.
References ast_clear_flag, ast_debug, ast_test_flag, sip_pvt::callid, DEFAULT_TRANS_TIMEOUT, FALSE, sip_pvt::flags, INV_CALLING, INV_EARLY_MEDIA, INV_PROCEEDING, sip_pvt::invitestate, sip_pvt::pendinginvite, SIP_BYE, SIP_CANCEL, SIP_NEEDREINVITE, SIP_PENDINGBYE, sip_scheddestroy(), t38properties::state, sip_pvt::t38, T38_LOCAL_REINVITE, transmit_reinvite_with_sdp(), transmit_request(), transmit_request_with_auth(), TRUE, sip_pvt::waitid, and XMIT_RELIABLE.
Referenced by handle_incoming(), handle_response_invite(), and sip_reinvite_retry().
15810 { 15811 if (ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) { 15812 /* if we can't BYE, then this is really a pending CANCEL */ 15813 if (p->invitestate == INV_PROCEEDING || p->invitestate == INV_EARLY_MEDIA) 15814 transmit_request(p, SIP_CANCEL, p->lastinvite, XMIT_RELIABLE, FALSE); 15815 /* Actually don't destroy us yet, wait for the 487 on our original 15816 INVITE, but do set an autodestruct just in case we never get it. */ 15817 else { 15818 /* We have a pending outbound invite, don't send someting 15819 new in-transaction */ 15820 if (p->pendinginvite) 15821 return; 15822 15823 /* Perhaps there is an SD change INVITE outstanding */ 15824 transmit_request_with_auth(p, SIP_BYE, 0, XMIT_RELIABLE, TRUE); 15825 } 15826 ast_clear_flag(&p->flags[0], SIP_PENDINGBYE); 15827 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 15828 } else if (ast_test_flag(&p->flags[0], SIP_NEEDREINVITE)) { 15829 /* if we can't REINVITE, hold it for later */ 15830 if (p->pendinginvite || p->invitestate == INV_CALLING || p->invitestate == INV_PROCEEDING || p->invitestate == INV_EARLY_MEDIA || p->waitid > 0) { 15831 ast_debug(2, "NOT Sending pending reinvite (yet) on '%s'\n", p->callid); 15832 } else { 15833 ast_debug(2, "Sending pending reinvite on '%s'\n", p->callid); 15834 /* Didn't get to reinvite yet, so do it now */ 15835 transmit_reinvite_with_sdp(p, (p->t38.state == T38_LOCAL_REINVITE ? TRUE : FALSE), FALSE); 15836 ast_clear_flag(&p->flags[0], SIP_NEEDREINVITE); 15837 } 15838 } 15839 }
| 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 20275 of file chan_sip.c.
References ast_channel::_state, ast_channel_trylock, ast_channel_unlock, ast_log(), ast_rtp_get_peer(), ast_rtp_get_rtpholdtimeout(), ast_rtp_get_rtpkeepalive(), ast_rtp_get_rtptimeout(), ast_rtp_sendcng(), ast_rtp_set_rtpholdtimeout(), ast_rtp_set_rtptimeout(), AST_SOFTHANGUP_DEV, ast_softhangup_nolock(), AST_STATE_UP, ast_test_flag, sip_pvt::flags, sip_pvt::lastrtprx, sip_pvt::lastrtptx, LOG_NOTICE, ast_channel::name, sip_pvt::owner, sip_pvt::redirip, sip_pvt::rtp, SIP_PAGE2_CALL_ONHOLD, sip_pvt_lock, sip_pvt_unlock, t38properties::state, sip_pvt::t38, T38_ENABLED, and sip_pvt::vrtp.
Referenced by dialog_needdestroy().
20276 { 20277 /* If we have no RTP or no active owner, no need to check timers */ 20278 if (!dialog->rtp || !dialog->owner) 20279 return; 20280 /* If the call is not in UP state or redirected outside Asterisk, no need to check timers */ 20281 20282 if (dialog->owner->_state != AST_STATE_UP || dialog->redirip.sin_addr.s_addr) 20283 return; 20284 20285 /* If the call is involved in a T38 fax session do not check RTP timeout */ 20286 if (dialog->t38.state == T38_ENABLED) 20287 return; 20288 20289 /* If we have no timers set, return now */ 20290 if ((ast_rtp_get_rtpkeepalive(dialog->rtp) == 0) && (ast_rtp_get_rtptimeout(dialog->rtp) == 0) && (ast_rtp_get_rtpholdtimeout(dialog->rtp) == 0)) 20291 return; 20292 20293 /* Check AUDIO RTP keepalives */ 20294 if (dialog->lastrtptx && ast_rtp_get_rtpkeepalive(dialog->rtp) && 20295 (t > dialog->lastrtptx + ast_rtp_get_rtpkeepalive(dialog->rtp))) { 20296 /* Need to send an empty RTP packet */ 20297 dialog->lastrtptx = time(NULL); 20298 ast_rtp_sendcng(dialog->rtp, 0); 20299 } 20300 20301 /*! \todo Check video RTP keepalives 20302 20303 Do we need to move the lastrtptx to the RTP structure to have one for audio and one 20304 for video? It really does belong to the RTP structure. 20305 */ 20306 20307 /* Check AUDIO RTP timers */ 20308 if (dialog->lastrtprx && (ast_rtp_get_rtptimeout(dialog->rtp) || ast_rtp_get_rtpholdtimeout(dialog->rtp)) && 20309 (t > dialog->lastrtprx + ast_rtp_get_rtptimeout(dialog->rtp))) { 20310 20311 /* Might be a timeout now -- see if we're on hold */ 20312 struct sockaddr_in sin; 20313 ast_rtp_get_peer(dialog->rtp, &sin); 20314 if (!ast_test_flag(&dialog->flags[1], SIP_PAGE2_CALL_ONHOLD) || (ast_rtp_get_rtpholdtimeout(dialog->rtp) && 20315 (t > dialog->lastrtprx + ast_rtp_get_rtpholdtimeout(dialog->rtp)))) { 20316 /* Needs a hangup */ 20317 if (ast_rtp_get_rtptimeout(dialog->rtp)) { 20318 while (dialog->owner && ast_channel_trylock(dialog->owner)) { 20319 sip_pvt_unlock(dialog); 20320 usleep(1); 20321 sip_pvt_lock(dialog); 20322 } 20323 ast_log(LOG_NOTICE, "Disconnecting call '%s' for lack of RTP activity in %ld seconds\n", 20324 dialog->owner->name, (long) (t - dialog->lastrtprx)); 20325 /* Issue a softhangup */ 20326 ast_softhangup_nolock(dialog->owner, AST_SOFTHANGUP_DEV); 20327 ast_channel_unlock(dialog->owner); 20328 /* forget the timeouts for this call, since a hangup 20329 has already been requested and we don't want to 20330 repeatedly request hangups 20331 */ 20332 ast_rtp_set_rtptimeout(dialog->rtp, 0); 20333 ast_rtp_set_rtpholdtimeout(dialog->rtp, 0); 20334 if (dialog->vrtp) { 20335 ast_rtp_set_rtptimeout(dialog->vrtp, 0); 20336 ast_rtp_set_rtpholdtimeout(dialog->vrtp, 0); 20337 } 20338 } 20339 } 20340 } 20341 }
| 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 21335 of file chan_sip.c.
References ast_copy_string(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strlen_zero(), domain::context, domain::domain, and domain::list.
Referenced by func_check_sipdomain(), get_destination(), handle_request_refer(), and register_verify().
21336 { 21337 struct domain *d; 21338 int result = 0; 21339 21340 AST_LIST_LOCK(&domain_list); 21341 AST_LIST_TRAVERSE(&domain_list, d, list) { 21342 if (strcasecmp(d->domain, domain)) 21343 continue; 21344 21345 if (len && !ast_strlen_zero(d->context)) 21346 ast_copy_string(context, d->context, len); 21347 21348 result = 1; 21349 break; 21350 } 21351 AST_LIST_UNLOCK(&domain_list); 21352 21353 return result; 21354 }
| static int check_user | ( | struct sip_pvt * | p, | |
| struct sip_request * | req, | |||
| int | sipmethod, | |||
| char * | uri, | |||
| enum xmittype | reliable, | |||
| struct sockaddr_in * | sin | |||
| ) | [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 12484 of file chan_sip.c.
References check_user_full().
Referenced by handle_request_invite().
12485 { 12486 return check_user_full(p, req, sipmethod, uri, reliable, sin, NULL); 12487 }
| static enum check_auth_result check_user_full | ( | struct sip_pvt * | p, | |
| struct sip_request * | req, | |||
| int | sipmethod, | |||
| char * | uri, | |||
| enum xmittype | reliable, | |||
| struct sockaddr_in * | sin, | |||
| 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 12364 of file chan_sip.c.
References ast_copy_string(), ast_is_shrinkable_phonenumber(), ast_log(), ast_shrink_phone_number(), ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_uri_decode(), AUTH_DONT_KNOW, AUTH_FAKE_AUTH, AUTH_SECRET_FAILED, AUTH_SUCCESSFUL, build_contact(), check_peer_ok(), cid_name, cid_num, dummy(), exten, get_calleridname(), get_header(), get_in_brackets(), get_rpid_num(), LOG_NOTICE, parse_uri(), replace_cid(), SIP_TRANSPORT_TLS, strsep(), and terminate_uri().
Referenced by check_user(), and handle_request_subscribe().
12367 { 12368 char from[256]; 12369 char *dummy; /* dummy return value for parse_uri */ 12370 char *domain; /* dummy return value for parse_uri */ 12371 char *of, *of2; 12372 char rpid_num[50]; 12373 const char *rpid; 12374 enum check_auth_result res; 12375 char calleridname[50]; 12376 char *uri2 = ast_strdupa(uri); 12377 12378 terminate_uri(uri2); /* trim extra stuff */ 12379 12380 ast_copy_string(from, get_header(req, "From"), sizeof(from)); 12381 if (pedanticsipchecking) 12382 ast_uri_decode(from); 12383 /* XXX here tries to map the username for invite things */ 12384 memset(calleridname, 0, sizeof(calleridname)); 12385 get_calleridname(from, calleridname, sizeof(calleridname)); 12386 if (calleridname[0]) 12387 ast_string_field_set(p, cid_name, calleridname); 12388 12389 rpid = get_header(req, "Remote-Party-ID"); 12390 memset(rpid_num, 0, sizeof(rpid_num)); 12391 if (!ast_strlen_zero(rpid)) 12392 p->callingpres = get_rpid_num(rpid, rpid_num, sizeof(rpid_num)); 12393 12394 of = get_in_brackets(from); 12395 if (ast_strlen_zero(p->exten)) { 12396 char *t = uri2; 12397 if (!strncasecmp(t, "sip:", 4)) 12398 t+= 4; 12399 else if (!strncasecmp(t, "sips:", 5)) 12400 t += 5; 12401 ast_string_field_set(p, exten, t); 12402 t = strchr(p->exten, '@'); 12403 if (t) 12404 *t = '\0'; 12405 if (ast_strlen_zero(p->our_contact)) 12406 build_contact(p); 12407 } 12408 /* save the URI part of the From header */ 12409 ast_string_field_set(p, from, of); 12410 12411 of2 = ast_strdupa(of); 12412 12413 /* ignore all fields but name */ 12414 if (p->socket.type == SIP_TRANSPORT_TLS) { 12415 if (parse_uri(of, "sips:", &of, &dummy, &domain, &dummy, &dummy)) { 12416 if (parse_uri(of2, "sip:", &of, &dummy, &domain, &dummy, &dummy)) 12417 ast_log(LOG_NOTICE, "From address missing 'sip:', using it anyway\n"); 12418 } 12419 } else { 12420 if (parse_uri(of, "sip:", &of, &dummy, &domain, &dummy, &dummy)) 12421 ast_log(LOG_NOTICE, "From address missing 'sip:', using it anyway\n"); 12422 } 12423 12424 if (ast_strlen_zero(of)) { 12425 /* XXX note: the original code considered a missing @host 12426 * as a username-only URI. The SIP RFC (19.1.1) says that 12427 * this is wrong, and it should be considered as a domain-only URI. 12428 * For backward compatibility, we keep this block, but it is 12429 * really a mistake and should go away. 12430 */ 12431 of = domain; 12432 } 12433 { 12434 char *tmp = ast_strdupa(of); 12435 /* We need to be able to handle auth-headers looking like 12436 <sip:8164444422;phone-context=+1@1.2.3.4:5060;user=phone;tag=SDadkoa01-gK0c3bdb43> 12437 */ 12438 tmp = strsep(&tmp, ";"); 12439 if (ast_is_shrinkable_phonenumber(tmp)) 12440 ast_shrink_phone_number(tmp); 12441 ast_string_field_set(p, cid_num, tmp); 12442 } 12443 12444 if (global_match_auth_username) { 12445 /* 12446 * XXX This is experimental code to grab the search key from the 12447 * Auth header's username instead of the 'From' name, if available. 12448 * Do not enable this block unless you understand the side effects (if any!) 12449 * Note, the search for "username" should be done in a more robust way. 12450 * Note2, at the moment we check both fields, though maybe we should 12451 * pick one or another depending on the request ? XXX 12452 */ 12453 const char *hdr = get_header(req, "Authorization"); 12454 if (ast_strlen_zero(hdr)) 12455 hdr = get_header(req, "Proxy-Authorization"); 12456 12457 if ( !ast_strlen_zero(hdr) && (hdr = strstr(hdr, "username=\"")) ) { 12458 ast_copy_string(from, hdr + strlen("username=\""), sizeof(from)); 12459 of = from; 12460 of = strsep(&of, "\""); 12461 } 12462 } 12463 12464 res = check_peer_ok(p, of, req, sipmethod, sin, 12465 authpeer, reliable, rpid_num, calleridname, uri2); 12466 if (res != AUTH_DONT_KNOW) 12467 return res; 12468 12469 /* Finally, apply the guest policy */ 12470 if (global_allowguest) { 12471 replace_cid(p, rpid_num, calleridname); 12472 res = AUTH_SUCCESSFUL; 12473 } else if (global_alwaysauthreject) 12474 res = AUTH_FAKE_AUTH; /* reject with fake authorization request */ 12475 else 12476 res = AUTH_SECRET_FAILED; /* we don't want any guests, authentication will fail */ 12477 12478 return res; 12479 }
| 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 12049 of file chan_sip.c.
References ahp, ast_copy_string(), ast_gethostbyname(), ast_inet_ntoa(), ast_log(), ast_set_flag, ast_skip_blanks(), ast_verbose, sip_pvt::flags, get_header(), hp, LOG_WARNING, sip_pvt::sa, sip_debug_test_pvt(), sip_nat_mode(), SIP_NAT_ROUTE, sip_real_dst(), and STANDARD_SIP_PORT.
Referenced by handle_request_bye(), handle_request_cancel(), handle_request_invite(), handle_request_register(), and handle_request_subscribe().
12050 { 12051 char via[512]; 12052 char *c, *pt; 12053 struct hostent *hp; 12054 struct ast_hostent ahp; 12055 12056 ast_copy_string(via, get_header(req, "Via"), sizeof(via)); 12057 12058 /* Work on the leftmost value of the topmost Via header */ 12059 c = strchr(via, ','); 12060 if (c) 12061 *c = '\0'; 12062 12063 /* Check for rport */ 12064 c = strstr(via, ";rport"); 12065 if (c && (c[6] != '=')) /* rport query, not answer */ 12066 ast_set_flag(&p->flags[0], SIP_NAT_ROUTE); 12067 12068 c = strchr(via, ';'); 12069 if (c) 12070 *c = '\0'; 12071 12072 c = strchr(via, ' '); 12073 if (c) { 12074 *c = '\0'; 12075 c = ast_skip_blanks(c+1); 12076 if (strcasecmp(via, "SIP/2.0/UDP") && strcasecmp(via, "SIP/2.0/TCP") && strcasecmp(via, "SIP/2.0/TLS")) { 12077 ast_log(LOG_WARNING, "Don't know how to respond via '%s'\n", via); 12078 return; 12079 } 12080 pt = strchr(c, ':'); 12081 if (pt) 12082 *pt++ = '\0'; /* remember port pointer */ 12083 hp = ast_gethostbyname(c, &ahp); 12084 if (!hp) { 12085 ast_log(LOG_WARNING, "'%s' is not a valid host\n", c); 12086 return; 12087 } 12088 memset(&p->sa, 0, sizeof(p->sa)); 12089 p->sa.sin_family = AF_INET; 12090 memcpy(&p->sa.sin_addr, hp->h_addr, sizeof(p->sa.sin_addr)); 12091 p->sa.sin_port = htons(pt ? atoi(pt) : STANDARD_SIP_PORT); 12092 12093 if (sip_debug_test_pvt(p)) { 12094 const struct sockaddr_in *dst = sip_real_dst(p); 12095 ast_verbose("Sending to %s : %d (%s)\n", ast_inet_ntoa(dst->sin_addr), ntohs(dst->sin_port), sip_nat_mode(p)); 12096 } 12097 } 12098 }
| 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 externip/seternaddr/stunaddr.
Definition at line 12019 of file chan_sip.c.
References ast_copy_string(), ast_parse_arg(), get_header(), sip_pvt::ourip, PARSE_INADDR, and strsep().
12020 { 12021 char via[256]; 12022 char *cur, *opts; 12023 12024 ast_copy_string(via, get_header(req, "Via"), sizeof(via)); 12025 12026 /* Work on the leftmost value of the topmost Via header */ 12027 opts = strchr(via, ','); 12028 if (opts) 12029 *opts = '\0'; 12030 12031 /* parse all relevant options */ 12032 opts = strchr(via, ';'); 12033 if (!opts) 12034 return; /* no options to parse */ 12035 *opts++ = '\0'; 12036 while ( (cur = strsep(&opts, ";")) ) { 12037 if (!strncmp(cur, "rport=", 6)) { 12038 int port = strtol(cur+6, NULL, 10); 12039 /* XXX add error checking */ 12040 p->ourip.sin_port = ntohs(port); 12041 } else if (!strncmp(cur, "received=", 9)) { 12042 if (ast_parse_arg(cur+9, PARSE_INADDR, &p->ourip)) 12043 ; /* XXX add error checking */ 12044 } 12045 } 12046 }
| 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 13209 of file chan_sip.c.
References ast_context_destroy(), ast_context_find(), ast_copy_string(), AST_MAX_CONTEXT, and strsep().
Referenced by reload_config().
13210 { 13211 char *oldcontext, *newcontext, *stalecontext, *stringp, newlist[AST_MAX_CONTEXT]; 13212 13213 while ((oldcontext = strsep(&old, "&"))) { 13214 stalecontext = '\0'; 13215 ast_copy_string(newlist, new, sizeof(newlist)); 13216 stringp = newlist; 13217 while ((newcontext = strsep(&stringp, "&"))) { 13218 if (!strcmp(newcontext, oldcontext)) { 13219 /* This is not the context you're looking for */ 13220 stalecontext = '\0'; 13221 break; 13222 } else if (strcmp(newcontext, oldcontext)) { 13223 stalecontext = oldcontext; 13224 } 13225 13226 } 13227 if (stalecontext) 13228 ast_context_destroy(ast_context_find(stalecontext), "SIP"); 13229 } 13230 }
| static void clear_peer_mailboxes | ( | struct sip_peer * | peer | ) | [static] |
Destroy all peer-related mailbox subscriptions
Definition at line 3843 of file chan_sip.c.
References AST_LIST_REMOVE_HEAD, destroy_mailbox(), sip_mailbox::entry, mailbox, and sip_peer::mailboxes.
Referenced by set_peer_defaults(), and sip_destroy_peer().
03844 { 03845 struct sip_mailbox *mailbox; 03846 03847 while ((mailbox = AST_LIST_REMOVE_HEAD(&peer->mailboxes, entry))) 03848 destroy_mailbox(mailbox); 03849 }
| static int clear_realm_authentication | ( | struct sip_auth * | authlist | ) | [static] |
Clear realm authentication list (at reload).
Definition at line 21426 of file chan_sip.c.
References ast_free, and sip_auth::next.
Referenced by build_peer(), reload_config(), sip_destroy_peer(), and unload_module().
21427 { 21428 struct sip_auth *a = authlist; 21429 struct sip_auth *b; 21430 21431 while (a) { 21432 b = a; 21433 a = a->next; 21434 ast_free(b); 21435 } 21436 21437 return 1; 21438 }
| static void clear_sip_domains | ( | void | ) | [static] |
Clear our domain list (at reload).
Definition at line 21357 of file chan_sip.c.
References ast_free, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, and domain::list.
Referenced by reload_config(), and unload_module().
21358 { 21359 struct domain *d; 21360 21361 AST_LIST_LOCK(&domain_list); 21362 while ((d = AST_LIST_REMOVE_HEAD(&domain_list, list))) 21363 ast_free(d); 21364 AST_LIST_UNLOCK(&domain_list); 21365 }
| static const char* cli_yesno | ( | int | x | ) | [static] |
return Yes or No depending on the argument. This is used in many places in CLI command, having a function to generate this helps maintaining a consistent output (and possibly emitting the output in other languages, at some point).
Definition at line 12724 of file chan_sip.c.
Referenced by _sip_show_peer(), show_channels_cb(), sip_show_channel(), sip_show_settings(), sip_show_user(), and sip_show_users().
| static char * complete_sip_peer | ( | const char * | word, | |
| int | state, | |||
| int | flags2 | |||
| ) | [static] |
Do completion on peer name.
Definition at line 14530 of file chan_sip.c.
References ao2_iterator_init(), ao2_t_iterator_next, ast_strdup, ast_test_flag, sip_peer::flags, sip_peer::name, and unref_peer().
Referenced by complete_sip_show_peer(), complete_sipnotify(), sip_do_debug(), and sip_prune_realtime().
14531 { 14532 char *result = NULL; 14533 int wordlen = strlen(word); 14534 int which = 0; 14535 struct ao2_iterator i = ao2_iterator_init(peers, 0); 14536 struct sip_peer *peer; 14537 14538 while ((peer = ao2_t_iterator_next(&i, "iterate thru peers table"))) { 14539 /* locking of the object is not required because only the name and flags are being compared */ 14540 if (!strncasecmp(word, peer->name, wordlen) && 14541 (!flags2 || ast_test_flag(&peer->flags[1], flags2)) && 14542 ++which > state) 14543 result = ast_strdup(peer->name); 14544 unref_peer(peer, "toss iterator peer ptr before break"); 14545 if (result) { 14546 break; 14547 } 14548 } 14549 return result; 14550 }
| static char * complete_sip_registered_peer | ( | const char * | word, | |
| int | state, | |||
| int | flags2 | |||
| ) | [static] |
Do completion on registered peer name.
Definition at line 14553 of file chan_sip.c.
References ao2_iterator_init(), ao2_t_iterator_next, ast_strdup, ast_test_flag, sip_peer::expire, sip_peer::flags, sip_peer::name, and unref_peer().
Referenced by complete_sip_unregister().
14554 { 14555 char *result = NULL; 14556 int wordlen = strlen(word); 14557 int which = 0; 14558 struct ao2_iterator i; 14559 struct sip_peer *peer; 14560 14561 i = ao2_iterator_init(peers, 0); 14562 while ((peer = ao2_t_iterator_next(&i, "iterate thru peers table"))) { 14563 if (!strncasecmp(word, peer->name, wordlen) && 14564 (!flags2 || ast_test_flag(&peer->flags[1], flags2)) && 14565 ++which > state && peer->expire > 0) 14566 result = ast_strdup(peer->name); 14567 if (result) { 14568 unref_peer(peer, "toss iterator peer ptr before break"); 14569 break; 14570 } 14571 unref_peer(peer, "toss iterator peer ptr"); 14572 } 14573 return result; 14574 }
| 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 14577 of file chan_sip.c.
References complete_sipch().
Referenced by sip_show_history().
14578 { 14579 if (pos == 3) 14580 return complete_sipch(line, word, pos, state); 14581 14582 return NULL; 14583 }
| 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 14586 of file chan_sip.c.
References complete_sip_peer().
Referenced by sip_qualify_peer(), and sip_show_peer().
14587 { 14588 if (pos == 3) { 14589 return complete_sip_peer(word, state, 0); 14590 } 14591 14592 return NULL; 14593 }
| 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 13884 of file chan_sip.c.
References complete_sip_user().
Referenced by sip_show_user().
13885 { 13886 if (pos == 3) 13887 return complete_sip_user(word, state); 13888 13889 return NULL; 13890 }
| 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 14596 of file chan_sip.c.
References complete_sip_registered_peer().
Referenced by sip_unregister().
14597 { 14598 if (pos == 2) 14599 return complete_sip_registered_peer(word, state, 0); 14600 14601 return NULL; 14602 }
| static char* complete_sip_user | ( | const char * | word, | |
| int | state | |||
| ) | [static] |
Do completion on user name.
Definition at line 13858 of file chan_sip.c.
References ao2_iterator_init(), ao2_iterator_next, ao2_lock(), ao2_unlock(), ast_strdup, SIP_TYPE_USER, unref_peer(), and user.
Referenced by complete_sip_show_user().
13859 { 13860 char *result = NULL; 13861 int wordlen = strlen(word); 13862 int which = 0; 13863 struct ao2_iterator user_iter; 13864 struct sip_peer *user; 13865 13866 user_iter = ao2_iterator_init(peers, 0); 13867 while ((user = ao2_iterator_next(&user_iter))) { 13868 ao2_lock(user); 13869 if (!(user->type & SIP_TYPE_USER)) { 13870 ao2_unlock(user); 13871 unref_peer(user, "complete sip user"); 13872 continue; 13873 } 13874 /* locking of the object is not required because only the name and flags are being compared */ 13875 if (!strncasecmp(word, user->name, wordlen) && ++which > state) { 13876 result = ast_strdup(user->name); 13877 } 13878 ao2_unlock(user); 13879 unref_peer(user, "complete sip user"); 13880 } 13881 return result; 13882 }
| 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 14500 of file chan_sip.c.
References ao2_iterator_init(), ao2_t_iterator_next, ast_strdup, sip_pvt::callid, dialog_unref(), dialogs, sip_pvt_lock, and sip_pvt_unlock.
Referenced by complete_sip_show_history(), and sip_show_channel().
14501 { 14502 int which=0; 14503 struct sip_pvt *cur; 14504 char *c = NULL; 14505 int wordlen = strlen(word); 14506 struct ao2_iterator i; 14507 14508 if (pos != 3) { 14509 return NULL; 14510 } 14511 14512 i = ao2_iterator_init(dialogs, 0); 14513 14514 while ((cur = ao2_t_iterator_next(&i, "iterate thru dialogs"))) { 14515 sip_pvt_lock(cur); 14516 if (!strncasecmp(word, cur->callid, wordlen) && ++which > state) { 14517 c = ast_strdup(cur->callid); 14518 sip_pvt_unlock(cur); 14519 dialog_unref(cur, "drop ref in iterator loop break"); 14520 break; 14521 } 14522 sip_pvt_unlock(cur); 14523 dialog_unref(cur, "drop ref in iterator loop"); 14524 } 14525 return c; 14526 }
| static char * complete_sipnotify | ( | const char * | line, | |
| const char * | word, | |||
| int | pos, | |||
| int | state | |||
| ) | [static] |
Support routine for 'sip notify' CLI.
Definition at line 14605 of file chan_sip.c.
References ast_category_browse(), ast_strdup, complete_sip_peer(), and notify_types.
Referenced by sip_cli_notify().
14606 { 14607 char *c = NULL; 14608 14609 if (pos == 2) { 14610 int which = 0; 14611 char *cat = NULL; 14612 int wordlen = strlen(word); 14613 14614 /* do completion for notify type */ 14615 14616 if (!notify_types) 14617 return NULL; 14618 14619 while ( (cat = ast_category_browse(notify_types, cat)) ) { 14620 if (!strncasecmp(word, cat, wordlen) && ++which > state) { 14621 c = ast_strdup(cat); 14622 break; 14623 } 14624 } 14625 return c; 14626 } 14627 14628 if (pos > 2) 14629 return complete_sip_peer(word, state, 0); 14630 14631 return NULL; 14632 }
| 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 7693 of file chan_sip.c.
References __get_header(), add_header(), and ast_strlen_zero().
Referenced by respprep().
07694 { 07695 int start = 0; 07696 int copied = 0; 07697 for (;;) { 07698 const char *tmp = __get_header(orig, field, &start); 07699 07700 if (ast_strlen_zero(tmp)) 07701 break; 07702 /* Add what we're responding to */ 07703 add_header(req, field, tmp); 07704 copied++; 07705 } 07706 return copied ? 0 : -1; 07707 }
| 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 7682 of file chan_sip.c.
References add_header(), ast_log(), ast_strlen_zero(), get_header(), and LOG_NOTICE.
Referenced by reqprep(), and respprep().
07683 { 07684 const char *tmp = get_header(orig, field); 07685 07686 if (!ast_strlen_zero(tmp)) /* Add what we're responding to */ 07687 return add_header(req, field, tmp); 07688 ast_log(LOG_NOTICE, "No field '%s' present to copy\n", field); 07689 return -1; 07690 }
| 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 8972 of file chan_sip.c.
References ast_str_create(), ast_str_make_space(), sip_request::data, ast_str::str, and ast_str::used.
Referenced by _sip_tcp_helper_thread(), handle_request_bye(), handle_request_invite(), handle_request_refer(), handle_request_register(), handle_request_subscribe(), initialize_initreq(), parse_copy(), queue_request(), sip_park(), and sip_park_thread().
08973 { 08974 struct ast_str *duplicate = dst->data; 08975 08976 /* First copy stuff */ 08977 memcpy(dst, src, sizeof(*dst)); 08978 dst->data = duplicate; 08979 08980 /* All these + 1's are to account for the need to include the NULL terminator 08981 * Using typical string functions like ast_copy_string or ast_str_set will not 08982 * work in this case because the src's data string is riddled with \0's all over 08983 * the place and so a memcpy is the only way to accurately copy the string 08984 */ 08985 08986 if (!dst->data && !(dst->data = ast_str_create(src->data->used + 1))) 08987 return; 08988 else if (dst->data->len < src->data->used + 1) 08989 ast_str_make_space(&dst->data, src->data->used + 1); 08990 08991 memcpy(dst->data->str, src->data->str, src->data->used + 1); 08992 dst->data->used = src->data->used; 08993 }
| static void copy_socket_data | ( | struct sip_socket * | to_sock, | |
| const struct sip_socket * | from_sock | |||
| ) | [static] |
Definition at line 4287 of file chan_sip.c.
References ao2_ref, and sip_socket::tcptls_session.
Referenced by create_addr_from_peer(), handle_request_do(), parse_register_contact(), sip_poke_peer(), and transmit_response_using_temp().
04288 { 04289 if (to_sock->tcptls_session) { 04290 ao2_ref(to_sock->tcptls_session, -1); 04291 to_sock->tcptls_session = NULL; 04292 } 04293 04294 if (from_sock->tcptls_session) { 04295 ao2_ref(from_sock->tcptls_session, +1); 04296 } 04297 04298 *to_sock = *from_sock; 04299 }
| static struct ast_variable* copy_vars | ( | struct ast_variable * | src | ) | [static] |
duplicate a list of channel variables,
Definition at line 12178 of file chan_sip.c.
References ast_variable_new(), and ast_variable::next.
Referenced by check_peer_ok().
12179 { 12180 struct ast_variable *res = NULL, *tmp, *v = NULL; 12181 12182 for (v = src ; v ; v = v->next) { 12183 if ((tmp = ast_variable_new(v->name, v->value, v->file))) { 12184 tmp->next = res; 12185 res = tmp; 12186 } 12187 } 12188 return res; 12189 }
| 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 7717 of file chan_sip.c.
References __get_header(), add_header(), ast_copy_string(), ast_inet_ntoa(), ast_log(), ast_strlen_zero(), ast_test_flag, sip_pvt::flags, LOG_NOTICE, sip_pvt::recv, SIP_NAT, SIP_NAT_ALWAYS, and SIP_NAT_RFC3581.
Referenced by respprep().
07718 { 07719 int copied = 0; 07720 int start = 0; 07721 07722 for (;;) { 07723 char new[512]; 07724 const char *oh = __get_header(orig, field, &start); 07725 07726 if (ast_strlen_zero(oh)) 07727 break; 07728 07729 if (!copied) { /* Only check for empty rport in topmost via header */ 07730 char leftmost[512], *others, *rport; 07731 07732 /* Only work on leftmost value */ 07733 ast_copy_string(leftmost, oh, sizeof(leftmost)); 07734 others = strchr(leftmost, ','); 07735 if (others) 07736 *others++ = '\0'; 07737 07738 /* Find ;rport; (empty request) */ 07739 rport = strstr(leftmost, ";rport"); 07740 if (rport && *(rport+6) == '=') 07741 rport = NULL; /* We already have a parameter to rport */ 07742 07743 /* Check rport if NAT=yes or NAT=rfc3581 (which is the default setting) */ 07744 if (rport && ((ast_test_flag(&p->flags[0], SIP_NAT) == SIP_NAT_ALWAYS) || (ast_test_flag(&p->flags[0], SIP_NAT) == SIP_NAT_RFC3581))) { 07745 /* We need to add received port - rport */ 07746 char *end; 07747 07748 rport = strstr(leftmost, ";rport"); 07749 07750 if (rport) { 07751 end = strchr(rport + 1, ';'); 07752 if (end) 07753 memmove(rport, end, strlen(end) + 1); 07754 else 07755 *rport = '\0'; 07756 } 07757 07758 /* Add rport to first VIA header if requested */ 07759 snprintf(new, sizeof(new), "%s;received=%s;rport=%d%s%s", 07760 leftmost, ast_inet_ntoa(p->recv.sin_addr), 07761 ntohs(p->recv.sin_port), 07762 others ? "," : "", others ? others : ""); 07763 } else { 07764 /* We should *always* add a received to the topmost via */ 07765 snprintf(new, sizeof(new), "%s;received=%s%s%s", 07766 leftmost, ast_inet_ntoa(p->recv.sin_addr), 07767 others ? "," : "", others ? others : ""); 07768 } 07769 oh = new; /* the header to copy */ 07770 } /* else add the following via headers untouched */ 07771 add_header(req, field, oh); 07772 copied++; 07773 } 07774 if (!copied) { 07775 ast_log(LOG_NOTICE, "No header field '%s' present to copy\n", field); 07776 return -1; 07777 } 07778 return 0; 07779 }
| static int create_addr | ( | struct sip_pvt * | dialog, | |
| const char * | opeer, | |||
| struct sockaddr_in * | sin, | |||
| int | newdialog | |||
| ) | [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 4448 of file chan_sip.c.
References ahp, ast_copy_string(), ast_get_srv(), ast_gethostbyname(), ast_log(), ast_string_field_set, ast_strlen_zero(), ast_test_flag, create_addr_from_peer(), do_setnat(), FALSE, find_peer(), FINDPEERS, sip_pvt::flags, get_transport(), hp, LOG_WARNING, MAXHOSTNAMELEN, obproxy_get(), sip_socket::port, sip_pvt::recv, ref_proxy(), sip_pvt::sa, service, SIP_NAT, SIP_NAT_ROUTE, SIP_TRANSPORT_TLS, SIP_TRANSPORT_UDP, sip_pvt::socket, STANDARD_SIP_PORT, STANDARD_TLS_PORT, sip_pvt::timer_b, sip_pvt::timer_t1, sip_peer::tohost, TRUE, sip_socket::type, and unref_peer().
04449 { 04450 struct hostent *hp; 04451 struct ast_hostent ahp; 04452 struct sip_peer *peer; 04453 char *port; 04454 int portno = 0; 04455 char host[MAXHOSTNAMELEN], *hostn; 04456 char peername[256]; 04457 int srv_ret = 0; 04458 04459 ast_copy_string(peername, opeer, sizeof(peername)); 04460 port = strchr(peername, ':'); 04461 if (port) 04462 *port++ = '\0'; 04463 dialog->sa.sin_family = AF_INET; 04464 dialog->timer_t1 = global_t1; /* Default SIP retransmission timer T1 (RFC 3261) */ 04465 dialog->timer_b = global_timer_b; /* Default SIP transaction timer B (RFC 3261) */ 04466 peer = find_peer(peername, NULL, TRUE, FINDPEERS, FALSE); 04467 04468 if (peer) { 04469 int res; 04470 if (newdialog) 04471 dialog->socket.type = 0; 04472 res = create_addr_from_peer(dialog, peer); 04473 if (!ast_strlen_zero(port)) { 04474 if ((portno = atoi(port))) { 04475 dialog->sa.sin_port = dialog->recv.sin_port = htons(portno); 04476 } 04477 } 04478 unref_peer(peer, "create_addr: unref peer from find_peer hashtab lookup"); 04479 return res; 04480 } 04481 04482 do_setnat(dialog, ast_test_flag(&dialog->flags[0], SIP_NAT) & SIP_NAT_ROUTE); 04483 04484 ast_string_field_set(dialog, tohost, peername); 04485 04486 /* Get the outbound proxy information */ 04487 ref_proxy(dialog, obproxy_get(dialog, NULL)); 04488 04489 if (sin) { 04490 /* This address should be updated using dnsmgr */ 04491 memcpy(&dialog->sa.sin_addr, &sin->sin_addr, sizeof(dialog->sa.sin_addr)); 04492 if (!sin->sin_port) { 04493 if (ast_strlen_zero(port) || sscanf(port, "%u", &portno) != 1) { 04494 portno = (dialog->socket.type & SIP_TRANSPORT_TLS) ? 04495 STANDARD_TLS_PORT : STANDARD_SIP_PORT; 04496 } 04497 } else { 04498 portno = ntohs(sin->sin_port); 04499 } 04500 } else { 04501 04502 /* Let's see if we can find the host in DNS. First try DNS SRV records, 04503 then hostname lookup */ 04504 /*! \todo Fix this function. When we ask SRC, we should check all transports 04505 In the future, we should first check NAPTR to find out transport preference 04506 */ 04507 hostn = peername; 04508 /* Section 4.2 of RFC 3263 specifies that if a port number is specified, then 04509 * an A record lookup should be used instead of SRV. 04510 */ 04511 if (!port && global_srvlookup) { 04512 char service[MAXHOSTNAMELEN]; 04513 int tportno; 04514 04515 snprintf(service, sizeof(service), "_sip._%s.%s", get_transport(dialog->socket.type), peername); 04516 srv_ret = ast_get_srv(NULL, host, sizeof(host), &tportno, service); 04517 if (srv_ret > 0) { 04518 hostn = host; 04519 portno = tportno; 04520 } 04521 } 04522 if (!portno) 04523 portno = port ? atoi(port) : (dialog->socket.type & SIP_TRANSPORT_TLS) ? STANDARD_TLS_PORT : STANDARD_SIP_PORT; 04524 hp = ast_gethostbyname(hostn, &ahp); 04525 if (!hp) { 04526 ast_log(LOG_WARNING, "No such host: %s\n", peername); 04527 return -1; 04528 } 04529 memcpy(&dialog->sa.sin_addr, hp->h_addr, sizeof(dialog->sa.sin_addr)); 04530 } 04531 04532 if (!dialog->socket.type) 04533 dialog->socket.type = SIP_TRANSPORT_UDP; 04534 if (!dialog->socket.port) 04535 dialog->socket.port = bindaddr.sin_port; 04536 dialog->sa.sin_port = htons(portno); 04537 dialog->recv = dialog->sa; 04538 return 0; 04539 }
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 4308 of file chan_sip.c.
References sip_peer::addr, sip_peer::allowtransfer, sip_pvt::allowtransfer, ao2_t_link, ao2_t_unlink, ast_copy_flags, AST_FORMAT_VIDEO_MASK, ast_inet_ntoa(), ast_rtp_codec_setpref(), ast_rtp_destroy(), AST_RTP_DTMF, ast_rtp_set_rtpholdtimeout(), ast_rtp_set_rtpkeepalive(), ast_rtp_set_rtptimeout(), ast_rtp_setdtmf(), ast_rtp_setdtmfcompensate(), ast_set_flag, ast_strdupa, ast_string_field_build, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_udptl_destroy(), ast_udptl_new_with_bindaddr(), sip_peer::auth, sip_peer::autoframing, sip_pvt::autoframing, sip_peer::call_limit, sip_peer::callgroup, sip_pvt::callgroup, sip_pvt::callid, t38properties::capability, sip_peer::capability, sip_pvt::capability, check_request_transport, sip_peer::context, context, copy_socket_data(), sip_peer::defaddr, dialogs, do_setnat(), sip_peer::flags, sip_pvt::flags, sip_peer::fromdomain, sip_peer::fromuser, sip_peer::fullcontact, sip_request::headers, sip_pvt::initreq, io, t38properties::jointcapability, sip_pvt::jointnoncodeccapability, language, sip_peer::language, sip_peer::lastms, sip_peer::maxcallbitrate, sip_pvt::maxcallbitrate, sip_peer::maxms, sip_peer::md5secret, sip_peer::mohinterpret, mohinterpret, sip_peer::mohsuggest, mohsuggest, sip_peer::name, sip_pvt::noncodeccapability, obproxy_get(), sip_peer::parkinglot, parkinglot, sip_pvt::peerauth, sip_peer::pickupgroup, sip_pvt::pickupgroup, sip_peer::prefs, sip_pvt::prefs, sip_pvt::recv, ref_proxy(), sip_pvt::rtp, sip_peer::rtpholdtimeout, sip_peer::rtpkeepalive, sip_pvt::rtptimeout, sip_peer::rtptimeout, sip_pvt::sa, sched, sip_peer::secret, set_t38_capabilities(), SIP_CALL_LIMIT, SIP_DTMF, SIP_DTMF_AUTO, SIP_DTMF_RFC2833, SIP_FLAGS_TO_COPY, SIP_NAT, SIP_NAT_ROUTE, SIP_PAGE2_FLAGS_TO_COPY, SIP_PAGE2_RFC2833_COMPENSATE, SIP_PAGE2_T38SUPPORT, SIP_PAGE2_TEXTSUPPORT, SIP_PAGE2_VIDEOSUPPORT, SIP_PAGE2_VIDEOSUPPORT_ALWAYS, sip_peer::socket, sip_pvt::socket, sip_pvt::t38, t38properties::t38support, sip_pvt::timer_b, sip_peer::timer_b, sip_peer::timer_t1, sip_pvt::timer_t1, sip_pvt::tohost, sip_peer::tohost, sip_pvt::trtp, sip_socket::type, sip_pvt::udptl, sip_peer::username, and sip_pvt::vrtp.
Referenced by create_addr(), and sip_send_mwi_to_peer().
04309 { 04310 /* this checks that the dialog is contacting the peer on a valid 04311 * transport type based on the peers transport configuration, 04312 * otherwise, this function bails out */ 04313 if (dialog->socket.type && check_request_transport(peer, dialog)) 04314 return -1; 04315 copy_socket_data(&dialog->socket, &peer->socket); 04316 04317 if ((peer->addr.sin_addr.s_addr || peer->defaddr.sin_addr.s_addr) && 04318 (!peer->maxms || ((peer->lastms >= 0) && (peer->lastms <= peer->maxms)))) { 04319 dialog->sa = (peer->addr.sin_addr.s_addr) ? peer->addr : peer->defaddr; 04320 dialog->recv = dialog->sa; 04321 } else 04322 return -1; 04323 04324 ast_copy_flags(&dialog->flags[0], &peer->flags[0], SIP_FLAGS_TO_COPY); 04325 ast_copy_flags(&dialog->flags[1], &peer->flags[1], SIP_PAGE2_FLAGS_TO_COPY); 04326 dialog->capability = peer->capability; 04327 if (!ast_test_flag(&dialog->flags[1], SIP_PAGE2_VIDEOSUPPORT_ALWAYS) && 04328 (!ast_test_flag(&dialog->flags[1], SIP_PAGE2_VIDEOSUPPORT) || 04329 !(dialog->capability & AST_FORMAT_VIDEO_MASK)) && 04330 dialog->vrtp) { 04331 ast_rtp_destroy(dialog->vrtp); 04332 dialog->vrtp = NULL; 04333 } 04334 if (!ast_test_flag(&dialog->flags[1], SIP_PAGE2_TEXTSUPPORT) && dialog->trtp) { 04335 ast_rtp_destroy(dialog->trtp); 04336 dialog->trtp = NULL; 04337 } 04338 dialog->prefs = peer->prefs; 04339 if (ast_test_flag(&dialog->flags[1], SIP_PAGE2_T38SUPPORT)) { 04340 if (!dialog->udptl) { 04341 /* t38pt_udptl was enabled in the peer and not in [general] */ 04342 dialog->udptl = ast_udptl_new_with_bindaddr(sched, io, 0, bindaddr.sin_addr); 04343 } 04344 ast_copy_flags(&dialog->t38.t38support, &peer->flags[1], SIP_PAGE2_T38SUPPORT); 04345 set_t38_capabilities(dialog); 04346 dialog->t38.jointcapability = dialog->t38.capability; 04347 } else if (dialog->udptl) { 04348 ast_udptl_destroy(dialog->udptl); 04349 dialog->udptl = NULL; 04350 } 04351 do_setnat(dialog, ast_test_flag(&dialog->flags[0], SIP_NAT) & SIP_NAT_ROUTE); 04352 04353 if (dialog->rtp) { /* Audio */ 04354 ast_rtp_setdtmf(dialog->rtp, ast_test_flag(&dialog->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833); 04355 ast_rtp_setdtmfcompensate(dialog->rtp, ast_test_flag(&dialog->flags[1], SIP_PAGE2_RFC2833_COMPENSATE)); 04356 ast_rtp_set_rtptimeout(dialog->rtp, peer->rtptimeout); 04357 ast_rtp_set_rtpholdtimeout(dialog->rtp, peer->rtpholdtimeout); 04358 ast_rtp_set_rtpkeepalive(dialog->rtp, peer->rtpkeepalive); 04359 /* Set Frame packetization */ 04360 ast_rtp_codec_setpref(dialog->rtp, &dialog->prefs); 04361 dialog->autoframing = peer->autoframing; 04362 } 04363 if (dialog->vrtp) { /* Video */ 04364 ast_rtp_setdtmf(dialog->vrtp, 0); 04365 ast_rtp_setdtmfcompensate(dialog->vrtp, 0); 04366 ast_rtp_set_rtptimeout(dialog->vrtp, peer->rtptimeout); 04367 ast_rtp_set_rtpholdtimeout(dialog->vrtp, peer->rtpholdtimeout); 04368 ast_rtp_set_rtpkeepalive(dialog->vrtp, peer->rtpkeepalive); 04369 } 04370 if (dialog->trtp) { /* Realtime text */ 04371 ast_rtp_setdtmf(dialog->trtp, 0); 04372 ast_rtp_setdtmfcompensate(dialog->trtp, 0); 04373 ast_rtp_set_rtptimeout(dialog->trtp, peer->rtptimeout); 04374 ast_rtp_set_rtpholdtimeout(dialog->trtp, peer->rtpholdtimeout); 04375 ast_rtp_set_rtpkeepalive(dialog->trtp, peer->rtpkeepalive); 04376 } 04377 04378 ast_string_field_set(dialog, peername, peer->name); 04379 ast_string_field_set(dialog, authname, peer->username); 04380 ast_string_field_set(dialog, username, peer->username); 04381 ast_string_field_set(dialog, peersecret, peer->secret); 04382 ast_string_field_set(dialog, peermd5secret, peer->md5secret); 04383 ast_string_field_set(dialog, mohsuggest, peer->mohsuggest); 04384 ast_string_field_set(dialog, mohinterpret, peer->mohinterpret); 04385 ast_string_field_set(dialog, tohost, peer->tohost); 04386 ast_string_field_set(dialog, fullcontact, peer->fullcontact); 04387 ast_string_field_set(dialog, context, peer->context); 04388 ast_string_field_set(dialog, parkinglot, peer->parkinglot); 04389 ref_proxy(dialog, obproxy_get(dialog, peer)); 04390 dialog->callgroup = peer->callgroup; 04391 dialog->pickupgroup = peer->pickupgroup; 04392 dialog->allowtransfer = peer->allowtransfer; 04393 dialog->jointnoncodeccapability = dialog->noncodeccapability; 04394 dialog->rtptimeout = peer->rtptimeout; 04395 dialog->peerauth = peer->auth; 04396 dialog->maxcallbitrate = peer->maxcallbitrate; 04397 if (ast_strlen_zero(dialog->tohost)) 04398 ast_string_field_set(dialog, tohost, ast_inet_ntoa(dialog->sa.sin_addr)); 04399 if (!ast_strlen_zero(peer->fromdomain)) { 04400 ast_string_field_set(dialog, fromdomain, peer->fromdomain); 04401 if (!dialog->initreq.headers) { 04402 char *c; 04403 char *tmpcall = ast_strdupa(dialog->callid); 04404 /* this sure looks to me like we are going to change the callid on this dialog!! */ 04405 c = strchr(tmpcall, '@'); 04406 if (c) { 04407 *c = '\0'; 04408 ao2_t_unlink(dialogs, dialog, "About to change the callid -- remove the old name"); 04409 ast_string_field_build(dialog, callid, "%s@%s", tmpcall, peer->fromdomain); 04410 ao2_t_link(dialogs, dialog, "New dialog callid -- inserted back into table"); 04411 } 04412 } 04413 } 04414 if (!ast_strlen_zero(peer->fromuser)) 04415 ast_string_field_set(dialog, fromuser, peer->fromuser); 04416 if (!ast_strlen_zero(peer->language)) 04417 ast_string_field_set(dialog, language, peer->language); 04418 /* Set timer T1 to RTT for this peer (if known by qualify=) */ 04419 /* Minimum is settable or default to 100 ms */ 04420 /* If there is a maxms and lastms from a qualify use that over a manual T1 04421 value. Otherwise, use the peer's T1 value. */ 04422 if (peer->maxms && peer->lastms) 04423 dialog->timer_t1 = peer->lastms < global_t1min ? global_t1min : peer->lastms; 04424 else 04425 dialog->timer_t1 = peer->timer_t1; 04426 04427 /* Set timer B to control transaction timeouts, the peer setting is the default and overrides 04428 the known timer */ 04429 if (peer->timer_b) 04430 dialog->timer_b = peer->timer_b; 04431 else 04432 dialog->timer_b = 64 * dialog->timer_t1; 04433 04434 if ((ast_test_flag(&dialog->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833) || 04435 (ast_test_flag(&dialog->flags[0], SIP_DTMF) == SIP_DTMF_AUTO)) 04436 dialog->noncodeccapability |= AST_RTP_DTMF; 04437 else 04438 dialog->noncodeccapability &= ~AST_RTP_DTMF; 04439 if (peer->call_limit) 04440 ast_set_flag(&dialog->flags[0], SIP_CALL_LIMIT); 04441 04442 return 0; 04443 }
| static void destroy_association | ( | struct sip_peer * | peer | ) | [static] |
Remove registration data from realtime database or AST/DB when registration expires.
Definition at line 10377 of file chan_sip.c.
References ast_check_realtime(), ast_db_del(), ast_update_realtime(), sip_peer::deprecated_username, sip_settings::ignore_regexpire, sip_peer::name, sip_settings::peer_rtupdate, sip_peer::rt_fromcontact, SENTINEL, and sip_cfg.
Referenced by build_peer(), expire_register(), and parse_register_contact().
10378 { 10379 int realtimeregs = ast_check_realtime("sipregs"); 10380 char *tablename = (realtimeregs) ? "sipregs" : "sippeers"; 10381 10382 if (!sip_cfg.ignore_regexpire) { 10383 if (peer->rt_fromcontact && sip_cfg.peer_rtupdate) { 10384 ast_update_realtime(tablename, "name", peer->name, "fullcontact", "", "ipaddr", "", "port", "", "regseconds", "0", peer->deprecated_username ? "username" : "defaultuser", "", "regserver", "", "useragent", "", "lastms", "", SENTINEL); 10385 } else { 10386 ast_db_del("SIP/Registry", peer->name); 10387 } 10388 } 10389 }
| static void destroy_mailbox | ( | struct sip_mailbox * | mailbox | ) | [static] |
Destroy mailbox subscriptions
Definition at line 3831 of file chan_sip.c.
References ast_event_unsubscribe(), ast_free, and mailbox.
Referenced by clear_peer_mailboxes().
03832 { 03833 if (mailbox->mailbox) 03834 ast_free(mailbox->mailbox); 03835 if (mailbox->context) 03836 ast_free(mailbox->context); 03837 if (mailbox->event_sub) 03838 ast_event_unsubscribe(mailbox->event_sub); 03839 ast_free(mailbox); 03840 }
| static int determine_firstline_parts | ( | struct sip_request * | req | ) | [static] |
Parse first line of incoming SIP request.
Definition at line 9026 of file chan_sip.c.
References ast_debug, ast_skip_blanks(), ast_skip_nonblanks(), ast_trim_blanks(), sip_request::data, sip_request::rlPart1, sip_request::rlPart2, and ast_str::str.
09027 { 09028 char *e = ast_skip_blanks(req->data->str); /* there shouldn't be any */ 09029 char *local_rlPart1; 09030 09031 if (!*e) 09032 return -1; 09033 req->rlPart1 = e - req->data->str; /* method or protocol */ 09034 local_rlPart1 = e; 09035 e = ast_skip_nonblanks(e); 09036 if (*e) 09037 *e++ = '\0'; 09038 /* Get URI or status code */ 09039 e = ast_skip_blanks(e); 09040 if ( !*e ) 09041 return -1; 09042 ast_trim_blanks(e); 09043 09044 if (!strcasecmp(local_rlPart1, "SIP/2.0") ) { /* We have a response */ 09045 if (strlen(e) < 3) /* status code is 3 digits */ 09046 return -1; 09047 req->rlPart2 = e - req->data->str; 09048 } else { /* We have a request */ 09049 if ( *e == '<' ) { /* XXX the spec says it must not be in <> ! */ 09050 ast_debug(3, "Oops. Bogus uri in <> %s\n", e); 09051 e++; 09052 if (!*e) 09053 return -1; 09054 } 09055 req->rlPart2 = e - req->data->str; /* URI */ 09056 e = ast_skip_nonblanks(e); 09057 if (*e) 09058 *e++ = '\0'; 09059 e = ast_skip_blanks(e); 09060 if (strcasecmp(e, "SIP/2.0") ) { 09061 ast_debug(3, "Skipping packet - Bad request protocol %s\n", e); 09062 return -1; 09063 } 09064 } 09065 return 1; 09066 }
| static int dialog_cmp_cb | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 1749 of file chan_sip.c.
References sip_pvt::callid, CMP_MATCH, and CMP_STOP.
Referenced by load_module().
01750 { 01751 struct sip_pvt *pvt = obj, *pvt2 = arg; 01752 01753 return !strcasecmp(pvt->callid, pvt2->callid) ? CMP_MATCH | CMP_STOP : 0; 01754 }
| static int dialog_dump_func | ( | void * | userobj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 13125 of file chan_sip.c.
References ao2_t_ref, ast_cli(), and sip_pvt::callid.
Referenced by sip_show_objects().
13126 { 13127 struct sip_pvt *pvt = userobj; 13128 int refc = ao2_t_ref(userobj, 0, ""); 13129 int *fd = arg; 13130 13131 ast_cli(*fd, "name: %s\ntype: dialog\nobjflags: %d\nrefcount: %d\n\n", 13132 pvt->callid, 0, refc); 13133 return 0; 13134 }
| static int dialog_hash_cb | ( | const void * | obj, | |
| const int | flags | |||
| ) | [static] |
Definition at line 1739 of file chan_sip.c.
References ast_str_case_hash(), and sip_pvt::callid.
Referenced by load_module().
01740 { 01741 const struct sip_pvt *pvt = obj; 01742 01743 return ast_str_case_hash(pvt->callid); 01744 }
| static int dialog_needdestroy | ( | void * | dialogobj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 13240 of file chan_sip.c.
References ao2_lock(), ao2_unlock(), ast_debug, ast_rtp_get_bridged(), sip_pvt::callid, check_rtp_timeout(), dialog_unlink_all(), dialogs, FALSE, sip_pvt::method, sip_pvt::needdestroy, sip_pvt::owner, sip_pvt::packets, sip_pvt::rtp, sip_methods, sip_pvt_trylock, sip_pvt_unlock, TRUE, and sip_pvt::vrtp.
Referenced by do_monitor().
13241 { 13242 struct sip_pvt *dialog = dialogobj; 13243 time_t *t = arg; 13244 13245 /* log_show_lock(ao2_object_get_lockaddr(dialog)); this is an example of how to use log_show_lock() */ 13246 13247 if (sip_pvt_trylock(dialog)) { 13248 /* In very short-duration calls via sipp, 13249 this path gets executed fairly frequently (3% or so) even in low load 13250 situations; the routines we most commonly fight for a lock with: 13251 sip_answer (7 out of 9) 13252 sip_hangup (2 out of 9) 13253 */ 13254 ao2_unlock(dialogs); 13255 usleep(1); 13256 ao2_lock(dialogs); 13257 13258 /* I had previously returned CMP_STOP here; but changed it to return 13259 a zero instead, because there is no need to stop at the first sign 13260 of trouble. The old algorithm would restart in such circumstances, 13261 but there is no need for this now in astobj2-land. We'll 13262 just skip over this element this time, and catch it on the 13263 next traversal, which is about once a second or so. See the 13264 ao2_callback call in do_monitor. We don't want the number of 13265 dialogs to back up too much between runs. 13266 */ 13267 return 0; 13268 } 13269 13270 /* Check RTP timeouts and kill calls if we have a timeout set and do not get RTP */ 13271 check_rtp_timeout(dialog, *t); 13272 13273 /* If we have sessions that needs to be destroyed, do it now */ 13274 /* Check if we have outstanding requests not responsed to or an active call 13275 - if that's the case, wait with destruction */ 13276 if (dialog->needdestroy && !dialog->packets && !dialog->owner) { 13277 /* We absolutely cannot destroy the rtp struct while a bridge is active or we WILL crash */ 13278 if (dialog->rtp && ast_rtp_get_bridged(dialog->rtp)) { 13279 ast_debug(2, "Bridge still active. Delaying destruction of SIP dialog '%s' Method: %s\n", dialog->callid, sip_methods[dialog->method].text); 13280 sip_pvt_unlock(dialog); 13281 return 0; 13282 } 13283 13284 if (dialog->vrtp && ast_rtp_get_bridged(dialog->vrtp)) { 13285 ast_debug(2, "Bridge still active. Delaying destroy of SIP dialog '%s' Method: %s\n", dialog->callid, sip_methods[dialog->method].text); 13286 sip_pvt_unlock(dialog); 13287 return 0; 13288 } 13289 13290 sip_pvt_unlock(dialog); 13291 /* no, the unlink should handle this: dialog_unref(dialog, "needdestroy: one more refcount decrement to allow dialog to be destroyed"); */ 13292 /* the CMP_MATCH will unlink this dialog from the dialog hash table */ 13293 dialog_unlink_all(dialog, TRUE, FALSE); 13294 return 0; /* the unlink_all should unlink this from the table, so.... no need to return a match */ 13295 } 13296 13297 sip_pvt_unlock(dialog); 13298 13299 return 0; 13300 }
when we create or delete references, make sure to use these functions so we keep track of the refcounts. To simplify the code, we allow a NULL to be passed to dialog_unref().
Definition at line 1450 of file chan_sip.c.
References ao2_ref, ast_log(), and LOG_ERROR.
Referenced by __sip_reliable_xmit(), dialog_unlink_all(), handle_request_invite(), handle_request_subscribe(), handle_response_invite(), manager_sipnotify(), queue_request(), sip_call(), sip_cli_notify(), sip_new(), sip_poke_peer(), sip_scheddestroy(), sip_send_mwi_to_peer(), start_session_timer(), and transmit_register().
01451 { 01452 if (p) 01453 ao2_ref(p, 1); 01454 else 01455 ast_log(LOG_ERROR, "Attempt to Ref a null pointer\n"); 01456 return p; 01457 }
| static void * dialog_unlink_all | ( | struct sip_pvt * | dialog, | |
| int | lockowner, | |||
| int | lockdialoglist | |||
| ) | [static] |
Unlink a dialog from the dialogs container, as well as any other places that it may be currently stored.
Definition at line 2535 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, sip_pvt::autokillid, sip_peer::call, sip_registry::call, dialog_ref(), dialog_unref(), dialogs, sip_pvt::initid, sip_peer::mwipvt, ast_channel::name, sip_pkt::next, sip_pkt::owner, sip_pvt::owner, sip_pvt::packets, sip_pvt::registry, registry_unref(), sip_pvt::relatedpeer, sip_pvt::request_queue_sched_id, sip_pkt::retransid, sched, sip_pvt::stateid, sip_pvt::t38id, ast_channel::tech_pvt, and sip_pvt::waitid.
Referenced by __sip_autodestruct(), 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_register(), and unload_module().
02536 { 02537 struct sip_pkt *cp; 02538 02539 dialog_ref(dialog, "Let's bump the count in the unlink so it doesn't accidentally become dead before we are done"); 02540 02541 ao2_t_unlink(dialogs, dialog, "unlinking dialog via ao2_unlink"); 02542 02543 /* Unlink us from the owner (channel) if we have one */ 02544 if (dialog->owner) { 02545 if (lockowner) 02546 ast_channel_lock(dialog->owner); 02547 ast_debug(1, "Detaching from channel %s\n", dialog->owner->name); 02548 dialog->owner->tech_pvt = dialog_unref(dialog->owner->tech_pvt, "resetting channel dialog ptr in unlink_all"); 02549 if (lockowner) 02550 ast_channel_unlock(dialog->owner); 02551 } 02552 if (dialog->registry) { 02553 if (dialog->registry->call == dialog) 02554 dialog->registry->call = dialog_unref(dialog->registry->call, "nulling out the registry's call dialog field in unlink_all"); 02555 dialog->registry = registry_unref(dialog->registry, "delete dialog->registry"); 02556 } 02557 if (dialog->stateid > -1) { 02558 ast_extension_state_del(dialog->stateid, NULL); 02559 dialog_unref(dialog, "removing extension_state, should unref the associated dialog ptr that was stored there."); 02560 dialog->stateid = -1; /* shouldn't we 'zero' this out? */ 02561 } 02562 /* Remove link from peer to subscription of MWI */ 02563 if (dialog->relatedpeer && dialog->relatedpeer->mwipvt == dialog) 02564 dialog->relatedpeer->mwipvt = dialog_unref(dialog->relatedpeer->mwipvt, "delete ->relatedpeer->mwipvt"); 02565 if (dialog->relatedpeer && dialog->relatedpeer->call == dialog) 02566 dialog->relatedpeer->call = dialog_unref(dialog->relatedpeer->call, "unset the relatedpeer->call field in tandem with relatedpeer field itself"); 02567 02568 /* remove all current packets in this dialog */ 02569 while((cp = dialog->packets)) { 02570 dialog->packets = dialog->packets->next; 02571 AST_SCHED_DEL(sched, cp->retransid); 02572 dialog_unref(cp->owner, "remove all current packets in this dialog, and the pointer to the dialog too as part of __sip_destroy"); 02573 ast_free(cp); 02574 } 02575 02576 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")); 02577 02578 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")); 02579 02580 if (dialog->autokillid > -1) 02581 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")); 02582 02583 if (dialog->request_queue_sched_id > -1) { 02584 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")); 02585 } 02586 02587 if (dialog->t38id > -1) { 02588 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")); 02589 } 02590 02591 dialog_unref(dialog, "Let's unbump the count in the unlink so the poor pvt can disappear if it is time"); 02592 return NULL; 02593 }
Definition at line 1459 of file chan_sip.c.
References ao2_ref.
Referenced by __sip_ack(), __sip_autodestruct(), __sip_destroy(), __sip_reliable_xmit(), auto_congest(), complete_sipch(), dialog_unlink_all(), get_also_info(), handle_invite_replaces(), handle_request_do(), handle_request_invite(), handle_request_subscribe(), handle_response_invite(), handle_response_peerpoke(), handle_response_register(), manager_sipnotify(), proc_session_timer(), queue_request(), reload_config(), restart_session_timer(), retrans_pkt(), sip_call(), sip_cancel_destroy(), sip_cli_notify(), sip_destroy_peer(), sip_hangup(), sip_indicate(), sip_poke_noanswer(), sip_poke_peer(), sip_reg_timeout(), sip_registry_destroy(), sip_reinvite_retry(), sip_request_call(), sip_send_mwi_to_peer(), sip_t38_abort(), start_session_timer(), stop_session_timer(), and transmit_register().
01460 { 01461 if (p) 01462 ao2_ref(p, -1); 01463 return NULL; 01464 }
| static void * do_monitor | ( | void * | data | ) | [static] |
The SIP monitoring thread.
Definition at line 20347 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(), dialogs, FALSE, io, monlock, OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, sched, sip_do_reload(), sip_reload_lock, sipsock, and sipsock_read().
20348 { 20349 int res; 20350 time_t t; 20351 int reloading; 20352 20353 /* Add an I/O event to our SIP UDP socket */ 20354 if (sipsock > -1) 20355 sipsock_read_id = ast_io_add(io, sipsock, sipsock_read, AST_IO_IN, NULL); 20356 20357 /* From here on out, we die whenever asked */ 20358 for(;;) { 20359 /* Check for a reload request */ 20360 ast_mutex_lock(&sip_reload_lock); 20361 reloading = sip_reloading; 20362 sip_reloading = FALSE; 20363 ast_mutex_unlock(&sip_reload_lock); 20364 if (reloading) { 20365 ast_verb(1, "Reloading SIP\n"); 20366 sip_do_reload(sip_reloadreason); 20367 20368 /* Change the I/O fd of our UDP socket */ 20369 if (sipsock > -1) { 20370 if (sipsock_read_id) 20371 sipsock_read_id = ast_io_change(io, sipsock_read_id, sipsock, NULL, 0, NULL); 20372 else 20373 sipsock_read_id = ast_io_add(io, sipsock, sipsock_read, AST_IO_IN, NULL); 20374 } else if (sipsock_read_id) { 20375 ast_io_remove(io, sipsock_read_id); 20376 sipsock_read_id = NULL; 20377 } 20378 } 20379 20380 /* Check for dialogs needing to be killed */ 20381 t = time(NULL); 20382 /* don't scan the dialogs list if it hasn't been a reasonable period 20383 of time since the last time we did it (when MWI is being sent, we can 20384 get back to this point every millisecond or less) 20385 */ 20386 ao2_t_callback(dialogs, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, dialog_needdestroy, &t, 20387 "callback to remove dialogs w/needdestroy"); 20388 20389 /* the old methodology would be to restart the search for dialogs to delete with every 20390 dialog that was found and destroyed, probably because the list contents would change, 20391 so we'd need to restart. This isn't the best thing to do with callbacks. */ 20392 20393 /* XXX TODO The scheduler usage in this module does not have sufficient 20394 * synchronization being done between running the scheduler and places 20395 * scheduling tasks. As it is written, any scheduled item may not run 20396 * any sooner than about 1 second, regardless of whether a sooner time 20397 * was asked for. */ 20398 20399 pthread_testcancel(); 20400 /* Wait for sched or io */ 20401 res = ast_sched_wait(sched); 20402 if ((res < 0) || (res > 1000)) 20403 res = 1000; 20404 res = ast_io_wait(io, res); 20405 if (res > 20) 20406 ast_debug(1, "chan_sip: ast_io_wait ran %d all at once\n", res); 20407 ast_mutex_lock(&monlock); 20408 res = ast_sched_runq(sched); 20409 if (res >= 20) 20410 ast_debug(1, "chan_sip: ast_sched_runq ran %d all at once\n", res); 20411 ast_mutex_unlock(&monlock); 20412 } 20413 20414 /* Never reached */ 20415 return NULL; 20416 }
| 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 15262 of file chan_sip.c.
References ast_calloc, ast_debug, sip_invite_param::auth, auth_headers(), sip_invite_param::authheader, sip_pvt::authtries, sip_pvt::options, reply_digest(), SIP_INVITE, sip_methods, cfsip_methods::text, and transmit_invite().
Referenced by handle_response(), handle_response_invite(), handle_response_notify(), and handle_response_refer().
15263 { 15264 char *header, *respheader; 15265 char digest[1024]; 15266 15267 if (!p->options && !(p->options = ast_calloc(1, sizeof(*p->options)))) 15268 return -2; 15269 15270 p->authtries++; 15271 auth_headers(code, &header, &respheader); 15272 ast_debug(2, "Auth attempt %d on %s\n", p->authtries, sip_methods[sipmethod].text); 15273 memset(digest, 0, sizeof(digest)); 15274 if (reply_digest(p, req, header, sipmethod, digest, sizeof(digest) )) { 15275 /* No way to authenticate */ 15276 return -1; 15277 } 15278 /* Now we have a reply digest */ 15279 p->options->auth = digest; 15280 p->options->authheader = respheader; 15281 return transmit_invite(p, sipmethod, sipmethod == SIP_INVITE, init); 15282 }
| 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 15238 of file chan_sip.c.
References append_history, ast_verbose, auth_headers(), sip_pvt::authtries, sip_pvt::do_history, sip_registry::hostname, sip_pvt::registry, reply_digest(), sip_debug_test_pvt(), SIP_REGISTER, and transmit_register().
Referenced by handle_response_register().
15239 { 15240 char *header, *respheader; 15241 char digest[1024]; 15242 15243 p->authtries++; 15244 auth_headers(code, &header, &respheader); 15245 memset(digest, 0, sizeof(digest)); 15246 if (reply_digest(p, req, header, SIP_REGISTER, digest, sizeof(digest))) { 15247 /* There's nothing to use for authentication */ 15248 /* No digest challenge in request */ 15249 if (sip_debug_test_pvt(p) && p->registry) 15250 ast_verbose("No authentication challenge, sending blank registration to domain/host name %s\n", p->registry->hostname); 15251 /* No old challenge */ 15252 return -1; 15253 } 15254 if (p->do_history) 15255 append_history(p, "RegistryAuth", "Try: %d", p->authtries); 15256 if (sip_debug_test_pvt(p) && p->registry) 15257 ast_verbose("Responding to challenge, registration to domain/host name %s\n", p->registry->hostname); 15258 return transmit_register(p->registry, SIP_REGISTER, digest, respheader); 15259 }
| static void do_setnat | ( | struct sip_pvt * | p, | |
| int | natflags | |||
| ) | [static] |
Set nat mode on the various data sockets.
Definition at line 4213 of file chan_sip.c.
References ast_debug, ast_rtp_setnat(), ast_udptl_setnat(), sip_pvt::rtp, sip_pvt::trtp, sip_pvt::udptl, and sip_pvt::vrtp.
Referenced by check_peer_ok(), create_addr(), create_addr_from_peer(), sip_alloc(), and transmit_response_using_temp().
04214 { 04215 const char *mode = natflags ? "On" : "Off"; 04216 04217 if (p->rtp) { 04218 ast_debug(1, "Setting NAT on RTP to %s\n", mode); 04219 ast_rtp_setnat(p->rtp, natflags); 04220 } 04221 if (p->vrtp) { 04222 ast_debug(1, "Setting NAT on VRTP to %s\n", mode); 04223 ast_rtp_setnat(p->vrtp, natflags); 04224 } 04225 if (p->udptl) { 04226 ast_debug(1, "Setting NAT on UDPTL to %s\n", mode); 04227 ast_udptl_setnat(p->udptl, natflags); 04228 } 04229 if (p->trtp) { 04230 ast_debug(1, "Setting NAT on TRTP to %s\n", mode); 04231 ast_rtp_setnat(p->trtp, natflags); 04232 } 04233 }
| static const char * domain_mode_to_text | ( | const enum domain_mode | mode | ) | [static] |
Print domain mode to cli.
Definition at line 13457 of file chan_sip.c.
References SIP_DOMAIN_AUTO, and SIP_DOMAIN_CONFIG.
Referenced by sip_show_domains().
13458 { 13459 switch (mode) { 13460 case SIP_DOMAIN_AUTO: 13461 return "[Automatic]"; 13462 case SIP_DOMAIN_CONFIG: 13463 return "[Configured]"; 13464 } 13465 13466 return ""; 13467 }
| static const char * dtmfmode2str | ( | int | mode | ) | const [static] |
Convert DTMF mode to printable string.
Definition at line 13181 of file chan_sip.c.
References dtmfstr, and map_x_s().
Referenced by _sip_show_peer(), sip_show_channel(), and sip_show_settings().
| static int expire_register | ( | const void * | data | ) | [static] |
Expire registration of SIP peer.
Definition at line 10392 of file chan_sip.c.
References sip_peer::addr, ao2_t_unlink, ast_debug, AST_DEVICE_UNKNOWN, ast_devstate_changed(), ast_test_flag, destroy_association(), EVENT_FLAG_SYSTEM, sip_peer::expire, FALSE, sip_peer::flags, sip_peer::is_realtime, manager_event, sip_peer::name, peers_by_ip, register_peer_exten(), sip_peer::selfdestruct, SIP_PAGE2_RTAUTOCLEAR, and unref_peer().
Referenced by parse_register_contact(), reg_source_db(), sip_show_sched(), and sip_unregister().
10393 { 10394 struct sip_peer *peer = (struct sip_peer *)data; 10395 10396 if (!peer) /* Hmmm. We have no peer. Weird. */ 10397 return 0; 10398 10399 peer->expire = -1; 10400 memset(&peer->addr, 0, sizeof(peer->addr)); 10401 10402 destroy_association(peer); /* remove registration data from storage */ 10403 10404 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: SIP\r\nPeer: SIP/%s\r\nPeerStatus: Unregistered\r\nCause: Expired\r\n", peer->name); 10405 register_peer_exten(peer, FALSE); /* Remove regexten */ 10406 ast_devstate_changed(AST_DEVICE_UNKNOWN, "SIP/%s", peer->name); 10407 10408 /* Do we need to release this peer from memory? 10409 Only for realtime peers and autocreated peers 10410 */ 10411 if (peer->is_realtime) 10412 ast_debug(3, "-REALTIME- peer expired registration. Name: %s. Realtime peer objects now %d\n", peer->name, rpeerobjs); 10413 10414 if (peer->selfdestruct || 10415 ast_test_flag(&peer->flags[1], SIP_PAGE2_RTAUTOCLEAR)) { 10416 ao2_t_unlink(peers, peer, "ao2_unlink of peer from peers table"); 10417 if (peer->addr.sin_addr.s_addr) { 10418 ao2_t_unlink(peers_by_ip, peer, "ao2_unlink of peer from peers_by_ip table"); 10419 } 10420 } 10421 10422 unref_peer(peer, "removing peer ref for expire_register"); 10423 10424 return 0; 10425 }
| static void extract_uri | ( | struct sip_pvt * | p, | |
| struct sip_request * | req | |||
| ) | [static] |
Check Contact: URI of SIP message.
Definition at line 9125 of file chan_sip.c.
References ast_copy_string(), ast_string_field_set, ast_strlen_zero(), get_header(), get_in_brackets(), remove_uri_parameters(), and SIPBUFSIZE.
Referenced by handle_incoming(), and handle_request_invite().
09126 { 09127 char stripped[SIPBUFSIZE]; 09128 char *c; 09129 09130 ast_copy_string(stripped, get_header(req, "Contact"), sizeof(stripped)); 09131 c = get_in_brackets(stripped); 09132 /* Cut the URI at the at sign after the @, not in the username part */ 09133 c = remove_uri_parameters(c); 09134 if (!ast_strlen_zero(c)) 09135 ast_string_field_set(p, uri, c); 09136 09137 }
| 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 5949 of file chan_sip.c.
References aliases, and ARRAY_LEN.
05950 { 05951 /*! \brief Structure for conversion between compressed SIP and "normal" SIP */ 05952 static const struct cfalias { 05953 char * const fullname; 05954 char * const shortname; 05955 } aliases[] = { 05956 { "Content-Type", "c" }, 05957 { "Content-Encoding", "e" }, 05958 { "From", "f" }, 05959 { "Call-ID", "i" }, 05960 { "Contact", "m" }, 05961 { "Content-Length", "l" }, 05962 { "Subject", "s" }, 05963 { "To", "t" }, 05964 { "Supported", "k" }, 05965 { "Refer-To", "r" }, 05966 { "Referred-By", "b" }, 05967 { "Allow-Events", "u" }, 05968 { "Event", "o" }, 05969 { "Via", "v" }, 05970 { "Accept-Contact", "a" }, 05971 { "Reject-Contact", "j" }, 05972 { "Request-Disposition", "d" }, 05973 { "Session-Expires", "x" }, 05974 { "Identity", "y" }, 05975 { "Identity-Info", "n" }, 05976 }; 05977 int x; 05978 05979 for (x = 0; x < ARRAY_LEN(aliases); x++) { 05980 if (!strcasecmp(aliases[x].fullname, name)) 05981 return aliases[x].shortname; 05982 } 05983 05984 return _default; 05985 }
| static int find_by_name | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 4140 of file chan_sip.c.
References CMP_MATCH, CMP_STOP, FINDALLDEVICES, FINDPEERS, FINDUSERS, sip_peer::name, SIP_TYPE_PEER, SIP_TYPE_USER, peer_finding_info::tmp_peer, sip_peer::type, and peer_finding_info::which_objects.
Referenced by find_peer().
04141 { 04142 struct sip_peer *search = obj; 04143 struct peer_finding_info *pfi = arg; 04144 04145 /* Usernames in SIP uri's are case sensitive. Domains are not */ 04146 if (strcmp(search->name, pfi->tmp_peer.name)) { 04147 return 0; 04148 } 04149 04150 switch (pfi->which_objects) { 04151 case FINDUSERS: 04152 if (!(search->type & SIP_TYPE_USER)) { 04153 return 0; 04154 } 04155 break; 04156 case FINDPEERS: 04157 if (!(search->type & SIP_TYPE_PEER)) { 04158 return 0; 04159 } 04160 break; 04161 case FINDALLDEVICES: 04162 break; 04163 } 04164 04165 return CMP_MATCH | CMP_STOP; 04166 }
| static struct sip_pvt * find_call | ( | struct sip_request * | req, | |
| struct sockaddr_in * | sin, | |||
| const int | intended_method | |||
| ) | [static] |
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 6404 of file chan_sip.c.
References ao2_lock(), ao2_t_callback, ao2_t_find, ao2_unlock(), ast_debug, ast_strlen_zero(), sip_pvt::callid, find_call_cb_arg::callid, CAN_CREATE_DIALOG, dialogs, find_call_cb(), find_call_cb_arg::fromtag, get_header(), gettag(), sip_request::method, find_call_cb_arg::method, OBJ_POINTER, SIP_ACK, sip_alloc(), SIP_BYE, SIP_INFO, sip_methods, SIP_NOTIFY, sip_pvt_lock, sip_pvt_trylock, SIP_REFER, SIP_RESPONSE, find_call_cb_arg::tag, cfsip_methods::text, find_call_cb_arg::totag, and transmit_response_using_temp().
Referenced by handle_request_do().
06405 { 06406 struct sip_pvt *p = NULL; 06407 char *tag = ""; /* note, tag is never NULL */ 06408 char totag[128]; 06409 char fromtag[128]; 06410 struct find_call_cb_arg arg; 06411 const char *callid = get_header(req, "Call-ID"); 06412 const char *from = get_header(req, "From"); 06413 const char *to = get_header(req, "To"); 06414 const char *cseq = get_header(req, "Cseq"); 06415 struct sip_pvt *sip_pvt_ptr; 06416 06417 /* Call-ID, to, from and Cseq are required by RFC 3261. (Max-forwards and via too - ignored now) */ 06418 /* get_header always returns non-NULL so we must use ast_strlen_zero() */ 06419 if (ast_strlen_zero(callid) || ast_strlen_zero(to) || 06420 ast_strlen_zero(from) || ast_strlen_zero(cseq)) 06421 return NULL; /* Invalid packet */ 06422 06423 arg.method = req->method; 06424 arg.callid = callid; 06425 arg.fromtag = fromtag; 06426 arg.totag = totag; 06427 arg.tag = ""; /* make sure tag is never NULL */ 06428 06429 if (pedanticsipchecking) { 06430 /* In principle Call-ID's uniquely identify a call, but with a forking SIP proxy 06431 we need more to identify a branch - so we have to check branch, from 06432 and to tags to identify a call leg. 06433 For Asterisk to behave correctly, you need to turn on pedanticsipchecking 06434 in sip.conf 06435 */ 06436 if (gettag(req, "To", totag, sizeof(totag))) 06437 req->has_to_tag = 1; /* Used in handle_request/response */ 06438 gettag(req, "From", fromtag, sizeof(fromtag)); 06439 06440 tag = (req->method == SIP_RESPONSE) ? totag : fromtag; 06441 06442 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); 06443 06444 /* All messages must always have From: tag */ 06445 if (ast_strlen_zero(fromtag)) { 06446 ast_debug(5, "%s request has no from tag, dropping callid: %s from: %s\n", sip_methods[req->method].text , callid, from ); 06447 return NULL; 06448 } 06449 /* reject requests that must always have a To: tag */ 06450 if (ast_strlen_zero(totag) && (req->method == SIP_ACK || req->method == SIP_BYE || req->method == SIP_INFO )) { 06451 ast_debug(5, "%s must have a to tag. dropping callid: %s from: %s\n", sip_methods[req->method].text , callid, from ); 06452 return NULL; 06453 } 06454 } 06455 06456 restartsearch: 06457 if (!pedanticsipchecking) { 06458 struct sip_pvt tmp_dialog = { 06459 .callid = callid, 06460 }; 06461 sip_pvt_ptr = ao2_t_find(dialogs, &tmp_dialog, OBJ_POINTER, "ao2_find in dialogs"); 06462 if (sip_pvt_ptr) { /* well, if we don't find it-- what IS in there? */ 06463 /* Found the call */ 06464 sip_pvt_lock(sip_pvt_ptr); 06465 return sip_pvt_ptr; 06466 } 06467 } else { /* in pedantic mode! -- do the fancy linear search */ 06468 ao2_lock(dialogs); 06469 p = ao2_t_callback(dialogs, 0 /* single, data */, find_call_cb, &arg, "pedantic linear search for dialog"); 06470 if (p) { 06471 if (sip_pvt_trylock(p)) { 06472 ao2_unlock(dialogs); 06473 usleep(1); 06474 goto restartsearch; 06475 } 06476 ao2_unlock(dialogs); 06477 return p; 06478 } 06479 ao2_unlock(dialogs); 06480 } 06481 06482 /* See if the method is capable of creating a dialog */ 06483 if (sip_methods[intended_method].can_create == CAN_CREATE_DIALOG) { 06484 if (intended_method == SIP_REFER) { 06485 /* We do support REFER, but not outside of a dialog yet */ 06486 transmit_response_using_temp(callid, sin, 1, intended_method, req, "603 Declined (no dialog)"); 06487 } else if (intended_method == SIP_NOTIFY) { 06488 /* We do not support out-of-dialog NOTIFY either, 06489 like voicemail notification, so cancel that early */ 06490 transmit_response_using_temp(callid, sin, 1, intended_method, req, "489 Bad event"); 06491 } else { 06492 /* Ok, time to create a new SIP dialog object, a pvt */ 06493 if ((p = sip_alloc(callid, sin, 1, intended_method))) { 06494 /* Ok, we've created a dialog, let's go and process it */ 06495 sip_pvt_lock(p); 06496 } else { 06497 /* We have a memory or file/socket error (can't allocate RTP sockets or something) so we're not 06498 getting a dialog from sip_alloc. 06499 06500 Without a dialog we can't retransmit and handle ACKs and all that, but at least 06501 send an error message. 06502 06503 Sorry, we apologize for the inconvienience 06504 */ 06505 transmit_response_using_temp(callid, sin, 1, intended_method, req, "500 Server internal error"); 06506 ast_debug(4, "Failed allocating SIP dialog, sending 500 Server internal error and giving up\n"); 06507 } 06508 } 06509 return p; /* can be NULL */ 06510 } else if( sip_methods[intended_method].can_create == CAN_CREATE_DIALOG_UNSUPPORTED_METHOD) { 06511 /* A method we do not support, let's take it on the volley */ 06512 transmit_response_using_temp(callid, sin, 1, intended_method, req, "501 Method Not Implemented"); 06513 ast_debug(2, "Got a request with unsupported SIP method.\n"); 06514 } else if (intended_method != SIP_RESPONSE && intended_method != SIP_ACK) { 06515 /* This is a request outside of a dialog that we don't know about */ 06516 transmit_response_using_temp(callid, sin, 1, intended_method, req, "481 Call leg/transaction does not exist"); 06517 ast_debug(2, "That's odd... Got a request in unknown dialog. Callid %s\n", callid ? callid : "<unknown>"); 06518 } 06519 /* We do not respond to responses for dialogs that we don't know about, we just drop 06520 the session quickly */ 06521 if (intended_method == SIP_RESPONSE) 06522 ast_debug(2, "That's odd... Got a response on a call we dont know about. Callid %s\n", callid ? callid : "<unknown>"); 06523 06524 return NULL; 06525 }
| static int find_call_cb | ( | void * | __pvt, | |
| void * | __arg, | |||
| int | flags | |||
| ) | [static] |
code to determine whether this is the pvt that we are looking for. Return FALSE if not found, true otherwise. p is unlocked.
Definition at line 6363 of file chan_sip.c.
References ast_debug, ast_strlen_zero(), ast_test_flag, find_call_cb_arg::callid, sip_pvt::callid, FALSE, sip_pvt::flags, find_call_cb_arg::method, sip_methods, SIP_PAGE2_DIALOG_ESTABLISHED, SIP_REGISTER, SIP_RESPONSE, sip_pvt::tag, find_call_cb_arg::tag, sip_pvt::theirtag, and find_call_cb_arg::totag.
Referenced by find_call().
06364 { 06365 struct sip_pvt *p = __pvt; 06366 struct find_call_cb_arg *arg = __arg; 06367 /* In pedantic, we do not want packets with bad syntax to be connected to a PVT */ 06368 int found = FALSE; 06369 06370 if (!ast_strlen_zero(p->callid)) { /* XXX double check, do we allow match on empty p->callid ? */ 06371 if (arg->method == SIP_REGISTER) 06372 found = (!strcmp(p->callid, arg->callid)); 06373 else { 06374 found = !strcmp(p->callid, arg->callid); 06375 if (pedanticsipchecking && found) { 06376 found = ast_strlen_zero(arg->tag) || ast_strlen_zero(p->theirtag) || !ast_test_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED) || !strcmp(p->theirtag, arg->tag); 06377 } 06378 } 06379 06380 ast_debug(5, "= %s Their Call ID: %s Their Tag %s Our tag: %s\n", found ? "Found" : "No match", p->callid, p->theirtag, p->tag); 06381 06382 /* If we get a new request within an existing to-tag - check the to tag as well */ 06383 if (pedanticsipchecking && found && arg->method != SIP_RESPONSE) { /* SIP Request */ 06384 if (p->tag[0] == '\0' && arg->totag[0]) { 06385 /* We have no to tag, but they have. Wrong dialog */ 06386 found = FALSE; 06387 } else if (arg->totag[0]) { /* Both have tags, compare them */ 06388 if (strcmp(arg->totag, p->tag)) { 06389 found = FALSE; /* This is not our packet */ 06390 } 06391 } 06392 if (!found) 06393 ast_debug(5, "= Being pedantic: This is not our match on request: Call ID: %s Ourtag <null> Totag %s Method %s\n", p->callid, arg->totag, sip_methods[arg->method].text); 06394 } 06395 } 06396 return found; 06397 }
| static const char* find_closing_quote | ( | const char * | start, | |
| const char * | lim | |||
| ) | [static] |
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 3545 of file chan_sip.c.
References s.
Referenced by get_in_brackets().
03546 { 03547 char last_char = '\0'; 03548 const char *s; 03549 for (s = start; *s && s != lim; last_char = *s++) { 03550 if (*s == '"' && last_char != '\\') 03551 break; 03552 } 03553 return s; 03554 }
| static struct sip_peer * find_peer | ( | const char * | peer, | |
| struct sockaddr_in * | sin, | |||
| int | realtime, | |||
| int | which_objects, | |||
| int | devstate_only | |||
| ) | [static] |
Locate device by name or ip address.
| 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 4181 of file chan_sip.c.
References sip_peer::addr, ao2_t_callback, ao2_t_find, ast_copy_string(), ast_set_flag, find_by_name(), ast_flags::flags, sip_peer::flags, sip_peer::name, OBJ_POINTER, peers_by_ip, realtime_peer(), SIP_INSECURE_PORT, peer_finding_info::tmp_peer, and peer_finding_info::which_objects.
04182 { 04183 struct sip_peer *p = NULL; 04184 04185 if (peer) { 04186 struct peer_finding_info pfi = { 04187 .which_objects = which_objects, 04188 }; 04189 ast_copy_string(pfi.tmp_peer.name, peer, sizeof(pfi.tmp_peer.name)); 04190 p = ao2_t_callback(peers, OBJ_POINTER, find_by_name, &pfi, "ao2_callback in peers table"); 04191 } else if (sin) { /* search by addr? */ 04192 struct sip_peer tmp_peer; 04193 tmp_peer.addr.sin_addr.s_addr = sin->sin_addr.s_addr; 04194 tmp_peer.addr.sin_port = sin->sin_port; 04195 tmp_peer.flags[0].flags = 0; 04196 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); */ 04197 if (!p) { 04198 ast_set_flag(&tmp_peer.flags[0], SIP_INSECURE_PORT); 04199 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); */ 04200 if (p) { 04201 return p; 04202 } 04203 } 04204 } 04205 04206 if (!p && (realtime || devstate_only)) 04207 p = realtime_peer(peer, sin, devstate_only); 04208 04209 return p; 04210 }
| static struct sip_auth * find_realm_authentication | ( | struct sip_auth * | authlist, | |
| const char * | realm | |||
| ) | [static] |
Find authentication for a specific realm.
Definition at line 21441 of file chan_sip.c.
References sip_auth::next, and sip_auth::realm.
Referenced by build_reply_digest().
21442 { 21443 struct sip_auth *a; 21444 21445 for (a = authlist; a; a = a->next) { 21446 if (!strcasecmp(a->realm, realm)) 21447 break; 21448 } 21449 21450 return a; 21451 }
| 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 6755 of file chan_sip.c.
References ast_log(), ast_strdupa, ast_strlen_zero(), FALSE, get_header(), sip_request::lines, LOG_WARNING, REQ_OFFSET_TO_STR, sip_request::sdp_end, sip_request::sdp_start, strcasestr(), and TRUE.
Referenced by handle_incoming(), handle_request_invite(), handle_response(), and handle_response_invite().
06756 { 06757 const char *content_type; 06758 const char *content_length; 06759 const char *search; 06760 char *boundary; 06761 unsigned int x; 06762 int boundaryisquoted = FALSE; 06763 int found_application_sdp = FALSE; 06764 int found_end_of_headers = FALSE; 06765 06766 content_length = get_header(req, "Content-Length"); 06767 06768 if (!ast_strlen_zero(content_length)) { 06769 if (sscanf(content_length, "%ud", &x) != 1) { 06770 ast_log(LOG_WARNING, "Invalid Content-Length: %s\n", content_length); 06771 return 0; 06772 } 06773 06774 /* Content-Length of zero means there can't possibly be an 06775 SDP here, even if the Content-Type says there is */ 06776 if (x == 0) 06777 return 0; 06778 } 06779 06780 content_type = get_header(req, "Content-Type"); 06781 06782 /* if the body contains only SDP, this is easy */ 06783 if (!strncasecmp(content_type, "application/sdp", 15)) { 06784 req->sdp_start = 0; 06785 req->sdp_end = req->lines; 06786 return req->lines ? 1 : 0; 06787 } 06788 06789 /* if it's not multipart/mixed, there cannot be an SDP */ 06790 if (strncasecmp(content_type, "multipart/mixed", 15)) 06791 return 0; 06792 06793 /* if there is no boundary marker, it's invalid */ 06794 if ((search = strcasestr(content_type, ";boundary="))) 06795 search += 10; 06796 else if ((search = strcasestr(content_type, "; boundary="))) 06797 search += 11; 06798 else 06799 return 0; 06800 06801 if (ast_strlen_zero(search)) 06802 return 0; 06803 06804 /* If the boundary is quoted with ", remove quote */ 06805 if (*search == '\"') { 06806 search++; 06807 boundaryisquoted = TRUE; 06808 } 06809 06810 /* make a duplicate of the string, with two extra characters 06811 at the beginning */ 06812 boundary = ast_strdupa(search - 2); 06813 boundary[0] = boundary[1] = '-'; 06814 /* Remove final quote */ 06815 if (boundaryisquoted) 06816 boundary[strlen(boundary) - 1] = '\0'; 06817 06818 /* search for the boundary marker, the empty line delimiting headers from 06819 sdp part and the end boundry if it exists */ 06820 06821 for (x = 0; x < (req->lines); x++) { 06822 char *line = REQ_OFFSET_TO_STR(req, line[x]); 06823 if (!strncasecmp(line, boundary, strlen(boundary))){ 06824 if (found_application_sdp && found_end_of_headers) { 06825 req->sdp_end = x-1; 06826 return 1; 06827 } 06828 found_application_sdp = FALSE; 06829 } 06830 if (!strcasecmp(line, "Content-Type: application/sdp")) 06831 found_application_sdp = TRUE; 06832 06833 if (ast_strlen_zero(line)) { 06834 if (found_application_sdp && !found_end_of_headers){ 06835 req->sdp_start = x; 06836 found_end_of_headers = TRUE; 06837 } 06838 } 06839 } 06840 if (found_application_sdp && found_end_of_headers) { 06841 req->sdp_end = x; 06842 return TRUE; 06843 } 06844 return FALSE; 06845 }
| static int find_sip_method | ( | const char * | msg | ) | [static] |
find_sip_method: Find SIP method from header
Definition at line 2716 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(), and handle_response().
02717 { 02718 int i, res = 0; 02719 02720 if (ast_strlen_zero(msg)) 02721 return 0; 02722 for (i = 1; i < ARRAY_LEN(sip_methods) && !res; i++) { 02723 if (method_match(i, msg)) 02724 res = sip_methods[i].id; 02725 } 02726 return res; 02727 }
| static struct cfsubscription_types * find_subscription_type | ( | enum subscriptiontype | subtype | ) | [static] |
Find subscription type in array.
Definition at line 14386 of file chan_sip.c.
References ARRAY_LEN, and subscription_types.
Referenced by transmit_state_notify().
14387 { 14388 int i; 14389 14390 for (i = 1; i < ARRAY_LEN(subscription_types); i++) { 14391 if (subscription_types[i].type == subtype) { 14392 return &subscription_types[i]; 14393 } 14394 } 14395 return &subscription_types[0]; 14396 }
| static void free_old_route | ( | struct sip_route * | route | ) | [static] |
Remove route from route list.
Definition at line 10757 of file chan_sip.c.
References ast_free, sip_route::next, and sip_request::next.
Referenced by __sip_destroy(), and build_route().
10758 { 10759 struct sip_route *next; 10760 10761 while (route) { 10762 next = route->next; 10763 ast_free(route); 10764 route = next; 10765 } 10766 }
| 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 15504 of file chan_sip.c.
References ast_copy_string(), ast_log(), ast_strlen_zero(), check_sip_domain(), and LOG_WARNING.
15505 { 15506 if (ast_strlen_zero(data)) { 15507 ast_log(LOG_WARNING, "CHECKSIPDOMAIN requires an argument - A domain name\n"); 15508 return -1; 15509 } 15510 if (check_sip_domain(data, NULL, 0)) 15511 ast_copy_string(buf, data, len); 15512 else 15513 buf[0] = '\0'; 15514 return 0; 15515 }
| 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 15440 of file chan_sip.c.
References __get_header(), 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(), chan, sip_request::header, sip_pvt::initreq, IS_SIP_TECH, LOG_WARNING, ast_channel::tech, and ast_channel::tech_pvt.
15441 { 15442 struct sip_pvt *p; 15443 const char *content = NULL; 15444 AST_DECLARE_APP_ARGS(args, 15445 AST_APP_ARG(header); 15446 AST_APP_ARG(number); 15447 ); 15448 int i, number, start = 0; 15449 15450 if (ast_strlen_zero(data)) { 15451 ast_log(LOG_WARNING, "This function requires a header name.\n"); 15452 return -1; 15453 } 15454 15455 ast_channel_lock(chan); 15456 if (!IS_SIP_TECH(chan->tech)) { 15457 ast_log(LOG_WARNING, "This function can only be used on SIP channels.\n"); 15458 ast_channel_unlock(chan); 15459 return -1; 15460 } 15461 15462 AST_STANDARD_APP_ARGS(args, data); 15463 if (!args.number) { 15464 number = 1; 15465 } else { 15466 sscanf(args.number, "%d", &number); 15467 if (number < 1) 15468 number = 1; 15469 } 15470 15471 p = chan->tech_pvt; 15472 15473 /* If there is no private structure, this channel is no longer alive */ 15474 if (!p) { 15475 ast_channel_unlock(chan); 15476 return -1; 15477 } 15478 15479 for (i = 0; i < number; i++) 15480 content = __get_header(&p->initreq, args.header, &start); 15481 15482 if (ast_strlen_zero(content)) { 15483 ast_channel_unlock(chan); 15484 return -1; 15485 } 15486 15487 ast_copy_string(buf, content, len); 15488 ast_channel_unlock(chan); 15489 15490 return 0; 15491 }
| 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 15648 of file chan_sip.c.
References ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_inet_ntoa(), ast_log(), chan, sip_pvt::from, IS_SIP_TECH, LOG_WARNING, sip_pvt::peername, sip_pvt::recv, sip_pvt::sa, t38properties::state, sip_pvt::t38, T38_DISABLED, ast_channel::tech, ast_channel::tech_pvt, sip_pvt::uri, and sip_pvt::useragent.
15649 { 15650 struct sip_pvt *p; 15651 static int deprecated = 0; 15652 15653 *buf = 0; 15654 15655 if (!data) { 15656 ast_log(LOG_WARNING, "This function requires a parameter name.\n"); 15657 return -1; 15658 } 15659 15660 ast_channel_lock(chan); 15661 if (!IS_SIP_TECH(chan->tech)) { 15662 ast_log(LOG_WARNING, "This function can only be used on SIP channels.\n"); 15663 ast_channel_unlock(chan); 15664 return -1; 15665 } 15666 15667 if (deprecated++ % 20 == 0) { 15668 /* Deprecated in 1.6.1 */ 15669 ast_log(LOG_WARNING, "SIPCHANINFO() is deprecated. Please transition to using CHANNEL().\n"); 15670 } 15671 15672 p = chan->tech_pvt; 15673 15674 /* If there is no private structure, this channel is no longer alive */ 15675 if (!p) { 15676 ast_channel_unlock(chan); 15677 return -1; 15678 } 15679 15680 if (!strcasecmp(data, "peerip")) { 15681 ast_copy_string(buf, p->sa.sin_addr.s_addr ? ast_inet_ntoa(p->sa.sin_addr) : "", len); 15682 } else if (!strcasecmp(data, "recvip")) { 15683 ast_copy_string(buf, p->recv.sin_addr.s_addr ? ast_inet_ntoa(p->recv.sin_addr) : "", len); 15684 } else if (!strcasecmp(data, "from")) { 15685 ast_copy_string(buf, p->from, len); 15686 } else if (!strcasecmp(data, "uri")) { 15687 ast_copy_string(buf, p->uri, len); 15688 } else if (!strcasecmp(data, "useragent")) { 15689 ast_copy_string(buf, p->useragent, len); 15690 } else if (!strcasecmp(data, "peername")) { 15691 ast_copy_string(buf, p->peername, len); 15692 } else if (!strcasecmp(data, "t38passthrough")) { 15693 if (p->t38.state == T38_DISABLED) 15694 ast_copy_string(buf, "0", sizeof("0")); 15695 else /* T38 is offered or enabled in this call */ 15696 ast_copy_string(buf, "1", sizeof("1")); 15697 } else { 15698 ast_channel_unlock(chan); 15699 return -1; 15700 } 15701 ast_channel_unlock(chan); 15702 15703 return 0; 15704 }
| 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 15529 of file chan_sip.c.
References sip_peer::accountcode, sip_peer::addr, ast_codec_pref_index(), ast_copy_string(), ast_getformatname(), ast_getformatname_multiple(), ast_inet_ntoa(), ast_log(), ast_print_group(), ast_str_alloca, sip_peer::busy_level, sip_peer::call_limit, sip_peer::callgroup, sip_peer::capability, chanvar, sip_peer::chanvars, sip_peer::cid_name, sip_peer::cid_num, sip_peer::context, sip_peer::expire, FALSE, find_peer(), FINDPEERS, sip_peer::host_dynamic, sip_peer::inUse, sip_peer::language, LOG_WARNING, ast_variable::name, ast_variable::next, peer_mailboxes_to_str(), peer_status(), sip_peer::pickupgroup, sip_peer::prefs, sip_peer::regexten, ast_str::str, strsep(), TRUE, unref_peer(), sip_peer::useragent, and ast_variable::value.
15530 { 15531 struct sip_peer *peer; 15532 char *colname; 15533 15534 if ((colname = strchr(data, ':'))) { /*! \todo Will be deprecated after 1.4 */ 15535 static int deprecation_warning = 0; 15536 *colname++ = '\0'; 15537 if (deprecation_warning++ % 10 == 0) 15538 ast_log(LOG_WARNING, "SIPPEER(): usage of ':' to separate arguments is deprecated. Please use ',' instead.\n"); 15539 } else if ((colname = strchr(data, ','))) 15540 *colname++ = '\0'; 15541 else 15542 colname = "ip"; 15543 15544 if (!(peer = find_peer(data, NULL, TRUE, FINDPEERS, FALSE))) 15545 return -1; 15546 15547 if (!strcasecmp(colname, "ip")) { 15548 ast_copy_string(buf, peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "", len); 15549 } else if (!strcasecmp(colname, "port")) { 15550 snprintf(buf, len, "%d", ntohs(peer->addr.sin_port)); 15551 } else if (!strcasecmp(colname, "status")) { 15552 peer_status(peer, buf, len); 15553 } else if (!strcasecmp(colname, "language")) { 15554 ast_copy_string(buf, peer->language, len); 15555 } else if (!strcasecmp(colname, "regexten")) { 15556 ast_copy_string(buf, peer->regexten, len); 15557 } else if (!strcasecmp(colname, "limit")) { 15558 snprintf(buf, len, "%d", peer->call_limit); 15559 } else if (!strcasecmp(colname, "busylevel")) { 15560 snprintf(buf, len, "%d", peer->busy_level); 15561 } else if (!strcasecmp(colname, "curcalls")) { 15562 snprintf(buf, len, "%d", peer->inUse); 15563 } else if (!strcasecmp(colname, "accountcode")) { 15564 ast_copy_string(buf, peer->accountcode, len); 15565 } else if (!strcasecmp(colname, "callgroup")) { 15566 ast_print_group(buf, len, peer->callgroup); 15567 } else if (!strcasecmp(colname, "pickupgroup")) { 15568 ast_print_group(buf, len, peer->pickupgroup); 15569 } else if (!strcasecmp(colname, "useragent")) { 15570 ast_copy_string(buf, peer->useragent, len); 15571 } else if (!strcasecmp(colname, "mailbox")) { 15572 struct ast_str *mailbox_str = ast_str_alloca(512); 15573 peer_mailboxes_to_str(&mailbox_str, peer); 15574 ast_copy_string(buf, mailbox_str->str, len); 15575 } else if (!strcasecmp(colname, "context")) { 15576 ast_copy_string(buf, peer->context, len); 15577 } else if (!strcasecmp(colname, "expire")) { 15578 snprintf(buf, len, "%d", peer->expire); 15579 } else if (!strcasecmp(colname, "dynamic")) { 15580 ast_copy_string(buf, peer->host_dynamic ? "yes" : "no", len); 15581 } else if (!strcasecmp(colname, "callerid_name")) { 15582 ast_copy_string(buf, peer->cid_name, len); 15583 } else if (!strcasecmp(colname, "callerid_num")) { 15584 ast_copy_string(buf, peer->cid_num, len); 15585 } else if (!strcasecmp(colname, "codecs")) { 15586 ast_getformatname_multiple(buf, len -1, peer->capability); 15587 } else if (!strncasecmp(colname, "chanvar[", 8)) { 15588 char *chanvar=colname + 8; 15589 struct ast_variable *v; 15590 15591 chanvar = strsep(&chanvar, "]"); 15592 for (v = peer->chanvars ; v ; v = v->next) 15593 if (!strcasecmp(v->name, chanvar)) 15594 ast_copy_string(buf, v->value, len); 15595 } else if (!strncasecmp(colname, "codec[", 6)) { 15596 char *codecnum; 15597 int codec = 0; 15598 15599 codecnum = colname + 6; /* move past the '[' */ 15600 codecnum = strsep(&codecnum, "]"); /* trim trailing ']' if any */ 15601 if((codec = ast_codec_pref_index(&peer->prefs, atoi(codecnum)))) { 15602 ast_copy_string(buf, ast_getformatname(codec), len); 15603 } else { 15604 buf[0] = '\0'; 15605 } 15606 } else { 15607 buf[0] = '\0'; 15608 } 15609 15610 unref_peer(peer, "unref_peer from function_sippeer, just before return"); 15611 15612 return 0; 15613 }
| static char * generate_random_string | ( | char * | buf, | |
| size_t | size | |||
| ) | [static] |
Generate 32 byte random string for callid's etc.
Definition at line 6150 of file chan_sip.c.
References ast_random().
Referenced by build_callid_pvt(), and build_callid_registry().
06151 { 06152 long val[4]; 06153 int x; 06154 06155 for (x=0; x<4; x++) 06156 val[x] = ast_random(); 06157 snprintf(buf, size, "%08lx%08lx%08lx%08lx", val[0], val[1], val[2], val[3]); 06158 06159 return buf; 06160 }
| 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 11946 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_uri_decode(), ast_verbose, context, sip_pvt::context, dialog_unref(), get_header(), get_in_brackets(), sip_pvt::initreq, LOG_WARNING, ast_channel::macrocontext, sip_pvt::owner, pbx_builtin_getvar_helper(), sip_pvt::refer, sip_refer::refer_call, sip_refer::refer_contact, sip_refer::refer_to, sip_refer::refer_to_domain, sip_refer::referred_by, S_OR, sip_debug_test_pvt(), and sip_refer_allocate().
Referenced by handle_request_bye().
11947 { 11948 char tmp[256] = "", *c, *a; 11949 struct sip_request *req = oreq ? oreq : &p->initreq; 11950 struct sip_refer *referdata = NULL; 11951 const char *transfer_context = NULL; 11952 11953 if (!p->refer && !sip_refer_allocate(p)) 11954 return -1; 11955 11956 referdata = p->refer; 11957 11958 ast_copy_string(tmp, get_header(req, "Also"), sizeof(tmp)); 11959 c = get_in_brackets(tmp); 11960 11961 if (pedanticsipchecking) 11962 ast_uri_decode(c); 11963 11964 if (!strncasecmp(c, "sip:", 4)) { 11965 c += 4; 11966 } else if (!strncasecmp(c, "sips:", 5)) { 11967 c += 5; 11968 } else { 11969 ast_log(LOG_WARNING, "Huh? Not a SIP header in Also: transfer (%s)?\n", c); 11970 return -1; 11971 } 11972 11973 if ((a = strchr(c, ';'))) /* Remove arguments */ 11974 *a = '\0'; 11975 11976 if ((a = strchr(c, '@'))) { /* Separate Domain */ 11977 *a++ = '\0'; 11978 ast_copy_string(referdata->refer_to_domain, a, sizeof(referdata->refer_to_domain)); 11979 } 11980 11981 if (sip_debug_test_pvt(p)) 11982 ast_verbose("Looking for %s in %s\n", c, p->context); 11983 11984 if (p->owner) /* Mimic behaviour in res_features.c */ 11985 transfer_context = pbx_builtin_getvar_helper(p->owner, "TRANSFER_CONTEXT"); 11986 11987 /* By default, use the context in the channel sending the REFER */ 11988 if (ast_strlen_zero(transfer_context)) { 11989 transfer_context = S_OR(p->owner->macrocontext, 11990 S_OR(p->context, default_context)); 11991 } 11992 if (ast_exists_extension(NULL, transfer_context, c, 1, NULL)) { 11993 /* This is a blind transfer */ 11994 ast_debug(1, "SIP Bye-also transfer to Extension %s@%s \n", c, transfer_context); 11995 ast_copy_string(referdata->refer_to, c, sizeof(referdata->refer_to)); 11996 ast_copy_string(referdata->referred_by, "", sizeof(referdata->referred_by)); 11997 ast_copy_string(referdata->refer_contact, "", sizeof(referdata->refer_contact)); 11998 referdata->refer_call = dialog_unref(referdata->refer_call, "unreffing referdata->refer_call"); 11999 /* Set new context */ 12000 ast_string_field_set(p, context, transfer_context); 12001 return 0; 12002 } else if (ast_canmatch_extension(NULL, p->context, c, 1, NULL)) { 12003 return 1; 12004 } 12005 12006 return -1; 12007 }
| static char* get_body | ( | struct sip_request * | req, | |
| char * | name | |||
| ) | [static] |
Get a specific line from the message body.
Definition at line 5933 of file chan_sip.c.
References get_body_by_line(), sip_request::len, sip_request::lines, and REQ_OFFSET_TO_STR.
Referenced by handle_request_info().
05934 { 05935 int x; 05936 int len = strlen(name); 05937 char *r; 05938 05939 for (x = 0; x < req->lines; x++) { 05940 r = get_body_by_line(REQ_OFFSET_TO_STR(req, line[x]), name, len); 05941 if (r[0] != '\0') 05942 return r; 05943 } 05944 05945 return ""; 05946 }
| static char* get_body_by_line | ( | const char * | line, | |
| const char * | name, | |||
| int | nameLen | |||
| ) | [static] |
Reads one line of SIP message body.
Definition at line 5899 of file chan_sip.c.
References ast_skip_blanks().
Referenced by get_body(), and get_sdp_iterate().
05900 { 05901 if (!strncasecmp(line, name, nameLen) && line[nameLen] == '=') 05902 return ast_skip_blanks(line + nameLen + 1); 05903 05904 return ""; 05905 }
| 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 20190 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, sip_mailbox::entry, mailbox, sip_peer::mailboxes, and S_OR.
Referenced by sip_send_mwi_to_peer().
20191 { 20192 struct sip_mailbox *mailbox; 20193 20194 AST_LIST_TRAVERSE(&peer->mailboxes, mailbox, entry) { 20195 struct ast_event *event; 20196 event = ast_event_get_cached(AST_EVENT_MWI, 20197 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox->mailbox, 20198 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, S_OR(mailbox->context, "default"), 20199 AST_EVENT_IE_END); 20200 if (!event) 20201 continue; 20202 *new += ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS); 20203 *old += ast_event_get_ie_uint(event, AST_EVENT_IE_OLDMSGS); 20204 ast_event_destroy(event); 20205 } 20206 20207 return (*new || *old) ? 0 : 1; 20208 }
| static char * get_calleridname | ( | const char * | input, | |
| char * | output, | |||
| size_t | outputsize | |||
| ) | [static] |
Get caller id name from SIP headers.
Definition at line 12101 of file chan_sip.c.
References ast_copy_string(), and ast_skip_blanks().
Referenced by check_user_full().
12102 { 12103 const char *end = strchr(input, '<'); /* first_bracket */ 12104 const char *tmp = strchr(input, '"'); /* first quote */ 12105 int bytes = 0; 12106 int maxbytes = outputsize - 1; 12107 12108 if (!end || end == input) /* we require a part in brackets */ 12109 return NULL; 12110 12111 end--; /* move just before "<" */ 12112 12113 if (tmp && tmp <= end) { 12114 /* The quote (tmp) precedes the bracket (end+1). 12115 * Find the matching quote and return the content. 12116 */ 12117 end = strchr(tmp+1, '"'); 12118 if (!end) 12119 return NULL; 12120 bytes = (int) (end - tmp); 12121 /* protect the output buffer */ 12122 if (bytes > maxbytes) 12123 bytes = maxbytes; 12124 ast_copy_string(output, tmp + 1, bytes); 12125 } else { 12126 /* No quoted string, or it is inside brackets. */ 12127 /* clear the empty characters in the begining*/ 12128 input = ast_skip_blanks(input); 12129 /* clear the empty characters in the end */ 12130 while(*end && *end < 33 && end > input) 12131 end--; 12132 if (end >= input) { 12133 bytes = (int) (end - input) + 2; 12134 /* protect the output buffer */ 12135 if (bytes > maxbytes) 12136 bytes = maxbytes; 12137 ast_copy_string(output, input, bytes); 12138 } else 12139 return NULL; 12140 } 12141 return output; 12142 }
| static int get_destination | ( | struct sip_pvt * | p, | |
| struct sip_request * | oreq | |||
| ) | [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 11556 of file chan_sip.c.
References ast_canmatch_extension(), 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(), sip_pvt::cid_num, sip_pvt::context, context, sip_pvt::domain, exten, sip_pvt::exten, get_header(), get_in_brackets(), global_flags, sip_pvt::initreq, LOG_WARNING, sip_request::method, REQ_OFFSET_TO_STR, sip_request::rlPart2, S_OR, sip_debug_test_pvt(), SIP_INVITE, sip_methods, SIP_PAGE2_ALLOWOVERLAP, SIP_REFER, SIP_SUBSCRIBE, strsep(), and sip_pvt::subscribecontext.
Referenced by handle_request_invite(), handle_request_options(), and handle_request_subscribe().
11557 { 11558 char tmp[256] = "", *uri, *a; 11559 char tmpf[256] = "", *from = NULL; 11560 struct sip_request *req; 11561 char *colon; 11562 char *decoded_uri; 11563 11564 req = oreq; 11565 if (!req) 11566 req = &p->initreq; 11567 11568 /* Find the request URI */ 11569 if (req->rlPart2) 11570 ast_copy_string(tmp, REQ_OFFSET_TO_STR(req, rlPart2), sizeof(tmp)); 11571 11572 if (pedanticsipchecking) 11573 ast_uri_decode(tmp); 11574 11575 uri = get_in_brackets(tmp); 11576 11577 if (!strncasecmp(uri, "sip:", 4)) { 11578 uri += 4; 11579 } else if (!strncasecmp(uri, "sips:", 5)) { 11580 uri += 5; 11581 } else { 11582 ast_log(LOG_WARNING, "Huh? Not a SIP header (%s)?\n", uri); 11583 return -1; 11584 } 11585 11586 /* Now find the From: caller ID and name */ 11587 /* XXX Why is this done in get_destination? Isn't it already done? 11588 Needs to be checked 11589 */ 11590 ast_copy_string(tmpf, get_header(req, "From"), sizeof(tmpf)); 11591 if (!ast_strlen_zero(tmpf)) { 11592 if (pedanticsipchecking) 11593 ast_uri_decode(tmpf); 11594 from = get_in_brackets(tmpf); 11595 } 11596 11597 if (!ast_strlen_zero(from)) { 11598 if (!strncasecmp(from, "sip:", 4)) { 11599 from += 4; 11600 } else if (!strncasecmp(from, "sips:", 5)) { 11601 from += 5; 11602 } else { 11603 ast_log(LOG_WARNING, "Huh? Not a SIP header (%s)?\n", from); 11604 return -1; 11605 } 11606 if ((a = strchr(from, '@'))) 11607 *a++ = '\0'; 11608 else 11609 a = from; /* just a domain */ 11610 from = strsep(&from, ";"); /* Remove userinfo options */ 11611 a = strsep(&a, ";"); /* Remove URI options */ 11612 ast_string_field_set(p, fromdomain, a); 11613 } 11614 11615 /* Skip any options and find the domain */ 11616 11617 /* Get the target domain */ 11618 if ((a = strchr(uri, '@'))) { 11619 *a++ = '\0'; 11620 } else { /* No username part */ 11621 a = uri; 11622 uri = "s"; /* Set extension to "s" */ 11623 } 11624 colon = strchr(a, ':'); /* Remove :port */ 11625 if (colon) 11626 *colon = '\0'; 11627 11628 uri = strsep(&uri, ";"); /* Remove userinfo options */ 11629 a = strsep(&a, ";"); /* Remove URI options */ 11630 11631 ast_string_field_set(p, domain, a); 11632 11633 if (!AST_LIST_EMPTY(&domain_list)) { 11634 char domain_context[AST_MAX_EXTENSION]; 11635 11636 domain_context[0] = '\0'; 11637 if (!check_sip_domain(p->domain, domain_context, sizeof(domain_context))) { 11638 if (!allow_external_domains && (req->method == SIP_INVITE || req->method == SIP_REFER)) { 11639 ast_debug(1, "Got SIP %s to non-local domain '%s'; refusing request.\n", sip_methods[req->method].text, p->domain); 11640 return -2; 11641 } 11642 } 11643 /* If we have a context defined, overwrite the original context */ 11644 if (!ast_strlen_zero(domain_context)) 11645 ast_string_field_set(p, context, domain_context); 11646 } 11647 11648 /* If the request coming in is a subscription and subscribecontext has been specified use it */ 11649 if (req->method == SIP_SUBSCRIBE && !ast_strlen_zero(p->subscribecontext)) 11650 ast_string_field_set(p, context, p->subscribecontext); 11651 11652 if (sip_debug_test_pvt(p)) 11653 ast_verbose("Looking for %s in %s (domain %s)\n", uri, p->context, p->domain); 11654 11655 /* If this is a subscription we actually just need to see if a hint exists for the extension */ 11656 if (req->method == SIP_SUBSCRIBE) { 11657 char hint[AST_MAX_EXTENSION]; 11658 return (ast_get_hint(hint, sizeof(hint), NULL, 0, NULL, p->context, p->exten) ? 0 : -1); 11659 } else { 11660 decoded_uri = ast_strdupa(uri); 11661 ast_uri_decode(decoded_uri); 11662 /* Check the dialplan for the username part of the request URI, 11663 the domain will be stored in the SIPDOMAIN variable 11664 Since extensions.conf can have unescaped characters, try matching a decoded 11665 uri in addition to the non-decoded uri 11666 Return 0 if we have a matching extension */ 11667 if (ast_exists_extension(NULL, p->context, uri, 1, S_OR(p->cid_num, from)) || ast_exists_extension(NULL, p->context, decoded_uri, 1, S_OR(p->cid_num, from)) || 11668 !strcmp(decoded_uri, ast_pickup_ext())) { 11669 if (!oreq) 11670 ast_string_field_set(p, exten, decoded_uri); 11671 return 0; 11672 } 11673 } 11674 11675 /* Return 1 for pickup extension or overlap dialling support (if we support it) */ 11676 if((ast_test_flag(&global_flags[1], SIP_PAGE2_ALLOWOVERLAP) && 11677 ast_canmatch_extension(NULL, p->context, decoded_uri, 1, S_OR(p->cid_num, from))) || 11678 !strncmp(decoded_uri, ast_pickup_ext(), strlen(decoded_uri))) { 11679 return 1; 11680 } 11681 11682 return -1; 11683 }
| static const char * get_header | ( | const struct sip_request * | req, | |
| const char * | name | |||
| ) | [static] |
Get header from SIP request.
Definition at line 6026 of file chan_sip.c.
References __get_header().
06027 { 06028 int start = 0; 06029 return __get_header(req, name, &start); 06030 }
| static char * get_in_brackets | ( | char * | tmp | ) | [static] |
Pick out text in brackets from character string.
| tmp | input string that will be modified Examples: "foo" <bar> valid input, returns bar foo returns the whole string < "foo ... > returns the string between brackets < "foo... bogus (missing closing bracket), returns the whole string XXX maybe should still skip the opening bracket |
Definition at line 3568 of file chan_sip.c.
References ast_log(), find_closing_quote(), LOG_WARNING, and parse().
Referenced by check_user_full(), extract_uri(), get_also_info(), get_destination(), get_rdnis(), get_refer_info(), parse_moved_contact(), parse_ok_contact(), parse_register_contact(), register_verify(), reqprep(), transmit_refer(), and transmit_state_notify().
03569 { 03570 const char *parse = tmp; 03571 char *first_bracket; 03572 03573 /* 03574 * Skip any quoted text until we find the part in brackets. 03575 * On any error give up and return the full string. 03576 */ 03577 while ( (first_bracket = strchr(parse, '<')) ) { 03578 char *first_quote = strchr(parse, '"'); 03579 03580 if (!first_quote || first_quote > first_bracket) 03581 break; /* no need to look at quoted part */ 03582 /* the bracket is within quotes, so ignore it */ 03583 parse = find_closing_quote(first_quote + 1, NULL); 03584 if (!*parse) { /* not found, return full string ? */ 03585 /* XXX or be robust and return in-bracket part ? */ 03586 ast_log(LOG_WARNING, "No closing quote found in '%s'\n", tmp); 03587 break; 03588 } 03589 parse++; 03590 } 03591 if (first_bracket) { 03592 char *second_bracket = strchr(first_bracket + 1, '>'); 03593 if (second_bracket) { 03594 *second_bracket = '\0'; 03595 tmp = first_bracket + 1; 03596 } else { 03597 ast_log(LOG_WARNING, "No closing bracket found in '%s'\n", tmp); 03598 } 03599 } 03600 03601 return tmp; 03602 }
| static struct ast_variable * get_insecure_variable_from_config | ( | struct ast_config * | config | ) | [static] |
Definition at line 3912 of file chan_sip.c.
References ast_category_browse(), ast_category_root(), ast_test_flag, ast_variable_retrieve(), ast_flags::flags, set_insecure_flags(), SIP_INSECURE_PORT, and var.
03913 { 03914 struct ast_variable *var = NULL; 03915 struct ast_flags flags = {0}; 03916 char *cat = NULL; 03917 const char *insecure; 03918 while ((cat = ast_category_browse(cfg, cat))) { 03919 insecure = ast_variable_retrieve(cfg, cat, "insecure"); 03920 set_insecure_flags(&flags, insecure, -1); 03921 if (ast_test_flag(&flags, SIP_INSECURE_PORT)) { 03922 var = ast_category_root(cfg, cat); 03923 break; 03924 } 03925 } 03926 return var; 03927 }
| 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 12490 of file chan_sip.c.
References sip_request::lines, and REQ_OFFSET_TO_STR.
Referenced by handle_request_info(), handle_request_notify(), and receive_message().
12491 { 12492 int x; 12493 int y; 12494 12495 buf[0] = '\0'; 12496 /*XXX isn't strlen(buf) going to always be 0? */ 12497 y = len - strlen(buf) - 5; 12498 if (y < 0) 12499 y = 0; 12500 for (x = 0; x < req->lines; x++) { 12501 char *line = REQ_OFFSET_TO_STR(req, line[x]); 12502 strncat(buf, line, y); /* safe */ 12503 y -= strlen(line) + 1; 12504 if (y < 0) 12505 y = 0; 12506 if (y != 0 && addnewline) 12507 strcat(buf, "\n"); /* safe */ 12508 } 12509 return 0; 12510 }
| static const char * get_name_from_variable | ( | struct ast_variable * | var, | |
| const char * | newpeername | |||
| ) | [static] |
Definition at line 3929 of file chan_sip.c.
References ast_variable::name, ast_variable::next, ast_variable::value, and var.
03930 { 03931 struct ast_variable *tmp; 03932 for (tmp = var; tmp; tmp = tmp->next) { 03933 if (!newpeername && !strcasecmp(tmp->name, "name")) 03934 newpeername = tmp->value; 03935 } 03936 return newpeername; 03937 }
| static void get_our_media_address | ( | struct sip_pvt * | p, | |
| int | needvideo, | |||
| struct sockaddr_in * | sin, | |||
| struct sockaddr_in * | vsin, | |||
| struct sockaddr_in * | tsin, | |||
| struct sockaddr_in * | dest, | |||
| struct sockaddr_in * | vdest | |||
| ) | [static] |
Set all IP media addresses for this call.
Definition at line 8558 of file chan_sip.c.
References ast_rtp_get_us(), sip_pvt::ourip, sip_pvt::redirip, sip_pvt::rtp, sip_pvt::trtp, sip_pvt::vredirip, and sip_pvt::vrtp.
Referenced by add_sdp().
08561 { 08562 /* First, get our address */ 08563 ast_rtp_get_us(p->rtp, sin); 08564 if (p->vrtp) 08565 ast_rtp_get_us(p->vrtp, vsin); 08566 if (p->trtp) 08567 ast_rtp_get_us(p->trtp, tsin); 08568 08569 /* Now, try to figure out where we want them to send data */ 08570 /* Is this a re-invite to move the media out, then use the original offer from caller */ 08571 if (p->redirip.sin_addr.s_addr) { /* If we have a redirection IP, use it */ 08572 dest->sin_port = p->redirip.sin_port; 08573 dest->sin_addr = p->redirip.sin_addr; 08574 } else { 08575 dest->sin_addr = p->ourip.sin_addr; 08576 dest->sin_port = sin->sin_port; 08577 } 08578 if (needvideo) { 08579 /* Determine video destination */ 08580 if (p->vredirip.sin_addr.s_addr) { 08581 vdest->sin_addr = p->vredirip.sin_addr; 08582 vdest->sin_port = p->vredirip.sin_port; 08583 } else { 08584 vdest->sin_addr = p->ourip.sin_addr; 08585 vdest->sin_port = vsin->sin_port; 08586 } 08587 } 08588 08589 }
| static int get_rdnis | ( | struct sip_pvt * | p, | |
| struct sip_request * | oreq | |||
| ) | [static] |
Get referring dnis.
Definition at line 11489 of file chan_sip.c.
References ast_copy_string(), ast_log(), ast_string_field_set, ast_strip_quoted(), ast_strlen_zero(), ast_verbose, exten, get_header(), get_in_brackets(), sip_pvt::initreq, LOG_WARNING, sip_pvt::owner, pbx_builtin_setvar_helper(), sip_debug_test_pvt(), sip_set_redirstr(), strcasestr(), and strsep().
Referenced by handle_request_invite().
11490 { 11491 char tmp[256], *exten, *rexten, *rdomain; 11492 char *params, *reason = NULL; 11493 struct sip_request *req; 11494 11495 req = oreq ? oreq : &p->initreq; 11496 11497 ast_copy_string(tmp, get_header(req, "Diversion"), sizeof(tmp)); 11498 if (ast_strlen_zero(tmp)) 11499 return 0; 11500 11501 params = strchr(tmp, ';'); 11502 11503 exten = get_in_brackets(tmp); 11504 if (!strncasecmp(exten, "sip:", 4)) { 11505 exten += 4; 11506 } else if (!strncasecmp(exten, "sips:", 5)) { 11507 exten += 5; 11508 } else { 11509 ast_log(LOG_WARNING, "Huh? Not an RDNIS SIP header (%s)?\n", exten); 11510 return -1; 11511 } 11512 11513 /* Get diversion-reason param if present */ 11514 if (params) { 11515 *params = '\0'; /* Cut off parameters */ 11516 params++; 11517 while (*params == ';' || *params == ' ') 11518 params++; 11519 /* Check if we have a reason parameter */ 11520 if ((reason = strcasestr(params, "reason="))) { 11521 reason+=7; 11522 /* Remove enclosing double-quotes */ 11523 if (*reason == '"') 11524 ast_strip_quoted(reason, "\"", "\""); 11525 if (!ast_strlen_zero(reason)) { 11526 sip_set_redirstr(p, reason); 11527 if (p->owner) { 11528 pbx_builtin_setvar_helper(p->owner, "__PRIREDIRECTREASON", p->redircause); 11529 pbx_builtin_setvar_helper(p->owner, "__SIPREDIRECTREASON", reason); 11530 } 11531 } 11532 } 11533 } 11534 11535 rdomain = exten; 11536 rexten = strsep(&rdomain, "@"); /* trim anything after @ */ 11537 if (p->owner) 11538 pbx_builtin_setvar_helper(p->owner, "__SIPRDNISDOMAIN", rdomain); 11539 11540 if (sip_debug_test_pvt(p)) 11541 ast_verbose("RDNIS for this call is is %s (reason %s)\n", exten, reason ? reason : ""); 11542 11543 ast_string_field_set(p, rdnis, rexten); 11544 11545 return 0; 11546 }
| 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 11770 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, sip_refer::attendedtransfer, sip_pvt::context, get_header(), get_in_brackets(), sip_pvt::initreq, LOG_WARNING, ast_channel::macrocontext, sip_pvt::owner, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), sip_pvt::refer, sip_refer::refer_to, sip_refer::refer_to_context, sip_refer::refer_to_domain, sip_refer::refer_to_urioption, sip_refer::referred_by, sip_refer::referred_by_name, sip_refer::replaces_callid, sip_refer::replaces_callid_fromtag, sip_refer::replaces_callid_totag, S_OR, sip_debug_test_pvt(), and strcasestr().
Referenced by handle_request_refer().
11771 { 11772 11773 const char *p_referred_by = NULL; 11774 char *h_refer_to = NULL; 11775 char *h_referred_by = NULL; 11776 char *refer_to; 11777 const char *p_refer_to; 11778 char *referred_by_uri = NULL; 11779 char *ptr; 11780 struct sip_request *req = NULL; 11781 const char *transfer_context = NULL; 11782 struct sip_refer *referdata; 11783 11784 11785 req = outgoing_req; 11786 referdata = transferer->refer; 11787 11788 if (!req) 11789 req = &transferer->initreq; 11790 11791 p_refer_to = get_header(req, "Refer-To"); 11792 if (ast_strlen_zero(p_refer_to)) { 11793 ast_log(LOG_WARNING, "Refer-To Header missing. Skipping transfer.\n"); 11794 return -2; /* Syntax error */ 11795 } 11796 h_refer_to = ast_strdupa(p_refer_to); 11797 refer_to = get_in_brackets(h_refer_to); 11798 if (pedanticsipchecking) 11799 ast_uri_decode(refer_to); 11800 11801 if (!strncasecmp(refer_to, "sip:", 4)) { 11802 refer_to += 4; /* Skip sip: */ 11803 } else if (!strncasecmp(refer_to, "sips:", 5)) { 11804 refer_to += 5; 11805 } else { 11806 ast_log(LOG_WARNING, "Can't transfer to non-sip: URI. (Refer-to: %s)?\n", refer_to); 11807 return -3; 11808 } 11809 11810 /* Get referred by header if it exists */ 11811 p_referred_by = get_header(req, "Referred-By"); 11812 11813 /* Give useful transfer information to the dialplan */ 11814 if (transferer->owner) { 11815 struct ast_channel *peer = ast_bridged_channel(transferer->owner); 11816 if (peer) { 11817 pbx_builtin_setvar_helper(peer, "SIPREFERRINGCONTEXT", transferer->context); 11818 pbx_builtin_setvar_helper(peer, "SIPREFERREDBYHDR", p_referred_by); 11819 } 11820 } 11821 11822 if (!ast_strlen_zero(p_referred_by)) { 11823 char *lessthan; 11824 h_referred_by = ast_strdupa(p_referred_by); 11825 if (pedanticsipchecking) 11826 ast_uri_decode(h_referred_by); 11827 11828 /* Store referrer's caller ID name */ 11829 ast_copy_string(referdata->referred_by_name, h_referred_by, sizeof(referdata->referred_by_name)); 11830 if ((lessthan = strchr(referdata->referred_by_name, '<'))) { 11831 *(lessthan - 1) = '\0'; /* Space */ 11832 } 11833 11834 referred_by_uri = get_in_brackets(h_referred_by); 11835 if (!strncasecmp(referred_by_uri, "sip:", 4)) { 11836 referred_by_uri += 4; /* Skip sip: */ 11837 } else if (!strncasecmp(referred_by_uri, "sips:", 5)) { 11838 referred_by_uri += 5; /* Skip sips: */ 11839 } else { 11840 ast_log(LOG_WARNING, "Huh? Not a sip: header (Referred-by: %s). Skipping.\n", referred_by_uri); 11841 referred_by_uri = NULL; 11842 } 11843 } 11844 11845 /* Check for arguments in the refer_to header */ 11846 if ((ptr = strcasestr(refer_to, "replaces="))) { 11847 char *to = NULL, *from = NULL; 11848 11849 /* This is an attended transfer */ 11850 referdata->attendedtransfer = 1; 11851 ast_copy_string(referdata->replaces_callid, ptr+9, sizeof(referdata->replaces_callid)); 11852 ast_uri_decode(referdata->replaces_callid); 11853 if ((ptr = strchr(referdata->replaces_callid, ';'))) /* Find options */ { 11854 *ptr++ = '\0'; 11855 } 11856 11857 if (ptr) { 11858 /* Find the different tags before we destroy the string */ 11859 to = strcasestr(ptr, "to-tag="); 11860 from = strcasestr(ptr, "from-tag="); 11861 } 11862 11863 /* Grab the to header */ 11864 if (to) { 11865 ptr = to + 7; 11866 if ((to = strchr(ptr, '&'))) 11867 *to = '\0'; 11868 if ((to = strchr(ptr, ';'))) 11869 *to = '\0'; 11870 ast_copy_string(referdata->replaces_callid_totag, ptr, sizeof(referdata->replaces_callid_totag)); 11871 } 11872 11873 if (from) { 11874 ptr = from + 9; 11875 if ((to = strchr(ptr, '&'))) 11876 *to = '\0'; 11877 if ((to = strchr(ptr, ';'))) 11878 *to = '\0'; 11879 ast_copy_string(referdata->replaces_callid_fromtag, ptr, sizeof(referdata->replaces_callid_fromtag)); 11880 } 11881 11882 if (!pedanticsipchecking) 11883 ast_debug(2, "Attended transfer: Will use Replace-Call-ID : %s (No check of from/to tags)\n", referdata->replaces_callid ); 11884 else 11885 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>" ); 11886 } 11887 11888 if ((ptr = strchr(refer_to, '@'))) { /* Separate domain */ 11889 char *urioption = NULL, *domain; 11890 *ptr++ = '\0'; 11891 11892 if ((urioption = strchr(ptr, ';'))) /* Separate urioptions */ 11893 *urioption++ = '\0'; 11894 11895 domain = ptr; 11896 if ((ptr = strchr(domain, ':'))) /* Remove :port */ 11897 *ptr = '\0'; 11898 11899 /* Save the domain for the dial plan */ 11900 ast_copy_string(referdata->refer_to_domain, domain, sizeof(referdata->refer_to_domain)); 11901 if (urioption) 11902 ast_copy_string(referdata->refer_to_urioption, urioption, sizeof(referdata->refer_to_urioption)); 11903 } 11904 11905 if ((ptr = strchr(refer_to, ';'))) /* Remove options */ 11906 *ptr = '\0'; 11907 ast_copy_string(referdata->refer_to, refer_to, sizeof(referdata->refer_to)); 11908 11909 if (referred_by_uri) { 11910 if ((ptr = strchr(referred_by_uri, ';'))) /* Remove options */ 11911 *ptr = '\0'; 11912 ast_copy_string(referdata->referred_by, referred_by_uri, sizeof(referdata->referred_by)); 11913 } else { 11914 referdata->referred_by[0] = '\0'; 11915 } 11916 11917 /* Determine transfer context */ 11918 if (transferer->owner) /* Mimic behaviour in res_features.c */ 11919 transfer_context = pbx_builtin_getvar_helper(transferer->owner, "TRANSFER_CONTEXT"); 11920 11921 /* By default, use the context in the channel sending the REFER */ 11922 if (ast_strlen_zero(transfer_context)) { 11923 transfer_context = S_OR(transferer->owner->macrocontext, 11924 S_OR(transferer->context, default_context)); 11925 } 11926 11927 ast_copy_string(referdata->refer_to_context, transfer_context, sizeof(referdata->refer_to_context)); 11928 11929 /* Either an existing extension or the parking extension */ 11930 if (referdata->attendedtransfer || ast_exists_extension(NULL, transfer_context, refer_to, 1, NULL) ) { 11931 if (sip_debug_test_pvt(transferer)) { 11932 ast_verbose("SIP transfer to extension %s@%s by %s\n", refer_to, transfer_context, referred_by_uri); 11933 } 11934 /* We are ready to transfer to the extension */ 11935 return 0; 11936 } 11937 if (sip_debug_test_pvt(transferer)) 11938 ast_verbose("Failed SIP Transfer to non-existing extension %s in context %s\n n", refer_to, transfer_context); 11939 11940 /* Failure, we can't find this extension */ 11941 return -1; 11942 }
| static int get_rpid_num | ( | const char * | input, | |
| char * | output, | |||
| int | maxlen | |||
| ) | [static] |
Get caller id number from Remote-Party-ID header field Returns true if number should be restricted (privacy setting found) output is set to NULL if no number found.
Definition at line 12148 of file chan_sip.c.
References ast_copy_string(), and AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED.
Referenced by check_user_full().
12149 { 12150 char *start; 12151 char *end; 12152 12153 start = strchr(input, ':'); 12154 if (!start) { 12155 output[0] = '\0'; 12156 return 0; 12157 } 12158 start++; 12159 12160 /* we found "number" */ 12161 ast_copy_string(output, start, maxlen); 12162 output[maxlen-1] = '\0'; 12163 12164 end = strchr(output, '@'); 12165 if (end) 12166 *end = '\0'; 12167 else 12168 output[0] = '\0'; 12169 if (strstr(input, "privacy=full") || strstr(input, "privacy=uri")) 12170 return AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED; 12171 12172 return 0; 12173 }
| static const char * get_sdp | ( | struct sip_request * | req, | |
| const char * | name | |||
| ) | [static] |
Get a line from an SDP message body.
Definition at line 5925 of file chan_sip.c.
References dummy(), and get_sdp_iterate().
05926 { 05927 int dummy = 0; 05928 05929 return get_sdp_iterate(&dummy, req, name); 05930 }
| 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 5911 of file chan_sip.c.
References get_body_by_line(), sip_request::len, REQ_OFFSET_TO_STR, and sip_request::sdp_end.
05912 { 05913 int len = strlen(name); 05914 05915 while (*start < req->sdp_end) { 05916 const char *r = get_body_by_line(REQ_OFFSET_TO_STR(req, line[(*start)++]), name, len); 05917 if (r[0] != '\0') 05918 return r; 05919 } 05920 05921 return ""; 05922 }
| static struct sip_pvt * get_sip_pvt_byid_locked | ( | const char * | callid, | |
| const char * | totag, | |||
| const char * | fromtag | |||
| ) | [static] |
Lock dialog lock and find matching pvt lock.
Definition at line 11688 of file chan_sip.c.
References ao2_t_find, ast_channel_trylock, ast_debug, ast_strlen_zero(), sip_pvt::callid, dialogs, OBJ_POINTER, sip_pvt_lock, sip_pvt_unlock, and TRUE.
Referenced by handle_request_invite(), and local_attended_transfer().
11689 { 11690 struct sip_pvt *sip_pvt_ptr; 11691 struct sip_pvt tmp_dialog = { 11692 .callid = callid, 11693 }; 11694 11695 if (totag) 11696 ast_debug(4, "Looking for callid %s (fromtag %s totag %s)\n", callid, fromtag ? fromtag : "<no fromtag>", totag ? totag : "<no totag>"); 11697 11698 /* Search dialogs and find the match */ 11699 11700 sip_pvt_ptr = ao2_t_find(dialogs, &tmp_dialog, OBJ_POINTER, "ao2_find of dialog in dialogs table"); 11701 if (sip_pvt_ptr) { 11702 /* Go ahead and lock it (and its owner) before returning */ 11703 sip_pvt_lock(sip_pvt_ptr); 11704 if (pedanticsipchecking) { 11705 unsigned char frommismatch = 0, tomismatch = 0; 11706 11707 if (ast_strlen_zero(fromtag)) { 11708 sip_pvt_unlock(sip_pvt_ptr); 11709 ast_debug(4, "Matched %s call for callid=%s - no from tag specified, pedantic check fails\n", 11710 sip_pvt_ptr->outgoing_call == TRUE ? "OUTGOING": "INCOMING", sip_pvt_ptr->callid); 11711 return NULL; 11712 } 11713 11714 if (ast_strlen_zero(totag)) { 11715 sip_pvt_unlock(sip_pvt_ptr); 11716 ast_debug(4, "Matched %s call for callid=%s - no to tag specified, pedantic check fails\n", 11717 sip_pvt_ptr->outgoing_call == TRUE ? "OUTGOING": "INCOMING", sip_pvt_ptr->callid); 11718 return NULL; 11719 } 11720 /* RFC 3891 11721 * > 3. User Agent Server Behavior: Receiving a Replaces Header 11722 * > The Replaces header contains information used to match an existing 11723 * > SIP dialog (call-id, to-tag, and from-tag). Upon receiving an INVITE 11724 * > with a Replaces header, the User Agent (UA) attempts to match this 11725 * > information with a confirmed or early dialog. The User Agent Server 11726 * > (UAS) matches the to-tag and from-tag parameters as if they were tags 11727 * > present in an incoming request. In other words, the to-tag parameter 11728 * > is compared to the local tag, and the from-tag parameter is compared 11729 * > to the remote tag. 11730 * 11731 * Thus, the totag is always compared to the local tag, regardless if 11732 * this our call is an incoming or outgoing call. 11733 */ 11734 frommismatch = !!strcmp(fromtag, sip_pvt_ptr->theirtag); 11735 tomismatch = !!strcmp(totag, sip_pvt_ptr->tag); 11736 if (frommismatch || tomismatch) { 11737 sip_pvt_unlock(sip_pvt_ptr); 11738 if (frommismatch) { 11739 ast_debug(4, "Matched %s call for callid=%s - But the pedantic check rejected the match; their tag is %s Our tag is %s\n", 11740 sip_pvt_ptr->outgoing_call == TRUE ? "OUTGOING": "INCOMING", sip_pvt_ptr->callid, 11741 fromtag, sip_pvt_ptr->theirtag); 11742 } 11743 if (tomismatch) { 11744 ast_debug(4, "Matched %s call for callid=%s - pedantic to tag check fails; their tag is %s our tag is %s\n", 11745 sip_pvt_ptr->outgoing_call == TRUE ? "OUTGOING": "INCOMING", sip_pvt_ptr->callid, 11746 totag, sip_pvt_ptr->tag); 11747 } 11748 return NULL; 11749 } 11750 } 11751 11752 if (totag) 11753 ast_debug(4, "Matched %s call - their tag is %s Our tag is %s\n", 11754 sip_pvt_ptr->outgoing_call == TRUE ? "OUTGOING": "INCOMING", 11755 sip_pvt_ptr->theirtag, sip_pvt_ptr->tag); 11756 11757 /* deadlock avoidance... */ 11758 while (sip_pvt_ptr->owner && ast_channel_trylock(sip_pvt_ptr->owner)) { 11759 sip_pvt_unlock(sip_pvt_ptr); 11760 usleep(1); 11761 sip_pvt_lock(sip_pvt_ptr); 11762 } 11763 } 11764 11765 return sip_pvt_ptr; 11766 }
| static const char* get_transport | ( | enum sip_transport | t | ) | [inline, static] |
Definition at line 2838 of file chan_sip.c.
References SIP_TRANSPORT_TCP, SIP_TRANSPORT_TLS, and SIP_TRANSPORT_UDP.
Referenced by _sip_show_peer(), build_contact(), build_peer(), create_addr(), get_transport_pvt(), handle_request_do(), parse_moved_contact(), sip_show_tcp(), and transmit_register().
02839 { 02840 switch (t) { 02841 case SIP_TRANSPORT_UDP: 02842 return "UDP"; 02843 case SIP_TRANSPORT_TCP: 02844 return "TCP"; 02845 case SIP_TRANSPORT_TLS: 02846 return "TLS"; 02847 } 02848 02849 return "UNKNOWN"; 02850 }
| static const char* get_transport_list | ( | struct sip_peer * | peer | ) | [inline, static] |
Definition at line 2818 of file chan_sip.c.
References SIP_TRANSPORT_TCP, SIP_TRANSPORT_TLS, SIP_TRANSPORT_UDP, and sip_peer::transports.
02818 { 02819 switch (peer->transports) { 02820 case SIP_TRANSPORT_UDP: 02821 return "UDP"; 02822 case SIP_TRANSPORT_TCP: 02823 return "TCP"; 02824 case SIP_TRANSPORT_TLS: 02825 return "TLS"; 02826 case SIP_TRANSPORT_UDP | SIP_TRANSPORT_TCP: 02827 return "TCP,UDP"; 02828 case SIP_TRANSPORT_UDP | SIP_TRANSPORT_TLS: 02829 return "TLS,UDP"; 02830 case SIP_TRANSPORT_TCP | SIP_TRANSPORT_TLS: 02831 return "TLS,TCP"; 02832 default: 02833 return peer->transports ? 02834 "TLS,TCP,UDP" : "UNKNOWN"; 02835 } 02836 }
| static const char* get_transport_pvt | ( | struct sip_pvt * | p | ) | [inline, static] |
Definition at line 2852 of file chan_sip.c.
References get_transport(), sip_pvt::outboundproxy, sip_pvt::socket, sip_proxy::transport, and sip_socket::type.
Referenced by __sip_xmit(), and build_via().
02853 { 02854 if (p->outboundproxy && p->outboundproxy->transport) 02855 p->socket.type = p->outboundproxy->transport; 02856 02857 return get_transport(p->socket.type); 02858 }
| static const char * gettag | ( | const struct sip_request * | req, | |
| const char * | header, | |||
| char * | tagbuf, | |||
| int | tagbufsize | |||
| ) | [static] |
Get tag from packet.
Definition at line 17160 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().
17161 { 17162 const char *thetag; 17163 17164 if (!tagbuf) 17165 return NULL; 17166 tagbuf[0] = '\0'; /* reset the buffer */ 17167 thetag = get_header(req, header); 17168 thetag = strcasestr(thetag, ";tag="); 17169 if (thetag) { 17170 thetag += 5; 17171 ast_copy_string(tagbuf, thetag, tagbufsize); 17172 return strsep(&tagbuf, ";"); 17173 } 17174 return NULL; 17175 }
| 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 21181 of file chan_sip.c.
References ast_clear_flag, ast_copy_string(), ast_false(), ast_log(), ast_set2_flag, ast_set_flag, ast_true(), buf, ast_channel::flags, ast_variable::lineno, LOG_WARNING, ast_variable::name, ast_channel::next, set_insecure_flags(), SIP_CAN_REINVITE, SIP_CAN_REINVITE_NAT, SIP_DTMF, SIP_DTMF_AUTO, SIP_DTMF_INBAND, SIP_DTMF_INFO, SIP_DTMF_RFC2833, SIP_DTMF_SHORTINFO, SIP_G726_NONSTANDARD, SIP_INSECURE, SIP_NAT, SIP_NAT_ALWAYS, SIP_NAT_NEVER, SIP_NAT_RFC3581, SIP_NAT_ROUTE, SIP_PAGE2_ALLOWOVERLAP, SIP_PAGE2_ALLOWSUBSCRIBE, SIP_PAGE2_BUGGY_MWI, SIP_PAGE2_RFC2833_COMPENSATE, SIP_PAGE2_T38SUPPORT_RTP, SIP_PAGE2_T38SUPPORT_TCP, SIP_PAGE2_T38SUPPORT_UDPTL, SIP_PAGE2_TEXTSUPPORT, SIP_PAGE2_UDPTL_DESTINATION, SIP_PAGE2_VIDEOSUPPORT, SIP_PAGE2_VIDEOSUPPORT_ALWAYS, SIP_PROG_INBAND, SIP_PROG_INBAND_NO, SIP_PROG_INBAND_YES, SIP_PROMISCREDIR, SIP_REINVITE, SIP_REINVITE_UPDATE, SIP_SENDRPID, SIP_TRUSTRPID, SIP_USECLIENTCODE, strsep(), and ast_variable::value.
Referenced by build_peer().
21182 { 21183 int res = 1; 21184 21185 if (!strcasecmp(v->name, "trustrpid")) { 21186 ast_set_flag(&mask[0], SIP_TRUSTRPID); 21187 ast_set2_flag(&flags[0], ast_true(v->value), SIP_TRUSTRPID); 21188 } else if (!strcasecmp(v->name, "sendrpid")) { 21189 ast_set_flag(&mask[0], SIP_SENDRPID); 21190 ast_set2_flag(&flags[0], ast_true(v->value), SIP_SENDRPID); 21191 } else if (!strcasecmp(v->name, "g726nonstandard")) { 21192 ast_set_flag(&mask[0], SIP_G726_NONSTANDARD); 21193 ast_set2_flag(&flags[0], ast_true(v->value), SIP_G726_NONSTANDARD); 21194 } else if (!strcasecmp(v->name, "useclientcode")) { 21195 ast_set_flag(&mask[0], SIP_USECLIENTCODE); 21196 ast_set2_flag(&flags[0], ast_true(v->value), SIP_USECLIENTCODE); 21197 } else if (!strcasecmp(v->name, "dtmfmode")) { 21198 ast_set_flag(&mask[0], SIP_DTMF); 21199 ast_clear_flag(&flags[0], SIP_DTMF); 21200 if (!strcasecmp(v->value, "inband")) 21201 ast_set_flag(&flags[0], SIP_DTMF_INBAND); 21202 else if (!strcasecmp(v->value, "rfc2833")) 21203 ast_set_flag(&flags[0], SIP_DTMF_RFC2833); 21204 else if (!strcasecmp(v->value, "info")) 21205 ast_set_flag(&flags[0], SIP_DTMF_INFO); 21206 else if (!strcasecmp(v->value, "shortinfo")) 21207 ast_set_flag(&flags[0], SIP_DTMF_SHORTINFO); 21208 else if (!strcasecmp(v->value, "auto")) 21209 ast_set_flag(&flags[0], SIP_DTMF_AUTO); 21210 else { 21211 ast_log(LOG_WARNING, "Unknown dtmf mode '%s' on line %d, using rfc2833\n", v->value, v->lineno); 21212 ast_set_flag(&flags[0], SIP_DTMF_RFC2833); 21213 } 21214 } else if (!strcasecmp(v->name, "nat")) { 21215 ast_set_flag(&mask[0], SIP_NAT); 21216 ast_clear_flag(&flags[0], SIP_NAT); 21217 if (!strcasecmp(v->value, "never")) 21218 ast_set_flag(&flags[0], SIP_NAT_NEVER); 21219 else if (!strcasecmp(v->value, "route")) 21220 ast_set_flag(&flags[0], SIP_NAT_ROUTE); 21221 else if (ast_true(v->value)) 21222 ast_set_flag(&flags[0], SIP_NAT_ALWAYS); 21223 else 21224 ast_set_flag(&flags[0], SIP_NAT_RFC3581); 21225 } else if (!strcasecmp(v->name, "canreinvite")) { 21226 ast_set_flag(&mask[0], SIP_REINVITE); 21227 ast_clear_flag(&flags[0], SIP_REINVITE); 21228 if (ast_true(v->value)) { 21229 ast_set_flag(&flags[0], SIP_CAN_REINVITE | SIP_CAN_REINVITE_NAT); 21230 } else if (!ast_false(v->value)) { 21231 char buf[64]; 21232 char *word, *next = buf; 21233 21234 ast_copy_string(buf, v->value, sizeof(buf)); 21235 while ((word = strsep(&next, ","))) { 21236 if (!strcasecmp(word, "update")) { 21237 ast_set_flag(&flags[0], SIP_REINVITE_UPDATE | SIP_CAN_REINVITE); 21238 } else if (!strcasecmp(word, "nonat")) { 21239 ast_set_flag(&flags[0], SIP_CAN_REINVITE); 21240 ast_clear_flag(&flags[0], SIP_CAN_REINVITE_NAT); 21241 } else { 21242 ast_log(LOG_WARNING, "Unknown canreinvite mode '%s' on line %d\n", v->value, v->lineno); 21243 } 21244 } 21245 } 21246 } else if (!strcasecmp(v->name, "insecure")) { 21247 ast_set_flag(&mask[0], SIP_INSECURE); 21248 ast_clear_flag(&flags[0], SIP_INSECURE); 21249 set_insecure_flags(&flags[0], v->value, v->lineno); 21250 } else if (!strcasecmp(v->name, "progressinband")) { 21251 ast_set_flag(&mask[0], SIP_PROG_INBAND); 21252 ast_clear_flag(&flags[0], SIP_PROG_INBAND); 21253 if (ast_true(v->value)) 21254 ast_set_flag(&flags[0], SIP_PROG_INBAND_YES); 21255 else if (strcasecmp(v->value, "never")) 21256 ast_set_flag(&flags[0], SIP_PROG_INBAND_NO); 21257 } else if (!strcasecmp(v->name, "promiscredir")) { 21258 ast_set_flag(&mask[0], SIP_PROMISCREDIR); 21259 ast_set2_flag(&flags[0], ast_true(v->value), SIP_PROMISCREDIR); 21260 } else if (!strcasecmp(v->name, "videosupport")) { 21261 if (!strcasecmp(v->value, "always")) { 21262 ast_set_flag(&mask[1], SIP_PAGE2_VIDEOSUPPORT_ALWAYS); 21263 ast_set_flag(&flags[1], SIP_PAGE2_VIDEOSUPPORT_ALWAYS); 21264 } else { 21265 ast_set_flag(&mask[1], SIP_PAGE2_VIDEOSUPPORT); 21266 ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_VIDEOSUPPORT); 21267 } 21268 } else if (!strcasecmp(v->name, "textsupport")) { 21269 ast_set_flag(&mask[1], SIP_PAGE2_TEXTSUPPORT); 21270 ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_TEXTSUPPORT); 21271 res = 1; 21272 } else if (!strcasecmp(v->name, "allowoverlap")) { 21273 ast_set_flag(&mask[1], SIP_PAGE2_ALLOWOVERLAP); 21274 ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_ALLOWOVERLAP); 21275 } else if (!strcasecmp(v->name, "allowsubscribe")) { 21276 ast_set_flag(&mask[1], SIP_PAGE2_ALLOWSUBSCRIBE); 21277 ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_ALLOWSUBSCRIBE); 21278 } else if (!strcasecmp(v->name, "t38pt_udptl")) { 21279 ast_set_flag(&mask[1], SIP_PAGE2_T38SUPPORT_UDPTL); 21280 ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_T38SUPPORT_UDPTL); 21281 #ifdef WHEN_WE_HAVE_T38_FOR_OTHER_TRANSPORTS 21282 } else if (!strcasecmp(v->name, "t38pt_rtp")) { 21283 ast_set_flag(&mask[1], SIP_PAGE2_T38SUPPORT_RTP); 21284 ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_T38SUPPORT_RTP); 21285 } else if (!strcasecmp(v->name, "t38pt_tcp")) { 21286 ast_set_flag(&mask[1], SIP_PAGE2_T38SUPPORT_TCP); 21287 ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_T38SUPPORT_TCP); 21288 #endif 21289 } else if (!strcasecmp(v->name, "rfc2833compensate")) { 21290 ast_set_flag(&mask[1], SIP_PAGE2_RFC2833_COMPENSATE); 21291 ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_RFC2833_COMPENSATE); 21292 } else if (!strcasecmp(v->name, "buggymwi")) { 21293 ast_set_flag(&mask[1], SIP_PAGE2_BUGGY_MWI); 21294 ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_BUGGY_MWI); 21295 } else if (!strcasecmp(v->name, "t38pt_usertpsource")) { 21296 ast_set_flag(&mask[1], SIP_PAGE2_UDPTL_DESTINATION); 21297 ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_UDPTL_DESTINATION); 21298 } else 21299 res = 0; 21300 21301 return res; 21302 }
| static int handle_incoming | ( | struct sip_pvt * | p, | |
| struct sip_request * | req, | |||
| struct sockaddr_in * | sin, | |||
| int * | recount, | |||
| int * | nounlock | |||
| ) | [static] |
Handle incoming SIP requests (methods).
Definition at line 19554 of file chan_sip.c.
References __sip_ack(), append_history, ast_debug, ast_inet_ntoa(), ast_log(), ast_skip_blanks(), ast_string_field_set, ast_strlen_zero(), ast_verbose, check_pendings(), sip_request::debug, debug, DEFAULT_TRANS_TIMEOUT, 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_refer(), handle_request_register(), handle_request_subscribe(), handle_response(), sip_request::has_to_tag, sip_request::headers, cfsip_methods::id, sip_request::ignore, sip_pvt::initreq, INV_TERMINATED, len(), LOG_ERROR, LOG_NOTICE, LOG_WARNING, sip_request::method, sip_pvt::needdestroy, process_sdp(), REQ_OFFSET_TO_STR, SDP_T38_NONE, SIP_ACK, SIP_BYE, SIP_CANCEL, sip_debug_test_pvt(), SIP_INFO, SIP_INVITE, SIP_MESSAGE, sip_methods, SIP_NOTIFY, SIP_OPTIONS, SIP_REFER, SIP_REGISTER, SIP_RESPONSE, sip_scheddestroy(), SIP_SUBSCRIBE, cfsip_methods::text, sip_pvt::theirtag, transmit_response(), transmit_response_reliable(), transmit_response_with_allow(), and sip_pvt::useragent.
Referenced by handle_request_do(), and process_request_queue().
19555 { 19556 /* Called with p->lock held, as well as p->owner->lock if appropriate, keeping things 19557 relatively static */ 19558 const char *cmd; 19559 const char *cseq; 19560 const char *useragent; 19561 int seqno; 19562 int len; 19563 int respid; 19564 int res = 0; 19565 int debug = sip_debug_test_pvt(p); 19566 char *e; 19567 int error = 0; 19568 19569 /* Get Method and Cseq */ 19570 cseq = get_header(req, "Cseq"); 19571 cmd = REQ_OFFSET_TO_STR(req, header[0]); 19572 19573 /* Must have Cseq */ 19574 if (ast_strlen_zero(cmd) || ast_strlen_zero(cseq)) { 19575 ast_log(LOG_ERROR, "Missing Cseq. Dropping this SIP message, it's incomplete.\n"); 19576 error = 1; 19577 } 19578 if (!error && sscanf(cseq, "%d%n", &seqno, &len) != 1) { 19579 ast_log(LOG_ERROR, "No seqno in '%s'. Dropping incomplete message.\n", cmd); 19580 error = 1; 19581 } 19582 if (error) { 19583 if (!p->initreq.headers) /* New call */ 19584 p->needdestroy = 1; /* Make sure we destroy this dialog */ 19585 return -1; 19586 } 19587 /* Get the command XXX */ 19588 19589 cmd = REQ_OFFSET_TO_STR(req, rlPart1); 19590 e = REQ_OFFSET_TO_STR(req, rlPart2); 19591 19592 /* Save useragent of the client */ 19593 useragent = get_header(req, "User-Agent"); 19594 if (!ast_strlen_zero(useragent)) 19595 ast_string_field_set(p, useragent, useragent); 19596 19597 /* Find out SIP method for incoming request */ 19598 if (req->method == SIP_RESPONSE) { /* Response to our request */ 19599 /* When we get here, we know this is a SIP dialog where we've sent 19600 * a request and have a response, or at least get a response 19601 * within an existing dialog. Do some sanity checks, then 19602 * possibly process the request. In all cases, there function 19603 * terminates at the end of this block 19604 */ 19605 int ret = 0; 19606 19607 if (p->ocseq < seqno && seqno != p->lastnoninvite) { 19608 ast_debug(1, "Ignoring out of order response %d (expecting %d)\n", seqno, p->ocseq); 19609 ret = -1; 19610 } else if (p->ocseq != seqno && seqno != p->lastnoninvite) { 19611 /* ignore means "don't do anything with it" but still have to 19612 * respond appropriately. 19613 * But in this case this is a response already, so we really 19614 * have nothing to do with this message, and even setting the 19615 * ignore flag is pointless. 19616 */ 19617 req->ignore = 1; 19618 append_history(p, "Ignore", "Ignoring this retransmit\n"); 19619 } else if (e) { 19620 e = ast_skip_blanks(e); 19621 if (sscanf(e, "%d %n", &respid, &len) != 1) { 19622 ast_log(LOG_WARNING, "Invalid response: '%s'\n", e); 19623 /* XXX maybe should do ret = -1; */ 19624 } else if (respid <= 0) { 19625 ast_log(LOG_WARNING, "Invalid SIP response code: '%d'\n", respid); 19626 /* XXX maybe should do ret = -1; */ 19627 } else { /* finally, something worth processing */ 19628 /* More SIP ridiculousness, we have to ignore bogus contacts in 100 etc responses */ 19629 if ((respid == 200) || ((respid >= 300) && (respid <= 399))) 19630 extract_uri(p, req); 19631 handle_response(p, respid, e + len, req, seqno); 19632 } 19633 } 19634 return 0; 19635 } 19636 19637 /* New SIP request coming in 19638 (could be new request in existing SIP dialog as well...) 19639 */ 19640 19641 p->method = req->method; /* Find out which SIP method they are using */ 19642 ast_debug(4, "**** Received %s (%d) - Command in SIP %s\n", sip_methods[p->method].text, sip_methods[p->method].id, cmd); 19643 19644 if (p->icseq && (p->icseq > seqno) ) { 19645 if (p->pendinginvite && seqno == p->pendinginvite && (req->method == SIP_ACK || req->method == SIP_CANCEL)) { 19646 ast_debug(2, "Got CANCEL or ACK on INVITE with transactions in between.\n"); 19647 } else { 19648 ast_debug(1, "Ignoring too old SIP packet packet %d (expecting >= %d)\n", seqno, p->icseq); 19649 if (req->method != SIP_ACK) 19650 transmit_response(p, "503 Server error", req); /* We must respond according to RFC 3261 sec 12.2 */ 19651 return -1; 19652 } 19653 } else if (p->icseq && 19654 p->icseq == seqno && 19655 req->method != SIP_ACK && 19656 (p->method != SIP_CANCEL || p->alreadygone)) { 19657 /* ignore means "don't do anything with it" but still have to 19658 respond appropriately. We do this if we receive a repeat of 19659 the last sequence number */ 19660 req->ignore = 1; 19661 ast_debug(3, "Ignoring SIP message because of retransmit (%s Seqno %d, ours %d)\n", sip_methods[p->method].text, p->icseq, seqno); 19662 } 19663 19664 if (seqno >= p->icseq) 19665 /* Next should follow monotonically (but not necessarily 19666 incrementally -- thanks again to the genius authors of SIP -- 19667 increasing */ 19668 p->icseq = seqno; 19669 19670 /* Find their tag if we haven't got it */ 19671 if (ast_strlen_zero(p->theirtag)) { 19672 char tag[128]; 19673 19674 gettag(req, "From", tag, sizeof(tag)); 19675 ast_string_field_set(p, theirtag, tag); 19676 } 19677 snprintf(p->lastmsg, sizeof(p->lastmsg), "Rx: %s", cmd); 19678 19679 if (pedanticsipchecking) { 19680 /* If this is a request packet without a from tag, it's not 19681 correct according to RFC 3261 */ 19682 /* Check if this a new request in a new dialog with a totag already attached to it, 19683 RFC 3261 - section 12.2 - and we don't want to mess with recovery */ 19684 if (!p->initreq.headers && req->has_to_tag) { 19685 /* If this is a first request and it got a to-tag, it is not for us */ 19686 if (!req->ignore && req->method == SIP_INVITE) { 19687 transmit_response_reliable(p, "481 Call/Transaction Does Not Exist", req); 19688 /* Will cease to exist after ACK */ 19689 } else if (req->method != SIP_ACK) { 19690 transmit_response(p, "481 Call/Transaction Does Not Exist", req); 19691 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 19692 } else { 19693 ast_debug(1, "Got ACK for unknown dialog... strange.\n"); 19694 } 19695 return res; 19696 } 19697 } 19698 19699 if (!e && (p->method == SIP_INVITE || p->method == SIP_SUBSCRIBE || p->method == SIP_REGISTER || p->method == SIP_NOTIFY)) { 19700 transmit_response(p, "400 Bad request", req); 19701 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 19702 return -1; 19703 } 19704 19705 /* Handle various incoming SIP methods in requests */ 19706 switch (p->method) { 19707 case SIP_OPTIONS: 19708 res = handle_request_options(p, req); 19709 break; 19710 case SIP_INVITE: 19711 res = handle_request_invite(p, req, debug, seqno, sin, recount, e, nounlock); 19712 break; 19713 case SIP_REFER: 19714 res = handle_request_refer(p, req, debug, seqno, nounlock); 19715 break; 19716 case SIP_CANCEL: 19717 res = handle_request_cancel(p, req); 19718 break; 19719 case SIP_BYE: 19720 res = handle_request_bye(p, req); 19721 break; 19722 case SIP_MESSAGE: 19723 res = handle_request_message(p, req); 19724 break; 19725 case SIP_SUBSCRIBE: 19726 res = handle_request_subscribe(p, req, sin, seqno, e); 19727 break; 19728 case SIP_REGISTER: 19729 res = handle_request_register(p, req, sin, e); 19730 break; 19731 case SIP_INFO: 19732 if (req->debug) 19733 ast_verbose("Receiving INFO!\n"); 19734 if (!req->ignore) 19735 handle_request_info(p, req); 19736 else /* if ignoring, transmit response */ 19737 transmit_response(p, "200 OK", req); 19738 break; 19739 case SIP_NOTIFY: 19740 res = handle_request_notify(p, req, sin, seqno, e); 19741 break; 19742 case SIP_ACK: 19743 /* Make sure we don't ignore this */ 19744 if (seqno == p->pendinginvite) { 19745 p->invitestate = INV_TERMINATED; 19746 p->pendinginvite = 0; 19747 __sip_ack(p, seqno, 1 /* response */, 0); 19748 if (find_sdp(req)) { 19749 if (process_sdp(p, req, SDP_T38_NONE)) 19750 return -1; 19751 } 19752 check_pendings(p); 19753 } else if (p->glareinvite == seqno) { 19754 /* handle ack for the 491 pending sent for glareinvite */ 19755 p->glareinvite = 0; 19756 __sip_ack(p, seqno, 1, 0); 19757 } 19758 /* Got an ACK that we did not match. Ignore silently */ 19759 if (!p->lastinvite && ast_strlen_zero(p->randdata)) 19760 p->needdestroy = 1; 19761 break; 19762 default: 19763 transmit_response_with_allow(p, "501 Method Not Implemented", req, 0); 19764 ast_log(LOG_NOTICE, "Unknown SIP command '%s' from '%s'\n", 19765 cmd, ast_inet_ntoa(p->sa.sin_addr)); 19766 /* If this is some new method, and we don't have a call, destroy it now */ 19767 if (!p->initreq.headers) 19768 p->needdestroy = 1; 19769 break; 19770 } 19771 return res; 19772 }
| static int handle_invite_replaces | ( | struct sip_pvt * | p, | |
| struct sip_request * | req, | |||
| int | debug, | |||
| int | seqno, | |||
| struct sockaddr_in * | sin | |||
| ) | [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 17356 of file chan_sip.c.
References ast_channel::_state, append_history, ast_bridged_channel(), AST_CAUSE_SWITCH_CONGESTION, ast_channel_masquerade(), ast_channel_unlock, ast_debug, ast_frfree, ast_hangup(), ast_log(), ast_quiet_chan(), ast_read(), ast_set_flag, ast_setstate(), ast_state2str(), AST_STATE_DOWN, AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, DEFAULT_TRANS_TIMEOUT, dialog_unref(), f, FALSE, sip_pvt::flags, sip_request::ignore, LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_channel::name, sip_pvt::owner, sip_pvt::refer, sip_refer::refer_call, SIP_DEFER_BYE_ON_TRANSFER, sip_pvt_unlock, sip_scheddestroy(), transmit_response(), transmit_response_reliable(), transmit_response_with_sdp(), and XMIT_RELIABLE.
Referenced by handle_request_invite().
17357 { 17358 struct ast_frame *f; 17359 int earlyreplace = 0; 17360 int oneleggedreplace = 0; /* Call with no bridge, propably IVR or voice message */ 17361 struct ast_channel *c = p->owner; /* Our incoming call */ 17362 struct ast_channel *replacecall = p->refer->refer_call->owner; /* The channel we're about to take over */ 17363 struct ast_channel *targetcall; /* The bridge to the take-over target */ 17364 17365 struct ast_channel *test; 17366 17367 /* Check if we're in ring state */ 17368 if (replacecall->_state == AST_STATE_RING) 17369 earlyreplace = 1; 17370 17371 /* Check if we have a bridge */ 17372 if (!(targetcall = ast_bridged_channel(replacecall))) { 17373 /* We have no bridge */ 17374 if (!earlyreplace) { 17375 ast_debug(2, " Attended transfer attempted to replace call with no bridge (maybe ringing). Channel %s!\n", replacecall->name); 17376 oneleggedreplace = 1; 17377 } 17378 } 17379 if (targetcall && targetcall->_state == AST_STATE_RINGING) 17380 ast_debug(4, "SIP transfer: Target channel is in ringing state\n"); 17381 17382 if (targetcall) 17383 ast_debug(4, "SIP transfer: Invite Replace incoming channel should bridge to channel %s while hanging up channel %s\n", targetcall->name, replacecall->name); 17384 else 17385 ast_debug(4, "SIP transfer: Invite Replace incoming channel should replace and hang up channel %s (one call leg)\n", replacecall->name); 17386 17387 if (req->ignore) { 17388 ast_log(LOG_NOTICE, "Ignoring this INVITE with replaces in a stupid way.\n"); 17389 /* We should answer something here. If we are here, the 17390 call we are replacing exists, so an accepted 17391 can't harm */ 17392 transmit_response_with_sdp(p, "200 OK", req, XMIT_RELIABLE, FALSE); 17393 /* Do something more clever here */ 17394 ast_channel_unlock(c); 17395 sip_pvt_unlock(p->refer->refer_call); 17396 return 1; 17397 } 17398 if (!c) { 17399 /* What to do if no channel ??? */ 17400 ast_log(LOG_ERROR, "Unable to create new channel. Invite/replace failed.\n"); 17401 transmit_response_reliable(p, "503 Service Unavailable", req); 17402 append_history(p, "Xfer", "INVITE/Replace Failed. No new channel."); 17403 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 17404 sip_pvt_unlock(p->refer->refer_call); 17405 return 1; 17406 } 17407 append_history(p, "Xfer", "INVITE/Replace received"); 17408 /* We have three channels to play with 17409 channel c: New incoming call 17410 targetcall: Call from PBX to target 17411 p->refer->refer_call: SIP pvt dialog from transferer to pbx. 17412 replacecall: The owner of the previous 17413 We need to masq C into refer_call to connect to 17414 targetcall; 17415 If we are talking to internal audio stream, target call is null. 17416 */ 17417 17418 /* Fake call progress */ 17419 transmit_response(p, "100 Trying", req); 17420 ast_setstate(c, AST_STATE_RING); 17421 17422 /* Masquerade the new call into the referred call to connect to target call 17423 Targetcall is not touched by the masq */ 17424 17425 /* Answer the incoming call and set channel to UP state */ 17426 transmit_response_with_sdp(p, "200 OK", req, XMIT_RELIABLE, FALSE); 17427 17428 ast_setstate(c, AST_STATE_UP); 17429 17430 /* Stop music on hold and other generators */ 17431 ast_quiet_chan(replacecall); 17432 ast_quiet_chan(targetcall); 17433 ast_debug(4, "Invite/Replaces: preparing to masquerade %s into %s\n", c->name, replacecall->name); 17434 /* Unlock clone, but not original (replacecall) */ 17435 if (!oneleggedreplace) 17436 ast_channel_unlock(c); 17437 17438 /* Unlock PVT */ 17439 sip_pvt_unlock(p->refer->refer_call); 17440 17441 /* Make sure that the masq does not free our PVT for the old call */ 17442 if (! earlyreplace && ! oneleggedreplace ) 17443 ast_set_flag(&p->refer->refer_call->flags[0], SIP_DEFER_BYE_ON_TRANSFER); /* Delay hangup */ 17444 17445 /* Prepare the masquerade - if this does not happen, we will be gone */ 17446 if(ast_channel_masquerade(replacecall, c)) 17447 ast_log(LOG_ERROR, "Failed to masquerade C into Replacecall\n"); 17448 else 17449 ast_debug(4, "Invite/Replaces: Going to masquerade %s into %s\n", c->name, replacecall->name); 17450 17451 /* The masquerade will happen as soon as someone reads a frame from the channel */ 17452 17453 /* C should now be in place of replacecall */ 17454 /* ast_read needs to lock channel */ 17455 ast_channel_unlock(c); 17456 17457 if (earlyreplace || oneleggedreplace ) { 17458 /* Force the masq to happen */ 17459 if ((f = ast_read(replacecall))) { /* Force the masq to happen */ 17460 ast_frfree(f); 17461 f = NULL; 17462 ast_debug(4, "Invite/Replace: Could successfully read frame from RING channel!\n"); 17463 } else { 17464 ast_log(LOG_WARNING, "Invite/Replace: Could not read frame from RING channel \n"); 17465 } 17466 c->hangupcause = AST_CAUSE_SWITCH_CONGESTION; 17467 if (!oneleggedreplace) 17468 ast_channel_unlock(replacecall); 17469 } else { /* Bridged call, UP channel */ 17470 if ((f = ast_read(replacecall))) { /* Force the masq to happen */ 17471 /* Masq ok */ 17472 ast_frfree(f); 17473 f = NULL; 17474 ast_debug(3, "Invite/Replace: Could successfully read frame from channel! Masq done.\n"); 17475 } else { 17476 ast_log(LOG_WARNING, "Invite/Replace: Could not read frame from channel. Transfer failed\n"); 17477 } 17478 ast_channel_unlock(replacecall); 17479 } 17480 sip_pvt_unlock(p->refer->refer_call); 17481 17482 ast_setstate(c, AST_STATE_DOWN); 17483 ast_debug(4, "After transfer:----------------------------\n"); 17484 ast_debug(4, " -- C: %s State %s\n", c->name, ast_state2str(c->_state)); 17485 if (replacecall) 17486 ast_debug(4, " -- replacecall: %s State %s\n", replacecall->name, ast_state2str(replacecall->_state)); 17487 if (p->owner) { 17488 ast_debug(4, " -- P->owner: %s State %s\n", p->owner->name, ast_state2str(p->owner->_state)); 17489 test = ast_bridged_channel(p->owner); 17490 if (test) 17491 ast_debug(4, " -- Call bridged to P->owner: %s State %s\n", test->name, ast_state2str(test->_state)); 17492 else 17493 ast_debug(4, " -- No call bridged to C->owner \n"); 17494 } else 17495 ast_debug(4, " -- No channel yet \n"); 17496 ast_debug(4, "End After transfer:----------------------------\n"); 17497 17498 ast_channel_unlock(p->owner); /* Unlock new owner */ 17499 if (!oneleggedreplace) 17500 sip_pvt_unlock(p); /* Unlock SIP structure */ 17501 17502 /* The call should be down with no ast_channel, so hang it up */ 17503 c->tech_pvt = dialog_unref(c->tech_pvt, "unref dialog c->tech_pvt"); 17504 ast_hangup(c); 17505 return 0; 17506 }
| static int handle_request_bye | ( | struct sip_pvt * | p, | |
| struct sip_request * | req | |||
| ) | [static] |
Handle incoming BYE request.
Definition at line 19043 of file chan_sip.c.
References __sip_pretend_ack(), append_history, ast_async_goto(), ast_bridged_channel(), AST_CAUSE_PROTOCOL_ERROR, ast_clear_flag, AST_CONTROL_UNHOLD, ast_debug, ast_inet_ntoa(), ast_log(), ast_queue_control(), ast_queue_hangup(), ast_queue_hangup_with_cause(), ast_rtp_get_quality(), ast_rtp_set_vars(), ast_string_field_set, ast_strlen_zero(), ast_test_flag, sip_pvt::callid, check_via(), context, sip_pvt::context, copy_request(), DEFAULT_TRANS_TIMEOUT, sip_pvt::do_history, sip_pvt::flags, get_also_info(), get_header(), sip_request::ignore, sip_pvt::initreq, INV_TERMINATED, sip_pvt::invitestate, IS_SIP_TECH, LOG_NOTICE, LOG_WARNING, sip_request::method, sip_pvt::owner, pbx_builtin_setvar_helper(), sip_pvt::pendinginvite, sip_pvt::recv, sip_pvt::refer, sip_refer::refer_to, sip_pvt::rtp, RTPQOS_JITTER, RTPQOS_LOSS, RTPQOS_RTT, RTPQOS_SUMMARY, sip_alreadygone(), sip_methods, SIP_OUTGOING, SIP_PAGE2_DIALOG_ESTABLISHED, sip_scheddestroy(), stop_media_flows(), stop_session_timer(), ast_channel::tech, ast_channel::tech_pvt, transmit_response(), transmit_response_reliable(), sip_pvt::trtp, and sip_pvt::vrtp.
Referenced by handle_incoming().
19044 { 19045 struct ast_channel *c=NULL; 19046 int res; 19047 struct ast_channel *bridged_to; 19048 19049 /* If we have an INCOMING invite that we haven't answered, terminate that transaction */ 19050 if (p->pendinginvite && !ast_test_flag(&p->flags[0], SIP_OUTGOING) && !req->ignore) { 19051 transmit_response_reliable(p, "487 Request Terminated", &p->initreq); 19052 } 19053 19054 __sip_pretend_ack(p); 19055 19056 p->invitestate = INV_TERMINATED; 19057 19058 copy_request(&p->initreq, req); 19059 if (sipdebug) 19060 ast_debug(1, "Initializing initreq for method %s - callid %s\n", sip_methods[req->method].text, p->callid); 19061 check_via(p, req); 19062 sip_alreadygone(p); 19063 19064 /* Get RTCP quality before end of call */ 19065 if (p->do_history || p->owner) { 19066 struct ast_channel *bridge = p->owner ? ast_bridged_channel(p->owner) : NULL; 19067 char *videoqos, *textqos; 19068 19069 if (p->rtp) { 19070 if (p->do_history) { 19071 char *audioqos, 19072 *audioqos_jitter, 19073 *audioqos_loss, 19074 *audioqos_rtt; 19075 19076 audioqos = ast_rtp_get_quality(p->rtp, NULL, RTPQOS_SUMMARY); 19077 audioqos_jitter = ast_rtp_get_quality(p->rtp, NULL, RTPQOS_JITTER); 19078 audioqos_loss = ast_rtp_get_quality(p->rtp, NULL, RTPQOS_LOSS); 19079 audioqos_rtt = ast_rtp_get_quality(p->rtp, NULL, RTPQOS_RTT); 19080 19081 append_history(p, "RTCPaudio", "Quality:%s", audioqos); 19082 append_history(p, "RTCPaudioJitter", "Quality:%s", audioqos_jitter); 19083 append_history(p, "RTCPaudioLoss", "Quality:%s", audioqos_loss); 19084 append_history(p, "RTCPaudioRTT", "Quality:%s", audioqos_rtt); 19085 } 19086 19087 if (p->owner) { 19088 ast_rtp_set_vars(p->owner, p->rtp); 19089 } 19090 } 19091 19092 if (bridge) { 19093 struct sip_pvt *q = bridge->tech_pvt; 19094 19095 if (IS_SIP_TECH(bridge->tech) && q && q->rtp) 19096 ast_rtp_set_vars(bridge, q->rtp); 19097 } 19098 19099 if (p->vrtp) { 19100 videoqos = ast_rtp_get_quality(p->vrtp, NULL, RTPQOS_SUMMARY); 19101 if (p->do_history) 19102 append_history(p, "RTCPvideo", "Quality:%s", videoqos); 19103 if (p->owner) 19104 pbx_builtin_setvar_helper(p->owner, "RTPVIDEOQOS", videoqos); 19105 } 19106 19107 if (p->trtp) { 19108 textqos = ast_rtp_get_quality(p->trtp, NULL, RTPQOS_SUMMARY); 19109 if (p->do_history) 19110 append_history(p, "RTCPtext", "Quality:%s", textqos); 19111 if (p->owner) 19112 pbx_builtin_setvar_helper(p->owner, "RTPTEXTQOS", textqos); 19113 } 19114 } 19115 19116 stop_media_flows(p); /* Immediately stop RTP, VRTP and UDPTL as applicable */ 19117 stop_session_timer(p); /* Stop Session-Timer */ 19118 19119 if (!ast_strlen_zero(get_header(req, "Also"))) { 19120 ast_log(LOG_NOTICE, "Client '%s' using deprecated BYE/Also transfer method. Ask vendor to support REFER instead\n", 19121 ast_inet_ntoa(p->recv.sin_addr)); 19122 if (ast_strlen_zero(p->context)) 19123 ast_string_field_set(p, context, default_context); 19124 res = get_also_info(p, req); 19125 if (!res) { 19126 c = p->owner; 19127 if (c) { 19128 bridged_to = ast_bridged_channel(c); 19129 if (bridged_to) { 19130 /* Don't actually hangup here... */ 19131 ast_queue_control(c, AST_CONTROL_UNHOLD); 19132 ast_async_goto(bridged_to, p->context, p->refer->refer_to, 1); 19133 } else 19134 ast_queue_hangup(p->owner); 19135 } 19136 } else { 19137 ast_log(LOG_WARNING, "Invalid transfer information from '%s'\n", ast_inet_ntoa(p->recv.sin_addr)); 19138 if (p->owner) 19139 ast_queue_hangup_with_cause(p->owner, AST_CAUSE_PROTOCOL_ERROR); 19140 } 19141 } else if (p->owner) { 19142 ast_queue_hangup(p->owner); 19143 ast_debug(3, "Received bye, issuing owner hangup\n"); 19144 } else { 19145 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 19146 ast_debug(3, "Received bye, no owner, selfdestruct soon.\n"); 19147 } 19148 ast_clear_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED); 19149 transmit_response(p, "200 OK", req); 19150 19151 return 1; 19152 }
| static int handle_request_cancel | ( | struct sip_pvt * | p, | |
| struct sip_request * | req | |||
| ) | [static] |
Handle incoming CANCEL request.
Definition at line 18898 of file chan_sip.c.
References __sip_pretend_ack(), ast_debug, ast_queue_hangup(), AST_STATE_UP, ast_test_flag, check_via(), DEC_CALL_LIMIT, DEFAULT_TRANS_TIMEOUT, INV_CANCELLED, INV_TERMINATED, sip_pvt::invitestate, sip_dual::req, sip_alreadygone(), SIP_INC_COUNT, SIP_PAGE2_CALL_ONHOLD, sip_scheddestroy(), stop_media_flows(), transmit_response(), transmit_response_reliable(), and update_call_counter().
Referenced by handle_incoming().
18899 { 18900 18901 check_via(p, req); 18902 sip_alreadygone(p); 18903 18904 /* At this point, we could have cancelled the invite at the same time 18905 as the other side sends a CANCEL. Our final reply with error code 18906 might not have been received by the other side before the CANCEL 18907 was sent, so let's just give up retransmissions and waiting for 18908 ACK on our error code. The call is hanging up any way. */ 18909 if (p->invitestate == INV_TERMINATED) 18910 __sip_pretend_ack(p); 18911 else 18912 p->invitestate = INV_CANCELLED; 18913 18914 if (p->owner && p->owner->_state == AST_STATE_UP) { 18915 /* This call is up, cancel is ignored, we need a bye */ 18916 transmit_response(p, "200 OK", req); 18917 ast_debug(1, "Got CANCEL on an answered call. Ignoring... \n"); 18918 return 0; 18919 } 18920 18921 if (ast_test_flag(&p->flags[0], SIP_INC_COUNT) || ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD)) 18922 update_call_counter(p, DEC_CALL_LIMIT); 18923 18924 stop_media_flows(p); /* Immediately stop RTP, VRTP and UDPTL as applicable */ 18925 if (p->owner) 18926 ast_queue_hangup(p->owner); 18927 else 18928 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 18929 if (p->initreq.len > 0) { 18930 transmit_response_reliable(p, "487 Request Terminated", &p->initreq); 18931 transmit_response(p, "200 OK", req); 18932 return 1; 18933 } else { 18934 transmit_response(p, "481 Call Leg Does Not Exist", req); 18935 return 0; 18936 } 18937 }
| static int handle_request_do | ( | struct sip_request * | req, | |
| struct sockaddr_in * | sin | |||
| ) | [static] |
Definition at line 19914 of file chan_sip.c.
References ao2_t_ref, append_history, ast_channel_trylock, ast_channel_unlock, ast_debug, ast_inet_ntoa(), AST_LIST_EMPTY, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_SCHED_DEL_UNREF, ast_str_reset(), ast_update_use_count(), ast_verbose, sip_pvt::callid, copy_socket_data(), sip_request::data, sip_request::debug, dialog_unref(), sip_pvt::do_history, find_call(), find_sip_method(), get_header(), get_transport(), handle_incoming(), sip_request::headers, sip_request::len, sip_request::lines, LOG_ERROR, lws2sws(), sip_request::method, ast_channel::name, netlock, sip_pvt::owner, parse_request(), process_request_queue(), queue_request(), sip_pvt::recv, REQ_OFFSET_TO_STR, sip_pvt::request_queue, sip_pvt::request_queue_sched_id, S_OR, sched, SIP_ACK, sip_debug_test_addr(), sip_pvt_unlock, sip_pvt::socket, sip_request::socket, ast_str::str, transmit_response(), and sip_socket::type.
Referenced by _sip_tcp_helper_thread(), and sipsock_read().
19915 { 19916 struct sip_pvt *p; 19917 int recount = 0; 19918 int nounlock = 0; 19919 int lockretry; 19920 19921 if (sip_debug_test_addr(sin)) /* Set the debug flag early on packet level */ 19922 req->debug = 1; 19923 if (pedanticsipchecking) 19924 req->len = lws2sws(req->data->str, req->len); /* Fix multiline headers */ 19925 if (req->debug) { 19926 ast_verbose("\n<--- SIP read from %s://%s:%d --->\n%s\n<------------->\n", 19927 get_transport(req->socket.type), ast_inet_ntoa(sin->sin_addr), 19928 ntohs(sin->sin_port), req->data->str); 19929 } 19930 19931 if (parse_request(req) == -1) { /* Bad packet, can't parse */ 19932 ast_str_reset(req->data); /* nulling this out is NOT a good idea here. */ 19933 return 1; 19934 } 19935 req->method = find_sip_method(REQ_OFFSET_TO_STR(req, rlPart1)); 19936 19937 if (req->debug) 19938 ast_verbose("--- (%d headers %d lines)%s ---\n", req->headers, req->lines, (req->headers + req->lines == 0) ? " Nat keepalive" : ""); 19939 19940 if (req->headers < 2) { /* Must have at least two headers */ 19941 ast_str_reset(req->data); /* nulling this out is NOT a good idea here. */ 19942 return 1; 19943 } 19944 19945 /* Process request, with netlock held, and with usual deadlock avoidance */ 19946 for (lockretry = 10; lockretry > 0; lockretry--) { 19947 ast_mutex_lock(&netlock); 19948 19949 /* Find the active SIP dialog or create a new one */ 19950 p = find_call(req, sin, req->method); /* returns p locked */ 19951 if (p == NULL) { 19952 ast_debug(1, "Invalid SIP message - rejected , no callid, len %d\n", req->len); 19953 ast_mutex_unlock(&netlock); 19954 return 1; 19955 } 19956 19957 copy_socket_data(&p->socket, &req->socket); 19958 19959 /* Go ahead and lock the owner if it has one -- we may need it */ 19960 /* becaues this is deadlock-prone, we need to try and unlock if failed */ 19961 if (!p->owner || !ast_channel_trylock(p->owner)) 19962 break; /* locking succeeded */ 19963 19964 if (lockretry != 1) { 19965 sip_pvt_unlock(p); 19966 ao2_t_ref(p, -1, "release p (from find_call) inside lockretry loop"); /* we'll look for it again, but p is dead now */ 19967 ast_mutex_unlock(&netlock); 19968 /* Sleep for a very short amount of time */ 19969 usleep(1); 19970 } 19971 } 19972 p->recv = *sin; 19973 19974 if (p->do_history) /* This is a request or response, note what it was for */ 19975 append_history(p, "Rx", "%s / %s / %s", req->data->str, get_header(req, "CSeq"), REQ_OFFSET_TO_STR(req, rlPart2)); 19976 19977 if (!lockretry) { 19978 if (!queue_request(p, req)) { 19979 /* the request has been queued for later handling */ 19980 sip_pvt_unlock(p); 19981 ao2_t_ref(p, -1, "release p (from find_call) after queueing request"); 19982 ast_mutex_unlock(&netlock); 19983 return 1; 19984 } 19985 19986 if (p->owner) 19987 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 ??? - ")); 19988 ast_log(LOG_ERROR, "SIP transaction failed: %s \n", p->callid); 19989 if (req->method != SIP_ACK) 19990 transmit_response(p, "503 Server error", req); /* We must respond according to RFC 3261 sec 12.2 */ 19991 /* XXX We could add retry-after to make sure they come back */ 19992 append_history(p, "LockFail", "Owner lock failed, transaction failed."); 19993 sip_pvt_unlock(p); 19994 ao2_t_ref(p, -1, "release p (from find_call) at end of lockretry"); /* p is gone after the return */ 19995 ast_mutex_unlock(&netlock); 19996 return 1; 19997 } 19998 19999 /* if there are queued requests on this sip_pvt, process them first, so that everything is 20000 handled in order 20001 */ 20002 if (!AST_LIST_EMPTY(&p->request_queue)) { 20003 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")); 20004 process_request_queue(p, &recount, &nounlock); 20005 } 20006 20007 if (handle_incoming(p, req, sin, &recount, &nounlock) == -1) { 20008 /* Request failed */ 20009 ast_debug(1, "SIP message could not be handled, bad request: %-70.70s\n", p->callid[0] ? p->callid : "<no callid>"); 20010 } 20011 20012 if (recount) 20013 ast_update_use_count(); 20014 20015 if (p->owner && !nounlock) 20016 ast_channel_unlock(p->owner); 20017 sip_pvt_unlock(p); 20018 ast_mutex_unlock(&netlock); 20019 ao2_t_ref(p, -1, "throw away dialog ptr from find_call at end of routine"); /* p is gone after the return */ 20020 return 1; 20021 }
| static void handle_request_info | ( | struct sip_pvt * | p, | |
| struct sip_request * | req | |||
| ) | [static] |
Receive SIP INFO Message.
Definition at line 14834 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, buf, sip_pvt::callid, ast_channel::cdr, DEFAULT_TRANS_TIMEOUT, sip_history::event, ast_call_feature::exten, f, sip_pvt::flags, get_body(), get_header(), get_msg_text(), LOG_WARNING, sip_pvt::owner, sip_scheddestroy(), SIP_USECLIENTCODE, transmit_response(), and TRUE.
Referenced by handle_incoming().
14835 { 14836 char buf[1024]; 14837 unsigned int event; 14838 const char *c = get_header(req, "Content-Type"); 14839 14840 /* Need to check the media/type */ 14841 if (!strcasecmp(c, "application/dtmf-relay") || 14842 !strcasecmp(c, "application/vnd.nortelnetworks.digits")) { 14843 unsigned int duration = 0; 14844 14845 if (!p->owner) { /* not a PBX call */ 14846 transmit_response(p, "481 Call leg/transaction does not exist", req); 14847 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 14848 return; 14849 } 14850 14851 /* Try getting the "signal=" part */ 14852 if (ast_strlen_zero(c = get_body(req, "Signal")) && ast_strlen_zero(c = get_body(req, "d"))) { 14853 ast_log(LOG_WARNING, "Unable to retrieve DTMF signal from INFO message from %s\n", p->callid); 14854 transmit_response(p, "200 OK", req); /* Should return error */ 14855 return; 14856 } else { 14857 ast_copy_string(buf, c, sizeof(buf)); 14858 } 14859 14860 if (!ast_strlen_zero((c = get_body(req, "Duration")))) 14861 duration = atoi(c); 14862 if (!duration) 14863 duration = 100; /* 100 ms */ 14864 14865 14866 if (ast_strlen_zero(buf)) { 14867 transmit_response(p, "200 OK", req); 14868 return; 14869 } 14870 14871 if (buf[0] == '*') 14872 event = 10; 14873 else if (buf[0] == '#') 14874 event = 11; 14875 else if ((buf[0] >= 'A') && (buf[0] <= 'D')) 14876 event = 12 + buf[0] - 'A'; 14877 else if (buf[0] == '!') 14878 event = 16; 14879 else 14880 event = atoi(buf); 14881 if (event == 16) { 14882 /* send a FLASH event */ 14883 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_FLASH, }; 14884 ast_queue_frame(p->owner, &f); 14885 if (sipdebug) 14886 ast_verbose("* DTMF-relay event received: FLASH\n"); 14887 } else { 14888 /* send a DTMF event */ 14889 struct ast_frame f = { AST_FRAME_DTMF, }; 14890 if (event < 10) { 14891 f.subclass = '0' + event; 14892 } else if (event < 11) { 14893 f.subclass = '*'; 14894 } else if (event < 12) { 14895 f.subclass = '#'; 14896 } else if (event < 16) { 14897 f.subclass = 'A' + (event - 12); 14898 } 14899 f.len = duration; 14900 ast_queue_frame(p->owner, &f); 14901 if (sipdebug) 14902 ast_verbose("* DTMF-relay event received: %c\n", f.subclass); 14903 } 14904 transmit_response(p, "200 OK", req); 14905 return; 14906 } else if (!strcasecmp(c, "application/dtmf")) { 14907 /*! \todo Note: Doesn't read the duration of the DTMF. Should be fixed. */ 14908 unsigned int duration = 0; 14909 14910 if (!p->owner) { /* not a PBX call */ 14911 transmit_response(p, "481 Call leg/transaction does not exist", req); 14912 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 14913 return; 14914 } 14915 14916 get_msg_text(buf, sizeof(buf), req, TRUE); 14917 duration = 100; /* 100 ms */ 14918 14919 if (ast_strlen_zero(buf)) { 14920 transmit_response(p, "200 OK", req); 14921 return; 14922 } 14923 event = atoi(buf); 14924 if (event == 16) { 14925 /* send a FLASH event */ 14926 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_FLASH, }; 14927 ast_queue_frame(p->owner, &f); 14928 if (sipdebug) 14929 ast_verbose("* DTMF-relay event received: FLASH\n"); 14930 } else { 14931 /* send a DTMF event */ 14932 struct ast_frame f = { AST_FRAME_DTMF, }; 14933 if (event < 10) { 14934 f.subclass = '0' + event; 14935 } else if (event < 11) { 14936 f.subclass = '*'; 14937 } else if (event < 12) { 14938 f.subclass = '#'; 14939 } else if (event < 16) { 14940 f.subclass = 'A' + (event - 12); 14941 } 14942 f.len = duration; 14943 ast_queue_frame(p->owner, &f); 14944 if (sipdebug) 14945 ast_verbose("* DTMF-relay event received: %c\n", f.subclass); 14946 } 14947 transmit_response(p, "200 OK", req); 14948 return; 14949 14950 } else if (!strcasecmp(c, "application/media_control+xml")) { 14951 /* Eh, we'll just assume it's a fast picture update for now */ 14952 if (p->owner) 14953 ast_queue_control(p->owner, AST_CONTROL_VIDUPDATE); 14954 transmit_response(p, "200 OK", req); 14955 return; 14956 } else if (!ast_strlen_zero(c = get_header(req, "X-ClientCode"))) { 14957 /* Client code (from SNOM phone) */ 14958 if (ast_test_flag(&p->flags[0], SIP_USECLIENTCODE)) { 14959 if (p->owner && p->owner->cdr) 14960 ast_cdr_setuserfield(p->owner, c); 14961 if (p->owner && ast_bridged_channel(p->owner) && ast_bridged_channel(p->owner)->cdr) 14962 ast_cdr_setuserfield(ast_bridged_channel(p->owner), c); 14963 transmit_response(p, "200 OK", req); 14964 } else { 14965 transmit_response(p, "403 Forbidden", req); 14966 } 14967 return; 14968 } else if (!ast_strlen_zero(c = get_header(req, "Record"))) { 14969 /* INFO messages generated by some phones to start/stop recording 14970 on phone calls. 14971 OEJ: I think this should be something that is enabled/disabled 14972 per device. I don't want incoming callers to record calls in my 14973 pbx. 14974 */ 14975 /* first, get the feature string, if it exists */ 14976 struct ast_call_feature *feat; 14977 int j; 14978 struct ast_frame f = { AST_FRAME_DTMF, }; 14979 14980 ast_rdlock_call_features(); 14981 feat = ast_find_call_feature("automon"); 14982 if (!feat || ast_strlen_zero(feat->exten)) { 14983 ast_log(LOG_WARNING, "Recording requested, but no One Touch Monitor registered. (See features.conf)\n"); 14984 /* 403 means that we don't support this feature, so don't request it again */ 14985 transmit_response(p, "403 Forbidden", req); 14986 ast_unlock_call_features(); 14987 return; 14988 } 14989 /* Send the feature code to the PBX as DTMF, just like the handset had sent it */ 14990 f.len = 100; 14991 for (j=0; j < strlen(feat->exten); j++) { 14992 f.subclass = feat->exten[j]; 14993 ast_queue_frame(p->owner, &f); 14994 if (sipdebug) 14995 ast_verbose("* DTMF-relay event faked: %c\n", f.subclass); 14996 } 14997 ast_unlock_call_features(); 14998 14999 ast_debug(1, "Got a Request to Record the channel, state %s\n", c); 15000 transmit_response(p, "200 OK", req); 15001 return; 15002 } else if (ast_strlen_zero(c = get_header(req, "Content-Length")) || !strcasecmp(c, "0")) { 15003 /* This is probably just a packet making sure the signalling is still up, just send back a 200 OK */ 15004 transmit_response(p, "200 OK", req); 15005 return; 15006 } 15007 15008 /* Other type of INFO message, not really understood by Asterisk */ 15009 /* if (get_msg_text(buf, sizeof(buf), req)) { */ 15010 15011 ast_log(LOG_WARNING, "Unable to parse INFO message from %s. Content %s\n", p->callid, buf); 15012 transmit_response(p, "415 Unsupported media type", req); 15013 return; 15014 }
| static int handle_request_invite | ( | struct sip_pvt * | p, | |
| struct sip_request * | req, | |||
| int | debug, | |||
| int | seqno, | |||
| struct sockaddr_in * | sin, | |||
| int * | recount, | |||
| 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 17811 of file chan_sip.c.
References __sip_ack(), ast_channel::_state, append_history, AST_CAUSE_CALL_REJECTED, AST_CAUSE_NORMAL_CLEARING, ast_channel_lock, ast_channel_unlock, ast_clear_flag, ast_debug, ast_hangup(), ast_log(), ast_null_frame, AST_PBX_CALL_LIMIT, AST_PBX_FAILED, ast_pbx_start(), AST_PBX_SUCCESS, ast_pickup_call(), ast_pickup_ext(), ast_queue_frame(), ast_rtp_setdtmf(), ast_rtp_setdtmfcompensate(), ast_sched_add(), AST_SCHED_DEL, ast_set_flag, ast_setstate(), 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_uri_decode(), ast_verbose, AUTH_CHALLENGE_SENT, AUTH_FAKE_AUTH, sip_pvt::autokillid, build_contact(), build_route(), sip_pvt::callid, sip_pvt::capability, check_user(), check_via(), context, sip_pvt::context, copy_request(), create_addr(), DEC_CALL_LIMIT, DEFAULT_TRANS_TIMEOUT, dialog_ref(), dialog_unref(), sip_pvt::do_history, exten, sip_pvt::exten, extract_uri(), FALSE, find_sdp(), sip_pvt::flags, get_destination(), get_header(), get_rdnis(), get_sip_pvt_byid_locked(), sip_pvt::glareinvite, handle_invite_replaces(), ast_channel::hangupcause, sip_request::headers, sip_pvt::icseq, sip_request::ignore, INC_CALL_LIMIT, sip_pvt::initreq, INV_COMPLETED, INV_PROCEEDING, INV_TERMINATED, sip_pvt::invitestate, sip_pvt::jointcapability, sip_pvt::lastinvite, LOG_DEBUG, LOG_ERROR, LOG_NOTICE, LOG_WARNING, make_our_tag(), sip_request::method, sip_pkt::method, msg, ast_channel::name, sip_pkt::next, option_debug, sip_pvt::owner, sip_pvt::packets, parse_minse(), parse_ok_contact(), parse_session_expires(), parse_sip_options(), sip_pvt::peername, sip_pvt::pendinginvite, process_sdp(), sip_pvt::refer, sip_refer::refer_call, REQ_OFFSET_TO_STR, sip_pvt::reqsipoptions, restart_session_timer(), sip_pkt::retransid, sip_pvt::rtp, S_OR, sched, SDP_T38_INITIATE, sip_pkt::seqno, sip_pvt::session_modify, SESSION_TIMER_MODE_ACCEPT, SESSION_TIMER_MODE_ORIGINATE, SESSION_TIMER_MODE_REFUSE, SESSION_TIMER_REFRESHER_AUTO, SESSION_TIMER_REFRESHER_UAS, sip_alreadygone(), sip_cancel_destroy(), SIP_DTMF, SIP_DTMF_RFC2833, SIP_INVITE, sip_methods, sip_new(), SIP_OPT_REPLACES, SIP_OPT_TIMER, SIP_OUTGOING, SIP_PAGE2_ALLOWOVERLAP, SIP_PAGE2_DIALOG_ESTABLISHED, SIP_PAGE2_RFC2833_COMPENSATE, sip_pvt_lock, sip_pvt_unlock, sip_refer_allocate(), sip_scheddestroy(), sip_st_alloc(), sip_t38_abort(), sip_uri_cmp(), sip_pvt::sipoptions, sip_st_dlg::st_active, sip_st_dlg::st_active_peer_ua, sip_st_dlg::st_expirys, st_get_mode(), st_get_refresher(), st_get_se(), sip_st_dlg::st_interval, sip_st_dlg::st_ref, start_session_timer(), t38properties::state, sip_pvt::stimer, strcasestr(), strsep(), sip_pvt::t38, T38_DISABLED, T38_ENABLED, T38_PEER_REINVITE, sip_pvt::t38id, sip_pvt::tag, transmit_fake_auth_response(), transmit_invite(), transmit_response(), transmit_response_reliable(), transmit_response_with_minse(), transmit_response_with_sdp(), transmit_response_with_t38_sdp(), transmit_response_with_unsupported(), TRUE, update_call_counter(), sip_pvt::username, XMIT_CRITICAL, XMIT_RELIABLE, and XMIT_UNRELIABLE.
Referenced by handle_incoming().
17812 { 17813 int res = 1; 17814 int gotdest; 17815 const char *p_replaces; 17816 char *replace_id = NULL; 17817 const char *required; 17818 unsigned int required_profile = 0; 17819 struct ast_channel *c = NULL; /* New channel */ 17820 int reinvite = 0; 17821 int rtn; 17822 17823 const char *p_uac_se_hdr; /* UAC's Session-Expires header string */ 17824 const char *p_uac_min_se; /* UAC's requested Min-SE interval (char string) */ 17825 int uac_max_se = -1; /* UAC's Session-Expires in integer format */ 17826 int uac_min_se = -1; /* UAC's Min-SE in integer format */ 17827 int st_active = FALSE; /* Session-Timer on/off boolean */ 17828 int st_interval = 0; /* Session-Timer negotiated refresh interval */ 17829 enum st_refresher st_ref; /* Session-Timer session refresher */ 17830 int dlg_min_se = -1; 17831 st_ref = SESSION_TIMER_REFRESHER_AUTO; 17832 17833 /* Find out what they support */ 17834 if (!p->sipoptions) { 17835 const char *supported = get_header(req, "Supported"); 17836 if (!ast_strlen_zero(supported)) 17837 parse_sip_options(p, supported); 17838 } 17839 17840 /* Find out what they require */ 17841 required = get_header(req, "Require"); 17842 if (!ast_strlen_zero(required)) { 17843 required_profile = parse_sip_options(NULL, required); 17844 if (required_profile && required_profile != SIP_OPT_REPLACES && required_profile != SIP_OPT_TIMER) { 17845 /* At this point we only support REPLACES and Session-Timer */ 17846 transmit_response_with_unsupported(p, "420 Bad extension (unsupported)", req, required); 17847 ast_log(LOG_WARNING, "Received SIP INVITE with unsupported required extension: %s\n", required); 17848 p->invitestate = INV_COMPLETED; 17849 if (!p->lastinvite) 17850 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 17851 return -1; 17852 } 17853 } 17854 17855 /* The option tags may be present in Supported: or Require: headers. 17856 Include the Require: option tags for further processing as well */ 17857 p->sipoptions |= required_profile; 17858 p->reqsipoptions = required_profile; 17859 17860 /* Check if this is a loop */ 17861 if (ast_test_flag(&p->flags[0], SIP_OUTGOING) && p->owner && (p->owner->_state != AST_STATE_UP)) { 17862 /* This is a call to ourself. Send ourselves an error code and stop 17863 processing immediately, as SIP really has no good mechanism for 17864 being able to call yourself */ 17865 /* If pedantic is on, we need to check the tags. If they're different, this is 17866 in fact a forked call through a SIP proxy somewhere. */ 17867 int different; 17868 char *initial_rlPart2 = REQ_OFFSET_TO_STR(&p->initreq, rlPart2); 17869 char *this_rlPart2 = REQ_OFFSET_TO_STR(req, rlPart2); 17870 if (pedanticsipchecking) 17871 different = sip_uri_cmp(initial_rlPart2, this_rlPart2); 17872 else 17873 different = strcmp(initial_rlPart2, this_rlPart2); 17874 if (!different) { 17875 transmit_response(p, "482 Loop Detected", req); 17876 p->invitestate = INV_COMPLETED; 17877 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 17878 return 0; 17879 } else { 17880 /*! This is a spiral. What we need to do is to just change the outgoing INVITE 17881 * so that it now routes to the new Request URI. Since we created the INVITE ourselves 17882 * that should be all we need to do. 17883 * 17884 * \todo XXX This needs to be reviewed. YOu don't change the request URI really, you route the packet 17885 * correctly instead... 17886 */ 17887 char *uri = ast_strdupa(this_rlPart2); 17888 char *at = strchr(uri, '@'); 17889 char *peerorhost; 17890 struct sip_pkt *pkt = NULL; 17891 if (option_debug > 2) { 17892 ast_log(LOG_DEBUG, "Potential spiral detected. Original RURI was %s, new RURI is %s\n", initial_rlPart2, this_rlPart2); 17893 } 17894 if (at) { 17895 *at = '\0'; 17896 } 17897 /* Parse out "sip:" */ 17898 if ((peerorhost = strchr(uri, ':'))) { 17899 *peerorhost++ = '\0'; 17900 } 17901 create_addr(p, peerorhost, NULL, 0); 17902 ast_string_field_set(p, theirtag, NULL); 17903 for (pkt = p->packets; pkt; pkt = pkt->next) { 17904 if (pkt->seqno == p->icseq && pkt->method == SIP_INVITE) { 17905 AST_SCHED_DEL(sched, pkt->retransid); 17906 } 17907 } 17908 return transmit_invite(p, SIP_INVITE, 1, 3); 17909 } 17910 } 17911 17912 if (!req->ignore && p->pendinginvite) { 17913 if (!ast_test_flag(&p->flags[0], SIP_OUTGOING) && ast_test_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED)) { 17914 /* We have received a reINVITE on an incoming call to which we have sent a 200 OK but not yet received 17915 * an ACK. According to RFC 5407, Section 3.1.4, the proper way to handle this race condition is to accept 17916 * the reINVITE since we have established a dialog. 17917 */ 17918 17919 /* Note that this will both clear the pendinginvite flag and cancel the 17920 * retransmission of the 200 OK. Basically, we're accepting this reINVITE as both an ACK 17921 * and a reINVITE in one request. 17922 */ 17923 __sip_ack(p, p->lastinvite, 1, 0); 17924 } else { 17925 /* We already have a pending invite. Sorry. You are on hold. */ 17926 p->glareinvite = seqno; 17927 transmit_response_reliable(p, "491 Request Pending", req); 17928 ast_debug(1, "Got INVITE on call where we already have pending INVITE, deferring that - %s\n", p->callid); 17929 /* Don't destroy dialog here */ 17930 return 0; 17931 } 17932 } 17933 17934 p_replaces = get_header(req, "Replaces"); 17935 if (!ast_strlen_zero(p_replaces)) { 17936 /* We have a replaces header */ 17937 char *ptr; 17938 char *fromtag = NULL; 17939 char *totag = NULL; 17940 char *start, *to; 17941 int error = 0; 17942 17943 if (p->owner) { 17944 ast_debug(3, "INVITE w Replaces on existing call? Refusing action. [%s]\n", p->callid); 17945 transmit_response_reliable(p, "400 Bad request", req); /* The best way to not not accept the transfer */ 17946 /* Do not destroy existing call */ 17947 return -1; 17948 } 17949 17950 if (sipdebug) 17951 ast_debug(3, "INVITE part of call transfer. Replaces [%s]\n", p_replaces); 17952 /* Create a buffer we can manipulate */ 17953 replace_id = ast_strdupa(p_replaces); 17954 ast_uri_decode(replace_id); 17955 17956 if (!p->refer && !sip_refer_allocate(p)) { 17957 transmit_response_reliable(p, "500 Server Internal Error", req); 17958 append_history(p, "Xfer", "INVITE/Replace Failed. Out of memory."); 17959 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 17960 p->invitestate = INV_COMPLETED; 17961 return -1; 17962 } 17963 17964 /* Todo: (When we find phones that support this) 17965 if the replaces header contains ";early-only" 17966 we can only replace the call in early 17967 stage, not after it's up. 17968 17969 If it's not in early mode, 486 Busy. 17970 */ 17971 17972 /* Skip leading whitespace */ 17973 replace_id = ast_skip_blanks(replace_id); 17974 17975 start = replace_id; 17976 while ( (ptr = strsep(&start, ";")) ) { 17977 ptr = ast_skip_blanks(ptr); /* XXX maybe unnecessary ? */ 17978 if ( (to = strcasestr(ptr, "to-tag=") ) ) 17979 totag = to + 7; /* skip the keyword */ 17980 else if ( (to = strcasestr(ptr, "from-tag=") ) ) { 17981 fromtag = to + 9; /* skip the keyword */ 17982 fromtag = strsep(&fromtag, "&"); /* trim what ? */ 17983 } 17984 } 17985 17986 if (sipdebug) 17987 ast_debug(4, "Invite/replaces: Will use Replace-Call-ID : %s Fromtag: %s Totag: %s\n", replace_id, fromtag ? fromtag : "<no from tag>", totag ? totag : "<no to tag>"); 17988 17989 17990 /* Try to find call that we are replacing 17991 If we have a Replaces header, we need to cancel that call if we succeed with this call 17992 */ 17993 if ((p->refer->refer_call = get_sip_pvt_byid_locked(replace_id, totag, fromtag)) == NULL) { 17994 ast_log(LOG_NOTICE, "Supervised transfer attempted to replace non-existent call id (%s)!\n", replace_id); 17995 transmit_response_reliable(p, "481 Call Leg Does Not Exist (Replaces)", req); 17996 error = 1; 17997 } 17998 17999 /* At this point, bot the pvt and the owner of the call to be replaced is locked */ 18000 18001 /* The matched call is the call from the transferer to Asterisk . 18002 We want to bridge the bridged part of the call to the 18003 incoming invite, thus taking over the refered call */ 18004 18005 if (p->refer->refer_call == p) { 18006 ast_log(LOG_NOTICE, "INVITE with replaces into it's own call id (%s == %s)!\n", replace_id, p->callid); 18007 p->refer->refer_call = dialog_unref(p->refer->refer_call, "unref dialog p->refer->refer_call"); 18008 transmit_response_reliable(p, "400 Bad request", req); /* The best way to not not accept the transfer */ 18009 error = 1; 18010 } 18011 18012 if (!error && !p->refer->refer_call->owner) { 18013 /* Oops, someting wrong anyway, no owner, no call */ 18014 ast_log(LOG_NOTICE, "Supervised transfer attempted to replace non-existing call id (%s)!\n", replace_id); 18015 /* Check for better return code */ 18016 transmit_response_reliable(p, "481 Call Leg Does Not Exist (Replace)", req); 18017 error = 1; 18018 } 18019 18020 if (!error && 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 ) { 18021 ast_log(LOG_NOTICE, "Supervised transfer attempted to replace non-ringing or active call id (%s)!\n", replace_id); 18022 transmit_response_reliable(p, "603 Declined (Replaces)", req); 18023 error = 1; 18024 } 18025 18026 if (error) { /* Give up this dialog */ 18027 append_history(p, "Xfer", "INVITE/Replace Failed."); 18028 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 18029 sip_pvt_unlock(p); 18030 if (p->refer->refer_call) { 18031 sip_pvt_unlock(p->refer->refer_call); 18032 if (p->refer->refer_call->owner) { 18033 ast_channel_unlock(p->refer->refer_call->owner); 18034 } 18035 } 18036 p->invitestate = INV_COMPLETED; 18037 return -1; 18038 } 18039 } 18040 18041 /* Check if this is an INVITE that sets up a new dialog or 18042 a re-invite in an existing dialog */ 18043 18044 if (!req->ignore) { 18045 int newcall = (p->initreq.headers ? TRUE : FALSE); 18046 18047 if (sip_cancel_destroy(p)) 18048 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 18049 /* This also counts as a pending invite */ 18050 p->pendinginvite = seqno; 18051 check_via(p, req); 18052 18053 copy_request(&p->initreq, req); /* Save this INVITE as the transaction basis */ 18054 if (sipdebug) 18055 ast_debug(1, "Initializing initreq for method %s - callid %s\n", sip_methods[req->method].text, p->callid); 18056 if (!p->owner) { /* Not a re-invite */ 18057 if (debug) 18058 ast_verbose("Using INVITE request as basis request - %s\n", p->callid); 18059 if (newcall) 18060 append_history(p, "Invite", "New call: %s", p->callid); 18061 parse_ok_contact(p, req); 18062 } else { /* Re-invite on existing call */ 18063 ast_clear_flag(&p->flags[0], SIP_OUTGOING); /* This is now an inbound dialog */ 18064 /* Handle SDP here if we already have an owner */ 18065 if (find_sdp(req)) { 18066 if (process_sdp(p, req, SDP_T38_INITIATE)) { 18067 transmit_response_reliable(p, "488 Not acceptable here", req); 18068 if (!p->lastinvite) 18069 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 18070 return -1; 18071 } 18072 } else { 18073 p->jointcapability = p->capability; 18074 ast_debug(1, "Hm.... No sdp for the moment\n"); 18075 } 18076 if (p->do_history) /* This is a response, note what it was for */ 18077 append_history(p, "ReInv", "Re-invite received"); 18078 } 18079 } else if (debug) 18080 ast_verbose("Ignoring this INVITE request\n"); 18081 18082 18083 if (!p->lastinvite && !req->ignore && !p->owner) { 18084 /* This is a new invite */ 18085 /* Handle authentication if this is our first invite */ 18086 res = check_user(p, req, SIP_INVITE, e, XMIT_RELIABLE, sin); 18087 if (res == AUTH_CHALLENGE_SENT) { 18088 p->invitestate = INV_COMPLETED; /* Needs to restart in another INVITE transaction */ 18089 return 0; 18090 } 18091 if (res < 0) { /* Something failed in authentication */ 18092 if (res == AUTH_FAKE_AUTH) { 18093 ast_log(LOG_NOTICE, "Sending fake auth rejection for device %s\n", get_header(req, "From")); 18094 transmit_fake_auth_response(p, SIP_INVITE, req, XMIT_RELIABLE); 18095 } else { 18096 ast_log(LOG_NOTICE, "Failed to authenticate device %s\n", get_header(req, "From")); 18097 transmit_response_reliable(p, "403 Forbidden", req); 18098 } 18099 p->invitestate = INV_COMPLETED; 18100 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 18101 ast_string_field_set(p, theirtag, NULL); 18102 return 0; 18103 } 18104 18105 /* We have a succesful authentication, process the SDP portion if there is one */ 18106 if (find_sdp(req)) { 18107 if (process_sdp(p, req, SDP_T38_INITIATE)) { 18108 /* Unacceptable codecs */ 18109 transmit_response_reliable(p, "488 Not acceptable here", req); 18110 p->invitestate = INV_COMPLETED; 18111 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 18112 ast_debug(1, "No compatible codecs for this SIP call.\n"); 18113 return -1; 18114 } 18115 } else { /* No SDP in invite, call control session */ 18116 p->jointcapability = p->capability; 18117 ast_debug(2, "No SDP in Invite, third party call control\n"); 18118 } 18119 18120 /* Queue NULL frame to prod ast_rtp_bridge if appropriate */ 18121 /* This seems redundant ... see !p-owner above */ 18122 if (p->owner) 18123 ast_queue_frame(p->owner, &ast_null_frame); 18124 18125 18126 /* Initialize the context if it hasn't been already */ 18127 if (ast_strlen_zero(p->context)) 18128 ast_string_field_set(p, context, default_context); 18129 18130 18131 /* Check number of concurrent calls -vs- incoming limit HERE */ 18132 ast_debug(1, "Checking SIP call limits for device %s\n", p->username); 18133 if ((res = update_call_counter(p, INC_CALL_LIMIT))) { 18134 if (res < 0) { 18135 ast_log(LOG_NOTICE, "Failed to place call for device %s, too many calls\n", p->username); 18136 transmit_response_reliable(p, "480 Temporarily Unavailable (Call limit) ", req); 18137 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 18138 p->invitestate = INV_COMPLETED; 18139 } 18140 return 0; 18141 } 18142 gotdest = get_destination(p, NULL); /* Get destination right away */ 18143 get_rdnis(p, NULL); /* Get redirect information */ 18144 extract_uri(p, req); /* Get the Contact URI */ 18145 build_contact(p); /* Build our contact header */ 18146 18147 if (p->rtp) { 18148 ast_rtp_setdtmf(p->rtp, ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833); 18149 ast_rtp_setdtmfcompensate(p->rtp, ast_test_flag(&p->flags[1], SIP_PAGE2_RFC2833_COMPENSATE)); 18150 } 18151 18152 if (!replace_id && gotdest) { /* No matching extension found */ 18153 if (gotdest == 1 && ast_test_flag(&p->flags[1], SIP_PAGE2_ALLOWOVERLAP)) 18154 transmit_response_reliable(p, "484 Address Incomplete", req); 18155 else { 18156 char *decoded_exten = ast_strdupa(p->exten); 18157 18158 transmit_response_reliable(p, "404 Not Found", req); 18159 ast_uri_decode(decoded_exten); 18160 ast_log(LOG_NOTICE, "Call from '%s' to extension" 18161 " '%s' rejected because extension not found.\n", 18162 S_OR(p->username, p->peername), decoded_exten); 18163 } 18164 p->invitestate = INV_COMPLETED; 18165 update_call_counter(p, DEC_CALL_LIMIT); 18166 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 18167 return 0; 18168 } else { 18169 18170 /* If no extension was specified, use the s one */ 18171 /* Basically for calling to IP/Host name only */ 18172 if (ast_strlen_zero(p->exten)) 18173 ast_string_field_set(p, exten, "s"); 18174 /* Initialize our tag */ 18175 18176 make_our_tag(p->tag, sizeof(p->tag)); 18177 /* First invitation - create the channel */ 18178 c = sip_new(p, AST_STATE_DOWN, S_OR(p->peername, NULL)); 18179 *recount = 1; 18180 18181 /* Save Record-Route for any later requests we make on this dialogue */ 18182 build_route(p, req, 0); 18183 18184 if (c) { 18185 /* Pre-lock the call */ 18186 ast_channel_lock(c); 18187 } 18188 } 18189 } else { 18190 if (sipdebug) { 18191 if (!req->ignore) 18192 ast_debug(2, "Got a SIP re-invite for call %s\n", p->callid); 18193 else 18194 ast_debug(2, "Got a SIP re-transmit of INVITE for call %s\n", p->callid); 18195 } 18196 if (!req->ignore) 18197 reinvite = 1; 18198 c = p->owner; 18199 } 18200 18201 /* Session-Timers */ 18202 if (p->sipoptions == SIP_OPT_TIMER) { 18203 /* The UAC has requested session-timers for this session. Negotiate 18204 the session refresh interval and who will be the refresher */ 18205 ast_debug(2, "Incoming INVITE with 'timer' option enabled\n"); 18206 18207 /* Allocate Session-Timers struct w/in the dialog */ 18208 if (!p->stimer) 18209 sip_st_alloc(p); 18210 18211 /* Parse the Session-Expires header */ 18212 p_uac_se_hdr = get_header(req, "Session-Expires"); 18213 if (!ast_strlen_zero(p_uac_se_hdr)) { 18214 rtn = parse_session_expires(p_uac_se_hdr, &uac_max_se, &st_ref); 18215 if (rtn != 0) { 18216 transmit_response_reliable(p, "400 Session-Expires Invalid Syntax", req); 18217 p->invitestate = INV_COMPLETED; 18218 if (!p->lastinvite) { 18219 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 18220 } 18221 return -1; 18222 } 18223 } 18224 18225 /* Parse the Min-SE header */ 18226 p_uac_min_se = get_header(req, "Min-SE"); 18227 if (!ast_strlen_zero(p_uac_min_se)) { 18228 rtn = parse_minse(p_uac_min_se, &uac_min_se); 18229 if (rtn != 0) { 18230 transmit_response_reliable(p, "400 Min-SE Invalid Syntax", req); 18231 p->invitestate = INV_COMPLETED; 18232 if (!p->lastinvite) { 18233 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 18234 } 18235 return -1; 18236 } 18237 } 18238 18239 dlg_min_se = st_get_se(p, FALSE); 18240 switch (st_get_mode(p)) { 18241 case SESSION_TIMER_MODE_ACCEPT: 18242 case SESSION_TIMER_MODE_ORIGINATE: 18243 if (uac_max_se > 0 && uac_max_se < dlg_min_se) { 18244 transmit_response_with_minse(p, "422 Session Interval Too Small", req, dlg_min_se); 18245 p->invitestate = INV_COMPLETED; 18246 if (!p->lastinvite) { 18247 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 18248 } 18249 return -1; 18250 } 18251 18252 p->stimer->st_active_peer_ua = TRUE; 18253 st_active = TRUE; 18254 if (st_ref == SESSION_TIMER_REFRESHER_AUTO) { 18255 st_ref = st_get_refresher(p); 18256 } 18257 18258 if (uac_max_se > 0) { 18259 int dlg_max_se = st_get_se(p, TRUE); 18260 if (dlg_max_se >= uac_min_se) { 18261 st_interval = (uac_max_se < dlg_max_se) ? uac_max_se : dlg_max_se; 18262 } else { 18263 st_interval = uac_max_se; 18264 } 18265 } else { 18266 st_interval = uac_min_se; 18267 } 18268 break; 18269 18270 case SESSION_TIMER_MODE_REFUSE: 18271 if (p->reqsipoptions == SIP_OPT_TIMER) { 18272 transmit_response_with_unsupported(p, "420 Option Disabled", req, required); 18273 ast_log(LOG_WARNING, "Received SIP INVITE with supported but disabled option: %s\n", required); 18274 p->invitestate = INV_COMPLETED; 18275 if (!p->lastinvite) { 18276 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 18277 } 18278 return -1; 18279 } 18280 break; 18281 18282 default: 18283 ast_log(LOG_ERROR, "Internal Error %d at %s:%d\n", st_get_mode(p), __FILE__, __LINE__); 18284 break; 18285 } 18286 } else { 18287 /* The UAC did not request session-timers. Asterisk (UAS), will now decide 18288 (based on session-timer-mode in sip.conf) whether to run session-timers for 18289 this session or not. */ 18290 switch (st_get_mode(p)) { 18291 case SESSION_TIMER_MODE_ORIGINATE: 18292 st_active = TRUE; 18293 st_interval = st_get_se(p, TRUE); 18294 st_ref = SESSION_TIMER_REFRESHER_UAS; 18295 p->stimer->st_active_peer_ua = FALSE; 18296 break; 18297 18298 default: 18299 break; 18300 } 18301 } 18302 18303 if (reinvite == 0) { 18304 /* Session-Timers: Start session refresh timer based on negotiation/config */ 18305 if (st_active == TRUE) { 18306 p->stimer->st_active = TRUE; 18307 p->stimer->st_interval = st_interval; 18308 p->stimer->st_ref = st_ref; 18309 start_session_timer(p); 18310 } 18311 } else { 18312 if (p->stimer->st_active == TRUE) { 18313 /* Session-Timers: A re-invite request sent within a dialog will serve as 18314 a refresh request, no matter whether the re-invite was sent for refreshing 18315 the session or modifying it.*/ 18316 ast_debug (2, "Restarting session-timers on a refresh - %s\n", p->callid); 18317 18318 /* The UAC may be adjusting the session-timers mid-session */ 18319 if (st_interval > 0) { 18320 p->stimer->st_interval = st_interval; 18321 p->stimer->st_ref = st_ref; 18322 } 18323 18324 restart_session_timer(p); 18325 if (p->stimer->st_expirys > 0) { 18326 p->stimer->st_expirys--; 18327 } 18328 } 18329 } 18330 18331 if (!req->ignore && p) 18332 p->lastinvite = seqno; 18333 18334 if (replace_id) { /* Attended transfer or call pickup - we're the target */ 18335 /* Go and take over the target call */ 18336 if (sipdebug) 18337 ast_debug(4, "Sending this call to the invite/replcaes handler %s\n", p->callid); 18338 return handle_invite_replaces(p, req, debug, seqno, sin); 18339 } 18340 18341 18342 if (c) { /* We have a call -either a new call or an old one (RE-INVITE) */ 18343 switch(c->_state) { 18344 case AST_STATE_DOWN: 18345 ast_debug(2, "%s: New call is still down.... Trying... \n", c->name); 18346 transmit_response(p, "100 Trying", req); 18347 p->invitestate = INV_PROCEEDING; 18348 ast_setstate(c, AST_STATE_RING); 18349 if (strcmp(p->exten, ast_pickup_ext())) { /* Call to extension -start pbx on this call */ 18350 enum ast_pbx_result result; 18351 18352 result = ast_pbx_start(c); 18353 18354 switch(result) { 18355 case AST_PBX_FAILED: 18356 ast_log(LOG_WARNING, "Failed to start PBX :(\n"); 18357 p->invitestate = INV_COMPLETED; 18358 transmit_response_reliable(p, "503 Unavailable", req); 18359 break; 18360 case AST_PBX_CALL_LIMIT: 18361 ast_log(LOG_WARNING, "Failed to start PBX (call limit reached) \n"); 18362 p->invitestate = INV_COMPLETED; 18363 transmit_response_reliable(p, "480 Temporarily Unavailable", req); 18364 break; 18365 case AST_PBX_SUCCESS: 18366 /* nothing to do */ 18367 break; 18368 } 18369 18370 if (result) { 18371 18372 /* Unlock locks so ast_hangup can do its magic */ 18373 ast_channel_unlock(c); 18374 sip_pvt_unlock(p); 18375 ast_hangup(c); 18376 sip_pvt_lock(p); 18377 c = NULL; 18378 } 18379 } else { /* Pickup call in call group */ 18380 ast_channel_unlock(c); 18381 *nounlock = 1; 18382 if (ast_pickup_call(c)) { 18383 ast_log(LOG_NOTICE, "Nothing to pick up for %s\n", p->callid); 18384 transmit_response_reliable(p, "503 Unavailable", req); 18385 sip_alreadygone(p); 18386 /* Unlock locks so ast_hangup can do its magic */ 18387 sip_pvt_unlock(p); 18388 c->hangupcause = AST_CAUSE_CALL_REJECTED; 18389 } else { 18390 sip_pvt_unlock(p); 18391 ast_setstate(c, AST_STATE_DOWN); 18392 c->hangupcause = AST_CAUSE_NORMAL_CLEARING; 18393 } 18394 p->invitestate = INV_COMPLETED; 18395 ast_hangup(c); 18396 sip_pvt_lock(p); 18397 c = NULL; 18398 } 18399 break; 18400 case AST_STATE_RING: 18401 transmit_response(p, "100 Trying", req); 18402 p->invitestate = INV_PROCEEDING; 18403 break; 18404 case AST_STATE_RINGING: 18405 transmit_response(p, "180 Ringing", req); 18406 p->invitestate = INV_PROCEEDING; 18407 break; 18408 case AST_STATE_UP: 18409 ast_debug(2, "%s: This call is UP.... \n", c->name); 18410 18411 transmit_response(p, "100 Trying", req); 18412 18413 if (p->t38.state == T38_PEER_REINVITE) { 18414 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.")); 18415 } else if (p->t38.state == T38_ENABLED) { 18416 ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED); 18417 transmit_response_with_t38_sdp(p, "200 OK", req, (reinvite ? XMIT_RELIABLE : (req->ignore ? XMIT_UNRELIABLE : XMIT_CRITICAL))); 18418 } else if (p->t38.state == T38_DISABLED) { 18419 /* If this is not a re-invite or something to ignore - it's critical */ 18420 ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED); 18421 transmit_response_with_sdp(p, "200 OK", req, (reinvite ? XMIT_RELIABLE : (req->ignore ? XMIT_UNRELIABLE : XMIT_CRITICAL)), p->session_modify == TRUE ? FALSE:TRUE); 18422 } 18423 18424 p->invitestate = INV_TERMINATED; 18425 break; 18426 default: 18427 ast_log(LOG_WARNING, "Don't know how to handle INVITE in state %d\n", c->_state); 18428 transmit_response(p, "100 Trying", req); 18429 break; 18430 } 18431 } else { 18432 if (p && (p->autokillid == -1)) { 18433 const char *msg; 18434 18435 if (!p->jointcapability) 18436 msg = "488 Not Acceptable Here (codec error)"; 18437 else { 18438 ast_log(LOG_NOTICE, "Unable to create/find SIP channel for this INVITE\n"); 18439 msg = "503 Unavailable"; 18440 } 18441 transmit_response_reliable(p, msg, req); 18442 p->invitestate = INV_COMPLETED; 18443 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 18444 } 18445 } 18446 return res; 18447 }
| static int handle_request_message | ( | struct sip_pvt * | p, | |
| struct sip_request * | req | |||
| ) | [static] |
Handle incoming MESSAGE request.
Definition at line 19155 of file chan_sip.c.
References ast_verbose, sip_request::debug, sip_request::ignore, receive_message(), and transmit_response().
Referenced by handle_incoming().
19156 { 19157 if (!req->ignore) { 19158 if (req->debug) 19159 ast_verbose("Receiving message!\n"); 19160 receive_message(p, req); 19161 } else 19162 transmit_response(p, "202 Accepted", req); 19163 return 1; 19164 }
| static int handle_request_notify | ( | struct sip_pvt * | p, | |
| struct sip_request * | req, | |||
| struct sockaddr_in * | sin, | |||
| int | seqno, | |||
| char * | e | |||
| ) | [static] |
Handle incoming notifications.
Definition at line 17178 of file chan_sip.c.
References ast_debug, ast_log(), ast_skip_blanks(), buf, sip_pvt::callid, DEFAULT_TRANS_TIMEOUT, FALSE, get_header(), get_msg_text(), sip_pvt::lastinvite, LOG_NOTICE, LOG_WARNING, sip_scheddestroy(), transmit_response(), and TRUE.
Referenced by handle_incoming().
17179 { 17180 /* This is mostly a skeleton for future improvements */ 17181 /* Mostly created to return proper answers on notifications on outbound REFER's */ 17182 int res = 0; 17183 const char *event = get_header(req, "Event"); 17184 char *eventid = NULL; 17185 char *sep; 17186 17187 if( (sep = strchr(event, ';')) ) { /* XXX bug here - overwriting string ? */ 17188 *sep++ = '\0'; 17189 eventid = sep; 17190 } 17191 17192 if (sipdebug) 17193 ast_debug(2, "Got NOTIFY Event: %s\n", event); 17194 17195 if (strcmp(event, "refer")) { 17196 /* We don't understand this event. */ 17197 /* Here's room to implement incoming voicemail notifications :-) */ 17198 transmit_response(p, "489 Bad event", req); 17199 res = -1; 17200 } else { 17201 /* Save nesting depth for now, since there might be other events we will 17202 support in the future */ 17203 17204 /* Handle REFER notifications */ 17205 17206 char buf[1024]; 17207 char *cmd, *code; 17208 int respcode; 17209 int success = TRUE; 17210 17211 /* EventID for each transfer... EventID is basically the REFER cseq 17212 17213 We are getting notifications on a call that we transfered 17214 We should hangup when we are getting a 200 OK in a sipfrag 17215 Check if we have an owner of this event */ 17216 17217 /* Check the content type */ 17218 if (strncasecmp(get_header(req, "Content-Type"), "message/sipfrag", strlen("message/sipfrag"))) { 17219 /* We need a sipfrag */ 17220 transmit_response(p, "400 Bad request", req); 17221 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 17222 return -1; 17223 } 17224 17225 /* Get the text of the attachment */ 17226 if (get_msg_text(buf, sizeof(buf), req, TRUE)) { 17227 ast_log(LOG_WARNING, "Unable to retrieve attachment from NOTIFY %s\n", p->callid); 17228 transmit_response(p, "400 Bad request", req); 17229 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 17230 return -1; 17231 } 17232 17233 /* 17234 From the RFC... 17235 A minimal, but complete, implementation can respond with a single 17236 NOTIFY containing either the body: 17237 SIP/2.0 100 Trying 17238 17239 if the subscription is pending, the body: 17240 SIP/2.0 200 OK 17241 if the reference was successful, the body: 17242 SIP/2.0 503 Service Unavailable 17243 if the reference failed, or the body: 17244 SIP/2.0 603 Declined 17245 17246 if the REFER request was accepted before approval to follow the 17247 reference could be obtained and that approval was subsequently denied 17248 (see Section 2.4.7). 17249 17250 If there are several REFERs in the same dialog, we need to 17251 match the ID of the event header... 17252 */ 17253 ast_debug(3, "* SIP Transfer NOTIFY Attachment: \n---%s\n---\n", buf); 17254 cmd = ast_skip_blanks(buf); 17255 code = cmd; 17256 /* We are at SIP/2.0 */ 17257 while(*code && (*code > 32)) { /* Search white space */ 17258 code++; 17259 } 17260 *code++ = '\0'; 17261 code = ast_skip_blanks(code); 17262 sep = code; 17263 sep++; 17264 while(*sep && (*sep > 32)) { /* Search white space */ 17265 sep++; 17266 } 17267 *sep++ = '\0'; /* Response string */ 17268 respcode = atoi(code); 17269 switch (respcode) { 17270 case 100: /* Trying: */ 17271 case 101: /* dialog establishment */ 17272 /* Don't do anything yet */ 17273 break; 17274 case 183: /* Ringing: */ 17275 /* Don't do anything yet */ 17276 break; 17277 case 200: /* OK: The new call is up, hangup this call */ 17278 /* Hangup the call that we are replacing */ 17279 break; 17280 case 301: /* Moved permenantly */ 17281 case 302: /* Moved temporarily */ 17282 /* Do we get the header in the packet in this case? */ 17283 success = FALSE; 17284 break; 17285 case 503: /* Service Unavailable: The new call failed */ 17286 /* Cancel transfer, continue the call */ 17287 success = FALSE; 17288 break; 17289 case 603: /* Declined: Not accepted */ 17290 /* Cancel transfer, continue the current call */ 17291 success = FALSE; 17292 break; 17293 } 17294 if (!success) { 17295 ast_log(LOG_NOTICE, "Transfer failed. Sorry. Nothing further to do with this call\n"); 17296 } 17297 17298 /* Confirm that we received this packet */ 17299 transmit_response(p, "200 OK", req); 17300 }; 17301 17302 if (!p->lastinvite) 17303 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 17304 17305 return res; 17306 }
| static int handle_request_options | ( | struct sip_pvt * | p, | |
| struct sip_request * | req | |||
| ) | [static] |
Handle incoming OPTIONS request An OPTIONS request should be answered like an INVITE from the same UA, including SDP.
XXX get_destination assumes we're already authenticated. This means that a request from a known device (peer) will end up in the wrong context if this is out-of-dialog. However, we want to handle OPTIONS as light as possible, so we might want to have a configuration option whether we care or not. Some devices use this for testing capabilities, which means that we need to match device to answer with proper capabilities (including SDP).
Definition at line 17311 of file chan_sip.c.
References ast_shutting_down(), ast_string_field_set, ast_strlen_zero(), build_contact(), context, sip_pvt::context, DEFAULT_TRANS_TIMEOUT, get_destination(), sip_pvt::lastinvite, sip_scheddestroy(), and transmit_response_with_allow().
Referenced by handle_incoming().
17312 { 17313 int res; 17314 17315 /*! XXX get_destination assumes we're already authenticated. This means that a request from 17316 a known device (peer) will end up in the wrong context if this is out-of-dialog. 17317 However, we want to handle OPTIONS as light as possible, so we might want to have 17318 a configuration option whether we care or not. Some devices use this for testing 17319 capabilities, which means that we need to match device to answer with proper 17320 capabilities (including SDP). 17321 \todo Fix handle_request_options device handling with optional authentication 17322 (this needs to be fixed in 1.4 as well) 17323 */ 17324 17325 if (p->lastinvite) { 17326 /* if this is a request in an active dialog, just confirm that the dialog exists. */ 17327 transmit_response_with_allow(p, "200 OK", req, 0); 17328 return 0; 17329 } 17330 17331 res = get_destination(p, req); 17332 build_contact(p); 17333 17334 if (ast_strlen_zero(p->context)) 17335 ast_string_field_set(p, context, default_context); 17336 17337 if (ast_shutting_down()) 17338 transmit_response_with_allow(p, "503 Unavailable", req, 0); 17339 else if (res < 0) 17340 transmit_response_with_allow(p, "404 Not Found", req, 0); 17341 else 17342 transmit_response_with_allow(p, "200 OK", req, 0); 17343 17344 /* Destroy if this OPTIONS was the opening request, but not if 17345 it's in the middle of a normal call flow. */ 17346 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 17347 17348 return res; 17349 }
| static int handle_request_refer | ( | struct sip_pvt * | p, | |
| struct sip_request * | req, | |||
| int | debug, | |||
| int | seqno, | |||
| int * | nounlock | |||
| ) | [static] |
Definition at line 18615 of file chan_sip.c.
References sip_pvt::allowtransfer, append_history, ast_async_goto(), ast_bridged_channel(), AST_CAUSE_NORMAL_CLEARING, ast_channel_unlock, ast_clear_flag, AST_CONTROL_UNHOLD, ast_debug, AST_LIST_EMPTY, ast_parking_ext(), ast_queue_control(), ast_set_flag, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_verbose, sip_refer::attendedtransfer, sip_pvt::callid, sip_dual::chan1, sip_dual::chan2, check_sip_domain(), context, sip_pvt::context, copy_request(), sip_request::data, sip_request::debug, EVENT_FLAG_CALL, FALSE, sip_pvt::flags, get_refer_info(), ast_channel::hangupcause, sip_request::ignore, local_attended_transfer(), sip_refer::localtransfer, manager_event, ast_channel::name, sip_pvt::needdestroy, sip_pvt::owner, pbx_builtin_setvar_helper(), sip_pvt::refer, REFER_200OK, REFER_FAILED, REFER_SENT, sip_refer::refer_to, sip_refer::refer_to_context, sip_refer::refer_to_domain, sip_refer::referred_by, sip_refer::replaces_callid, sip_refer::replaces_callid_fromtag, sip_refer::replaces_callid_totag, sip_dual::req, sip_alreadygone(), SIP_DEFER_BYE_ON_TRANSFER, SIP_GOTREFER, SIP_OUTGOING, sip_park(), sip_refer_allocate(), SIPBUFSIZE, sip_refer::status, TRANSFER_CLOSED, transmit_notify_with_sipfrag(), transmit_response(), TRUE, and ast_channel::uniqueid.
Referenced by handle_incoming().
18616 { 18617 struct sip_dual current; /* Chan1: Call between asterisk and transferer */ 18618 /* Chan2: Call between asterisk and transferee */ 18619 18620 int res = 0; 18621 current.req.data = NULL; 18622 18623 if (req->debug) 18624 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"); 18625 18626 if (!p->owner) { 18627 /* This is a REFER outside of an existing SIP dialog */ 18628 /* We can't handle that, so decline it */ 18629 ast_debug(3, "Call %s: Declined REFER, outside of dialog...\n", p->callid); 18630 transmit_response(p, "603 Declined (No dialog)", req); 18631 if (!req->ignore) { 18632 append_history(p, "Xfer", "Refer failed. Outside of dialog."); 18633 sip_alreadygone(p); 18634 p->needdestroy = 1; 18635 } 18636 return 0; 18637 } 18638 18639 18640 /* Check if transfer is allowed from this device */ 18641 if (p->allowtransfer == TRANSFER_CLOSED ) { 18642 /* Transfer not allowed, decline */ 18643 transmit_response(p, "603 Declined (policy)", req); 18644 append_history(p, "Xfer", "Refer failed. Allowtransfer == closed."); 18645 /* Do not destroy SIP session */ 18646 return 0; 18647 } 18648 18649 if (!req->ignore && ast_test_flag(&p->flags[0], SIP_GOTREFER)) { 18650 /* Already have a pending REFER */ 18651 transmit_response(p, "491 Request pending", req); 18652 append_history(p, "Xfer", "Refer failed. Request pending."); 18653 return 0; 18654 } 18655 18656 /* Allocate memory for call transfer data */ 18657 if (!p->refer && !sip_refer_allocate(p)) { 18658 transmit_response(p, "500 Internal Server Error", req); 18659 append_history(p, "Xfer", "Refer failed. Memory allocation error."); 18660 return -3; 18661 } 18662 18663 res = get_refer_info(p, req); /* Extract headers */ 18664 18665 p->refer->status = REFER_SENT; 18666 18667 if (res != 0) { 18668 switch (res) { 18669 case -2: /* Syntax error */ 18670 transmit_response(p, "400 Bad Request (Refer-to missing)", req); 18671 append_history(p, "Xfer", "Refer failed. Refer-to missing."); 18672 if (req->debug) 18673 ast_debug(1, "SIP transfer to black hole can't be handled (no refer-to: )\n"); 18674 break; 18675 case -3: 18676 transmit_response(p, "603 Declined (Non sip: uri)", req); 18677 append_history(p, "Xfer", "Refer failed. Non SIP uri"); 18678 if (req->debug) 18679 ast_debug(1, "SIP transfer to non-SIP uri denied\n"); 18680 break; 18681 default: 18682 /* Refer-to extension not found, fake a failed transfer */ 18683 transmit_response(p, "202 Accepted", req); 18684 append_history(p, "Xfer", "Refer failed. Bad extension."); 18685 transmit_notify_with_sipfrag(p, seqno, "404 Not found", TRUE); 18686 ast_clear_flag(&p->flags[0], SIP_GOTREFER); 18687 if (req->debug) 18688 ast_debug(1, "SIP transfer to bad extension: %s\n", p->refer->refer_to); 18689 break; 18690 } 18691 return 0; 18692 } 18693 if (ast_strlen_zero(p->context)) 18694 ast_string_field_set(p, context, default_context); 18695 18696 /* If we do not support SIP domains, all transfers are local */ 18697 if (allow_external_domains && check_sip_domain(p->refer->refer_to_domain, NULL, 0)) { 18698 p->refer->localtransfer = 1; 18699 if (sipdebug) 18700 ast_debug(3, "This SIP transfer is local : %s\n", p->refer->refer_to_domain); 18701 } else if (AST_LIST_EMPTY(&domain_list) || check_sip_domain(p->refer->refer_to_domain, NULL, 0)) { 18702 /* This PBX doesn't bother with SIP domains or domain is local, so this transfer is local */ 18703 p->refer->localtransfer = 1; 18704 } else if (sipdebug) 18705 ast_debug(3, "This SIP transfer is to a remote SIP extension (remote domain %s)\n", p->refer->refer_to_domain); 18706 18707 /* Is this a repeat of a current request? Ignore it */ 18708 /* Don't know what else to do right now. */ 18709 if (req->ignore) 18710 return res; 18711 18712 /* If this is a blind transfer, we have the following 18713 channels to work with: 18714 - chan1, chan2: The current call between transferer and transferee (2 channels) 18715 - target_channel: A new call from the transferee to the target (1 channel) 18716 We need to stay tuned to what happens in order to be able 18717 to bring back the call to the transferer */ 18718 18719 /* If this is a attended transfer, we should have all call legs within reach: 18720 - chan1, chan2: The call between the transferer and transferee (2 channels) 18721 - target_channel, targetcall_pvt: The call between the transferer and the target (2 channels) 18722 We want to bridge chan2 with targetcall_pvt! 18723 18724 The replaces call id in the refer message points 18725 to the call leg between Asterisk and the transferer. 18726 So we need to connect the target and the transferee channel 18727 and hangup the two other channels silently 18728 18729 If the target is non-local, the call ID could be on a remote 18730 machine and we need to send an INVITE with replaces to the 18731 target. We basically handle this as a blind transfer 18732 and let the sip_call function catch that we need replaces 18733 header in the INVITE. 18734 */ 18735 18736 18737 /* Get the transferer's channel */ 18738 current.chan1 = p->owner; 18739 18740 /* Find the other part of the bridge (2) - transferee */ 18741 current.chan2 = ast_bridged_channel(current.chan1); 18742 18743 if (sipdebug) 18744 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>"); 18745 18746 if (!current.chan2 && !p->refer->attendedtransfer) { 18747 /* No bridged channel, propably IVR or echo or similar... */ 18748 /* Guess we should masquerade or something here */ 18749 /* Until we figure it out, refuse transfer of such calls */ 18750 if (sipdebug) 18751 ast_debug(3, "Refused SIP transfer on non-bridged channel.\n"); 18752 p->refer->status = REFER_FAILED; 18753 append_history(p, "Xfer", "Refer failed. Non-bridged channel."); 18754 transmit_response(p, "603 Declined", req); 18755 return -1; 18756 } 18757 18758 if (current.chan2) { 18759 if (sipdebug) 18760 ast_debug(4, "Got SIP transfer, applying to bridged peer '%s'\n", current.chan2->name); 18761 18762 ast_queue_control(current.chan1, AST_CONTROL_UNHOLD); 18763 } 18764 18765 ast_set_flag(&p->flags[0], SIP_GOTREFER); 18766 18767 /* Attended transfer: Find all call legs and bridge transferee with target*/ 18768 if (p->refer->attendedtransfer) { 18769 if ((res = local_attended_transfer(p, ¤t, req, seqno))) 18770 return res; /* We're done with the transfer */ 18771 /* Fall through for remote transfers that we did not find locally */ 18772 if (sipdebug) 18773 ast_debug(4, "SIP attended transfer: Still not our call - generating INVITE with replaces\n"); 18774 /* Fallthrough if we can't find the call leg internally */ 18775 } 18776 18777 18778 /* Parking a call */ 18779 if (p->refer->localtransfer && !strcmp(p->refer->refer_to, ast_parking_ext())) { 18780 /* Must release c's lock now, because it will not longer be accessible after the transfer! */ 18781 *nounlock = 1; 18782 ast_channel_unlock(current.chan1); 18783 copy_request(¤t.req, req); 18784 ast_clear_flag(&p->flags[0], SIP_GOTREFER); 18785 p->refer->status = REFER_200OK; 18786 append_history(p, "Xfer", "REFER to call parking."); 18787 manager_event(EVENT_FLAG_CALL, "Transfer", "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", 18788 current.chan1->name, 18789 current.chan1->uniqueid, 18790 p->callid, 18791 current.chan2->name, 18792 current.chan2->uniqueid, 18793 p->refer->refer_to); 18794 if (sipdebug) 18795 ast_debug(4, "SIP transfer to parking: trying to park %s. Parked by %s\n", current.chan2->name, current.chan1->name); 18796 sip_park(current.chan2, current.chan1, req, seqno); 18797 return res; 18798 } 18799 18800 /* Blind transfers and remote attended xfers */ 18801 transmit_response(p, "202 Accepted", req); 18802 18803 if (current.chan1 && current.chan2) { 18804 ast_debug(3, "chan1->name: %s\n", current.chan1->name); 18805 pbx_builtin_setvar_helper(current.chan1, "BLINDTRANSFER", current.chan2->name); 18806 } 18807 if (current.chan2) { 18808 pbx_builtin_setvar_helper(current.chan2, "BLINDTRANSFER", current.chan1->name); 18809 pbx_builtin_setvar_helper(current.chan2, "SIPDOMAIN", p->refer->refer_to_domain); 18810 pbx_builtin_setvar_helper(current.chan2, "SIPTRANSFER", "yes"); 18811 /* One for the new channel */ 18812 pbx_builtin_setvar_helper(current.chan2, "_SIPTRANSFER", "yes"); 18813 /* Attended transfer to remote host, prepare headers for the INVITE */ 18814 if (p->refer->referred_by) 18815 pbx_builtin_setvar_helper(current.chan2, "_SIPTRANSFER_REFERER", p->refer->referred_by); 18816 } 18817 /* Generate a Replaces string to be used in the INVITE during attended transfer */ 18818 if (!ast_strlen_zero(p->refer->replaces_callid)) { 18819 char tempheader[SIPBUFSIZE]; 18820 snprintf(tempheader, sizeof(tempheader), "%s%s%s%s%s", p->refer->replaces_callid, 18821 p->refer->replaces_callid_totag ? ";to-tag=" : "", 18822 p->refer->replaces_callid_totag, 18823 p->refer->replaces_callid_fromtag ? ";from-tag=" : "", 18824 p->refer->replaces_callid_fromtag); 18825 if (current.chan2) 18826 pbx_builtin_setvar_helper(current.chan2, "_SIPTRANSFER_REPLACES", tempheader); 18827 } 18828 /* Must release lock now, because it will not longer 18829 be accessible after the transfer! */ 18830 *nounlock = 1; 18831 ast_channel_unlock(current.chan1); 18832 18833 /* Connect the call */ 18834 18835 /* FAKE ringing if not attended transfer */ 18836 if (!p->refer->attendedtransfer) 18837 transmit_notify_with_sipfrag(p, seqno, "183 Ringing", FALSE); 18838 18839 /* For blind transfer, this will lead to a new call */ 18840 /* For attended transfer to remote host, this will lead to 18841 a new SIP call with a replaces header, if the dial plan allows it 18842 */ 18843 if (!current.chan2) { 18844 /* We have no bridge, so we're talking with Asterisk somehow */ 18845 /* We need to masquerade this call */ 18846 /* What to do to fix this situation: 18847 * Set up the new call in a new channel 18848 * Let the new channel masq into this channel 18849 Please add that code here :-) 18850 */ 18851 p->refer->status = REFER_FAILED; 18852 transmit_notify_with_sipfrag(p, seqno, "503 Service Unavailable (can't handle one-legged xfers)", TRUE); 18853 ast_clear_flag(&p->flags[0], SIP_GOTREFER); 18854 append_history(p, "Xfer", "Refer failed (only bridged calls)."); 18855 return -1; 18856 } 18857 ast_set_flag(&p->flags[0], SIP_DEFER_BYE_ON_TRANSFER); /* Delay hangup */ 18858 18859 18860 /* For blind transfers, move the call to the new extensions. For attended transfers on multiple 18861 servers - generate an INVITE with Replaces. Either way, let the dial plan decided */ 18862 res = ast_async_goto(current.chan2, p->refer->refer_to_context, p->refer->refer_to, 1); 18863 18864 if (!res) { 18865 manager_event(EVENT_FLAG_CALL, "Transfer", "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", 18866 current.chan1->name, 18867 current.chan1->uniqueid, 18868 p->callid, 18869 current.chan2->name, 18870 current.chan2->uniqueid, 18871 p->refer->refer_to, p->refer->refer_to_context); 18872 /* Success - we have a new channel */ 18873 ast_debug(3, "%s transfer succeeded. Telling transferer.\n", p->refer->attendedtransfer? "Attended" : "Blind"); 18874 transmit_notify_with_sipfrag(p, seqno, "200 Ok", TRUE); 18875 if (p->refer->localtransfer) 18876 p->refer->status = REFER_200OK; 18877 if (p->owner) 18878 p->owner->hangupcause = AST_CAUSE_NORMAL_CLEARING; 18879 append_history(p, "Xfer", "Refer succeeded."); 18880 ast_clear_flag(&p->flags[0], SIP_GOTREFER); 18881 /* Do not hangup call, the other side do that when we say 200 OK */ 18882 /* We could possibly implement a timer here, auto congestion */ 18883 res = 0; 18884 } else { 18885 ast_clear_flag(&p->flags[0], SIP_DEFER_BYE_ON_TRANSFER); /* Don't delay hangup */ 18886 ast_debug(3, "%s transfer failed. Resuming original call.\n", p->refer->attendedtransfer? "Attended" : "Blind"); 18887 append_history(p, "Xfer", "Refer failed."); 18888 /* Failure of some kind */ 18889 p->refer->status = REFER_FAILED; 18890 transmit_notify_with_sipfrag(p, seqno, "503 Service Unavailable", TRUE); 18891 ast_clear_flag(&p->flags[0], SIP_GOTREFER); 18892 res = -1; 18893 } 18894 return res; 18895 }
| static int handle_request_register | ( | struct sip_pvt * | p, | |
| struct sip_request * | req, | |||
| struct sockaddr_in * | sin, | |||
| char * | e | |||
| ) | [static] |
Handle incoming REGISTER request.
Definition at line 19498 of file chan_sip.c.
References append_history, ast_debug, ast_inet_ntoa(), ast_log(), AUTH_ACL_FAILED, AUTH_BAD_TRANSPORT, AUTH_NOT_FOUND, AUTH_PEER_NOT_DYNAMIC, AUTH_SECRET_FAILED, AUTH_UNKNOWN_DOMAIN, AUTH_USERNAME_MISMATCH, sip_pvt::callid, check_via(), copy_request(), DEFAULT_TRANS_TIMEOUT, get_header(), sip_pvt::initreq, LOG_NOTICE, sip_request::method, register_verify(), sip_methods, and sip_scheddestroy().
Referenced by handle_incoming().
19499 { 19500 enum check_auth_result res; 19501 19502 /* Use this as the basis */ 19503 copy_request(&p->initreq, req); 19504 if (sipdebug) 19505 ast_debug(4, "Initializing initreq for method %s - callid %s\n", sip_methods[req->method].text, p->callid); 19506 check_via(p, req); 19507 if ((res = register_verify(p, sin, req, e)) < 0) { 19508 const char *reason; 19509 19510 switch (res) { 19511 case AUTH_SECRET_FAILED: 19512 reason = "Wrong password"; 19513 break; 19514 case AUTH_USERNAME_MISMATCH: 19515 reason = "Username/auth name mismatch"; 19516 break; 19517 case AUTH_NOT_FOUND: 19518 reason = "No matching peer found"; 19519 break; 19520 case AUTH_UNKNOWN_DOMAIN: 19521 reason = "Not a local domain"; 19522 break; 19523 case AUTH_PEER_NOT_DYNAMIC: 19524 reason = "Peer is not supposed to register"; 19525 break; 19526 case AUTH_ACL_FAILED: 19527 reason = "Device does not match ACL"; 19528 break; 19529 case AUTH_BAD_TRANSPORT: 19530 reason = "Device not configured to use this transport type"; 19531 break; 19532 default: 19533 reason = "Unknown failure"; 19534 break; 19535 } 19536 ast_log(LOG_NOTICE, "Registration from '%s' failed for '%s' - %s\n", 19537 get_header(req, "To"), ast_inet_ntoa(sin->sin_addr), 19538 reason); 19539 append_history(p, "RegRequest", "Failed : Account %s : %s", get_header(req, "To"), reason); 19540 } else 19541 append_history(p, "RegRequest", "Succeeded : Account %s", get_header(req, "To")); 19542 19543 if (res < 1) { 19544 /* Destroy the session, but keep us around for just a bit in case they don't 19545 get our 200 OK */ 19546 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 19547 } 19548 return res; 19549 }
| static int handle_request_subscribe | ( | struct sip_pvt * | p, | |
| struct sip_request * | req, | |||
| struct sockaddr_in * | sin, | |||
| int | seqno, | |||
| char * | e | |||
| ) | [static] |
Handle incoming SUBSCRIBE request.
Definition at line 19179 of file chan_sip.c.
References add_peer_mwi_subs(), 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_inet_ntoa(), AST_LIST_EMPTY, ast_log(), ast_set_flag, ast_strdupa, ast_string_field_build, ast_strlen_zero(), ast_test_flag, ast_verbose, AUTH_CHALLENGE_SENT, AUTH_FAKE_AUTH, sip_pvt::autokillid, build_contact(), sip_pvt::callid, cb_extensionstate(), check_user_full(), check_via(), sip_pvt::context, copy_request(), CPIM_PIDF_XML, sip_request::debug, DIALOG_INFO_XML, dialog_ref(), dialog_unlink_all(), dialog_unref(), dialogs, sip_pvt::dialogver, sip_pvt::expiry, sip_pvt::exten, FALSE, sip_peer::flags, sip_pvt::flags, get_destination(), get_header(), gettag(), sip_request::headers, sip_request::ignore, sip_pvt::initreq, sip_pvt::lastinvite, sip_pvt::laststate, LOG_NOTICE, LOG_WARNING, sip_peer::mailboxes, make_our_tag(), sip_request::method, sip_peer::mwipvt, sip_peer::name, sip_pvt::needdestroy, NONE, parse_ok_contact(), PIDF_XML, ref_peer(), sip_pvt::relatedpeer, sip_pvt::sa, sip_cancel_destroy(), sip_methods, SIP_PAGE2_ALLOWSUBSCRIBE, SIP_PAGE2_DIALOG_ESTABLISHED, SIP_PAGE2_SUBSCRIBEMWIONLY, sip_pvt_lock, sip_pvt_unlock, sip_scheddestroy(), sip_send_mwi_to_peer(), SIP_SUBSCRIBE, sip_pvt::stateid, sip_pvt::subscribecontext, sip_pvt::subscribed, sip_pvt::subscribeuri, sip_pvt::tag, cfsip_methods::text, transmit_fake_auth_response(), transmit_response(), transmit_response_reliable(), transmit_state_notify(), TRUE, unref_peer(), sip_pvt::useragent, sip_pvt::username, XMIT_UNRELIABLE, and XPIDF_XML.
Referenced by handle_incoming().
19180 { 19181 int gotdest = 0; 19182 int res = 0; 19183 int firststate = AST_EXTENSION_REMOVED; 19184 struct sip_peer *authpeer = NULL; 19185 const char *eventheader = get_header(req, "Event"); /* Get Event package name */ 19186 const char *acceptheader = get_header(req, "Accept"); 19187 int resubscribe = (p->subscribed != NONE); 19188 char *temp, *event; 19189 struct ao2_iterator i; 19190 19191 if (p->initreq.headers) { 19192 /* We already have a dialog */ 19193 if (p->initreq.method != SIP_SUBSCRIBE) { 19194 /* This is a SUBSCRIBE within another SIP dialog, which we do not support */ 19195 /* For transfers, this could happen, but since we haven't seen it happening, let us just refuse this */ 19196 transmit_response(p, "403 Forbidden (within dialog)", req); 19197 /* Do not destroy session, since we will break the call if we do */ 19198 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); 19199 return 0; 19200 } else if (req->debug) { 19201 if (resubscribe) 19202 ast_debug(1, "Got a re-subscribe on existing subscription %s\n", p->callid); 19203 else 19204 ast_debug(1, "Got a new subscription %s (possibly with auth)\n", p->callid); 19205 } 19206 } 19207 19208 /* Check if we have a global disallow setting on subscriptions. 19209 if so, we don't have to check peer settings after auth, which saves a lot of processing 19210 */ 19211 if (!global_allowsubscribe) { 19212 transmit_response(p, "403 Forbidden (policy)", req); 19213 p->needdestroy = 1; 19214 return 0; 19215 } 19216 19217 if (!req->ignore && !resubscribe) { /* Set up dialog, new subscription */ 19218 const char *to = get_header(req, "To"); 19219 char totag[128]; 19220 19221 /* Check to see if a tag was provided, if so this is actually a resubscription of a dialog we no longer know about */ 19222 if (!ast_strlen_zero(to) && gettag(req, "To", totag, sizeof(totag))) { 19223 if (req->debug) 19224 ast_verbose("Received resubscription for a dialog we no longer know about. Telling remote side to subscribe again.\n"); 19225 transmit_response(p, "481 Subscription does not exist", req); 19226 p->needdestroy = 1; 19227 return 0; 19228 } 19229 19230 /* Use this as the basis */ 19231 if (req->debug) 19232 ast_verbose("Creating new subscription\n"); 19233 19234 copy_request(&p->initreq, req); 19235 if (sipdebug) 19236 ast_debug(4, "Initializing initreq for method %s - callid %s\n", sip_methods[req->method].text, p->callid); 19237 check_via(p, req); 19238 } else if (req->debug && req->ignore) 19239 ast_verbose("Ignoring this SUBSCRIBE request\n"); 19240 19241 /* Find parameters to Event: header value and remove them for now */ 19242 if (ast_strlen_zero(eventheader)) { 19243 transmit_response(p, "489 Bad Event", req); 19244 ast_debug(2, "Received SIP subscribe for unknown event package: <none>\n"); 19245 p->needdestroy = 1; 19246 return 0; 19247 } 19248 19249 if ( (strchr(eventheader, ';'))) { 19250 event = ast_strdupa(eventheader); /* Since eventheader is a const, we can't change it */ 19251 temp = strchr(event, ';'); 19252 *temp = '\0'; /* Remove any options for now */ 19253 /* We might need to use them later :-) */ 19254 } else 19255 event = (char *) eventheader; /* XXX is this legal ? */ 19256 19257 /* Handle authentication */ 19258 res = check_user_full(p, req, SIP_SUBSCRIBE, e, 0, sin, &authpeer); 19259 /* if an authentication response was sent, we are done here */ 19260 if (res == AUTH_CHALLENGE_SENT) /* authpeer = NULL here */ 19261 return 0; 19262 if (res < 0) { 19263 if (res == AUTH_FAKE_AUTH) { 19264 ast_log(LOG_NOTICE, "Sending fake auth rejection for device %s\n", get_header(req, "From")); 19265 transmit_fake_auth_response(p, SIP_SUBSCRIBE, req, XMIT_UNRELIABLE); 19266 } else { 19267 ast_log(LOG_NOTICE, "Failed to authenticate device %s for SUBSCRIBE\n", get_header(req, "From")); 19268 transmit_response_reliable(p, "403 Forbidden", req); 19269 } 19270 p->needdestroy = 1; 19271 return 0; 19272 } 19273 19274 /* At this point, authpeer cannot be NULL. Remember we hold a reference, 19275 * so we must release it when done. 19276 * XXX must remove all the checks for authpeer == NULL. 19277 */ 19278 19279 /* Check if this device is allowed to subscribe at all */ 19280 if (!ast_test_flag(&p->flags[1], SIP_PAGE2_ALLOWSUBSCRIBE)) { 19281 transmit_response(p, "403 Forbidden (policy)", req); 19282 p->needdestroy = 1; 19283 if (authpeer) 19284 unref_peer(authpeer, "unref_peer, from handle_request_subscribe (authpeer 1)"); 19285 return 0; 19286 } 19287 19288 if (strcmp(event, "message-summary")) { 19289 /* Get destination right away */ 19290 gotdest = get_destination(p, NULL); 19291 } 19292 19293 /* Get full contact header - this needs to be used as a request URI in NOTIFY's */ 19294 parse_ok_contact(p, req); 19295 19296 build_contact(p); 19297 if (gotdest) { 19298 transmit_response(p, "404 Not Found", req); 19299 p->needdestroy = 1; 19300 if (authpeer) 19301 unref_peer(authpeer, "unref_peer, from handle_request_subscribe (authpeer 2)"); 19302 return 0; 19303 } 19304 19305 /* Initialize tag for new subscriptions */ 19306 if (ast_strlen_zero(p->tag)) 19307 make_our_tag(p->tag, sizeof(p->tag)); 19308 19309 if (!strcmp(event, "presence") || !strcmp(event, "dialog")) { /* Presence, RFC 3842 */ 19310 if (authpeer) /* We do not need the authpeer any more */ 19311 unref_peer(authpeer, "unref_peer, from handle_request_subscribe (authpeer 2)"); 19312 19313 /* Header from Xten Eye-beam Accept: multipart/related, application/rlmi+xml, application/pidf+xml, application/xpidf+xml */ 19314 /* Polycom phones only handle xpidf+xml, even if they say they can 19315 handle pidf+xml as well 19316 */ 19317 if (strstr(p->useragent, "Polycom")) { 19318 p->subscribed = XPIDF_XML; 19319 } else if (strstr(acceptheader, "application/pidf+xml")) { 19320 p->subscribed = PIDF_XML; /* RFC 3863 format */ 19321 } else if (strstr(acceptheader, "application/dialog-info+xml")) { 19322 p->subscribed = DIALOG_INFO_XML; 19323 /* IETF draft: draft-ietf-sipping-dialog-package-05.txt */ 19324 } else if (strstr(acceptheader, "application/cpim-pidf+xml")) { 19325 p->subscribed = CPIM_PIDF_XML; /* RFC 3863 format */ 19326 } else if (strstr(acceptheader, "application/xpidf+xml")) { 19327 p->subscribed = XPIDF_XML; /* Early pre-RFC 3863 format with MSN additions (Microsoft Messenger) */ 19328 } else if (ast_strlen_zero(acceptheader)) { 19329 if (p->subscribed == NONE) { /* if the subscribed field is not already set, and there is no accept header... */ 19330 transmit_response(p, "489 Bad Event", req); 19331 19332 ast_log(LOG_WARNING, "SUBSCRIBE failure: no Accept header: pvt: stateid: %d, laststate: %d, dialogver: %d, subscribecont: '%s', subscribeuri: '%s'\n", 19333 p->stateid, p->laststate, p->dialogver, p->subscribecontext, p->subscribeuri); 19334 p->needdestroy = 1; 19335 return 0; 19336 } 19337 /* if p->subscribed is non-zero, then accept is not obligatory; according to rfc 3265 section 3.1.3, at least. 19338 so, we'll just let it ride, keeping the value from a previous subscription, and not abort the subscription */ 19339 } else { 19340 /* Can't find a format for events that we know about */ 19341 char mybuf[200]; 19342 snprintf(mybuf, sizeof(mybuf), "489 Bad Event (format %s)", acceptheader); 19343 transmit_response(p, mybuf, req); 19344 19345 ast_log(LOG_WARNING, "SUBSCRIBE failure: unrecognized format: '%s' pvt: subscribed: %d, stateid: %d, laststate: %d, dialogver: %d, subscribecont: '%s', subscribeuri: '%s'\n", 19346 acceptheader, (int)p->subscribed, p->stateid, p->laststate, p->dialogver, p->subscribecontext, p->subscribeuri); 19347 p->needdestroy = 1; 19348 return 0; 19349 } 19350 } else if (!strcmp(event, "message-summary")) { 19351 if (!ast_strlen_zero(acceptheader) && strcmp(acceptheader, "application/simple-message-summary")) { 19352 /* Format requested that we do not support */ 19353 transmit_response(p, "406 Not Acceptable", req); 19354 ast_debug(2, "Received SIP mailbox subscription for unknown format: %s\n", acceptheader); 19355 p->needdestroy = 1; 19356 if (authpeer) 19357 unref_peer(authpeer, "unref_peer, from handle_request_subscribe (authpeer 3)"); 19358 return 0; 19359 } 19360 /* Looks like they actually want a mailbox status 19361 This version of Asterisk supports mailbox subscriptions 19362 The subscribed URI needs to exist in the dial plan 19363 In most devices, this is configurable to the voicemailmain extension you use 19364 */ 19365 if (!authpeer || AST_LIST_EMPTY(&authpeer->mailboxes)) { 19366 transmit_response(p, "404 Not found (no mailbox)", req); 19367 p->needdestroy = 1; 19368 ast_log(LOG_NOTICE, "Received SIP subscribe for peer without mailbox: %s\n", authpeer->name); 19369 if (authpeer) 19370 unref_peer(authpeer, "unref_peer, from handle_request_subscribe (authpeer 4)"); 19371 return 0; 19372 } 19373 19374 p->subscribed = MWI_NOTIFICATION; 19375 if (ast_test_flag(&authpeer->flags[1], SIP_PAGE2_SUBSCRIBEMWIONLY)) { 19376 add_peer_mwi_subs(authpeer); 19377 } 19378 if (authpeer->mwipvt && authpeer->mwipvt != p) { /* Destroy old PVT if this is a new one */ 19379 /* We only allow one subscription per peer */ 19380 dialog_unlink_all(authpeer->mwipvt, TRUE, TRUE); 19381 authpeer->mwipvt = dialog_unref(authpeer->mwipvt, "unref dialog authpeer->mwipvt"); 19382 /* sip_destroy(authpeer->mwipvt); */ 19383 } 19384 if (authpeer->mwipvt) 19385 dialog_unref(authpeer->mwipvt, "Unref previously stored mwipvt dialog pointer"); 19386 authpeer->mwipvt = dialog_ref(p, "setting peers' mwipvt to p"); /* Link from peer to pvt UH- should this be dialog_ref()? */ 19387 if (p->relatedpeer) 19388 unref_peer(p->relatedpeer, "Unref previously stored relatedpeer ptr"); 19389 p->relatedpeer = ref_peer(authpeer, "setting dialog's relatedpeer pointer"); /* already refcounted...Link from pvt to peer UH- should this be dialog_ref()? */ 19390 /* Do not release authpeer here */ 19391 } else { /* At this point, Asterisk does not understand the specified event */ 19392 transmit_response(p, "489 Bad Event", req); 19393 ast_debug(2, "Received SIP subscribe for unknown event package: %s\n", event); 19394 p->needdestroy = 1; 19395 if (authpeer) 19396 unref_peer(authpeer, "unref_peer, from handle_request_subscribe (authpeer 5)"); 19397 return 0; 19398 } 19399 19400 /* Add subscription for extension state from the PBX core */ 19401 if (p->subscribed != MWI_NOTIFICATION && !resubscribe) { 19402 if (p->stateid > -1) { 19403 ast_extension_state_del(p->stateid, cb_extensionstate); 19404 /* we need to dec the refcount, now that the extensionstate is removed */ 19405 dialog_unref(p, "the extensionstate containing this dialog ptr was deleted"); 19406 } 19407 p->stateid = ast_extension_state_add(p->context, p->exten, cb_extensionstate, dialog_ref(p,"copying dialog ptr into extension state struct")); 19408 } 19409 19410 if (!req->ignore && p) 19411 p->lastinvite = seqno; 19412 if (p && !p->needdestroy) { 19413 p->expiry = atoi(get_header(req, "Expires")); 19414 19415 /* check if the requested expiry-time is within the approved limits from sip.conf */ 19416 if (p->expiry > max_expiry) 19417 p->expiry = max_expiry; 19418 if (p->expiry < min_expiry && p->expiry > 0) 19419 p->expiry = min_expiry; 19420 19421 if (sipdebug) { 19422 if (p->subscribed == MWI_NOTIFICATION && p->relatedpeer) 19423 ast_debug(2, "Adding subscription for mailbox notification - peer %s\n", p->relatedpeer->name); 19424 else 19425 ast_debug(2, "Adding subscription for extension %s context %s for peer %s\n", p->exten, p->context, p->username); 19426 } 19427 if (p->autokillid > -1 && sip_cancel_destroy(p)) /* Remove subscription expiry for renewals */ 19428 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 19429 if (p->expiry > 0) 19430 sip_scheddestroy(p, (p->expiry + 10) * 1000); /* Set timer for destruction of call at expiration */ 19431 19432 if (p->subscribed == MWI_NOTIFICATION) { 19433 ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED); 19434 transmit_response(p, "200 OK", req); 19435 if (p->relatedpeer) { /* Send first notification */ 19436 ao2_lock(p->relatedpeer); /* was WRLOCK */ 19437 sip_send_mwi_to_peer(p->relatedpeer, NULL, 0); 19438 ao2_unlock(p->relatedpeer); 19439 } 19440 } else { 19441 struct sip_pvt *p_old; 19442 19443 if ((firststate = ast_extension_state(NULL, p->context, p->exten)) < 0) { 19444 19445 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_inet_ntoa(p->sa.sin_addr)); 19446 transmit_response(p, "404 Not found", req); 19447 p->needdestroy = 1; 19448 return 0; 19449 } 19450 ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED); 19451 transmit_response(p, "200 OK", req); 19452 transmit_state_notify(p, firststate, 1, FALSE); /* Send first notification */ 19453 append_history(p, "Subscribestatus", "%s", ast_extension_state2str(firststate)); 19454 /* hide the 'complete' exten/context in the refer_to field for later display */ 19455 ast_string_field_build(p, subscribeuri, "%s@%s", p->exten, p->context); 19456 19457 /* remove any old subscription from this peer for the same exten/context, 19458 as the peer has obviously forgotten about it and it's wasteful to wait 19459 for it to expire and send NOTIFY messages to the peer only to have them 19460 ignored (or generate errors) 19461 */ 19462 i = ao2_iterator_init(dialogs, 0); 19463 19464 while ((p_old = ao2_t_iterator_next(&i, "iterate thru dialogs"))) { 19465 if (p_old == p) { 19466 ao2_t_ref(p_old, -1, "toss dialog ptr from iterator_next before continue"); 19467 continue; 19468 } 19469 if (p_old->initreq.method != SIP_SUBSCRIBE) { 19470 ao2_t_ref(p_old, -1, "toss dialog ptr from iterator_next before continue"); 19471 continue; 19472 } 19473 if (p_old->subscribed == NONE) { 19474 ao2_t_ref(p_old, -1, "toss dialog ptr from iterator_next before continue"); 19475 continue; 19476 } 19477 sip_pvt_lock(p_old); 19478 if (!strcmp(p_old->username, p->username)) { 19479 if (!strcmp(p_old->exten, p->exten) && 19480 !strcmp(p_old->context, p->context)) { 19481 p_old->needdestroy = 1; 19482 sip_pvt_unlock(p_old); 19483 ao2_t_ref(p_old, -1, "toss dialog ptr from iterator_next before break"); 19484 break; 19485 } 19486 } 19487 sip_pvt_unlock(p_old); 19488 ao2_t_ref(p_old, -1, "toss dialog ptr from iterator_next"); 19489 } 19490 } 19491 if (!p->expiry) 19492 p->needdestroy = 1; 19493 } 19494 return 1; 19495 }
| static void handle_response | ( | struct sip_pvt * | p, | |
| int | resp, | |||
| char * | rest, | |||
| struct sip_request * | req, | |||
| int | seqno | |||
| ) | [static] |
Handle SIP response in dialogue.
Definition at line 16484 of file chan_sip.c.
References __sip_ack(), __sip_semi_ack(), AST_CAUSE_PROTOCOL_ERROR, ast_clear_flag, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_PROGRESS, ast_debug, ast_inet_ntoa(), ast_log(), ast_queue_control(), ast_queue_hangup_with_cause(), ast_set_flag, ast_skip_blanks(), ast_skip_nonblanks(), ast_strdupa, ast_string_field_build, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_verb, ast_verbose, ast_channel::call_forward, cb_extensionstate(), sip_pvt::context, sip_request::debug, do_proxy_auth(), sip_pvt::exten, FALSE, find_sdp(), find_sip_method(), sip_pvt::flags, get_header(), gettag(), handle_response_invite(), handle_response_notify(), handle_response_peerpoke(), handle_response_refer(), handle_response_register(), hangup_sip2cause(), ast_channel::hangupcause, sip_request::ignore, sip_pvt::laststate, LOG_NOTICE, LOG_WARNING, MAX_AUTHTRIES, sip_pvt::method, msg, sip_pvt::needdestroy, sip_pvt::owner, parse_moved_contact(), sip_pvt::pendinginvite, process_sdp(), sip_pvt::refer, sip_pvt::relatedpeer, SDP_T38_NONE, SIP_ACK, sip_alreadygone(), SIP_BYE, SIP_CANCEL, sip_cancel_destroy(), SIP_INFO, SIP_INVITE, SIP_MESSAGE, sip_methods, SIP_NOTIFY, SIP_OPTIONS, SIP_OUTGOING, SIP_PAGE2_DIALOG_ESTABLISHED, SIP_PAGE2_STATECHANGEQUEUE, SIP_REFER, SIP_REGISTER, SIP_SUBSCRIBE, stop_media_flows(), sip_pvt::subscribed, text, sip_pvt::theirtag, transmit_request(), and XMIT_UNRELIABLE.
16485 { 16486 struct ast_channel *owner; 16487 int sipmethod; 16488 int res = 1; 16489 const char *c = get_header(req, "Cseq"); 16490 /* 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 */ 16491 char *c_copy = ast_strdupa(c); 16492 /* Skip the Cseq and its subsequent spaces */ 16493 const char *msg = ast_skip_blanks(ast_skip_nonblanks(c_copy)); 16494 16495 if (!msg) 16496 msg = ""; 16497 16498 sipmethod = find_sip_method(msg); 16499 16500 owner = p->owner; 16501 if (owner) 16502 owner->hangupcause = hangup_sip2cause(resp); 16503 16504 /* Acknowledge whatever it is destined for */ 16505 if ((resp >= 100) && (resp <= 199)) 16506 __sip_semi_ack(p, seqno, 0, sipmethod); 16507 else 16508 __sip_ack(p, seqno, 0, sipmethod); 16509 16510 /* If this is a NOTIFY for a subscription clear the flag that indicates that we have a NOTIFY pending */ 16511 if (!p->owner && sipmethod == SIP_NOTIFY && p->pendinginvite) 16512 p->pendinginvite = 0; 16513 16514 /* Get their tag if we haven't already */ 16515 if (ast_strlen_zero(p->theirtag) || (resp >= 200)) { 16516 char tag[128]; 16517 16518 gettag(req, "To", tag, sizeof(tag)); 16519 ast_string_field_set(p, theirtag, tag); 16520 } 16521 /* This needs to be configurable on a channel/peer level, 16522 not mandatory for all communication. Sadly enough, NAT implementations 16523 are not so stable so we can always rely on these headers. 16524 Temporarily disabled, while waiting for fix. 16525 Fix assigned to Rizzo :-) 16526 */ 16527 /* check_via_response(p, req); */ 16528 16529 /* RFC 3261 Section 15 specifies that if we receive a 408 or 481 16530 * in response to a BYE, then we should end the current dialog 16531 * and session. It is known that at least one phone manufacturer 16532 * potentially will send a 404 in response to a BYE, so we'll be 16533 * liberal in what we accept and end the dialog and session if we 16534 * receive any of those responses to a BYE. 16535 */ 16536 if ((resp == 404 || resp == 408 || resp == 481) && sipmethod == SIP_BYE) { 16537 p->needdestroy = 1; 16538 return; 16539 } 16540 16541 if (p->relatedpeer && p->method == SIP_OPTIONS) { 16542 /* We don't really care what the response is, just that it replied back. 16543 Well, as long as it's not a 100 response... since we might 16544 need to hang around for something more "definitive" */ 16545 if (resp != 100) 16546 handle_response_peerpoke(p, resp, req); 16547 } else if (ast_test_flag(&p->flags[0], SIP_OUTGOING)) { 16548 switch(resp) { 16549 case 100: /* 100 Trying */ 16550 case 101: /* 101 Dialog establishment */ 16551 if (sipmethod == SIP_INVITE) 16552 handle_response_invite(p, resp, rest, req, seqno); 16553 break; 16554 case 183: /* 183 Session Progress */ 16555 if (sipmethod == SIP_INVITE) 16556 handle_response_invite(p, resp, rest, req, seqno); 16557 break; 16558 case 180: /* 180 Ringing */ 16559 if (sipmethod == SIP_INVITE) 16560 handle_response_invite(p, resp, rest, req, seqno); 16561 break; 16562 case 182: /* 182 Queued */ 16563 if (sipmethod == SIP_INVITE) 16564 handle_response_invite(p, resp, rest, req, seqno); 16565 break; 16566 case 200: /* 200 OK */ 16567 p->authtries = 0; /* Reset authentication counter */ 16568 if (sipmethod == SIP_MESSAGE || sipmethod == SIP_INFO) { 16569 /* We successfully transmitted a message 16570 or a video update request in INFO */ 16571 /* Nothing happens here - the message is inside a dialog */ 16572 } else if (sipmethod == SIP_INVITE) { 16573 handle_response_invite(p, resp, rest, req, seqno); 16574 } else if (sipmethod == SIP_NOTIFY) { 16575 handle_response_notify(p, resp, rest, req, seqno); 16576 } else if (sipmethod == SIP_REGISTER) 16577 res = handle_response_register(p, resp, rest, req, seqno); 16578 else if (sipmethod == SIP_BYE) { /* Ok, we're ready to go */ 16579 p->needdestroy = 1; 16580 ast_clear_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED); 16581 } else if (sipmethod == SIP_SUBSCRIBE) { 16582 ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED); 16583 } 16584 break; 16585 case 202: /* Transfer accepted */ 16586 if (sipmethod == SIP_REFER) 16587 handle_response_refer(p, resp, rest, req, seqno); 16588 break; 16589 case 401: /* Not www-authorized on SIP method */ 16590 case 407: /* Proxy auth required */ 16591 if (sipmethod == SIP_INVITE) 16592 handle_response_invite(p, resp, rest, req, seqno); 16593 else if (sipmethod == SIP_NOTIFY) 16594 handle_response_notify(p, resp, rest, req, seqno); 16595 else if (sipmethod == SIP_REFER) 16596 handle_response_refer(p, resp, rest, req, seqno); 16597 else if (p->registry && sipmethod == SIP_REGISTER) 16598 res = handle_response_register(p, resp, rest, req, seqno); 16599 else if (sipmethod == SIP_BYE) { 16600 if (p->options) 16601 p->options->auth_type = resp; 16602 if (ast_strlen_zero(p->authname)) { 16603 ast_log(LOG_WARNING, "Asked to authenticate %s, to %s:%d but we have no matching peer!\n", 16604 msg, ast_inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port)); 16605 p->needdestroy = 1; 16606 } else if ((p->authtries == MAX_AUTHTRIES) || do_proxy_auth(p, req, resp, sipmethod, 0)) { 16607 ast_log(LOG_NOTICE, "Failed to authenticate on %s to '%s'\n", msg, get_header(&p->initreq, "From")); 16608 p->needdestroy = 1; 16609 } 16610 } else { 16611 ast_log(LOG_WARNING, "Got authentication request (%d) on %s to '%s'\n", resp, sip_methods[sipmethod].text, get_header(req, "To")); 16612 p->needdestroy = 1; 16613 } 16614 break; 16615 case 403: /* Forbidden - we failed authentication */ 16616 if (sipmethod == SIP_INVITE) 16617 handle_response_invite(p, resp, rest, req, seqno); 16618 else if (p->registry && sipmethod == SIP_REGISTER) 16619 res = handle_response_register(p, resp, rest, req, seqno); 16620 else { 16621 ast_log(LOG_WARNING, "Forbidden - maybe wrong password on authentication for %s\n", msg); 16622 p->needdestroy = 1; 16623 } 16624 break; 16625 case 404: /* Not found */ 16626 if (p->registry && sipmethod == SIP_REGISTER) 16627 res = handle_response_register(p, resp, rest, req, seqno); 16628 else if (sipmethod == SIP_INVITE) 16629 handle_response_invite(p, resp, rest, req, seqno); 16630 else if (owner) 16631 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 16632 break; 16633 case 423: /* Interval too brief */ 16634 if (sipmethod == SIP_REGISTER) 16635 res = handle_response_register(p, resp, rest, req, seqno); 16636 break; 16637 case 408: /* Request timeout - terminate dialog */ 16638 if (sipmethod == SIP_INVITE) 16639 handle_response_invite(p, resp, rest, req, seqno); 16640 else if (sipmethod == SIP_REGISTER) 16641 res = handle_response_register(p, resp, rest, req, seqno); 16642 else if (sipmethod == SIP_BYE) { 16643 p->needdestroy = 1; 16644 ast_debug(4, "Got timeout on bye. Thanks for the answer. Now, kill this call\n"); 16645 } else { 16646 if (owner) 16647 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 16648 p->needdestroy = 1; 16649 } 16650 break; 16651 16652 case 422: /* Session-Timers: Session Interval Too Small */ 16653 if (sipmethod == SIP_INVITE) { 16654 handle_response_invite(p, resp, rest, req, seqno); 16655 } 16656 break; 16657 16658 case 481: /* Call leg does not exist */ 16659 if (sipmethod == SIP_INVITE) { 16660 handle_response_invite(p, resp, rest, req, seqno); 16661 } else if (sipmethod == SIP_REFER) { 16662 handle_response_refer(p, resp, rest, req, seqno); 16663 } else if (sipmethod == SIP_BYE) { 16664 /* The other side has no transaction to bye, 16665 just assume it's all right then */ 16666 ast_log(LOG_WARNING, "Remote host can't match request %s to call '%s'. Giving up.\n", sip_methods[sipmethod].text, p->callid); 16667 } else if (sipmethod == SIP_CANCEL) { 16668 /* The other side has no transaction to cancel, 16669 just assume it's all right then */ 16670 ast_log(LOG_WARNING, "Remote host can't match request %s to call '%s'. Giving up.\n", sip_methods[sipmethod].text, p->callid); 16671 } else { 16672 ast_log(LOG_WARNING, "Remote host can't match request %s to call '%s'. Giving up.\n", sip_methods[sipmethod].text, p->callid); 16673 /* Guessing that this is not an important request */ 16674 } 16675 break; 16676 case 487: 16677 if (sipmethod == SIP_INVITE) 16678 handle_response_invite(p, resp, rest, req, seqno); 16679 break; 16680 case 488: /* Not acceptable here - codec error */ 16681 if (sipmethod == SIP_INVITE) 16682 handle_response_invite(p, resp, rest, req, seqno); 16683 break; 16684 case 491: /* Pending */ 16685 if (sipmethod == SIP_INVITE) 16686 handle_response_invite(p, resp, rest, req, seqno); 16687 else { 16688 ast_debug(1, "Got 491 on %s, unspported. Call ID %s\n", sip_methods[sipmethod].text, p->callid); 16689 p->needdestroy = 1; 16690 } 16691 break; 16692 case 501: /* Not Implemented */ 16693 if (sipmethod == SIP_INVITE) 16694 handle_response_invite(p, resp, rest, req, seqno); 16695 else if (sipmethod == SIP_REFER) 16696 handle_response_refer(p, resp, rest, req, seqno); 16697 else 16698 ast_log(LOG_WARNING, "Host '%s' does not implement '%s'\n", ast_inet_ntoa(p->sa.sin_addr), msg); 16699 break; 16700 case 603: /* Declined transfer */ 16701 if (sipmethod == SIP_REFER) { 16702 handle_response_refer(p, resp, rest, req, seqno); 16703 break; 16704 } 16705 /* Fallthrough */ 16706 default: 16707 if ((resp >= 300) && (resp < 700)) { 16708 /* Fatal response */ 16709 if ((resp != 487)) 16710 ast_verb(3, "Got SIP response %d \"%s\" back from %s\n", resp, rest, ast_inet_ntoa(p->sa.sin_addr)); 16711 16712 if (sipmethod == SIP_INVITE) 16713 stop_media_flows(p); /* Immediately stop RTP, VRTP and UDPTL as applicable */ 16714 16715 /* XXX Locking issues?? XXX */ 16716 switch(resp) { 16717 case 300: /* Multiple Choices */ 16718 case 301: /* Moved permanently */ 16719 case 302: /* Moved temporarily */ 16720 case 305: /* Use Proxy */ 16721 parse_moved_contact(p, req); 16722 /* Fall through */ 16723 case 486: /* Busy here */ 16724 case 600: /* Busy everywhere */ 16725 case 603: /* Decline */ 16726 if (p->owner) 16727 ast_queue_control(p->owner, AST_CONTROL_BUSY); 16728 break; 16729 case 482: /*! 16730 \note SIP is incapable of performing a hairpin call, which 16731 is yet another failure of not having a layer 2 (again, YAY 16732 IETF for thinking ahead). So we treat this as a call 16733 forward and hope we end up at the right place... */ 16734 ast_debug(1, "Hairpin detected, setting up call forward for what it's worth\n"); 16735 if (p->owner) 16736 ast_string_field_build(p->owner, call_forward, 16737 "Local/%s@%s", p->username, p->context); 16738 /* Fall through */ 16739 case 480: /* Temporarily Unavailable */ 16740 case 404: /* Not Found */ 16741 case 410: /* Gone */ 16742 case 400: /* Bad Request */ 16743 case 500: /* Server error */ 16744 if (sipmethod == SIP_REFER) { 16745 handle_response_refer(p, resp, rest, req, seqno); 16746 break; 16747 } 16748 /* Fall through */ 16749 case 502: /* Bad gateway */ 16750 case 503: /* Service Unavailable */ 16751 case 504: /* Server Timeout */ 16752 if (owner) 16753 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 16754 break; 16755 default: 16756 /* Send hangup */ 16757 if (owner && sipmethod != SIP_MESSAGE && sipmethod != SIP_INFO && sipmethod != SIP_BYE) 16758 ast_queue_hangup_with_cause(p->owner, AST_CAUSE_PROTOCOL_ERROR); 16759 break; 16760 } 16761 /* ACK on invite */ 16762 if (sipmethod == SIP_INVITE) 16763 transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); 16764 if (sipmethod != SIP_MESSAGE && sipmethod != SIP_INFO) 16765 sip_alreadygone(p); 16766 if (!p->owner) 16767 p->needdestroy = 1; 16768 } else if ((resp >= 100) && (resp < 200)) { 16769 if (sipmethod == SIP_INVITE) { 16770 if (!req->ignore && sip_cancel_destroy(p)) 16771 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 16772 if (find_sdp(req)) 16773 process_sdp(p, req, SDP_T38_NONE); 16774 if (p->owner) { 16775 /* Queue a progress frame */ 16776 ast_queue_control(p->owner, AST_CONTROL_PROGRESS); 16777 } 16778 } 16779 } else 16780 ast_log(LOG_NOTICE, "Dont know how to handle a %d %s response from %s\n", resp, rest, p->owner ? p->owner->name : ast_inet_ntoa(p->sa.sin_addr)); 16781 } 16782 } else { 16783 /* Responses to OUTGOING SIP requests on INCOMING calls 16784 get handled here. As well as out-of-call message responses */ 16785 if (req->debug) 16786 ast_verbose("SIP Response message for INCOMING dialog %s arrived\n", msg); 16787 16788 if (sipmethod == SIP_INVITE && resp == 200) { 16789 /* Tags in early session is replaced by the tag in 200 OK, which is 16790 the final reply to our INVITE */ 16791 char tag[128]; 16792 16793 gettag(req, "To", tag, sizeof(tag)); 16794 ast_string_field_set(p, theirtag, tag); 16795 } 16796 16797 switch(resp) { 16798 case 200: 16799 if (sipmethod == SIP_INVITE) { 16800 handle_response_invite(p, resp, rest, req, seqno); 16801 } else if (sipmethod == SIP_CANCEL) { 16802 ast_debug(1, "Got 200 OK on CANCEL\n"); 16803 16804 /* Wait for 487, then destroy */ 16805 } else if (sipmethod == SIP_NOTIFY) { 16806 /* They got the notify, this is the end */ 16807 if (p->owner) { 16808 if (p->refer) { 16809 ast_debug(1, "Got 200 OK on NOTIFY for transfer\n"); 16810 } else 16811 ast_log(LOG_WARNING, "Notify answer on an owned channel?\n"); 16812 /* ast_queue_hangup(p->owner); Disabled */ 16813 } else { 16814 if (!p->subscribed && !p->refer) 16815 p->needdestroy = 1; 16816 if (ast_test_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE)) { 16817 /* Ready to send the next state we have on queue */ 16818 ast_clear_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE); 16819 cb_extensionstate((char *)p->context, (char *)p->exten, p->laststate, (void *) p); 16820 } 16821 } 16822 } else if (sipmethod == SIP_BYE) 16823 p->needdestroy = 1; 16824 else if (sipmethod == SIP_MESSAGE || sipmethod == SIP_INFO) 16825 /* We successfully transmitted a message or 16826 a video update request in INFO */ 16827 ; 16828 else if (sipmethod == SIP_BYE) 16829 /* Ok, we're ready to go */ 16830 p->needdestroy = 1; 16831 break; 16832 case 202: /* Transfer accepted */ 16833 if (sipmethod == SIP_REFER) 16834 handle_response_refer(p, resp, rest, req, seqno); 16835 break; 16836 case 401: /* www-auth */ 16837 case 407: 16838 if (sipmethod == SIP_REFER) 16839 handle_response_refer(p, resp, rest, req, seqno); 16840 else if (sipmethod == SIP_INVITE) 16841 handle_response_invite(p, resp, rest, req, seqno); 16842 else if (sipmethod == SIP_BYE) { 16843 if (p->authtries == MAX_AUTHTRIES || do_proxy_auth(p, req, resp, sipmethod, 0)) { 16844 ast_log(LOG_NOTICE, "Failed to authenticate on %s to '%s'\n", msg, get_header(&p->initreq, "From")); 16845 p->needdestroy = 1; 16846 } 16847 } 16848 break; 16849 case 481: /* Call leg does not exist */ 16850 if (sipmethod == SIP_INVITE) { 16851 /* Re-invite failed */ 16852 handle_response_invite(p, resp, rest, req, seqno); 16853 } else if (sipmethod == SIP_BYE) { 16854 p->needdestroy = 1; 16855 } else if (sipdebug) { 16856 ast_debug(1, "Remote host can't match request %s to call '%s'. Giving up\n", sip_methods[sipmethod].text, p->callid); 16857 } 16858 break; 16859 case 501: /* Not Implemented */ 16860 if (sipmethod == SIP_INVITE) 16861 handle_response_invite(p, resp, rest, req, seqno); 16862 else if (sipmethod == SIP_REFER) 16863 handle_response_refer(p, resp, rest, req, seqno); 16864 break; 16865 case 603: /* Declined transfer */ 16866 if (sipmethod == SIP_REFER) { 16867 handle_response_refer(p, resp, rest, req, seqno); 16868 break; 16869 } 16870 /* Fallthrough */ 16871 default: /* Errors without handlers */ 16872 if ((resp >= 100) && (resp < 200)) { 16873 if (sipmethod == SIP_INVITE) { /* re-invite */ 16874 if (!req->ignore && sip_cancel_destroy(p)) 16875 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 16876 } 16877 } 16878 if ((resp >= 300) && (resp < 700)) { 16879 if ((resp != 487)) 16880 ast_verb(3, "Incoming call: Got SIP response %d \"%s\" back from %s\n", resp, rest, ast_inet_ntoa(p->sa.sin_addr)); 16881 switch(resp) { 16882 case 488: /* Not acceptable here - codec error */ 16883 case 603: /* Decline */ 16884 case 500: /* Server error */ 16885 case 502: /* Bad gateway */ 16886 case 503: /* Service Unavailable */ 16887 case 504: /* Server timeout */ 16888 16889 /* re-invite failed */ 16890 if (sipmethod == SIP_INVITE && sip_cancel_destroy(p)) 16891 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 16892 break; 16893 } 16894 } 16895 break; 16896 } 16897 } 16898 }
| static void handle_response_invite | ( | struct sip_pvt * | p, | |
| int | resp, | |||
| char * | rest, | |||
| struct sip_request * | req, | |||
| int | seqno | |||
| ) | [static] |
Handle SIP response to INVITE dialogue.
Definition at line 15860 of file chan_sip.c.
References ast_channel::_state, sip_pvt::alreadygone, append_history, AST_CAUSE_NORMAL_CLEARING, AST_CONTROL_ANSWER, AST_CONTROL_CONGESTION, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, ast_debug, ast_log(), ast_null_frame, ast_queue_control(), ast_queue_frame(), ast_queue_hangup_with_cause(), ast_random(), ast_rtp_set_rtptimers_onhold(), ast_sched_add(), AST_SCHED_DEL_UNREF, ast_set_flag, ast_setstate(), AST_STATE_RINGING, AST_STATE_UP, ast_string_field_set, ast_strlen_zero(), ast_test_flag, sip_invite_param::auth_type, sip_pvt::authtries, build_route(), sip_pvt::callid, change_t38_state(), check_pendings(), DEC_CALL_LIMIT, DEC_CALL_RINGING, DEFAULT_TRANS_TIMEOUT, dialog_ref(), dialog_unref(), do_proxy_auth(), EVENT_FLAG_SYSTEM, FALSE, find_sdp(), sip_pvt::flags, sip_pvt::fullcontact, get_header(), sip_request::ignore, sip_pvt::initid, sip_pvt::initreq, INV_CALLING, INV_CANCELLED, INV_COMPLETED, INV_EARLY_MEDIA, INV_PROCEEDING, INV_TERMINATED, sip_pvt::invitestate, LOG_NOTICE, LOG_WARNING, manager_event, MAX_AUTHTRIES, ast_channel::name, sip_pvt::needdestroy, sip_pvt::options, sip_pvt::outgoing_call, sip_pvt::owner, parse_ok_contact(), parse_session_expires(), sip_pvt::peername, sip_pvt::pendinginvite, proc_422_rsp(), process_sdp(), sched, SDP_T38_ACCEPT, SDP_T38_NONE, SESSION_TIMER_MODE_ORIGINATE, SESSION_TIMER_MODE_REFUSE, SESSION_TIMER_REFRESHER_AUTO, SESSION_TIMER_REFRESHER_UAC, SESSION_TIMER_REFRESHER_UAS, set_address_from_contact(), SIP_ACK, sip_alreadygone(), sip_cancel_destroy(), SIP_INVITE, SIP_OUTGOING, SIP_PAGE2_DIALOG_ESTABLISHED, SIP_PENDINGBYE, sip_reinvite_retry(), sip_scheddestroy(), sip_st_dlg::st_active, sip_st_dlg::st_active_peer_ua, st_get_mode(), sip_st_dlg::st_interval, sip_st_dlg::st_ref, start_session_timer(), t38properties::state, sip_pvt::stimer, sip_pvt::t38, T38_DISABLED, T38_LOCAL_REINVITE, sip_pvt::theirtag, transmit_reinvite_with_sdp(), transmit_request(), TRUE, sip_pvt::udptl, ast_channel::uniqueid, update_call_counter(), sip_pvt::waitid, XMIT_ERROR, and XMIT_UNRELIABLE.
Referenced by handle_response().
15861 { 15862 int outgoing = ast_test_flag(&p->flags[0], SIP_OUTGOING); 15863 int res = 0; 15864 int xmitres = 0; 15865 int reinvite = (p->owner && p->owner->_state == AST_STATE_UP); 15866 char *p_hdrval; 15867 int rtn; 15868 15869 if (reinvite) 15870 ast_debug(4, "SIP response %d to RE-invite on %s call %s\n", resp, outgoing ? "outgoing" : "incoming", p->callid); 15871 else 15872 ast_debug(4, "SIP response %d to standard invite\n", resp); 15873 15874 if (p->alreadygone) { /* This call is already gone */ 15875 ast_debug(1, "Got response on call that is already terminated: %s (ignoring)\n", p->callid); 15876 return; 15877 } 15878 15879 /* Acknowledge sequence number - This only happens on INVITE from SIP-call */ 15880 /* Don't auto congest anymore since we've gotten something useful back */ 15881 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")); 15882 15883 /* RFC3261 says we must treat every 1xx response (but not 100) 15884 that we don't recognize as if it was 183. 15885 */ 15886 if (resp > 100 && resp < 200 && resp!=101 && resp != 180 && resp != 182 && resp != 183) 15887 resp = 183; 15888 15889 /* Any response between 100 and 199 is PROCEEDING */ 15890 if (resp >= 100 && resp < 200 && p->invitestate == INV_CALLING) 15891 p->invitestate = INV_PROCEEDING; 15892 15893 /* Final response, not 200 ? */ 15894 if (resp >= 300 && (p->invitestate == INV_CALLING || p->invitestate == INV_PROCEEDING || p->invitestate == INV_EARLY_MEDIA )) 15895 p->invitestate = INV_COMPLETED; 15896 15897 /* Final response, clear out pending invite */ 15898 if ((resp == 200 || resp >= 300) && p->pendinginvite && seqno == p->pendinginvite) 15899 p->pendinginvite = 0; 15900 15901 switch (resp) { 15902 case 100: /* Trying */ 15903 case 101: /* Dialog establishment */ 15904 if (!req->ignore && p->invitestate != INV_CANCELLED && sip_cancel_destroy(p)) 15905 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 15906 check_pendings(p); 15907 break; 15908 15909 case 180: /* 180 Ringing */ 15910 case 182: /* 182 Queued */ 15911 if (!req->ignore && p->invitestate != INV_CANCELLED && sip_cancel_destroy(p)) 15912 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 15913 if (!req->ignore && p->owner) { 15914 ast_queue_control(p->owner, AST_CONTROL_RINGING); 15915 if (p->owner->_state != AST_STATE_UP) { 15916 ast_setstate(p->owner, AST_STATE_RINGING); 15917 } 15918 } 15919 if (find_sdp(req)) { 15920 if (p->invitestate != INV_CANCELLED) 15921 p->invitestate = INV_EARLY_MEDIA; 15922 res = process_sdp(p, req, SDP_T38_NONE); 15923 if (!req->ignore && p->owner) { 15924 /* Queue a progress frame only if we have SDP in 180 or 182 */ 15925 ast_queue_control(p->owner, AST_CONTROL_PROGRESS); 15926 } 15927 } 15928 check_pendings(p); 15929 break; 15930 15931 case 183: /* Session progress */ 15932 if (!req->ignore && (p->invitestate != INV_CANCELLED) && sip_cancel_destroy(p)) 15933 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 15934 /* Ignore 183 Session progress without SDP */ 15935 if (find_sdp(req)) { 15936 if (p->invitestate != INV_CANCELLED) 15937 p->invitestate = INV_EARLY_MEDIA; 15938 res = process_sdp(p, req, SDP_T38_NONE); 15939 if (!req->ignore && p->owner) { 15940 /* Queue a progress frame */ 15941 ast_queue_control(p->owner, AST_CONTROL_PROGRESS); 15942 } 15943 } 15944 check_pendings(p); 15945 break; 15946 15947 case 200: /* 200 OK on invite - someone's answering our call */ 15948 if (!req->ignore && (p->invitestate != INV_CANCELLED) && sip_cancel_destroy(p)) 15949 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 15950 p->authtries = 0; 15951 if (find_sdp(req)) { 15952 if ((res = process_sdp(p, req, SDP_T38_ACCEPT)) && !req->ignore) 15953 if (!reinvite) 15954 /* This 200 OK's SDP is not acceptable, so we need to ack, then hangup */ 15955 /* For re-invites, we try to recover */ 15956 ast_set_flag(&p->flags[0], SIP_PENDINGBYE); 15957 } 15958 15959 /* Parse contact header for continued conversation */ 15960 /* When we get 200 OK, we know which device (and IP) to contact for this call */ 15961 /* This is important when we have a SIP proxy between us and the phone */ 15962 if (outgoing) { 15963 update_call_counter(p, DEC_CALL_RINGING); 15964 parse_ok_contact(p, req); 15965 /* Save Record-Route for any later requests we make on this dialogue */ 15966 if (!reinvite) 15967 build_route(p, req, 1); 15968 15969 if(set_address_from_contact(p)) { 15970 /* Bad contact - we don't know how to reach this device */ 15971 /* We need to ACK, but then send a bye */ 15972 if (!p->route && !req->ignore) 15973 ast_set_flag(&p->flags[0], SIP_PENDINGBYE); 15974 } 15975 15976 } 15977 15978 if (!req->ignore && p->owner) { 15979 if (!reinvite) { 15980 ast_queue_control(p->owner, AST_CONTROL_ANSWER); 15981 if (global_callevents) 15982 manager_event(EVENT_FLAG_SYSTEM, "ChannelUpdate", 15983 "Channel: %s\r\nChanneltype: %s\r\nUniqueid: %s\r\nSIPcallid: %s\r\nSIPfullcontact: %s\r\nPeername: %s\r\n", 15984 p->owner->name, "SIP", p->owner->uniqueid, p->callid, p->fullcontact, p->peername); 15985 } else { /* RE-invite */ 15986 ast_queue_frame(p->owner, &ast_null_frame); 15987 } 15988 } else { 15989 /* It's possible we're getting an 200 OK after we've tried to disconnect 15990 by sending CANCEL */ 15991 /* First send ACK, then send bye */ 15992 if (!req->ignore) 15993 ast_set_flag(&p->flags[0], SIP_PENDINGBYE); 15994 } 15995 15996 /* Check for Session-Timers related headers */ 15997 if (st_get_mode(p) != SESSION_TIMER_MODE_REFUSE && p->outgoing_call == TRUE && !reinvite) { 15998 p_hdrval = (char*)get_header(req, "Session-Expires"); 15999 if (!ast_strlen_zero(p_hdrval)) { 16000 /* UAS supports Session-Timers */ 16001 enum st_refresher tmp_st_ref = SESSION_TIMER_REFRESHER_AUTO; 16002 int tmp_st_interval = 0; 16003 rtn = parse_session_expires(p_hdrval, &tmp_st_interval, &tmp_st_ref); 16004 if (rtn != 0) { 16005 ast_set_flag(&p->flags[0], SIP_PENDINGBYE); 16006 } 16007 if (tmp_st_ref == SESSION_TIMER_REFRESHER_UAC || 16008 tmp_st_ref == SESSION_TIMER_REFRESHER_UAS) { 16009 p->stimer->st_ref = tmp_st_ref; 16010 } 16011 if (tmp_st_interval) { 16012 p->stimer->st_interval = tmp_st_interval; 16013 } 16014 p->stimer->st_active = TRUE; 16015 p->stimer->st_active_peer_ua = TRUE; 16016 start_session_timer(p); 16017 } else { 16018 /* UAS doesn't support Session-Timers */ 16019 if (st_get_mode(p) == SESSION_TIMER_MODE_ORIGINATE) { 16020 p->stimer->st_ref = SESSION_TIMER_REFRESHER_UAC; 16021 p->stimer->st_active_peer_ua = FALSE; 16022 start_session_timer(p); 16023 } 16024 } 16025 } 16026 16027 16028 /* If I understand this right, the branch is different for a non-200 ACK only */ 16029 p->invitestate = INV_TERMINATED; 16030 ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED); 16031 xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, TRUE); 16032 check_pendings(p); 16033 break; 16034 16035 case 407: /* Proxy authentication */ 16036 case 401: /* Www auth */ 16037 /* First we ACK */ 16038 xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); 16039 if (p->options) 16040 p->options->auth_type = resp; 16041 16042 /* Then we AUTH */ 16043 ast_string_field_set(p, theirtag, NULL); /* forget their old tag, so we don't match tags when getting response */ 16044 if (!req->ignore) { 16045 if (p->authtries < MAX_AUTHTRIES) 16046 p->invitestate = INV_CALLING; 16047 if (p->authtries == MAX_AUTHTRIES || do_proxy_auth(p, req, resp, SIP_INVITE, 1)) { 16048 ast_log(LOG_NOTICE, "Failed to authenticate on INVITE to '%s'\n", get_header(&p->initreq, "From")); 16049 p->needdestroy = 1; 16050 sip_alreadygone(p); 16051 if (p->owner) 16052 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 16053 } 16054 } 16055 break; 16056 16057 case 403: /* Forbidden */ 16058 /* First we ACK */ 16059 xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); 16060 ast_log(LOG_WARNING, "Received response: \"Forbidden\" from '%s'\n", get_header(&p->initreq, "From")); 16061 if (!req->ignore && p->owner) 16062 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 16063 p->needdestroy = 1; 16064 sip_alreadygone(p); 16065 break; 16066 16067 case 404: /* Not found */ 16068 xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); 16069 if (p->owner && !req->ignore) 16070 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 16071 sip_alreadygone(p); 16072 break; 16073 16074 case 408: /* Request timeout */ 16075 case 481: /* Call leg does not exist */ 16076 /* Could be REFER caused INVITE with replaces */ 16077 ast_log(LOG_WARNING, "Re-invite to non-existing call leg on other UA. SIP dialog '%s'. Giving up.\n", p->callid); 16078 xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); 16079 if (p->owner) 16080 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 16081 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 16082 break; 16083 16084 case 422: /* Session-Timers: Session interval too small */ 16085 xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); 16086 ast_string_field_set(p, theirtag, NULL); 16087 proc_422_rsp(p, req); 16088 break; 16089 16090 case 487: /* Cancelled transaction */ 16091 /* We have sent CANCEL on an outbound INVITE 16092 This transaction is already scheduled to be killed by sip_hangup(). 16093 */ 16094 xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); 16095 if (p->owner && !req->ignore) { 16096 ast_queue_hangup_with_cause(p->owner, AST_CAUSE_NORMAL_CLEARING); 16097 append_history(p, "Hangup", "Got 487 on CANCEL request from us. Queued AST hangup request"); 16098 } else if (!req->ignore) { 16099 update_call_counter(p, DEC_CALL_LIMIT); 16100 append_history(p, "Hangup", "Got 487 on CANCEL request from us on call without owner. Killing this dialog."); 16101 p->needdestroy = 1; 16102 sip_alreadygone(p); 16103 } 16104 break; 16105 case 488: /* Not acceptable here */ 16106 xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); 16107 if (p->udptl && p->t38.state == T38_LOCAL_REINVITE) { 16108 change_t38_state(p, T38_DISABLED); 16109 /* Try to reset RTP timers */ 16110 ast_rtp_set_rtptimers_onhold(p->rtp); 16111 16112 /* Trigger a reinvite back to audio */ 16113 transmit_reinvite_with_sdp(p, FALSE, FALSE); 16114 } else { 16115 /* We can't set up this call, so give up */ 16116 if (p->owner && !req->ignore) 16117 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 16118 p->needdestroy = 1; 16119 /* If there's no dialog to end, then mark p as already gone */ 16120 if (!reinvite) 16121 sip_alreadygone(p); 16122 } 16123 break; 16124 case 491: /* Pending */ 16125 xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); 16126 if (p->owner && !req->ignore) { 16127 if (p->owner->_state != AST_STATE_UP) { 16128 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 16129 p->needdestroy = 1; 16130 } else { 16131 /* This is a re-invite that failed. */ 16132 /* Reset the flag after a while 16133 */ 16134 int wait; 16135 /* RFC 3261, if owner of call, wait between 2.1 to 4 seconds, 16136 * if not owner of call, wait 0 to 2 seconds */ 16137 if (p->outgoing_call) { 16138 wait = 2100 + ast_random() % 2000; 16139 } else { 16140 wait = ast_random() % 2000; 16141 } 16142 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.")); 16143 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); 16144 ast_debug(2, "Reinvite race. Waiting %d secs before retry\n", wait); 16145 } 16146 } 16147 break; 16148 16149 case 501: /* Not implemented */ 16150 xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); 16151 if (p->owner) 16152 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 16153 break; 16154 } 16155 if (xmitres == XMIT_ERROR) 16156 ast_log(LOG_WARNING, "Could not transmit message in dialog %s\n", p->callid); 16157 }
| static void handle_response_notify | ( | struct sip_pvt * | p, | |
| int | resp, | |||
| char * | rest, | |||
| struct sip_request * | req, | |||
| int | seqno | |||
| ) | [static] |
Definition at line 16162 of file chan_sip.c.
References AST_CAUSE_NORMAL_UNSPECIFIED, ast_clear_flag, ast_debug, ast_inet_ntoa(), ast_log(), ast_queue_hangup_with_cause(), ast_string_field_set, ast_strlen_zero(), ast_test_flag, sip_pvt::authname, sip_pvt::authtries, cb_extensionstate(), sip_pvt::context, do_proxy_auth(), sip_pvt::exten, sip_pvt::flags, get_header(), sip_pvt::initreq, sip_pvt::laststate, LOG_NOTICE, LOG_WARNING, ast_channel::name, sip_pvt::needdestroy, NONE, sip_pvt::notify_headers, sip_pvt::owner, sip_pvt::recv, sip_pvt::refer, SIP_NOTIFY, SIP_PAGE2_STATECHANGEQUEUE, sip_pvt::subscribed, and sip_pvt::theirtag.
Referenced by handle_response().
16163 { 16164 switch (resp) { 16165 case 200: /* Notify accepted */ 16166 /* They got the notify, this is the end */ 16167 if (p->owner) { 16168 if (!p->refer) { 16169 ast_log(LOG_WARNING, "Notify answer on an owned channel? - %s\n", p->owner->name); 16170 ast_queue_hangup_with_cause(p->owner, AST_CAUSE_NORMAL_UNSPECIFIED); 16171 } else { 16172 ast_debug(4, "Got OK on REFER Notify message\n"); 16173 } 16174 } else { 16175 if (p->subscribed == NONE) { 16176 ast_debug(4, "Got 200 accepted on NOTIFY\n"); 16177 p->needdestroy = 1; 16178 } 16179 if (ast_test_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE)) { 16180 /* Ready to send the next state we have on queue */ 16181 ast_clear_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE); 16182 cb_extensionstate((char *)p->context, (char *)p->exten, p->laststate, (void *) p); 16183 } 16184 } 16185 break; 16186 case 401: /* Not www-authorized on SIP method */ 16187 case 407: /* Proxy auth */ 16188 if (!p->notify_headers) { 16189 break; /* Only device notify can use NOTIFY auth */ 16190 } 16191 ast_string_field_set(p, theirtag, NULL); 16192 if (ast_strlen_zero(p->authname)) { 16193 ast_log(LOG_WARNING, "Asked to authenticate NOTIFY to %s:%d but we have no matching peer or realm auth!\n", ast_inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port)); 16194 p->needdestroy = 1; 16195 } 16196 if (p->authtries > 1 || do_proxy_auth(p, req, resp, SIP_NOTIFY, 0)) { 16197 ast_log(LOG_NOTICE, "Failed to authenticate on NOTYFY to '%s'\n", get_header(&p->initreq, "From")); 16198 p->needdestroy = 1; 16199 } 16200 break; 16201 } 16202 }
| static void handle_response_peerpoke | ( | struct sip_pvt * | p, | |
| int | resp, | |||
| struct sip_request * | req | |||
| ) | [static] |
Handle qualification responses (OPTIONS).
Definition at line 16414 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(), sip_peer::call, DEFAULT_FREQ_NOTOK, dialog_unref(), EVENT_FLAG_SYSTEM, sip_peer::lastms, LOG_NOTICE, manager_event, sip_peer::maxms, sip_peer::name, sip_pvt::needdestroy, sip_settings::peer_rtupdate, sip_peer::pokeexpire, sip_peer::ps, sip_peer::qualifyfreq, ref_peer(), register_peer_exten(), sip_pvt::relatedpeer, s, sched, SENTINEL, sip_cfg, sip_poke_peer_s(), TRUE, and unref_peer().
Referenced by handle_response().
16415 { 16416 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! */ 16417 int statechanged, is_reachable, was_reachable; 16418 int pingtime = ast_tvdiff_ms(ast_tvnow(), peer->ps); 16419 16420 /* 16421 * Compute the response time to a ping (goes in peer->lastms.) 16422 * -1 means did not respond, 0 means unknown, 16423 * 1..maxms is a valid response, >maxms means late response. 16424 */ 16425 if (pingtime < 1) /* zero = unknown, so round up to 1 */ 16426 pingtime = 1; 16427 16428 /* Now determine new state and whether it has changed. 16429 * Use some helper variables to simplify the writing 16430 * of the expressions. 16431 */ 16432 was_reachable = peer->lastms > 0 && peer->lastms <= peer->maxms; 16433 is_reachable = pingtime <= peer->maxms; 16434 statechanged = peer->lastms == 0 /* yes, unknown before */ 16435 || was_reachable != is_reachable; 16436 16437 peer->lastms = pingtime; 16438 peer->call = dialog_unref(peer->call, "unref dialog peer->call"); 16439 if (statechanged) { 16440 const char *s = is_reachable ? "Reachable" : "Lagged"; 16441 char str_lastms[20]; 16442 snprintf(str_lastms, sizeof(str_lastms), "%d", pingtime); 16443 16444 ast_log(LOG_NOTICE, "Peer '%s' is now %s. (%dms / %dms)\n", 16445 peer->name, s, pingtime, peer->maxms); 16446 ast_devstate_changed(AST_DEVICE_UNKNOWN, "SIP/%s", peer->name); 16447 if (sip_cfg.peer_rtupdate) { 16448 ast_update_realtime(ast_check_realtime("sipregs") ? "sipregs" : "sippeers", "name", peer->name, "lastms", str_lastms, SENTINEL); 16449 } 16450 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", 16451 "ChannelType: SIP\r\nPeer: SIP/%s\r\nPeerStatus: %s\r\nTime: %d\r\n", 16452 peer->name, s, pingtime); 16453 if (is_reachable && global_regextenonqualify) 16454 register_peer_exten(peer, TRUE); 16455 } 16456 16457 p->needdestroy = 1; 16458 16459 /* Try again eventually */ 16460 AST_SCHED_REPLACE_UNREF(peer->pokeexpire, sched, 16461 is_reachable ? peer->qualifyfreq : DEFAULT_FREQ_NOTOK, 16462 sip_poke_peer_s, peer, 16463 unref_peer(_data, "removing poke peer ref"), 16464 unref_peer(peer, "removing poke peer ref"), 16465 ref_peer(peer, "adding poke peer ref")); 16466 }
| static void handle_response_refer | ( | struct sip_pvt * | p, | |
| int | resp, | |||
| char * | rest, | |||
| struct sip_request * | req, | |||
| int | seqno | |||
| ) | [static] |
Definition at line 16207 of file chan_sip.c.
References AST_CONTROL_CONGESTION, ast_debug, ast_inet_ntoa(), ast_log(), ast_queue_control(), ast_strlen_zero(), sip_pvt::authname, sip_pvt::authtries, sip_pvt::callid, do_proxy_auth(), get_header(), sip_pvt::initreq, LOG_NOTICE, LOG_WARNING, sip_pvt::needdestroy, sip_pvt::owner, sip_pvt::recv, sip_pvt::refer, REFER_ACCEPTED, REFER_FAILED, REFER_NOAUTH, sip_refer::refer_to, SIP_REFER, and sip_refer::status.
Referenced by handle_response().
16208 { 16209 /* If no refer structure exists, then do nothing */ 16210 if (!p->refer) 16211 return; 16212 16213 switch (resp) { 16214 case 202: /* Transfer accepted */ 16215 /* We need to do something here */ 16216 /* The transferee is now sending INVITE to target */ 16217 p->refer->status = REFER_ACCEPTED; 16218 /* Now wait for next message */ 16219 ast_debug(3, "Got 202 accepted on transfer\n"); 16220 /* We should hang along, waiting for NOTIFY's here */ 16221 break; 16222 16223 case 401: /* Not www-authorized on SIP method */ 16224 case 407: /* Proxy auth */ 16225 if (ast_strlen_zero(p->authname)) { 16226 ast_log(LOG_WARNING, "Asked to authenticate REFER to %s:%d but we have no matching peer or realm auth!\n", 16227 ast_inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port)); 16228 p->needdestroy = 1; 16229 } 16230 if (p->authtries > 1 || do_proxy_auth(p, req, resp, SIP_REFER, 0)) { 16231 ast_log(LOG_NOTICE, "Failed to authenticate on REFER to '%s'\n", get_header(&p->initreq, "From")); 16232 p->refer->status = REFER_NOAUTH; 16233 p->needdestroy = 1; 16234 } 16235 break; 16236 case 481: /* Call leg does not exist */ 16237 16238 /* A transfer with Replaces did not work */ 16239 /* OEJ: We should Set flag, cancel the REFER, go back 16240 to original call - but right now we can't */ 16241 ast_log(LOG_WARNING, "Remote host can't match REFER request to call '%s'. Giving up.\n", p->callid); 16242 if (p->owner) 16243 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 16244 p->needdestroy = 1; 16245 break; 16246 16247 case 500: /* Server error */ 16248 case 501: /* Method not implemented */ 16249 /* Return to the current call onhold */ 16250 /* Status flag needed to be reset */ 16251 ast_log(LOG_NOTICE, "SIP transfer to %s failed, call miserably fails. \n", p->refer->refer_to); 16252 p->needdestroy = 1; 16253 p->refer->status = REFER_FAILED; 16254 break; 16255 case 603: /* Transfer declined */ 16256 ast_log(LOG_NOTICE, "SIP transfer to %s declined, call miserably fails. \n", p->refer->refer_to); 16257 p->refer->status = REFER_FAILED; 16258 p->needdestroy = 1; 16259 break; 16260 } 16261 }
| static int handle_response_register | ( | struct sip_pvt * | p, | |
| int | resp, | |||
| char * | rest, | |||
| struct sip_request * | req, | |||
| int | seqno | |||
| ) | [static] |
Handle responses on REGISTER to services.
Definition at line 16264 of file chan_sip.c.
References __get_header(), ast_debug, ast_log(), AST_SCHED_DEL, AST_SCHED_REPLACE_UNREF, ast_strlen_zero(), ast_tvnow(), sip_pvt::authtries, sip_registry::call, sip_pvt::callid, DEFAULT_TRANS_TIMEOUT, dialog_unref(), do_register_auth(), EVENT_FLAG_SYSTEM, sip_registry::expire, sip_registry::expiry, EXPIRY_GUARD_LIMIT, EXPIRY_GUARD_MIN, EXPIRY_GUARD_PCT, EXPIRY_GUARD_SECS, get_header(), sip_registry::hostname, sip_pvt::initreq, LOG_NOTICE, LOG_WARNING, manager_event, MAX, MAX_AUTHTRIES, sip_pvt::needdestroy, sip_pvt::our_contact, sip_pvt::peername, sip_registry::refresh, REG_STATE_NOAUTH, REG_STATE_REGISTERED, REG_STATE_REJECTED, REG_STATE_UNREGISTERED, sip_registry::regattempts, sip_pvt::registry, registry_addref(), registry_unref(), sip_registry::regstate, regstate2str(), sip_registry::regtime, S_OR, sched, SIP_REGISTER, sip_reregister(), sip_scheddestroy(), strcasestr(), sip_registry::timeout, transmit_register(), sip_pvt::username, and sip_registry::username.
Referenced by handle_response().
16265 { 16266 int expires, expires_ms; 16267 struct sip_registry *r; 16268 r=p->registry; 16269 16270 switch (resp) { 16271 case 401: /* Unauthorized */ 16272 if (p->authtries == MAX_AUTHTRIES || do_register_auth(p, req, resp)) { 16273 ast_log(LOG_NOTICE, "Failed to authenticate on REGISTER to '%s@%s' (Tries %d)\n", p->registry->username, p->registry->hostname, p->authtries); 16274 p->needdestroy = 1; 16275 } 16276 break; 16277 case 403: /* Forbidden */ 16278 ast_log(LOG_WARNING, "Forbidden - wrong password on authentication for REGISTER for '%s' to '%s'\n", p->registry->username, p->registry->hostname); 16279 AST_SCHED_DEL(sched, r->timeout); 16280 r->regstate = REG_STATE_NOAUTH; 16281 p->needdestroy = 1; 16282 break; 16283 case 404: /* Not found */ 16284 ast_log(LOG_WARNING, "Got 404 Not found on SIP register to service %s@%s, giving up\n", p->registry->username, p->registry->hostname); 16285 p->needdestroy = 1; 16286 if (r->call) 16287 r->call = dialog_unref(r->call, "unsetting registry->call pointer-- case 404"); 16288 r->regstate = REG_STATE_REJECTED; 16289 AST_SCHED_DEL(sched, r->timeout); 16290 break; 16291 case 407: /* Proxy auth */ 16292 if (p->authtries == MAX_AUTHTRIES || do_register_auth(p, req, resp)) { 16293 ast_log(LOG_NOTICE, "Failed to authenticate on REGISTER to '%s' (tries '%d')\n", get_header(&p->initreq, "From"), p->authtries); 16294 p->needdestroy = 1; 16295 } 16296 break; 16297 case 408: /* Request timeout */ 16298 /* Got a timeout response, so reset the counter of failed responses */ 16299 if (r) { 16300 r->regattempts = 0; 16301 } else { 16302 ast_log(LOG_WARNING, "Got a 408 response to our REGISTER on call %s after we had destroyed the registry object\n", p->callid); 16303 } 16304 break; 16305 case 423: /* Interval too brief */ 16306 r->expiry = atoi(get_header(req, "Min-Expires")); 16307 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); 16308 AST_SCHED_DEL(sched, r->timeout); 16309 r->timeout = -1; 16310 if (r->call) { 16311 r->call = dialog_unref(r->call, "unsetting registry->call pointer-- case 423"); 16312 p->needdestroy = 1; 16313 } 16314 if (r->expiry > max_expiry) { 16315 ast_log(LOG_WARNING, "Required expiration time from %s@%s is too high, giving up\n", p->registry->username, p->registry->hostname); 16316 r->expiry = default_expiry; 16317 r->regstate = REG_STATE_REJECTED; 16318 } else { 16319 r->regstate = REG_STATE_UNREGISTERED; 16320 transmit_register(r, SIP_REGISTER, NULL, NULL); 16321 } 16322 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)); 16323 break; 16324 case 479: /* SER: Not able to process the URI - address is wrong in register*/ 16325 ast_log(LOG_WARNING, "Got error 479 on register to %s@%s, giving up (check config)\n", p->registry->username, p->registry->hostname); 16326 p->needdestroy = 1; 16327 if (r->call) 16328 r->call = dialog_unref(r->call, "unsetting registry->call pointer-- case 479"); 16329 r->regstate = REG_STATE_REJECTED; 16330 AST_SCHED_DEL(sched, r->timeout); 16331 break; 16332 case 200: /* 200 OK */ 16333 if (!r) { 16334 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)); 16335 p->needdestroy = 1; 16336 return 0; 16337 } 16338 16339 r->regstate = REG_STATE_REGISTERED; 16340 r->regtime = ast_tvnow(); /* Reset time of last succesful registration */ 16341 manager_event(EVENT_FLAG_SYSTEM, "Registry", "ChannelType: SIP\r\nDomain: %s\r\nStatus: %s\r\n", r->hostname, regstate2str(r->regstate)); 16342 r->regattempts = 0; 16343 ast_debug(1, "Registration successful\n"); 16344 if (r->timeout > -1) { 16345 ast_debug(1, "Cancelling timeout %d\n", r->timeout); 16346 } 16347 AST_SCHED_DEL(sched, r->timeout); 16348 if (r->call) 16349 r->call = dialog_unref(r->call, "unsetting registry->call pointer-- case 200"); 16350 p->registry = registry_unref(p->registry, "unref registry entry p->registry"); 16351 /* Let this one hang around until we have all the responses */ 16352 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 16353 /* p->needdestroy = 1; */ 16354 16355 /* set us up for re-registering */ 16356 /* figure out how long we got registered for */ 16357 AST_SCHED_DEL(sched, r->expire); 16358 16359 /* according to section 6.13 of RFC, contact headers override 16360 expires headers, so check those first */ 16361 expires = 0; 16362 16363 /* XXX todo: try to save the extra call */ 16364 if (!ast_strlen_zero(get_header(req, "Contact"))) { 16365 const char *contact = NULL; 16366 const char *tmptmp = NULL; 16367 int start = 0; 16368 for(;;) { 16369 contact = __get_header(req, "Contact", &start); 16370 /* this loop ensures we get a contact header about our register request */ 16371 if(!ast_strlen_zero(contact)) { 16372 if( (tmptmp=strstr(contact, p->our_contact))) { 16373 contact=tmptmp; 16374 break; 16375 } 16376 } else 16377 break; 16378 } 16379 tmptmp = strcasestr(contact, "expires="); 16380 if (tmptmp) { 16381 if (sscanf(tmptmp + 8, "%d;", &expires) != 1) 16382 expires = 0; 16383 } 16384 16385 } 16386 if (!expires) 16387 expires=atoi(get_header(req, "expires")); 16388 if (!expires) 16389 expires=default_expiry; 16390 16391 expires_ms = expires * 1000; 16392 if (expires <= EXPIRY_GUARD_LIMIT) 16393 expires_ms -= MAX((expires_ms * EXPIRY_GUARD_PCT), EXPIRY_GUARD_MIN); 16394 else 16395 expires_ms -= EXPIRY_GUARD_SECS * 1000; 16396 if (sipdebug) 16397 ast_log(LOG_NOTICE, "Outbound Registration: Expiry for %s is %d sec (Scheduling reregistration in %d s)\n", r->hostname, expires, expires_ms/1000); 16398 16399 r->refresh= (int) expires_ms / 1000; 16400 16401 /* Schedule re-registration before we expire */ 16402 AST_SCHED_REPLACE_UNREF(r->expire, sched, expires_ms, sip_reregister, r, 16403 registry_unref(_data,"unref in REPLACE del fail"), 16404 registry_unref(r,"unref in REPLACE add fail"), 16405 registry_addref(r,"The Addition side of REPLACE")); 16406 /* it is clear that we would not want to destroy the registry entry if we just 16407 scheduled a callback and recorded it in there! */ 16408 /* since we never bumped the count, we shouldn't decrement it! registry_unref(r, "unref registry ptr r"); if this gets deleted, p->registry will be a bad pointer! */ 16409 } 16410 return 1; 16411 }
| static const char * hangup_cause2sip | ( | int | cause | ) | [static] |
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 5076 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().
05077 { 05078 switch (cause) { 05079 case AST_CAUSE_UNALLOCATED: /* 1 */ 05080 case AST_CAUSE_NO_ROUTE_DESTINATION: /* 3 IAX2: Can't find extension in context */ 05081 case AST_CAUSE_NO_ROUTE_TRANSIT_NET: /* 2 */ 05082 return "404 Not Found"; 05083 case AST_CAUSE_CONGESTION: /* 34 */ 05084 case AST_CAUSE_SWITCH_CONGESTION: /* 42 */ 05085 return "503 Service Unavailable"; 05086 case AST_CAUSE_NO_USER_RESPONSE: /* 18 */ 05087 return "408 Request Timeout"; 05088 case AST_CAUSE_NO_ANSWER: /* 19 */ 05089 case AST_CAUSE_UNREGISTERED: /* 20 */ 05090 return "480 Temporarily unavailable"; 05091 case AST_CAUSE_CALL_REJECTED: /* 21 */ 05092 return "403 Forbidden"; 05093 case AST_CAUSE_NUMBER_CHANGED: /* 22 */ 05094 return "410 Gone"; 05095 case AST_CAUSE_NORMAL_UNSPECIFIED: /* 31 */ 05096 return "480 Temporarily unavailable"; 05097 case AST_CAUSE_INVALID_NUMBER_FORMAT: 05098 return "484 Address incomplete"; 05099 case AST_CAUSE_USER_BUSY: 05100 return "486 Busy here"; 05101 case AST_CAUSE_FAILURE: 05102 return "500 Server internal failure"; 05103 case AST_CAUSE_FACILITY_REJECTED: /* 29 */ 05104 return "501 Not Implemented"; 05105 case AST_CAUSE_CHAN_NOT_IMPLEMENTED: 05106 return "503 Service Unavailable"; 05107 /* Used in chan_iax2 */ 05108 case AST_CAUSE_DESTINATION_OUT_OF_ORDER: 05109 return "502 Bad Gateway"; 05110 case AST_CAUSE_BEARERCAPABILITY_NOTAVAIL: /* Can't find codec to connect to host */ 05111 return "488 Not Acceptable Here"; 05112 05113 case AST_CAUSE_NOTDEFINED: 05114 default: 05115 ast_debug(1, "AST hangup cause %d (no match found in SIP)\n", cause); 05116 return NULL; 05117 } 05118 05119 /* Never reached */ 05120 return 0; 05121 }
| static int hangup_sip2cause | ( | int | cause | ) | [static] |
Convert SIP hangup causes to Asterisk hangup causes.
Definition at line 4964 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_RECOVERY_ON_TIMER_EXPIRE, AST_CAUSE_UNALLOCATED, and AST_CAUSE_USER_BUSY.
Referenced by handle_response().
04965 { 04966 /* Possible values taken from causes.h */ 04967 04968 switch(cause) { 04969 case 401: /* Unauthorized */ 04970 return AST_CAUSE_CALL_REJECTED; 04971 case 403: /* Not found */ 04972 return AST_CAUSE_CALL_REJECTED; 04973 case 404: /* Not found */ 04974 return AST_CAUSE_UNALLOCATED; 04975 case 405: /* Method not allowed */ 04976 return AST_CAUSE_INTERWORKING; 04977 case 407: /* Proxy authentication required */ 04978 return AST_CAUSE_CALL_REJECTED; 04979 case 408: /* No reaction */ 04980 return AST_CAUSE_NO_USER_RESPONSE; 04981 case 409: /* Conflict */ 04982 return AST_CAUSE_NORMAL_TEMPORARY_FAILURE; 04983 case 410: /* Gone */ 04984 return AST_CAUSE_UNALLOCATED; 04985 case 411: /* Length required */ 04986 return AST_CAUSE_INTERWORKING; 04987 case 413: /* Request entity too large */ 04988 return AST_CAUSE_INTERWORKING; 04989 case 414: /* Request URI too large */ 04990 return AST_CAUSE_INTERWORKING; 04991 case 415: /* Unsupported media type */ 04992 return AST_CAUSE_INTERWORKING; 04993 case 420: /* Bad extension */ 04994 return AST_CAUSE_NO_ROUTE_DESTINATION; 04995 case 480: /* No answer */ 04996 return AST_CAUSE_NO_ANSWER; 04997 case 481: /* No answer */ 04998 return AST_CAUSE_INTERWORKING; 04999 case 482: /* Loop detected */ 05000 return AST_CAUSE_INTERWORKING; 05001 case 483: /* Too many hops */ 05002 return AST_CAUSE_NO_ANSWER; 05003 case 484: /* Address incomplete */ 05004 return AST_CAUSE_INVALID_NUMBER_FORMAT; 05005 case 485: /* Ambiguous */ 05006 return AST_CAUSE_UNALLOCATED; 05007 case 486: /* Busy everywhere */ 05008 return AST_CAUSE_BUSY; 05009 case 487: /* Request terminated */ 05010 return AST_CAUSE_INTERWORKING; 05011 case 488: /* No codecs approved */ 05012 return AST_CAUSE_BEARERCAPABILITY_NOTAVAIL; 05013 case 491: /* Request pending */ 05014 return AST_CAUSE_INTERWORKING; 05015 case 493: /* Undecipherable */ 05016 return AST_CAUSE_INTERWORKING; 05017 case 500: /* Server internal failure */ 05018 return AST_CAUSE_FAILURE; 05019 case 501: /* Call rejected */ 05020 return AST_CAUSE_FACILITY_REJECTED; 05021 case 502: 05022 return AST_CAUSE_DESTINATION_OUT_OF_ORDER; 05023 case 503: /* Service unavailable */ 05024 return AST_CAUSE_CONGESTION; 05025 case 504: /* Gateway timeout */ 05026 return AST_CAUSE_RECOVERY_ON_TIMER_EXPIRE; 05027 case 505: /* SIP version not supported */ 05028 return AST_CAUSE_INTERWORKING; 05029 case 600: /* Busy everywhere */ 05030 return AST_CAUSE_USER_BUSY; 05031 case 603: /* Decline */ 05032 return AST_CAUSE_CALL_REJECTED; 05033 case 604: /* Does not exist anywhere */ 05034 return AST_CAUSE_UNALLOCATED; 05035 case 606: /* Not acceptable */ 05036 return AST_CAUSE_BEARERCAPABILITY_NOTAVAIL; 05037 default: 05038 return AST_CAUSE_NORMAL; 05039 } 05040 /* Never reached */ 05041 return 0; 05042 }
| static int init_req | ( | struct sip_request * | req, | |
| int | sipmethod, | |||
| const char * | recip | |||
| ) | [static] |
Initialize SIP request.
Definition at line 7889 of file chan_sip.c.
References ast_str_create(), ast_str_set(), sip_methods, SIP_MIN_PACKET, and cfsip_methods::text.
07890 { 07891 /* Initialize a request */ 07892 memset(req, 0, sizeof(*req)); 07893 if (!(req->data = ast_str_create(SIP_MIN_PACKET))) 07894 return -1; 07895 req->method = sipmethod; 07896 req->header[0] = 0; 07897 ast_str_set(&req->data, 0, "%s %s SIP/2.0\r\n", sip_methods[sipmethod].text, recip); 07898 req->len = req->data->used; 07899 req->headers++; 07900 return 0; 07901 }
| static int init_resp | ( | struct sip_request * | resp, | |
| const char * | msg | |||
| ) | [static] |
Initialize SIP response, based on SIP request.
Definition at line 7874 of file chan_sip.c.
References ast_str_create(), ast_str_set(), SIP_MIN_PACKET, and SIP_RESPONSE.
07875 { 07876 /* Initialize a response */ 07877 memset(resp, 0, sizeof(*resp)); 07878 resp->method = SIP_RESPONSE; 07879 if (!(resp->data = ast_str_create(SIP_MIN_PACKET))) 07880 return -1; 07881 resp->header[0] = 0; 07882 ast_str_set(&resp->data, 0, "SIP/2.0 %s\r\n", msg); 07883 resp->len = resp->data->used; 07884 resp->headers++; 07885 return 0; 07886 }
| 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 2629 of file chan_sip.c.
References ast_debug, ast_verbose, sip_pvt::callid, copy_request(), sip_request::debug, sip_request::headers, sip_pvt::initreq, sip_request::lines, sip_request::method, parse_request(), and sip_methods.
Referenced by transmit_invite(), transmit_notify_custom(), transmit_notify_with_mwi(), transmit_notify_with_sipfrag(), transmit_register(), and transmit_reinvite_with_sdp().
02630 { 02631 if (p->initreq.headers) 02632 ast_debug(1, "Initializing already initialized SIP dialog %s (presumably reinvite)\n", p->callid); 02633 else 02634 ast_debug(1, "Initializing initreq for method %s - callid %s\n", sip_methods[req->method].text, p->callid); 02635 /* Use this as the basis */ 02636 copy_request(&p->initreq, req); 02637 parse_request(&p->initreq); 02638 if (req->debug) 02639 ast_verbose("Initreq: %d headers, %d lines\n", p->initreq.headers, p->initreq.lines); 02640 }
| static void initreqprep | ( | struct sip_request * | req, | |
| struct sip_pvt * | p, | |||
| int | sipmethod | |||
| ) | [static] |
Initiate new SIP request to peer/user.
Definition at line 9234 of file chan_sip.c.
References add_header(), AST_DIGIT_ANYNUM, ast_inet_ntoa(), AST_PRES_ALLOWED, AST_PRES_RESTRICTION, ast_str_alloca, ast_str_append(), ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_uri_encode(), build_contact(), build_rpid(), CALLERID_UNKNOWN, sip_pvt::callid, sip_pvt::callingpres, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, DEFAULT_MAX_FORWARDS, exten, sip_pvt::flags, sip_pvt::fromdomain, sip_pvt::fromname, sip_pvt::fromuser, sip_pvt::fullcontact, init_req(), sip_pvt::lastmsg, sip_pvt::ocseq, sip_pvt::options, sip_pvt::our_contact, sip_pvt::ourip, ourport, sip_pvt::owner, sip_pvt::rpid, s, S_OR, sip_pvt::sa, SIP_INVITE, sip_methods, SIP_NOTIFY, SIP_SENDRPID, sip_standard_port(), SIP_USEREQPHONE, SIPBUFSIZE, sip_pvt::socket, STANDARD_SIP_PORT, ast_str::str, sip_pvt::tag, cfsip_methods::text, sip_pvt::theirtag, sip_pvt::todnid, sip_pvt::tohost, sip_socket::type, sip_pvt::uri, sip_invite_param::uri_options, sip_pvt::username, sip_pvt::via, and sip_invite_param::vxml_url.
Referenced by transmit_invite(), transmit_notify_custom(), and transmit_notify_with_mwi().
09235 { 09236 struct ast_str *invite = ast_str_alloca(256); 09237 char from[256]; 09238 char to[256]; 09239 char tmp_n[SIPBUFSIZE/2]; /* build a local copy of 'n' if needed */ 09240 char tmp_l[SIPBUFSIZE/2]; /* build a local copy of 'l' if needed */ 09241 const char *l = NULL; /* XXX what is this, exactly ? */ 09242 const char *n = NULL; /* XXX what is this, exactly ? */ 09243 const char *urioptions = ""; 09244 int ourport; 09245 09246 if (ast_test_flag(&p->flags[0], SIP_USEREQPHONE)) { 09247 const char *s = p->username; /* being a string field, cannot be NULL */ 09248 09249 /* Test p->username against allowed characters in AST_DIGIT_ANY 09250 If it matches the allowed characters list, then sipuser = ";user=phone" 09251 If not, then sipuser = "" 09252 */ 09253 /* + is allowed in first position in a tel: uri */ 09254 if (*s == '+') 09255 s++; 09256 for (; *s; s++) { 09257 if (!strchr(AST_DIGIT_ANYNUM, *s) ) 09258 break; 09259 } 09260 /* If we have only digits, add ;user=phone to the uri */ 09261 if (!*s) 09262 urioptions = ";user=phone"; 09263 } 09264 09265 09266 snprintf(p->lastmsg, sizeof(p->lastmsg), "Init: %s", sip_methods[sipmethod].text); 09267 09268 if (p->owner) { 09269 l = p->owner->cid.cid_num; 09270 n = p->owner->cid.cid_name; 09271 } 09272 /* if we are not sending RPID and user wants his callerid restricted */ 09273 if (!ast_test_flag(&p->flags[0], SIP_SENDRPID) && 09274 ((p->callingpres & AST_PRES_RESTRICTION) != AST_PRES_ALLOWED)) { 09275 l = CALLERID_UNKNOWN; 09276 n = l; 09277 } 09278 if (ast_strlen_zero(l)) 09279 l = default_callerid; 09280 if (ast_strlen_zero(n)) 09281 n = l; 09282 /* Allow user to be overridden */ 09283 if (!ast_strlen_zero(p->fromuser)) 09284 l = p->fromuser; 09285 else /* Save for any further attempts */ 09286 ast_string_field_set(p, fromuser, l); 09287 09288 /* Allow user to be overridden */ 09289 if (!ast_strlen_zero(p->fromname)) 09290 n = p->fromname; 09291 else /* Save for any further attempts */ 09292 ast_string_field_set(p, fromname, n); 09293 09294 if (pedanticsipchecking) { 09295 ast_uri_encode(n, tmp_n, sizeof(tmp_n), 0); 09296 n = tmp_n; 09297 ast_uri_encode(l, tmp_l, sizeof(tmp_l), 0); 09298 l = tmp_l; 09299 } 09300 09301 ourport = ntohs(p->ourip.sin_port); 09302 if (!sip_standard_port(p->socket.type, ourport) && ast_strlen_zero(p->fromdomain)) 09303 snprintf(from, sizeof(from), "\"%s\" <sip:%s@%s:%d>;tag=%s", n, l, ast_inet_ntoa(p->ourip.sin_addr), ourport, p->tag); 09304 else 09305 snprintf(from, sizeof(from), "\"%s\" <sip:%s@%s>;tag=%s", n, l, S_OR(p->fromdomain, ast_inet_ntoa(p->ourip.sin_addr)), p->tag); 09306 09307 /* If we're calling a registered SIP peer, use the fullcontact to dial to the peer */ 09308 if (!ast_strlen_zero(p->fullcontact)) { 09309 /* If we have full contact, trust it */ 09310 ast_str_append(&invite, 0, "%s", p->fullcontact); 09311 } else { 09312 /* Otherwise, use the username while waiting for registration */ 09313 ast_str_append(&invite, 0, "sip:"); 09314 if (!ast_strlen_zero(p->username)) { 09315 n = p->username; 09316 if (pedanticsipchecking) { 09317 ast_uri_encode(n, tmp_n, sizeof(tmp_n), 0); 09318 n = tmp_n; 09319 } 09320 ast_str_append(&invite, 0, "%s@", n); 09321 } 09322 ast_str_append(&invite, 0, "%s", p->tohost); 09323 if (ntohs(p->sa.sin_port) != STANDARD_SIP_PORT) 09324 ast_str_append(&invite, 0, ":%d", ntohs(p->sa.sin_port)); 09325 ast_str_append(&invite, 0, "%s", urioptions); 09326 } 09327 09328 /* If custom URI options have been provided, append them */ 09329 if (p->options && !ast_strlen_zero(p->options->uri_options)) 09330 ast_str_append(&invite, 0, ";%s", p->options->uri_options); 09331 09332 /* This is the request URI, which is the next hop of the call 09333 which may or may not be the destination of the call 09334 */ 09335 ast_string_field_set(p, uri, invite->str); 09336 09337 if (!ast_strlen_zero(p->todnid)) { 09338 /*! \todo Need to add back the VXML URL here at some point, possibly use build_string for all this junk */ 09339 if (!strchr(p->todnid, '@')) { 09340 /* We have no domain in the dnid */ 09341 snprintf(to, sizeof(to), "<sip:%s@%s>%s%s", p->todnid, p->tohost, ast_strlen_zero(p->theirtag) ? "" : ";tag=", p->theirtag); 09342 } else { 09343 snprintf(to, sizeof(to), "<sip:%s>%s%s", p->todnid, ast_strlen_zero(p->theirtag) ? "" : ";tag=", p->theirtag); 09344 } 09345 } else { 09346 if (sipmethod == SIP_NOTIFY && !ast_strlen_zero(p->theirtag)) { 09347 /* If this is a NOTIFY, use the From: tag in the subscribe (RFC 3265) */ 09348 snprintf(to, sizeof(to), "<%s%s>;tag=%s", (!strncasecmp(p->uri, "sip:", 4) ? "sip:" : ""), p->uri, p->theirtag); 09349 } else if (p->options && p->options->vxml_url) { 09350 /* If there is a VXML URL append it to the SIP URL */ 09351 snprintf(to, sizeof(to), "<%s>;%s", p->uri, p->options->vxml_url); 09352 } else 09353 snprintf(to, sizeof(to), "<%s>", p->uri); 09354 } 09355 09356 init_req(req, sipmethod, p->uri); 09357 /* now tmp_n is available so reuse it to build the CSeq */ 09358 snprintf(tmp_n, sizeof(tmp_n), "%d %s", ++p->ocseq, sip_methods[sipmethod].text); 09359 09360 add_header(req, "Via", p->via); 09361 add_header(req, "Max-Forwards", DEFAULT_MAX_FORWARDS); 09362 /* SLD: FIXME?: do Route: here too? I think not cos this is the first request. 09363 * OTOH, then we won't have anything in p->route anyway */ 09364 09365 /* Build Remote Party-ID and From */ 09366 if (ast_test_flag(&p->flags[0], SIP_SENDRPID) && (sipmethod == SIP_INVITE)) { 09367 build_rpid(p); 09368 add_header(req, "From", p->rpid_from); 09369 } else 09370 add_header(req, "From", from); 09371 add_header(req, "To", to); 09372 ast_string_field_set(p, exten, l); 09373 build_contact(p); 09374 add_header(req, "Contact", p->our_contact); 09375 add_header(req, "Call-ID", p->callid); 09376 add_header(req, "CSeq", tmp_n); 09377 if (!ast_strlen_zero(global_useragent)) 09378 add_header(req, "User-Agent", global_useragent); 09379 if (!ast_strlen_zero(p->rpid)) 09380 add_header(req, "Remote-Party-ID", p->rpid); 09381 }
| static const char * insecure2str | ( | int | mode | ) | const [static] |
Convert Insecure setting to printable string.
Definition at line 13201 of file chan_sip.c.
References insecurestr, and map_x_s().
Referenced by _sip_show_peer().
13202 { 13203 return map_x_s(insecurestr, mode, "<error>"); 13204 }
| static void list_route | ( | struct sip_route * | route | ) | [static] |
List all routes - mostly for debugging.
Definition at line 10769 of file chan_sip.c.
References ast_verbose, sip_route::hop, and sip_route::next.
Referenced by build_route().
10770 { 10771 if (!route) 10772 ast_verbose("list_route: no route\n"); 10773 else { 10774 for (;route; route = route->next) 10775 ast_verbose("list_route: hop: <%s>\n", route->hop); 10776 } 10777 }
| static int load_module | ( | void | ) | [static] |
PBX load module - initialization.
Definition at line 23386 of file chan_sip.c.
References ao2_t_container_alloc, ast_channel_register(), ast_check_realtime(), ast_cli_register_multiple(), ast_custom_function_register, ast_log(), ast_manager_register2(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, ast_realtime_require_field(), ast_register_application, ast_rtp_proto_register(), ast_udptl_proto_register(), ast_verbose, ASTOBJ_CONTAINER_INIT, CHANNEL_MODULE_LOAD, checksipdomain_function, cli_sip, dialog_cmp_cb(), dialog_hash_cb(), dialogs, EVENT_FLAG_REPORTING, EVENT_FLAG_SYSTEM, hash_dialog_size, hash_peer_size, io, 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(), mandescr_show_peer, mandescr_show_peers, mandescr_show_registry, mandescr_sipnotify, peer_cmp_cb(), peer_hash_cb(), peer_ipcmp_cb(), peer_iphash_cb(), peers_by_ip, regl, reload_config(), restart_monitor(), RQ_CHAR, RQ_INTEGER4, RQ_UINTEGER2, sched, sched_context_create(), sched_context_destroy(), ast_channel_tech::send_digit_begin, SENTINEL, sip_addheader(), sip_dtmfmode(), sip_header_function, sip_poke_all_peers(), sip_rtp, sip_send_all_registers(), sip_tech, sip_tech_info, sip_udptl, sipchaninfo_function, and sippeer_function.
23387 { 23388 ast_verbose("SIP channel loading...\n"); 23389 /* the fact that ao2_containers can't resize automatically is a major worry! */ 23390 /* if the number of objects gets above MAX_XXX_BUCKETS, things will slow down */ 23391 peers = ao2_t_container_alloc(hash_peer_size, peer_hash_cb, peer_cmp_cb, "allocate peers"); 23392 peers_by_ip = ao2_t_container_alloc(hash_peer_size, peer_iphash_cb, peer_ipcmp_cb, "allocate peers_by_ip"); 23393 dialogs = ao2_t_container_alloc(hash_dialog_size, dialog_hash_cb, dialog_cmp_cb, "allocate dialogs"); 23394 23395 ASTOBJ_CONTAINER_INIT(®l); /* Registry object list -- not searched for anything */ 23396 23397 if (!(sched = sched_context_create())) { 23398 ast_log(LOG_ERROR, "Unable to create scheduler context\n"); 23399 return AST_MODULE_LOAD_FAILURE; 23400 } 23401 23402 if (!(io = io_context_create())) { 23403 ast_log(LOG_ERROR, "Unable to create I/O context\n"); 23404 sched_context_destroy(sched); 23405 return AST_MODULE_LOAD_FAILURE; 23406 } 23407 23408 sip_reloadreason = CHANNEL_MODULE_LOAD; 23409 23410 if(reload_config(sip_reloadreason)) /* Load the configuration from sip.conf */ 23411 return AST_MODULE_LOAD_DECLINE; 23412 23413 /* Prepare the version that does not require DTMF BEGIN frames. 23414 * We need to use tricks such as memcpy and casts because the variable 23415 * has const fields. 23416 */ 23417 memcpy(&sip_tech_info, &sip_tech, sizeof(sip_tech)); 23418 memset((void *) &sip_tech_info.send_digit_begin, 0, sizeof(sip_tech_info.send_digit_begin)); 23419 23420 /* Make sure we can register our sip channel type */ 23421 if (ast_channel_register(&sip_tech)) { 23422 ast_log(LOG_ERROR, "Unable to register channel type 'SIP'\n"); 23423 io_context_destroy(io); 23424 sched_context_destroy(sched); 23425 return AST_MODULE_LOAD_FAILURE; 23426 } 23427 23428 /* Register all CLI functions for SIP */ 23429 ast_cli_register_multiple(cli_sip, sizeof(cli_sip)/ sizeof(struct ast_cli_entry)); 23430 23431 /* Tell the RTP subdriver that we're here */ 23432 ast_rtp_proto_register(&sip_rtp); 23433 23434 /* Tell the UDPTL subdriver that we're here */ 23435 ast_udptl_proto_register(&sip_udptl); 23436 23437 /* Register dialplan applications */ 23438 ast_register_application(app_dtmfmode, sip_dtmfmode, synopsis_dtmfmode, descrip_dtmfmode); 23439 ast_register_application(app_sipaddheader, sip_addheader, synopsis_sipaddheader, descrip_sipaddheader); 23440 23441 /* Register dialplan functions */ 23442 ast_custom_function_register(&sip_header_function); 23443 ast_custom_function_register(&sippeer_function); 23444 ast_custom_function_register(&sipchaninfo_function); 23445 ast_custom_function_register(&checksipdomain_function); 23446 23447 /* Register manager commands */ 23448 ast_manager_register2("SIPpeers", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_sip_show_peers, 23449 "List SIP peers (text format)", mandescr_show_peers); 23450 ast_manager_register2("SIPshowpeer", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_sip_show_peer, 23451 "Show SIP peer (text format)", mandescr_show_peer); 23452 ast_manager_register2("SIPqualifypeer", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_sip_qualify_peer, 23453 "Show SIP peer (text format)", mandescr_show_peer); /*! \todo Fix this XXX This must be all wrong XXXX */ 23454 ast_manager_register2("SIPshowregistry", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_show_registry, 23455 "Show SIP registrations (text format)", mandescr_show_registry); 23456 ast_manager_register2("SIPnotify", EVENT_FLAG_SYSTEM, manager_sipnotify, 23457 "Send a SIP notify", mandescr_sipnotify); 23458 sip_poke_all_peers(); 23459 sip_send_all_registers(); 23460 23461 /* And start the monitor for the first time */ 23462 restart_monitor(); 23463 23464 ast_realtime_require_field(ast_check_realtime("sipregs") ? "sipregs" : "sippeers", 23465 "name", RQ_CHAR, 10, 23466 "ipaddr", RQ_CHAR, 15, 23467 "port", RQ_UINTEGER2, 5, 23468 "regseconds", RQ_INTEGER4, 11, 23469 "defaultuser", RQ_CHAR, 10, 23470 "fullcontact", RQ_CHAR, 35, 23471 "regserver", RQ_CHAR, 20, 23472 "useragent", RQ_CHAR, 20, 23473 "lastms", RQ_INTEGER4, 11, 23474 SENTINEL); 23475 23476 return AST_MODULE_LOAD_SUCCESS; 23477 }
| static int local_attended_transfer | ( | struct sip_pvt * | transferer, | |
| struct sip_dual * | current, | |||
| struct sip_request * | req, | |||
| int | seqno | |||
| ) | [static] |
Find all call legs and bridge transferee with target called from handle_request_refer.
Definition at line 18451 of file chan_sip.c.
References ast_channel::_state, ao2_t_ref, append_history, ast_bridged_channel(), ast_channel_unlock, ast_clear_flag, ast_debug, ast_set_flag, ast_state2str(), AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, attempt_transfer(), sip_pvt::callid, sip_dual::chan1, sip_dual::chan2, EVENT_FLAG_CALL, sip_pvt::flags, get_sip_pvt_byid_locked(), sip_refer::localtransfer, manager_event, ast_channel::name, sip_pvt::owner, sip_pvt::refer, REFER_200OK, REFER_FAILED, sip_refer::replaces_callid, sip_refer::replaces_callid_fromtag, sip_refer::replaces_callid_totag, SIP_DEFER_BYE_ON_TRANSFER, SIP_GOTREFER, sip_pvt_unlock, sip_refer::status, transmit_notify_with_sipfrag(), transmit_response(), TRUE, and ast_channel::uniqueid.
Referenced by handle_request_refer().
18452 { 18453 struct sip_dual target; /* Chan 1: Call from tranferer to Asterisk */ 18454 /* Chan 2: Call from Asterisk to target */ 18455 int res = 0; 18456 struct sip_pvt *targetcall_pvt; 18457 18458 /* Check if the call ID of the replaces header does exist locally */ 18459 if (!(targetcall_pvt = get_sip_pvt_byid_locked(transferer->refer->replaces_callid, transferer->refer->replaces_callid_totag, 18460 transferer->refer->replaces_callid_fromtag))) { 18461 if (transferer->refer->localtransfer) { 18462 /* We did not find the refered call. Sorry, can't accept then */ 18463 transmit_response(transferer, "202 Accepted", req); 18464 /* Let's fake a response from someone else in order 18465 to follow the standard */ 18466 transmit_notify_with_sipfrag(transferer, seqno, "481 Call leg/transaction does not exist", TRUE); 18467 append_history(transferer, "Xfer", "Refer failed"); 18468 ast_clear_flag(&transferer->flags[0], SIP_GOTREFER); 18469 transferer->refer->status = REFER_FAILED; 18470 return -1; 18471 } 18472 /* Fall through for remote transfers that we did not find locally */ 18473 ast_debug(3, "SIP attended transfer: Not our call - generating INVITE with replaces\n"); 18474 return 0; 18475 } 18476 18477 /* Ok, we can accept this transfer */ 18478 transmit_response(transferer, "202 Accepted", req); 18479 append_history(transferer, "Xfer", "Refer accepted"); 18480 if (!targetcall_pvt->owner) { /* No active channel */ 18481 ast_debug(4, "SIP attended transfer: Error: No owner of target call\n"); 18482 /* Cancel transfer */ 18483 transmit_notify_with_sipfrag(transferer, seqno, "503 Service Unavailable", TRUE); 18484 append_history(transferer, "Xfer", "Refer failed"); 18485 ast_clear_flag(&transferer->flags[0], SIP_GOTREFER); 18486 transferer->refer->status = REFER_FAILED; 18487 sip_pvt_unlock(targetcall_pvt); 18488 ast_channel_unlock(current->chan1); 18489 if (targetcall_pvt) 18490 ao2_t_ref(targetcall_pvt, -1, "Drop targetcall_pvt pointer"); 18491 return -1; 18492 } 18493 18494 /* We have a channel, find the bridge */ 18495 target.chan1 = targetcall_pvt->owner; /* Transferer to Asterisk */ 18496 target.chan2 = ast_bridged_channel(targetcall_pvt->owner); /* Asterisk to target */ 18497 18498 if (!target.chan2 || !(target.chan2->_state == AST_STATE_UP || target.chan2->_state == AST_STATE_RINGING) ) { 18499 /* Wrong state of new channel */ 18500 if (target.chan2) 18501 ast_debug(4, "SIP attended transfer: Error: Wrong state of target call: %s\n", ast_state2str(target.chan2->_state)); 18502 else if (target.chan1->_state != AST_STATE_RING) 18503 ast_debug(4, "SIP attended transfer: Error: No target channel\n"); 18504 else 18505 ast_debug(4, "SIP attended transfer: Attempting transfer in ringing state\n"); 18506 } 18507 18508 /* Transfer */ 18509 if (sipdebug) { 18510 if (current->chan2) /* We have two bridges */ 18511 ast_debug(4, "SIP attended transfer: trying to bridge %s and %s\n", target.chan1->name, current->chan2->name); 18512 else /* One bridge, propably transfer of IVR/voicemail etc */ 18513 ast_debug(4, "SIP attended transfer: trying to make %s take over (masq) %s\n", target.chan1->name, current->chan1->name); 18514 } 18515 18516 ast_set_flag(&transferer->flags[0], SIP_DEFER_BYE_ON_TRANSFER); /* Delay hangup */ 18517 18518 /* Perform the transfer */ 18519 manager_event(EVENT_FLAG_CALL, "Transfer", "TransferMethod: SIP\r\nTransferType: Attended\r\nChannel: %s\r\nUniqueid: %s\r\nSIP-Callid: %s\r\nTargetChannel: %s\r\nTargetUniqueid: %s\r\n", 18520 transferer->owner->name, 18521 transferer->owner->uniqueid, 18522 transferer->callid, 18523 target.chan1->name, 18524 target.chan1->uniqueid); 18525 res = attempt_transfer(current, &target); 18526 sip_pvt_unlock(targetcall_pvt); 18527 if (res) { 18528 /* Failed transfer */ 18529 transmit_notify_with_sipfrag(transferer, seqno, "486 Busy Here", TRUE); 18530 append_history(transferer, "Xfer", "Refer failed"); 18531 if (targetcall_pvt->owner) 18532 ast_channel_unlock(targetcall_pvt->owner); 18533 ast_clear_flag(&transferer->flags[0], SIP_DEFER_BYE_ON_TRANSFER); 18534 } else { 18535 /* Transfer succeeded! */ 18536 18537 /* Tell transferer that we're done. */ 18538 transmit_notify_with_sipfrag(transferer, seqno, "200 OK", TRUE); 18539 append_history(transferer, "Xfer", "Refer succeeded"); 18540 transferer->refer->status = REFER_200OK; 18541 if (targetcall_pvt->owner) { 18542 ast_debug(1, "SIP attended transfer: Unlocking channel %s\n", targetcall_pvt->owner->name); 18543 ast_channel_unlock(targetcall_pvt->owner); 18544 } 18545 } 18546 if (targetcall_pvt) 18547 ao2_t_ref(targetcall_pvt, -1, "drop targetcall_pvt"); 18548 return 1; 18549 }
| 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 6609 of file chan_sip.c.
Referenced by handle_request_do().
06610 { 06611 int h = 0, t = 0; 06612 int lws = 0; 06613 06614 for (; h < len;) { 06615 /* Eliminate all CRs */ 06616 if (msgbuf[h] == '\r') { 06617 h++; 06618 continue; 06619 } 06620 /* Check for end-of-line */ 06621 if (msgbuf[h] == '\n') { 06622 /* Check for end-of-message */ 06623 if (h + 1 == len) 06624 break; 06625 /* Check for a continuation line */ 06626 if (msgbuf[h + 1] == ' ' || msgbuf[h + 1] == '\t') { 06627 /* Merge continuation line */ 06628 h++; 06629 continue; 06630 } 06631 /* Propagate LF and start new line */ 06632 msgbuf[t++] = msgbuf[h++]; 06633 lws = 0; 06634 continue; 06635 } 06636 if (msgbuf[h] == ' ' || msgbuf[h] == '\t') { 06637 if (lws) { 06638 h++; 06639 continue; 06640 } 06641 msgbuf[t++] = msgbuf[h++]; 06642 lws = 1; 06643 continue; 06644 } 06645 msgbuf[t++] = msgbuf[h++]; 06646 if (lws) 06647 lws = 0; 06648 } 06649 msgbuf[t] = '\0'; 06650 return t; 06651 }
| static void make_our_tag | ( | char * | tagbuf, | |
| size_t | len | |||
| ) | [static] |
Make our SIP dialog tag.
Definition at line 6184 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().
06185 { 06186 snprintf(tagbuf, len, "as%08lx", ast_random()); 06187 }
| static int manager_show_registry | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Show SIP registrations in the manager API.
Definition at line 12845 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, STANDARD_SIP_PORT, and total.
Referenced by load_module().
12846 { 12847 const char *id = astman_get_header(m, "ActionID"); 12848 char idtext[256] = ""; 12849 int total = 0; 12850 12851 if (!ast_strlen_zero(id)) 12852 snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id); 12853 12854 astman_send_listack(s, m, "Registrations will follow", "start"); 12855 12856 ASTOBJ_CONTAINER_TRAVERSE(®l, 1, do { 12857 ASTOBJ_RDLOCK(iterator); 12858 astman_append(s, 12859 "Event: RegistryEntry\r\n" 12860 "Host: %s\r\n" 12861 "Port: %d\r\n" 12862 "Username: %s\r\n" 12863 "Refresh: %d\r\n" 12864 "State: %s\r\n" 12865 "RegistrationTime: %ld\r\n" 12866 "\r\n", iterator->hostname, iterator->portno ? iterator->portno : STANDARD_SIP_PORT, 12867 iterator->username, iterator->refresh, regstate2str(iterator->regstate), (long) iterator->regtime.tv_sec); 12868 ASTOBJ_UNLOCK(iterator); 12869 total++; 12870 } while(0)); 12871 12872 astman_append(s, 12873 "Event: RegistrationsComplete\r\n" 12874 "EventList: Complete\r\n" 12875 "ListItems: %d\r\n" 12876 "%s" 12877 "\r\n", total, idtext); 12878 12879 return 0; 12880 }
| static int manager_sip_qualify_peer | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Qualify SIP peers in the manager API.
Definition at line 13569 of file chan_sip.c.
References _sip_qualify_peer(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), and s.
Referenced by load_module().
13570 { 13571 const char *a[4]; 13572 const char *peer; 13573 13574 peer = astman_get_header(m, "Peer"); 13575 if (ast_strlen_zero(peer)) { 13576 astman_send_error(s, m, "Peer: <name> missing."); 13577 return 0; 13578 } 13579 a[0] = "sip"; 13580 a[1] = "qualify"; 13581 a[2] = "peer"; 13582 a[3] = peer; 13583 13584 _sip_qualify_peer(1, -1, s, m, 4, a); 13585 astman_append(s, "\r\n\r\n" ); 13586 return 0; 13587 }
| static int manager_sip_show_peer | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Show SIP peers in the manager API.
Definition at line 13510 of file chan_sip.c.
References _sip_show_peer(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), and s.
Referenced by load_module().
13511 { 13512 const char *a[4]; 13513 const char *peer; 13514 13515 peer = astman_get_header(m, "Peer"); 13516 if (ast_strlen_zero(peer)) { 13517 astman_send_error(s, m, "Peer: <name> missing."); 13518 return 0; 13519 } 13520 a[0] = "sip"; 13521 a[1] = "show"; 13522 a[2] = "peer"; 13523 a[3] = peer; 13524 13525 _sip_show_peer(1, -1, s, m, 4, a); 13526 astman_append(s, "\r\n\r\n" ); 13527 return 0; 13528 }
| static int manager_sip_show_peers | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Show SIP peers in the manager API.
Definition at line 12891 of file chan_sip.c.
References _sip_show_peers(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_listack(), s, and total.
Referenced by load_module().
12892 { 12893 const char *id = astman_get_header(m, "ActionID"); 12894 const char *a[] = {"sip", "show", "peers"}; 12895 char idtext[256] = ""; 12896 int total = 0; 12897 12898 if (!ast_strlen_zero(id)) 12899 snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id); 12900 12901 astman_send_listack(s, m, "Peer status list will follow", "start"); 12902 /* List the peers in separate manager events */ 12903 _sip_show_peers(-1, &total, s, m, 3, a); 12904 /* Send final confirmation */ 12905 astman_append(s, 12906 "Event: PeerlistComplete\r\n" 12907 "EventList: Complete\r\n" 12908 "ListItems: %d\r\n" 12909 "%s" 12910 "\r\n", total, idtext); 12911 return 0; 12912 }
| static int manager_sipnotify | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 9786 of file chan_sip.c.
References ao2_t_link, ao2_t_unlink, ast_set_flag, ast_sip_ouraddrfor(), ast_strlen_zero(), ast_variables_destroy(), astman_get_header(), astman_get_variables(), astman_send_ack(), astman_send_error(), build_callid_pvt(), build_via(), create_addr(), dialog_ref(), dialog_unlink_all(), dialog_unref(), dialogs, sip_pvt::flags, sip_pvt::ourip, s, sip_pvt::sa, sip_alloc(), SIP_NOTIFY, SIP_OUTGOING, sip_scheddestroy(), SIP_TRANS_TIMEOUT, transmit_notify_custom(), and TRUE.
Referenced by load_module().
09787 { 09788 const char *channame = astman_get_header(m, "Channel"); 09789 struct ast_variable *vars = astman_get_variables(m); 09790 struct sip_pvt *p; 09791 09792 if (ast_strlen_zero(channame)) { 09793 astman_send_error(s, m, "SIPNotify requires a channel name"); 09794 return 0; 09795 } 09796 09797 if (!strncasecmp(channame, "sip/", 4)) { 09798 channame += 4; 09799 } 09800 09801 if (!(p = sip_alloc(NULL, NULL, 0, SIP_NOTIFY))) { 09802 astman_send_error(s, m, "Unable to build sip pvt data for notify (memory/socket error)"); 09803 return 0; 09804 } 09805 09806 if (create_addr(p, channame, NULL, 0)) { 09807 /* Maybe they're not registered, etc. */ 09808 dialog_unlink_all(p, TRUE, TRUE); 09809 dialog_unref(p, "unref dialog inside for loop" ); 09810 /* sip_destroy(p); */ 09811 astman_send_error(s, m, "Could not create address"); 09812 return 0; 09813 } 09814 09815 /* Notify is outgoing call */ 09816 ast_set_flag(&p->flags[0], SIP_OUTGOING); 09817 09818 /* Recalculate our side, and recalculate Call ID */ 09819 ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip); 09820 build_via(p); 09821 ao2_t_unlink(dialogs, p, "About to change the callid -- remove the old name"); 09822 build_callid_pvt(p); 09823 ao2_t_link(dialogs, p, "Linking in new name"); 09824 dialog_ref(p, "bump the count of p, which transmit_sip_request will decrement."); 09825 sip_scheddestroy(p, SIP_TRANS_TIMEOUT); 09826 09827 if (!transmit_notify_custom(p, vars)) { 09828 astman_send_ack(s, m, "Notify Sent"); 09829 } else { 09830 astman_send_error(s, m, "Unable to send notify"); 09831 } 09832 ast_variables_destroy(vars); 09833 return 0; 09834 }
| 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 2337 of file chan_sip.c.
References _map_x_s::s, table, and _map_x_s::x.
Referenced by str2dtmfmode(), str2stmode(), and str2strefresher().
02338 { 02339 const struct _map_x_s *cur; 02340 02341 for (cur = table; cur->s; cur++) 02342 if (!strcasecmp(cur->s, s)) 02343 return cur->x; 02344 return errorvalue; 02345 }
| 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 2324 of file chan_sip.c.
References _map_x_s::s, table, and _map_x_s::x.
Referenced by dtmfmode2str(), insecure2str(), nat2str(), referstatus2str(), regstate2str(), stmode2str(), and strefresher2str().
02325 { 02326 const struct _map_x_s *cur; 02327 02328 for (cur = table; cur->s; cur++) 02329 if (cur->x == x) 02330 return cur->s; 02331 return errorstring; 02332 }
| 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 2706 of file chan_sip.c.
References sip_request::len, sip_methods, and text.
Referenced by __sip_semi_ack(), and find_sip_method().
02707 { 02708 int len = strlen(sip_methods[id].text); 02709 int l_name = name ? strlen(name) : 0; 02710 /* true if the string is long enough, and ends with whitespace, and matches */ 02711 return (l_name >= len && name[len] < 33 && 02712 !strncasecmp(sip_methods[id].text, name, len)); 02713 }
| static void mwi_event_cb | ( | const struct ast_event * | , | |
| void * | ||||
| ) | [static] |
Receive MWI events that we have subscribed to.
Definition at line 11083 of file chan_sip.c.
References ao2_lock(), ao2_unlock(), and sip_send_mwi_to_peer().
11084 { 11085 struct sip_peer *peer = userdata; 11086 11087 ao2_lock(peer); 11088 sip_send_mwi_to_peer(peer, event, 0); 11089 ao2_unlock(peer); 11090 }
| static const char * nat2str | ( | int | nat | ) | const [static] |
Convert NAT setting to text string.
Definition at line 12629 of file chan_sip.c.
References map_x_s(), and natmodes.
Referenced by _sip_show_peer(), sip_show_channel(), sip_show_settings(), and sip_show_users().
Get default outbound proxy or global proxy.
Definition at line 2681 of file chan_sip.c.
References append_history, ast_debug, global_outboundproxy, sip_proxy::name, and sip_peer::outboundproxy.
Referenced by create_addr(), create_addr_from_peer(), and transmit_register().
02682 { 02683 if (peer && peer->outboundproxy) { 02684 if (sipdebug) 02685 ast_debug(1, "OBPROXY: Applying peer OBproxy to this call\n"); 02686 append_history(dialog, "OBproxy", "Using peer obproxy %s", peer->outboundproxy->name); 02687 return peer->outboundproxy; 02688 } 02689 if (global_outboundproxy.name[0]) { 02690 if (sipdebug) 02691 ast_debug(1, "OBPROXY: Applying global OBproxy to this call\n"); 02692 append_history(dialog, "OBproxy", "Using global obproxy %s", global_outboundproxy.name); 02693 return &global_outboundproxy; 02694 } 02695 if (sipdebug) 02696 ast_debug(1, "OBPROXY: Not applying OBproxy to this call\n"); 02697 return NULL; 02698 }
| static void parse_copy | ( | struct sip_request * | dst, | |
| const struct sip_request * | src | |||
| ) | [static] |
Copy SIP request, parse it.
Definition at line 3413 of file chan_sip.c.
References copy_request(), and parse_request().
Referenced by send_request(), and send_response().
03414 { 03415 copy_request(dst, src); 03416 parse_request(dst); 03417 }
| int parse_minse | ( | const char * | p_hdrval, | |
| int *const | p_interval | |||
| ) | [static] |
Session-Timers: Function for parsing Min-SE header.
Definition at line 20571 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().
20572 { 20573 if (ast_strlen_zero(p_hdrval)) { 20574 ast_log(LOG_WARNING, "Null Min-SE header\n"); 20575 return -1; 20576 } 20577 20578 *p_interval = 0; 20579 p_hdrval = ast_skip_blanks(p_hdrval); 20580 if (!sscanf(p_hdrval, "%d", p_interval)) { 20581 ast_log(LOG_WARNING, "Parsing of Min-SE header failed %s\n", p_hdrval); 20582 return -1; 20583 } 20584 20585 ast_debug(2, "Received Min-SE: %d\n", *p_interval); 20586 return 0; 20587 }
| static void parse_moved_contact | ( | struct sip_pvt * | p, | |
| struct sip_request * | req | |||
| ) | [static] |
Parse 302 Moved temporalily response.
Definition at line 15723 of file chan_sip.c.
References ao2_ref, ast_copy_string(), ast_debug, ast_string_field_build, ast_string_field_set, ast_test_flag, sip_socket::fd, sip_pvt::flags, get_header(), get_in_brackets(), get_transport(), sip_pvt::owner, pbx_builtin_setvar_helper(), remove_uri_parameters(), s, SIP_PROMISCREDIR, SIP_TRANSPORT_TCP, SIP_TRANSPORT_TLS, SIP_TRANSPORT_UDP, SIPBUFSIZE, sip_pvt::socket, strcasestr(), sip_socket::tcptls_session, and sip_socket::type.
Referenced by handle_response().
15724 { 15725 char tmp[SIPBUFSIZE]; 15726 char *s, *e, *t, *trans; 15727 char *domain; 15728 enum sip_transport transport = SIP_TRANSPORT_UDP; 15729 15730 ast_copy_string(tmp, get_header(req, "Contact"), sizeof(tmp)); 15731 if ((t = strchr(tmp, ','))) 15732 *t = '\0'; 15733 15734 s = get_in_brackets(tmp); 15735 if ((trans = strcasestr(s, ";transport="))) do { 15736 trans += 11; 15737 15738 if ((e = strchr(trans, ';'))) 15739 *e = '\0'; 15740 15741 if (!strncasecmp(trans, "tcp", 3)) 15742 transport = SIP_TRANSPORT_TCP; 15743 else if (!strncasecmp(trans, "tls", 3)) 15744 transport = SIP_TRANSPORT_TLS; 15745 else { 15746 if (strncasecmp(trans, "udp", 3)) 15747 ast_debug(1, "received contact with an invalid transport, '%s'\n", s); 15748 transport = SIP_TRANSPORT_UDP; 15749 } 15750 } while(0); 15751 s = remove_uri_parameters(s); 15752 15753 if (p->socket.tcptls_session) { 15754 ao2_ref(p->socket.tcptls_session, -1); 15755 p->socket.tcptls_session = NULL; 15756 } 15757 15758 p->socket.fd = -1; 15759 p->socket.type = transport; 15760 15761 if (ast_test_flag(&p->flags[0], SIP_PROMISCREDIR)) { 15762 char *host = NULL; 15763 if (!strncasecmp(s, "sip:", 4)) 15764 s += 4; 15765 else if (!strncasecmp(s, "sips:", 5)) 15766 s += 5; 15767 e = strchr(s, '/'); 15768 if (e) 15769 *e = '\0'; 15770 if ((host = strchr(s, '@'))) { 15771 *host++ = '\0'; 15772 ast_debug(2, "Found promiscuous redirection to 'SIP/%s::::%s@%s'\n", s, get_transport(transport), host); 15773 if (p->owner) 15774 ast_string_field_build(p->owner, call_forward, "SIP/%s::::%s@%s", s, get_transport(transport), host); 15775 } else { 15776 ast_debug(2, "Found promiscuous redirection to 'SIP/::::%s@%s'\n", get_transport(transport), s); 15777 if (p->owner) 15778 ast_string_field_build(p->owner, call_forward, "SIP/::::%s@%s", get_transport(transport), s); 15779 } 15780 } else { 15781 e = strchr(tmp, '@'); 15782 if (e) { 15783 *e++ = '\0'; 15784 domain = e; 15785 } else { 15786 /* No username part */ 15787 domain = tmp; 15788 } 15789 e = strchr(tmp, '/'); /* WHEN do we hae a forward slash in the URI? */ 15790 if (e) 15791 *e = '\0'; 15792 15793 if (!strncasecmp(s, "sip:", 4)) 15794 s += 4; 15795 else if (!strncasecmp(s, "sips:", 5)) 15796 s += 5; 15797 e = strchr(s, ';'); /* And username ; parameters? */ 15798 if (e) 15799 *e = '\0'; 15800 ast_debug(2, "Received 302 Redirect to extension '%s' (domain %s)\n", s, domain); 15801 if (p->owner) { 15802 pbx_builtin_setvar_helper(p->owner, "SIPDOMAIN", domain); 15803 ast_string_field_set(p->owner, call_forward, s); 15804 } 15805 } 15806 }
| 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 10504 of file chan_sip.c.
References ast_copy_string(), ast_string_field_set, get_header(), get_in_brackets(), SIPBUFSIZE, and TRUE.
Referenced by handle_request_invite(), handle_request_subscribe(), and handle_response_invite().
10505 { 10506 char contact[SIPBUFSIZE]; 10507 char *c; 10508 10509 /* Look for brackets */ 10510 ast_copy_string(contact, get_header(req, "Contact"), sizeof(contact)); 10511 c = get_in_brackets(contact); 10512 10513 /* Save full contact to call pvt for later bye or re-invite */ 10514 ast_string_field_set(pvt, fullcontact, c); 10515 10516 /* Save URI for later ACKs, BYE or RE-invites */ 10517 ast_string_field_set(pvt, okcontacturi, c); 10518 10519 /* We should return false for URI:s we can't handle, 10520 like tel:, mailto:,ldap: etc */ 10521 return TRUE; 10522 }
| 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 10582 of file chan_sip.c.
References sip_peer::addr, ahp, ao2_t_link, ao2_t_unlink, ast_apply_ha(), ast_copy_string(), ast_db_put(), ast_gethostbyname(), ast_inet_ntoa(), ast_log(), ast_sched_add(), AST_SCHED_DEL_UNREF, ast_sched_when(), AST_SENSE_ALLOW, ast_strdupa, ast_string_field_build, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_verb, ast_verbose, sip_peer::contactha, copy_socket_data(), sip_request::data, destroy_association(), EVENT_FLAG_SYSTEM, sip_peer::expire, expire_register(), sip_pvt::expiry, FALSE, sip_peer::flags, sip_peer::fullcontact, get_header(), get_in_brackets(), global_contact_ha, hp, inaddrcmp(), sip_peer::is_realtime, sip_peer::lastms, LOG_NOTICE, LOG_WARNING, manager_event, sip_peer::name, PARSE_REGISTER_FAILED, PARSE_REGISTER_QUERY, PARSE_REGISTER_UPDATE, parse_uri(), peers_by_ip, sip_pvt::recv, ref_peer(), register_peer_exten(), sip_peer::rt_fromcontact, s, sched, SIP_NAT_ROUTE, SIP_PAGE2_RTCACHEFRIENDS, sip_poke_peer(), SIP_TRANSPORT_TLS, SIP_TRANSPORT_UDP, SIPBUFSIZE, sip_pvt::sipoptions, sip_peer::sipoptions, sip_pvt::socket, sip_request::socket, sip_peer::socket, STANDARD_SIP_PORT, STANDARD_TLS_PORT, strcasestr(), strsep(), sip_socket::type, unref_peer(), sip_peer::useragent, sip_peer::username, VERBOSE_PREFIX_3, and VERBOSITY_ATLEAST.
Referenced by register_verify().
10583 { 10584 char contact[SIPBUFSIZE]; 10585 char data[SIPBUFSIZE]; 10586 const char *expires = get_header(req, "Expires"); 10587 int expire = atoi(expires); 10588 char *curi, *host, *pt, *curi2; 10589 int port; 10590 const char *useragent; 10591 struct hostent *hp; 10592 struct ast_hostent ahp; 10593 struct sockaddr_in oldsin, testsin; 10594 10595 ast_copy_string(contact, get_header(req, "Contact"), sizeof(contact)); 10596 10597 if (ast_strlen_zero(expires)) { /* No expires header, try look in Contact: */ 10598 char *s = strcasestr(contact, ";expires="); 10599 if (s) { 10600 expires = strsep(&s, ";"); /* trim ; and beyond */ 10601 if (sscanf(expires + 9, "%d", &expire) != 1) 10602 expire = default_expiry; 10603 } else { 10604 /* Nothing has been specified */ 10605 expire = default_expiry; 10606 } 10607 } 10608 10609 if (peer->socket.type == req->socket.type) 10610 copy_socket_data(&peer->socket, &req->socket); 10611 copy_socket_data(&pvt->socket, &req->socket); 10612 10613 /* Look for brackets */ 10614 curi = contact; 10615 if (strchr(contact, '<') == NULL) /* No <, check for ; and strip it */ 10616 strsep(&curi, ";"); /* This is Header options, not URI options */ 10617 curi = get_in_brackets(contact); 10618 curi2 = ast_strdupa(curi); 10619 10620 /* if they did not specify Contact: or Expires:, they are querying 10621 what we currently have stored as their contact address, so return 10622 it 10623 */ 10624 if (ast_strlen_zero(curi) && ast_strlen_zero(expires)) { 10625 /* If we have an active registration, tell them when the registration is going to expire */ 10626 if (peer->expire > -1 && !ast_strlen_zero(peer->fullcontact)) 10627 pvt->expiry = ast_sched_when(sched, peer->expire); 10628 return PARSE_REGISTER_QUERY; 10629 } else if (!strcasecmp(curi, "*") || !expire) { /* Unregister this peer */ 10630 /* This means remove all registrations and return OK */ 10631 memset(&peer->addr, 0, sizeof(peer->addr)); 10632 10633 AST_SCHED_DEL_UNREF(sched, peer->expire, 10634 unref_peer(peer, "remove register expire ref")); 10635 10636 destroy_association(peer); 10637 10638 register_peer_exten(peer, FALSE); /* Remove extension from regexten= setting in sip.conf */ 10639 peer->fullcontact[0] = '\0'; 10640 peer->useragent[0] = '\0'; 10641 peer->sipoptions = 0; 10642 peer->lastms = 0; 10643 pvt->expiry = 0; 10644 10645 ast_verb(3, "Unregistered SIP '%s'\n", peer->name); 10646 10647 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: SIP\r\nPeer: SIP/%s\r\nPeerStatus: Unregistered\r\n", peer->name); 10648 return PARSE_REGISTER_UPDATE; 10649 } 10650 10651 /* Store whatever we got as a contact from the client */ 10652 ast_copy_string(peer->fullcontact, curi, sizeof(peer->fullcontact)); 10653 10654 /* For the 200 OK, we should use the received contact */ 10655 ast_string_field_build(pvt, our_contact, "<%s>", curi); 10656 10657 /* Make sure it's a SIP URL */ 10658 if (pvt->socket.type == SIP_TRANSPORT_TLS) { 10659 if (parse_uri(curi, "sips:", &curi, NULL, &host, &pt, NULL)) { 10660 if (parse_uri(curi2, "sip:", &curi, NULL, &host, &pt, NULL)) 10661 ast_log(LOG_NOTICE, "Not a valid SIP contact (missing sip:) trying to use anyway\n"); 10662 } 10663 port = !ast_strlen_zero(pt) ? atoi(pt) : STANDARD_TLS_PORT; 10664 } else { 10665 if (parse_uri(curi, "sip:", &curi, NULL, &host, &pt, NULL)) 10666 ast_log(LOG_NOTICE, "Not a valid SIP contact (missing sip:) trying to use anyway\n"); 10667 port = !ast_strlen_zero(pt) ? atoi(pt) : STANDARD_SIP_PORT; 10668 } 10669 10670 oldsin = peer->addr; 10671 10672 /* If we were already linked into the peers_by_ip container unlink ourselves so nobody can find us */ 10673 if (peer->addr.sin_addr.s_addr) { 10674 ao2_t_unlink(peers_by_ip, peer, "ao2_unlink of peer from peers_by_ip table"); 10675 } 10676 10677 /* Check that they're allowed to register at this IP */ 10678 /* XXX This could block for a long time XXX */ 10679 hp = ast_gethostbyname(host, &ahp); 10680 if (!hp) { 10681 ast_log(LOG_WARNING, "Invalid host '%s'\n", host); 10682 *peer->fullcontact = '\0'; 10683 ast_string_field_set(pvt, our_contact, ""); 10684 return PARSE_REGISTER_FAILED; 10685 } 10686 memcpy(&testsin.sin_addr, hp->h_addr, sizeof(testsin.sin_addr)); 10687 if ( ast_apply_ha(global_contact_ha, &testsin) != AST_SENSE_ALLOW || 10688 ast_apply_ha(peer->contactha, &testsin) != AST_SENSE_ALLOW) { 10689 ast_log(LOG_WARNING, "Host '%s' disallowed by rule\n", host); 10690 *peer->fullcontact = '\0'; 10691 ast_string_field_set(pvt, our_contact, ""); 10692 return PARSE_REGISTER_FAILED; 10693 } 10694 10695 if (!ast_test_flag(&peer->flags[0], SIP_NAT_ROUTE)) { 10696 peer->addr.sin_family = AF_INET; 10697 memcpy(&peer->addr.sin_addr, hp->h_addr, sizeof(peer->addr.sin_addr)); 10698 peer->addr.sin_port = htons(port); 10699 } else { 10700 /* Don't trust the contact field. Just use what they came to us 10701 with */ 10702 peer->addr = pvt->recv; 10703 } 10704 10705 /* Now that our address has been updated put ourselves back into the container for lookups */ 10706 ao2_t_link(peers_by_ip, peer, "ao2_link into peers_by_ip table"); 10707 10708 /* Save SIP options profile */ 10709 peer->sipoptions = pvt->sipoptions; 10710 10711 if (!ast_strlen_zero(curi) && ast_strlen_zero(peer->username)) 10712 ast_copy_string(peer->username, curi, sizeof(peer->username)); 10713 10714 AST_SCHED_DEL_UNREF(sched, peer->expire, 10715 unref_peer(peer, "remove register expire ref")); 10716 10717 if (expire > max_expiry) 10718 expire = max_expiry; 10719 if (expire < min_expiry) 10720 expire = min_expiry; 10721 if (peer->is_realtime && !ast_test_flag(&peer->flags[1], SIP_PAGE2_RTCACHEFRIENDS)) { 10722 peer->expire = -1; 10723 } else { 10724 peer->expire = ast_sched_add(sched, (expire + 10) * 1000, expire_register, 10725 ref_peer(peer, "add registration ref")); 10726 if (peer->expire == -1) { 10727 unref_peer(peer, "remote registration ref"); 10728 } 10729 } 10730 pvt->expiry = expire; 10731 snprintf(data, sizeof(data), "%s:%d:%d:%s:%s", ast_inet_ntoa(peer->addr.sin_addr), ntohs(peer->addr.sin_port), expire, peer->username, peer->fullcontact); 10732 /* Saving TCP connections is useless, we won't be able to reconnect 10733 XXX WHY???? XXX 10734 \todo check this 10735 */ 10736 if (!peer->rt_fromcontact && (peer->socket.type & SIP_TRANSPORT_UDP)) 10737 ast_db_put("SIP/Registry", peer->name, data); 10738 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: SIP\r\nPeer: SIP/%s\r\nPeerStatus: Registered\r\nAddress: %s\r\nPort: %d\r\n", peer->name, ast_inet_ntoa(peer->addr.sin_addr), ntohs(peer->addr.sin_port)); 10739 10740 /* Is this a new IP address for us? */ 10741 if (VERBOSITY_ATLEAST(2) && inaddrcmp(&peer->addr, &oldsin)) { 10742 ast_verbose(VERBOSE_PREFIX_3 "Registered SIP '%s' at %s port %d\n", peer->name, ast_inet_ntoa(peer->addr.sin_addr), ntohs(peer->addr.sin_port)); 10743 } 10744 sip_poke_peer(peer, 0); 10745 register_peer_exten(peer, 1); 10746 10747 /* Save User agent */ 10748 useragent = get_header(req, "User-Agent"); 10749 if (strcasecmp(useragent, peer->useragent)) { /* XXX copy if they are different ? */ 10750 ast_copy_string(peer->useragent, useragent, sizeof(peer->useragent)); 10751 ast_verb(4, "Saved useragent \"%s\" for peer %s\n", peer->useragent, peer->name); 10752 } 10753 return PARSE_REGISTER_UPDATE; 10754 }
| static int parse_request | ( | struct sip_request * | req | ) | [static] |
Parse a SIP message.
Definition at line 6656 of file chan_sip.c.
References ast_debug, ast_strlen_zero(), sip_request::data, sip_request::header, sip_request::headers, sip_request::line, SIP_MAX_HEADERS, SIP_MAX_LINES, and ast_str::str.
Referenced by _sip_tcp_helper_thread(), handle_request_do(), initialize_initreq(), and parse_copy().
06657 { 06658 char *c = req->data->str; 06659 ptrdiff_t *dst = req->header; 06660 int i = 0, lim = SIP_MAX_HEADERS - 1; 06661 unsigned int skipping_headers = 0; 06662 ptrdiff_t current_header_offset = 0; 06663 char *previous_header = ""; 06664 06665 req->header[0] = 0; 06666 req->headers = -1; /* mark that we are working on the header */ 06667 for (; *c; c++) { 06668 if (*c == '\r') { /* remove \r */ 06669 *c = '\0'; 06670 } else if (*c == '\n') { /* end of this line */ 06671 *c = '\0'; 06672 current_header_offset = (c + 1) - req->data->str; 06673 previous_header = req->data->str + dst[i]; 06674 if (skipping_headers) { 06675 /* check to see if this line is blank; if so, turn off 06676 the skipping flag, so the next line will be processed 06677 as a body line */ 06678 if (ast_strlen_zero(previous_header)) { 06679 skipping_headers = 0; 06680 } 06681 dst[i] = current_header_offset; /* record start of next line */ 06682 continue; 06683 } 06684 if (sipdebug) { 06685 ast_debug(4, "%7s %2d [%3d]: %s\n", 06686 req->headers < 0 ? "Header" : "Body", 06687 i, (int) strlen(previous_header), previous_header); 06688 } 06689 if (ast_strlen_zero(previous_header) && req->headers < 0) { 06690 req->headers = i; /* record number of header lines */ 06691 dst = req->line; /* start working on the body */ 06692 i = 0; 06693 lim = SIP_MAX_LINES - 1; 06694 } else { /* move to next line, check for overflows */ 06695 if (i++ == lim) { 06696 /* if we're processing headers, then skip any remaining 06697 headers and move on to processing the body, otherwise 06698 we're done */ 06699 if (req->headers != -1) { 06700 break; 06701 } else { 06702 req->headers = i; 06703 dst = req->line; 06704 i = 0; 06705 lim = SIP_MAX_LINES - 1; 06706 skipping_headers = 1; 06707 } 06708 } 06709 } 06710 dst[i] = current_header_offset; /* record start of next line */ 06711 } 06712 } 06713 06714 /* Check for last header or body line without CRLF. The RFC for SDP requires CRLF, 06715 but since some devices send without, we'll be generous in what we accept. However, 06716 if we've already reached the maximum number of lines for portion of the message 06717 we were parsing, we can't accept any more, so just ignore it. 06718 */ 06719 previous_header = req->data->str + dst[i]; 06720 if ((i < lim) && !ast_strlen_zero(previous_header)) { 06721 if (sipdebug) { 06722 ast_debug(4, "%7s %2d [%3d]: %s\n", 06723 req->headers < 0 ? "Header" : "Body", 06724 i, (int) strlen(previous_header), previous_header ); 06725 } 06726 i++; 06727 } 06728 06729 /* update count of header or body lines */ 06730 if (req->headers >= 0) { /* we are in the body */ 06731 req->lines = i; 06732 } else { /* no body */ 06733 req->headers = i; 06734 req->lines = 0; 06735 /* req->data->used will be a NULL byte */ 06736 req->line[0] = req->data->used; 06737 } 06738 06739 if (*c) { 06740 ast_log(LOG_WARNING, "Too many lines, skipping <%s>\n", c); 06741 } 06742 06743 /* Split up the first line parts */ 06744 return determine_firstline_parts(req); 06745 }
| 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 20591 of file chan_sip.c.
References ast_debug, ast_log(), ast_skip_blanks(), ast_strdupa, ast_strlen_zero(), LOG_WARNING, SESSION_TIMER_REFRESHER_AUTO, SESSION_TIMER_REFRESHER_UAC, SESSION_TIMER_REFRESHER_UAS, and strsep().
Referenced by handle_request_invite(), and handle_response_invite().
20592 { 20593 char *p_token; 20594 int ref_idx; 20595 char *p_se_hdr; 20596 20597 if (ast_strlen_zero(p_hdrval)) { 20598 ast_log(LOG_WARNING, "Null Session-Expires header\n"); 20599 return -1; 20600 } 20601 20602 *p_ref = SESSION_TIMER_REFRESHER_AUTO; 20603 *p_interval = 0; 20604 20605 p_se_hdr = ast_strdupa(p_hdrval); 20606 p_se_hdr = ast_skip_blanks(p_se_hdr); 20607 20608 while ((p_token = strsep(&p_se_hdr, ";"))) { 20609 p_token = ast_skip_blanks(p_token); 20610 if (!sscanf(p_token, "%d", p_interval)) { 20611 ast_log(LOG_WARNING, "Parsing of Session-Expires failed\n"); 20612 return -1; 20613 } 20614 20615 ast_debug(2, "Session-Expires: %d\n", *p_interval); 20616 20617 if (!p_se_hdr) 20618 continue; 20619 20620 ref_idx = strlen("refresher="); 20621 if (!strncasecmp(p_se_hdr, "refresher=", ref_idx)) { 20622 p_se_hdr += ref_idx; 20623 p_se_hdr = ast_skip_blanks(p_se_hdr); 20624 20625 if (!strncasecmp(p_se_hdr, "uac", strlen("uac"))) { 20626 *p_ref = SESSION_TIMER_REFRESHER_UAC; 20627 ast_debug(2, "Refresher: UAC\n"); 20628 } else if (!strncasecmp(p_se_hdr, "uas", strlen("uas"))) { 20629 *p_ref = SESSION_TIMER_REFRESHER_UAS; 20630 ast_debug(2, "Refresher: UAS\n"); 20631 } else { 20632 ast_log(LOG_WARNING, "Invalid refresher value %s\n", p_se_hdr); 20633 return -1; 20634 } 20635 break; 20636 } 20637 } 20638 return 0; 20639 }
| static unsigned int parse_sip_options | ( | struct sip_pvt * | pvt, | |
| const char * | supported | |||
| ) | [static] |
Parse supported header in incoming packet.
Definition at line 2730 of file chan_sip.c.
References ARRAY_LEN, ast_debug, ast_skip_blanks(), ast_strdupa, ast_strlen_zero(), FALSE, cfsip_options::id, sip_request::next, SIP_OPT_UNKNOWN, sip_options, sip_pvt::sipoptions, text, and TRUE.
Referenced by handle_request_invite().
02731 { 02732 char *next, *sep; 02733 char *temp; 02734 unsigned int profile = 0; 02735 int i, found; 02736 02737 if (ast_strlen_zero(supported) ) 02738 return 0; 02739 temp = ast_strdupa(supported); 02740 02741 if (sipdebug) 02742 ast_debug(3, "Begin: parsing SIP \"Supported: %s\"\n", supported); 02743 02744 for (next = temp; next; next = sep) { 02745 found = FALSE; 02746 if ( (sep = strchr(next, ',')) != NULL) 02747 *sep++ = '\0'; 02748 next = ast_skip_blanks(next); 02749 if (sipdebug) 02750 ast_debug(3, "Found SIP option: -%s-\n", next); 02751 for (i = 0; i < ARRAY_LEN(sip_options); i++) { 02752 if (!strcasecmp(next, sip_options[i].text)) { 02753 profile |= sip_options[i].id; 02754 found = TRUE; 02755 if (sipdebug) 02756 ast_debug(3, "Matched SIP option: %s\n", next); 02757 break; 02758 } 02759 } 02760 02761 /* This function is used to parse both Suported: and Require: headers. 02762 Let the caller of this function know that an unknown option tag was 02763 encountered, so that if the UAC requires it then the request can be 02764 rejected with a 420 response. */ 02765 if (!found) 02766 profile |= SIP_OPT_UNKNOWN; 02767 02768 if (!found && sipdebug) { 02769 if (!strncasecmp(next, "x-", 2)) 02770 ast_debug(3, "Found private SIP option, not supported: %s\n", next); 02771 else 02772 ast_debug(3, "Found no match for SIP option: %s (Please file bug report!)\n", next); 02773 } 02774 } 02775 02776 if (pvt) 02777 pvt->sipoptions = profile; 02778 return profile; 02779 }
| static int parse_uri | ( | char * | uri, | |
| char * | scheme, | |||
| char ** | ret_name, | |||
| char ** | pass, | |||
| char ** | domain, | |||
| char ** | port, | |||
| char ** | options | |||
| ) | [static] |
* parses a URI in its components.
* general form we are expecting is sip[s]:username[:password][;parameter]@host[:port][;...] *
Definition at line 3621 of file chan_sip.c.
References ast_debug, name, and strsep().
Referenced by __set_address_from_contact(), check_user_full(), and parse_register_contact().
03623 { 03624 char *name = NULL; 03625 int error = 0; 03626 03627 /* init field as required */ 03628 if (pass) 03629 *pass = ""; 03630 if (port) 03631 *port = ""; 03632 if (scheme) { 03633 int l = strlen(scheme); 03634 if (!strncasecmp(uri, scheme, l)) 03635 uri += l; 03636 else { 03637 ast_debug(1, "Missing scheme '%s' in '%s'\n", scheme, uri); 03638 error = -1; 03639 } 03640 } 03641 if (!domain) { 03642 /* if we don't want to split around domain, keep everything as a name, 03643 * so we need to do nothing here, except remember why. 03644 */ 03645 } else { 03646 /* store the result in a temp. variable to avoid it being 03647 * overwritten if arguments point to the same place. 03648 */ 03649 char *c, *dom = ""; 03650 03651 if ((c = strchr(uri, '@')) == NULL) { 03652 /* domain-only URI, according to the SIP RFC. */ 03653 dom = uri; 03654 name = ""; 03655 } else { 03656 *c++ = '\0'; 03657 dom = c; 03658 name = uri; 03659 } 03660 03661 /* Remove options in domain and name */ 03662 dom = strsep(&dom, ";"); 03663 name = strsep(&name, ";"); 03664 03665 if (port && (c = strchr(dom, ':'))) { /* Remove :port */ 03666 *c++ = '\0'; 03667 *port = c; 03668 } 03669 if (pass && (c = strchr(name, ':'))) { /* user:password */ 03670 *c++ = '\0'; 03671 *pass = c; 03672 } 03673 *domain = dom; 03674 } 03675 if (ret_name) /* same as for domain, store the result only at the end */ 03676 *ret_name = name; 03677 if (options) 03678 *options = uri ? uri : ""; 03679 03680 return error; 03681 }
| static int peer_cmp_cb | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 1690 of file chan_sip.c.
References CMP_MATCH, CMP_STOP, and sip_peer::name.
01691 { 01692 struct sip_peer *peer = obj, *peer2 = arg; 01693 01694 return !strcasecmp(peer->name, peer2->name) ? CMP_MATCH | CMP_STOP : 0; 01695 }
| static int peer_dump_func | ( | void * | userobj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 13114 of file chan_sip.c.
References ao2_t_ref, ast_cli(), and sip_peer::name.
Referenced by sip_show_objects().
13115 { 13116 struct sip_peer *peer = userobj; 13117 int refc = ao2_t_ref(userobj, 0, ""); 13118 int *fd = arg; 13119 13120 ast_cli(*fd, "name: %s\ntype: peer\nobjflags: %d\nrefcount: %d\n\n", 13121 peer->name, 0, refc); 13122 return 0; 13123 }
| static int peer_hash_cb | ( | const void * | obj, | |
| const int | flags | |||
| ) | [static] |
Definition at line 1680 of file chan_sip.c.
References ast_str_case_hash(), and sip_peer::name.
01681 { 01682 const struct sip_peer *peer = obj; 01683 01684 return ast_str_case_hash(peer->name); 01685 }
| static int peer_ipcmp_cb | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 1717 of file chan_sip.c.
References sip_peer::addr, ast_test_flag, CMP_MATCH, CMP_STOP, sip_peer::flags, and SIP_INSECURE_PORT.
Referenced by load_module().
01718 { 01719 struct sip_peer *peer = obj, *peer2 = arg; 01720 01721 if (peer->addr.sin_addr.s_addr != peer2->addr.sin_addr.s_addr) { 01722 return 0; 01723 } 01724 01725 if (!ast_test_flag(&peer->flags[0], SIP_INSECURE_PORT) && !ast_test_flag(&peer2->flags[0], SIP_INSECURE_PORT)) { 01726 if (peer->addr.sin_port == peer2->addr.sin_port) { 01727 return CMP_MATCH | CMP_STOP; 01728 } else { 01729 return 0; 01730 } 01731 } 01732 01733 return CMP_MATCH | CMP_STOP; 01734 }
| static int peer_iphash_cb | ( | const void * | obj, | |
| const int | flags | |||
| ) | [static] |
Definition at line 1700 of file chan_sip.c.
References sip_peer::addr, ast_test_flag, sip_peer::flags, and SIP_INSECURE_PORT.
Referenced by load_module().
01701 { 01702 const struct sip_peer *peer = obj; 01703 int ret1 = peer->addr.sin_addr.s_addr; 01704 if (ret1 < 0) 01705 ret1 = -ret1; 01706 01707 if (ast_test_flag(&peer->flags[0], SIP_INSECURE_PORT)) { 01708 return ret1; 01709 } else { 01710 return ret1 + peer->addr.sin_port; 01711 } 01712 }
| static int peer_is_marked | ( | void * | peerobj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 13304 of file chan_sip.c.
References CMP_MATCH, and sip_peer::the_mark.
Referenced by sip_do_reload(), and sip_prune_realtime().
| static void peer_mailboxes_to_str | ( | struct ast_str ** | mailbox_str, | |
| struct sip_peer * | peer | |||
| ) | [static] |
list peer mailboxes to CLI
Definition at line 13607 of file chan_sip.c.
References AST_LIST_NEXT, AST_LIST_TRAVERSE, ast_str_append(), ast_strlen_zero(), sip_mailbox::entry, mailbox, sip_peer::mailboxes, and S_OR.
Referenced by _sip_show_peer(), function_sippeer(), show_channels_cb(), and sip_send_mwi_to_peer().
13608 { 13609 struct sip_mailbox *mailbox; 13610 13611 AST_LIST_TRAVERSE(&peer->mailboxes, mailbox, entry) { 13612 ast_str_append(mailbox_str, 0, "%s%s%s%s", 13613 mailbox->mailbox, 13614 ast_strlen_zero(mailbox->context) ? "" : "@", 13615 S_OR(mailbox->context, ""), 13616 AST_LIST_NEXT(mailbox, entry) ? "," : ""); 13617 } 13618 }
| static int peer_markall_func | ( | void * | device, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 22038 of file chan_sip.c.
References sip_peer::the_mark.
Referenced by reload_config().
| static int peer_status | ( | struct sip_peer * | peer, | |
| char * | status, | |||
| int | statuslen | |||
| ) | [static] |
Definition at line 12696 of file chan_sip.c.
References ast_copy_string(), sip_peer::lastms, and sip_peer::maxms.
12697 { 12698 int res = 0; 12699 if (peer->maxms) { 12700 if (peer->lastms < 0) { 12701 ast_copy_string(status, "UNREACHABLE", statuslen); 12702 } else if (peer->lastms > peer->maxms) { 12703 snprintf(status, statuslen, "LAGGED (%d ms)", peer->lastms); 12704 res = 1; 12705 } else if (peer->lastms) { 12706 snprintf(status, statuslen, "OK (%d ms)", peer->lastms); 12707 res = 1; 12708 } else { 12709 ast_copy_string(status, "UNKNOWN", statuslen); 12710 } 12711 } else { 12712 ast_copy_string(status, "Unmonitored", statuslen); 12713 /* Checking if port is 0 */ 12714 res = -1; 12715 } 12716 return res; 12717 }
| int peercomparefunc | ( | const void * | a, | |
| const void * | b | |||
| ) |
Definition at line 12934 of file chan_sip.c.
Referenced by _sip_show_peers().
12935 { 12936 struct sip_peer **ap = (struct sip_peer **)a; 12937 struct sip_peer **bp = (struct sip_peer **)b; 12938 return strcmp((*ap)->name, (*bp)->name); 12939 }
| 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 13439 of file chan_sip.c.
References ast_cli(), ast_codec_pref_index(), ast_getformatname(), and ast_codec_pref::framing.
Referenced by _sip_show_peer(), handle_skinny_show_line(), sip_show_settings(), and sip_show_user().
13440 { 13441 int x, codec; 13442 13443 for(x = 0; x < 32 ; x++) { 13444 codec = ast_codec_pref_index(pref, x); 13445 if (!codec) 13446 break; 13447 ast_cli(fd, "%s", ast_getformatname(codec)); 13448 ast_cli(fd, ":%d", pref->framing[x]); 13449 if (x < 31 && ast_codec_pref_index(pref, x + 1)) 13450 ast_cli(fd, ","); 13451 } 13452 if (!x) 13453 ast_cli(fd, "none"); 13454 }
| static void print_group | ( | int | fd, | |
| ast_group_t | group, | |||
| int | crlf | |||
| ) | [static] |
Print call group and pickup group.
Definition at line 13164 of file chan_sip.c.
References ast_cli(), ast_print_group(), and buf.
Referenced by _sip_show_peer(), and sip_show_user().
13165 { 13166 char buf[256]; 13167 ast_cli(fd, crlf ? "%s\r\n" : "%s\n", ast_print_group(buf, sizeof(buf), group) ); 13168 }
| 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 20649 of file chan_sip.c.
References ast_log(), ast_strlen_zero(), get_header(), LOG_WARNING, parse_minse(), SIP_INVITE, sip_st_dlg::st_interval, sip_pvt::stimer, and transmit_invite().
Referenced by handle_response_invite().
20650 { 20651 int rtn; 20652 const char *p_hdrval; 20653 int minse; 20654 20655 p_hdrval = get_header(rsp, "Min-SE"); 20656 if (ast_strlen_zero(p_hdrval)) { 20657 ast_log(LOG_WARNING, "422 response without a Min-SE header %s\n", p_hdrval); 20658 return; 20659 } 20660 rtn = parse_minse(p_hdrval, &minse); 20661 if (rtn != 0) { 20662 ast_log(LOG_WARNING, "Parsing of Min-SE header failed %s\n", p_hdrval); 20663 return; 20664 } 20665 p->stimer->st_interval = minse; 20666 transmit_invite(p, SIP_INVITE, 1, 2); 20667 }
| static int proc_session_timer | ( | const void * | vp | ) | [static] |
Session-Timers: Process session refresh timeout event.
Definition at line 20499 of file chan_sip.c.
References ast_channel::_state, ast_channel_trylock, ast_channel_unlock, ast_debug, ast_log(), AST_SOFTHANGUP_DEV, ast_softhangup_nolock(), AST_STATE_UP, sip_pvt::callid, dialog_unref(), FALSE, LOG_ERROR, LOG_WARNING, sip_pvt::outgoing_call, sip_pvt::owner, SESSION_TIMER_REFRESHER_UAC, SESSION_TIMER_REFRESHER_UAS, sip_pvt_lock, sip_pvt_unlock, sip_st_dlg::st_active, sip_st_dlg::st_expirys, sip_st_dlg::st_ref, sip_st_dlg::st_schedid, sip_pvt::stimer, stop_session_timer(), transmit_reinvite_with_sdp(), and TRUE.
Referenced by start_session_timer().
20500 { 20501 struct sip_pvt *p = (struct sip_pvt *) vp; 20502 int sendreinv = FALSE; 20503 int res = 0; 20504 20505 if (!p->stimer) { 20506 ast_log(LOG_WARNING, "Null stimer in proc_session_timer - %s\n", p->callid); 20507 goto return_unref; 20508 } 20509 20510 ast_debug(2, "Session timer expired: %d - %s\n", p->stimer->st_schedid, p->callid); 20511 20512 if (!p->owner) { 20513 goto return_unref; 20514 } 20515 20516 if ((p->stimer->st_active != TRUE) || (p->owner->_state != AST_STATE_UP)) { 20517 goto return_unref; 20518 } 20519 20520 switch (p->stimer->st_ref) { 20521 case SESSION_TIMER_REFRESHER_UAC: 20522 if (p->outgoing_call == TRUE) { 20523 sendreinv = TRUE; 20524 } 20525 break; 20526 case SESSION_TIMER_REFRESHER_UAS: 20527 if (p->outgoing_call != TRUE) { 20528 sendreinv = TRUE; 20529 } 20530 break; 20531 default: 20532 ast_log(LOG_ERROR, "Unknown session refresher %d\n", p->stimer->st_ref); 20533 goto return_unref; 20534 } 20535 20536 if (sendreinv == TRUE) { 20537 res = 1; 20538 transmit_reinvite_with_sdp(p, FALSE, TRUE); 20539 } else { 20540 p->stimer->st_expirys++; 20541 if (p->stimer->st_expirys >= 2) { 20542 ast_log(LOG_WARNING, "Session-Timer expired - %s\n", p->callid); 20543 20544 while (p->owner && ast_channel_trylock(p->owner)) { 20545 sip_pvt_unlock(p); 20546 usleep(1); 20547 sip_pvt_lock(p); 20548 } 20549 20550 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_DEV); 20551 ast_channel_unlock(p->owner); 20552 } 20553 } 20554 20555 return_unref: 20556 if (!res) { 20557 /* An error occurred. Stop session timer processing */ 20558 p->stimer->st_schedid = -1; 20559 stop_session_timer(p); 20560 20561 /* If we are not asking to be rescheduled, then we need to release our 20562 * reference to the dialog. */ 20563 dialog_unref(p, "removing session timer ref"); 20564 } 20565 20566 return res; 20567 }
| static void process_request_queue | ( | struct sip_pvt * | p, | |
| int * | recount, | |||
| int * | nounlock | |||
| ) | [static] |
Definition at line 19774 of file chan_sip.c.
References ast_free, AST_LIST_REMOVE_HEAD, ast_log(), handle_incoming(), LOG_DEBUG, sip_request::next, option_debug, and sip_pvt::request_queue.
Referenced by handle_request_do().
19775 { 19776 struct sip_request *req; 19777 19778 while ((req = AST_LIST_REMOVE_HEAD(&p->request_queue, next))) { 19779 if (handle_incoming(p, req, &p->recv, recount, nounlock) == -1) { 19780 /* Request failed */ 19781 if (option_debug) { 19782 ast_log(LOG_DEBUG, "SIP message could not be handled, bad request: %-70.70s\n", p->callid[0] ? p->callid : "<no callid>"); 19783 } 19784 } 19785 ast_free(req); 19786 } 19787 }
| 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 port number
< RTP Video port number
< RTP Text port number
< media socket address
< Video socket address
< Text socket address
< RTP Audio host IP
< RTP video host IP
< RTP text host IP
Definition at line 6852 of file chan_sip.c.
References append_history, ast_clear_flag, ast_codec_choose(), ast_codec_pref_setsize(), AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, ast_debug, AST_FORMAT_AUDIO_MASK, AST_FORMAT_T140RED, ast_getformatname_multiple(), ast_gethostbyname(), ast_inet_ntoa(), ast_log(), ast_null_frame, ast_queue_control(), ast_queue_control_data(), ast_queue_frame(), ast_rtp_alloc_size(), ast_rtp_codec_getformat(), ast_rtp_codec_getpref(), ast_rtp_codec_setpref(), AST_RTP_DTMF, ast_rtp_get_current_formats(), ast_rtp_get_peer(), ast_rtp_lookup_mime_multiple(), ast_rtp_new_init(), AST_RTP_OPT_G726_NONSTANDARD, ast_rtp_pt_clear(), ast_rtp_pt_copy(), ast_rtp_set_m_type(), ast_rtp_set_peer(), ast_rtp_set_rtpmap_type(), ast_rtp_setdtmf(), ast_rtp_setdtmfcompensate(), ast_rtp_stop(), ast_rtp_unset_m_type(), ast_set_flag, ast_set_read_format(), ast_set_write_format(), ast_skip_blanks(), ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_threadstorage_get(), ast_udptl_set_error_correction_scheme(), ast_udptl_set_far_max_datagram(), ast_udptl_set_local_max_datagram(), ast_udptl_set_peer(), ast_udptl_stop(), ast_verbose, sip_pvt::autoframing, buf, sip_pvt::callid, sip_pvt::capability, t38properties::capability, change_t38_state(), sip_request::data, sip_request::debug, EVENT_FLAG_CALL, FALSE, sip_pvt::flags, format, get_sdp(), get_sdp_iterate(), hp, sip_pvt::jointcapability, t38properties::jointcapability, sip_pvt::jointnoncodeccapability, sip_pvt::lastinvite, sip_pvt::lastrtprx, sip_pvt::lastrtptx, sip_request::len, LOG_DEBUG, LOG_ERROR, LOG_NOTICE, LOG_WARNING, manager_event, MAX_RTP_PT, sip_pvt::mohsuggest, ast_channel::name, ast_channel::nativeformats, sip_pvt::noncodeccapability, sip_pvt::notext, sip_pvt::novideo, option_debug, sip_pvt::owner, sip_pvt::peercapability, t38properties::peercapability, sip_registry::portno, sip_pvt::prefs, ast_channel::readformat, sip_pvt::red, RED_MAX_GENERATION, sip_pvt::rtp, rtp_red_init(), s, S_OR, SDP_MAX_RTPMAP_CODECS, sip_request::sdp_start, SDP_T38_ACCEPT, SDP_T38_INITIATE, sip_pvt::session_modify, sip_pvt::sessionversion_remote, sip_debug_test_pvt(), SIP_DTMF, SIP_DTMF_AUTO, SIP_DTMF_INBAND, SIP_DTMF_RFC2833, SIP_G726_NONSTANDARD, SIP_NAT, SIP_PAGE2_CALL_ONHOLD, SIP_PAGE2_CALL_ONHOLD_ACTIVE, SIP_PAGE2_CALL_ONHOLD_INACTIVE, SIP_PAGE2_CALL_ONHOLD_ONEDIR, SIP_PAGE2_RFC2833_COMPENSATE, SIP_PAGE2_UDPTL_DESTINATION, sip_peer_hold(), SIPBUFSIZE, t38properties::state, ast_str::str, strsep(), sip_pvt::t38, T38_DISABLED, T38_ENABLED, T38_LOCAL_REINVITE, T38_PEER_DIRECT, T38_PEER_REINVITE, T38FAX_FILL_BIT_REMOVAL, T38FAX_RATE_12000, T38FAX_RATE_14400, T38FAX_RATE_2400, T38FAX_RATE_4800, T38FAX_RATE_7200, T38FAX_RATE_9600, T38FAX_RATE_MANAGEMENT_LOCAL_TCF, T38FAX_RATE_MANAGEMENT_TRANSFERED_TCF, T38FAX_TRANSCODING_JBIG, T38FAX_TRANSCODING_MMR, T38FAX_UDP_EC_FEC, T38FAX_UDP_EC_NONE, T38FAX_UDP_EC_REDUNDANCY, T38FAX_VERSION_0, T38FAX_VERSION_1, text, sip_pvt::trtp, TRUE, sip_pvt::udptl, UDPTL_ERROR_CORRECTION_FEC, UDPTL_ERROR_CORRECTION_NONE, UDPTL_ERROR_CORRECTION_REDUNDANCY, ast_channel::uniqueid, sip_pvt::vrtp, and ast_channel::writeformat.
06853 { 06854 const char *m; /* SDP media offer */ 06855 const char *c; 06856 const char *a; 06857 const char *o; /* Pointer to o= line */ 06858 char *o_copy; /* Copy of o= line */ 06859 char *token; 06860 char host[258]; 06861 int len = -1; 06862 int portno = -1; /*!< RTP Audio port number */ 06863 int vportno = -1; /*!< RTP Video port number */ 06864 int tportno = -1; /*!< RTP Text port number */ 06865 int udptlportno = -1; 06866 int peert38capability = 0; 06867 char s[256]; 06868 int old = 0; 06869 06870 /* Peer capability is the capability in the SDP, non codec is RFC2833 DTMF (101) */ 06871 int peercapability = 0, peernoncodeccapability = 0; 06872 int vpeercapability = 0, vpeernoncodeccapability = 0; 06873 int tpeercapability = 0, tpeernoncodeccapability = 0; 06874 struct sockaddr_in sin; /*!< media socket address */ 06875 struct sockaddr_in vsin; /*!< Video socket address */ 06876 struct sockaddr_in tsin; /*!< Text socket address */ 06877 06878 const char *codecs; 06879 struct hostent *hp; /*!< RTP Audio host IP */ 06880 struct hostent *vhp = NULL; /*!< RTP video host IP */ 06881 struct hostent *thp = NULL; /*!< RTP text host IP */ 06882 struct ast_hostent audiohp; 06883 struct ast_hostent videohp; 06884 struct ast_hostent texthp; 06885 int codec; 06886 int destiterator = 0; 06887 int iterator; 06888 int sendonly = -1; 06889 int numberofports; 06890 struct ast_rtp *newaudiortp, *newvideortp, *newtextrtp; /* Buffers for codec handling */ 06891 int newjointcapability; /* Negotiated capability */ 06892 int newpeercapability; 06893 int newnoncodeccapability; 06894 int numberofmediastreams = 0; 06895 int debug = sip_debug_test_pvt(p); 06896 06897 int found_rtpmap_codecs[SDP_MAX_RTPMAP_CODECS]; 06898 int last_rtpmap_codec=0; 06899 06900 char buf[SIPBUFSIZE]; 06901 uint64_t rua_version; 06902 06903 int red_data_pt[10]; 06904 int red_num_gen = 0; 06905 int red_pt = 0; 06906 06907 char *red_cp; /* For T.140 red */ 06908 char red_fmtp[100] = "empty"; /* For T.140 red */ 06909 06910 if (!p->rtp) { 06911 ast_log(LOG_ERROR, "Got SDP but have no RTP session allocated.\n"); 06912 return -1; 06913 } 06914 06915 /* Initialize the temporary RTP structures we use to evaluate the offer from the peer */ 06916 #ifdef LOW_MEMORY 06917 newaudiortp = ast_threadstorage_get(&ts_audio_rtp, ast_rtp_alloc_size()); 06918 #else 06919 newaudiortp = alloca(ast_rtp_alloc_size()); 06920 #endif 06921 memset(newaudiortp, 0, ast_rtp_alloc_size()); 06922 ast_rtp_new_init(newaudiortp); 06923 ast_rtp_pt_clear(newaudiortp); 06924 06925 #ifdef LOW_MEMORY 06926 newvideortp = ast_threadstorage_get(&ts_video_rtp, ast_rtp_alloc_size()); 06927 #else 06928 newvideortp = alloca(ast_rtp_alloc_size()); 06929 #endif 06930 memset(newvideortp, 0, ast_rtp_alloc_size()); 06931 ast_rtp_new_init(newvideortp); 06932 ast_rtp_pt_clear(newvideortp); 06933 06934 #ifdef LOW_MEMORY 06935 newtextrtp = ast_threadstorage_get(&ts_text_rtp, ast_rtp_alloc_size()); 06936 #else 06937 newtextrtp = alloca(ast_rtp_alloc_size()); 06938 #endif 06939 memset(newtextrtp, 0, ast_rtp_alloc_size()); 06940 ast_rtp_new_init(newtextrtp); 06941 ast_rtp_pt_clear(newtextrtp); 06942 06943 /* Update our last rtprx when we receive an SDP, too */ 06944 p->lastrtprx = p->lastrtptx = time(NULL); /* XXX why both ? */ 06945 06946 /* Store the SDP version number of remote UA. This will allow us to 06947 distinguish between session modifications and session refreshes. If 06948 the remote UA does not send an incremented SDP version number in a 06949 subsequent RE-INVITE then that means its not changing media session. 06950 The RE-INVITE may have been sent to update connected party, remote 06951 target or to refresh the session (Session-Timers). Asterisk must not 06952 change media session and increment its own version number in answer 06953 SDP in this case. */ 06954 06955 o = get_sdp(req, "o"); 06956 if (ast_strlen_zero(o)) { 06957 ast_log(LOG_WARNING, "SDP sytax error. SDP without an o= line\n"); 06958 return -1; 06959 } 06960 06961 o_copy = ast_strdupa(o); 06962 token = strsep(&o_copy, " "); /* Skip username */ 06963 if (!o_copy) { 06964 ast_log(LOG_WARNING, "SDP sytax error in o= line username\n"); 06965 return -1; 06966 } 06967 token = strsep(&o_copy, " "); /* Skip session-id */ 06968 if (!o_copy) { 06969 ast_log(LOG_WARNING, "SDP sytax error in o= line session-id\n"); 06970 return -1; 06971 } 06972 token = strsep(&o_copy, " "); /* Version */ 06973 if (!o_copy) { 06974 ast_log(LOG_WARNING, "SDP sytax error in o= line\n"); 06975 return -1; 06976 } 06977 if (!sscanf(token, "%" SCNu64, &rua_version)) { 06978 ast_log(LOG_WARNING, "SDP sytax error in o= line version\n"); 06979 return -1; 06980 } 06981 06982 if (p->sessionversion_remote < 0 || p->sessionversion_remote != rua_version) { 06983 p->sessionversion_remote = rua_version; 06984 p->session_modify = TRUE; 06985 } else if (p->sessionversion_remote == rua_version) { 06986 p->session_modify = FALSE; 06987 ast_debug(2, "SDP version number same as previous SDP\n"); 06988 return 0; 06989 } 06990 06991 /* Try to find first media stream */ 06992 m = get_sdp(req, "m"); 06993 destiterator = req->sdp_start; 06994 c = get_sdp_iterate(&destiterator, req, "c"); 06995 if (ast_strlen_zero(m) || ast_strlen_zero(c)) { 06996 ast_log(LOG_WARNING, "Insufficient information for SDP (m = '%s', c = '%s')\n", m, c); 06997 return -1; 06998 } 06999 07000 /* Check for IPv4 address (not IPv6 yet) */ 07001 if (sscanf(c, "IN IP4 %256s", host) != 1) { 07002 ast_log(LOG_WARNING, "Invalid host in c= line, '%s'\n", c); 07003 return -1; 07004 } 07005 07006 /* XXX This could block for a long time, and block the main thread! XXX */ 07007 hp = ast_gethostbyname(host, &audiohp); 07008 if (!hp) { 07009 ast_log(LOG_WARNING, "Unable to lookup host in c= line, '%s'\n", c); 07010 return -1; 07011 } 07012 vhp = hp; /* Copy to video address as default too */ 07013 thp = hp; /* Copy to text address as default too */ 07014 07015 iterator = req->sdp_start; 07016 /* default: novideo and notext set */ 07017 p->novideo = TRUE; 07018 p->notext = TRUE; 07019 07020 if (p->vrtp) 07021 ast_rtp_pt_clear(newvideortp); /* Must be cleared in case no m=video line exists */ 07022 07023 if (p->trtp) 07024 ast_rtp_pt_clear(newtextrtp); /* Must be cleared in case no m=text line exists */ 07025 07026 /* Find media streams in this SDP offer */ 07027 while ((m = get_sdp_iterate(&iterator, req, "m"))[0] != '\0') { 07028 int x; 07029 int audio = FALSE; 07030 int video = FALSE; 07031 int text = FALSE; 07032 07033 numberofports = 1; 07034 len = -1; 07035 if ((sscanf(m, "audio %d/%d RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) || 07036 (sscanf(m, "audio %d RTP/AVP %n", &x, &len) == 1 && len > 0)) { 07037 audio = TRUE; 07038 numberofmediastreams++; 07039 /* Found audio stream in this media definition */ 07040 portno = x; 07041 /* Scan through the RTP payload types specified in a "m=" line: */ 07042 for (codecs = m + len; !ast_strlen_zero(codecs); codecs = ast_skip_blanks(codecs + len)) { 07043 if (sscanf(codecs, "%d%n", &codec, &len) != 1) { 07044 ast_log(LOG_WARNING, "Error in codec string '%s'\n", codecs); 07045 return -1; 07046 } 07047 if (debug) 07048 ast_verbose("Found RTP audio format %d\n", codec); 07049 ast_rtp_set_m_type(newaudiortp, codec); 07050 } 07051 } else if ((sscanf(m, "video %d/%d RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) || 07052 (sscanf(m, "video %d RTP/AVP %n", &x, &len) == 1 && len >= 0)) { 07053 video = TRUE; 07054 p->novideo = FALSE; 07055 numberofmediastreams++; 07056 vportno = x; 07057 /* Scan through the RTP payload types specified in a "m=" line: */ 07058 for (codecs = m + len; !ast_strlen_zero(codecs); codecs = ast_skip_blanks(codecs + len)) { 07059 if (sscanf(codecs, "%d%n", &codec, &len) != 1) { 07060 ast_log(LOG_WARNING, "Error in codec string '%s'\n", codecs); 07061 return -1; 07062 } 07063 if (debug) 07064 ast_verbose("Found RTP video format %d\n", codec); 07065 ast_rtp_set_m_type(newvideortp, codec); 07066 } 07067 } else if ((sscanf(m, "text %d/%d RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) || 07068 (sscanf(m, "text %d RTP/AVP %n", &x, &len) == 1 && len > 0)) { 07069 text = TRUE; 07070 p->notext = FALSE; 07071 numberofmediastreams++; 07072 tportno = x; 07073 /* Scan through the RTP payload types specified in a "m=" line: */ 07074 for (codecs = m + len; !ast_strlen_zero(codecs); codecs = ast_skip_blanks(codecs + len)) { 07075 if (sscanf(codecs, "%d%n", &codec, &len) != 1) { 07076 ast_log(LOG_WARNING, "Error in codec string '%s'\n", codecs); 07077 return -1; 07078 } 07079 if (debug) 07080 ast_verbose("Found RTP text format %d\n", codec); 07081 ast_rtp_set_m_type(newtextrtp, codec); 07082 } 07083 } else if (p->udptl && ( (sscanf(m, "image %d udptl t38%n", &x, &len) == 1 && len > 0) || 07084 (sscanf(m, "image %d UDPTL t38%n", &x, &len) == 1 && len > 0) )) { 07085 if (debug) 07086 ast_verbose("Got T.38 offer in SDP in dialog %s\n", p->callid); 07087 udptlportno = x; 07088 numberofmediastreams++; 07089 } else 07090 ast_log(LOG_WARNING, "Unsupported SDP media type in offer: %s\n", m); 07091 if (numberofports > 1) 07092 ast_log(LOG_WARNING, "SDP offered %d ports for media, not supported by Asterisk. Will try anyway...\n", numberofports); 07093 07094 07095 /* Check for Media-description-level-address for audio */ 07096 c = get_sdp_iterate(&destiterator, req, "c"); 07097 if (!ast_strlen_zero(c)) { 07098 if (sscanf(c, "IN IP4 %256s", host) != 1) { 07099 ast_log(LOG_WARNING, "Invalid secondary host in c= line, '%s'\n", c); 07100 } else { 07101 /* XXX This could block for a long time, and block the main thread! XXX */ 07102 if (audio) { 07103 if ( !(hp = ast_gethostbyname(host, &audiohp))) { 07104 ast_log(LOG_WARNING, "Unable to lookup RTP Audio host in secondary c= line, '%s'\n", c); 07105 return -2; 07106 } 07107 } else if (video) { 07108 if (!(vhp = ast_gethostbyname(host, &videohp))) { 07109 ast_log(LOG_WARNING, "Unable to lookup RTP video host in secondary c= line, '%s'\n", c); 07110 return -2; 07111 } 07112 } else if (text) { 07113 if (!(thp = ast_gethostbyname(host, &texthp))) { 07114 ast_log(LOG_WARNING, "Unable to lookup RTP text host in secondary c= line, '%s'\n", c); 07115 return -2; 07116 } 07117 } 07118 } 07119 07120 } 07121 } 07122 if (portno == -1 && vportno == -1 && udptlportno == -1 && tportno == -1) 07123 /* No acceptable offer found in SDP - we have no ports */ 07124 /* Do not change RTP or VRTP if this is a re-invite */ 07125 return -2; 07126 07127 if (numberofmediastreams > 3) 07128 /* We have too many fax, audio and/or video and/or text media streams, fail this offer */ 07129 return -3; 07130 07131 /* RTP addresses and ports for audio and video */ 07132 sin.sin_family = AF_INET; 07133 vsin.sin_family = AF_INET; 07134 tsin.sin_family = AF_INET; 07135 memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr)); 07136 if (vhp) 07137 memcpy(&vsin.sin_addr, vhp->h_addr, sizeof(vsin.sin_addr)); 07138 if (thp) 07139 memcpy(&tsin.sin_addr, thp->h_addr, sizeof(tsin.sin_addr)); 07140 07141 /* Setup UDPTL port number */ 07142 if (p->udptl) { 07143 if (udptlportno > 0) { 07144 sin.sin_port = htons(udptlportno); 07145 if (ast_test_flag(&p->flags[0], SIP_NAT) && ast_test_flag(&p->flags[1], SIP_PAGE2_UDPTL_DESTINATION)) { 07146 struct sockaddr_in peer; 07147 ast_rtp_get_peer(p->rtp, &peer); 07148 if (peer.sin_addr.s_addr) { 07149 memcpy(&sin.sin_addr, &peer.sin_addr, sizeof(sin.sin_addr)); 07150 if (debug) { 07151 ast_log(LOG_DEBUG, "Peer T.38 UDPTL is set behind NAT and with destination, destination address now %s\n", ast_inet_ntoa(sin.sin_addr)); 07152 } 07153 } 07154 } 07155 ast_udptl_set_peer(p->udptl, &sin); 07156 if (debug) 07157 ast_debug(1, "Peer T.38 UDPTL is at port %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 07158 } else { 07159 ast_udptl_stop(p->udptl); 07160 if (debug) 07161 ast_debug(1, "Peer doesn't provide T.38 UDPTL\n"); 07162 } 07163 } 07164 07165 07166 if (p->rtp) { 07167 if (portno > 0) { 07168 sin.sin_port = htons(portno); 07169 ast_rtp_set_peer(p->rtp, &sin); 07170 if (debug) 07171 ast_verbose("Peer audio RTP is at port %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 07172 } else { 07173 if (udptlportno > 0) { 07174 if (debug) 07175 ast_verbose("Got T.38 Re-invite without audio. Keeping RTP active during T.38 session. Callid %s\n", p->callid); 07176 } else { 07177 ast_rtp_stop(p->rtp); 07178 if (debug) 07179 ast_verbose("Peer doesn't provide audio. Callid %s\n", p->callid); 07180 } 07181 } 07182 } 07183 /* Setup video port number, assumes we have audio */ 07184 if (vportno != -1) 07185 vsin.sin_port = htons(vportno); 07186 07187 /* Setup text port number, assumes we have audio */ 07188 if (tportno != -1) 07189 tsin.sin_port = htons(tportno); 07190 07191 /* Next, scan through each "a=xxxx:" line, noting each 07192 * specified RTP payload type (with corresponding MIME subtype): 07193 */ 07194 /* XXX This needs to be done per media stream, since it's media stream specific */ 07195 iterator = req->sdp_start; 07196 while ((a = get_sdp_iterate(&iterator, req, "a"))[0] != '\0') { 07197 char mimeSubtype[128]; 07198 if (option_debug > 1) { 07199 int breakout = FALSE; 07200 07201 /* If we're debugging, check for unsupported sdp options */ 07202 if (!strncasecmp(a, "rtcp:", (size_t) 5)) { 07203 if (debug) 07204 ast_verbose("Got unsupported a:rtcp in SDP offer \n"); 07205 breakout = TRUE; 07206 } else if (!strncasecmp(a, "fmtp:", (size_t) 5)) { 07207 /* Format parameters: Not supported */ 07208 /* Note: This is used for codec parameters, like bitrate for 07209 G722 and video formats for H263 and H264 07210 See RFC2327 for an example */ 07211 if (debug) 07212 ast_verbose("Got unsupported a:fmtp in SDP offer \n"); 07213 breakout = TRUE; 07214 } else if (!strncasecmp(a, "framerate:", (size_t) 10)) { 07215 /* Video stuff: Not supported */ 07216 if (debug) 07217 ast_verbose("Got unsupported a:framerate in SDP offer \n"); 07218 breakout = TRUE; 07219 } else if (!strncasecmp(a, "maxprate:", (size_t) 9)) { 07220 /* Video stuff: Not supported */ 07221 if (debug) 07222 ast_verbose("Got unsupported a:maxprate in SDP offer \n"); 07223 breakout = TRUE; 07224 } else if (!strncasecmp(a, "crypto:", (size_t) 7)) { 07225 /* SRTP stuff, not yet supported */ 07226 if (debug) 07227 ast_verbose("Got unsupported a:crypto in SDP offer \n"); 07228 breakout = TRUE; 07229 } 07230 if (breakout) /* We have a match, skip to next header */ 07231 continue; 07232 } 07233 if (!strcasecmp(a, "sendonly")) { 07234 if (sendonly == -1) 07235 sendonly = 1; 07236 continue; 07237 } else if (!strcasecmp(a, "inactive")) { 07238 if (sendonly == -1) 07239 sendonly = 2; 07240 continue; 07241 } else if (!strcasecmp(a, "sendrecv")) { 07242 if (sendonly == -1) 07243 sendonly = 0; 07244 continue; 07245 } else if (strlen(a) > 5 && !strncasecmp(a, "ptime", 5)) { 07246 char *tmp = strrchr(a, ':'); 07247 long int framing = 0; 07248 if (tmp) { 07249 tmp++; 07250 framing = strtol(tmp, NULL, 10); 07251 if (framing == LONG_MIN || framing == LONG_MAX) { 07252 framing = 0; 07253 ast_debug(1, "Can't read framing from SDP: %s\n", a); 07254 } 07255 } 07256 if (framing && p->autoframing) { 07257 struct ast_codec_pref *pref = ast_rtp_codec_getpref(p->rtp); 07258 int codec_n; 07259 int format = 0; 07260 for (codec_n = 0; codec_n < MAX_RTP_PT; codec_n++) { 07261 format = ast_rtp_codec_getformat(codec_n); 07262 if (!format) /* non-codec or not found */ 07263 continue; 07264 if (option_debug) 07265 ast_log(LOG_DEBUG, "Setting framing for %d to %ld\n", format, framing); 07266 ast_codec_pref_setsize(pref, format, framing); 07267 } 07268 ast_rtp_codec_setpref(p->rtp, pref); 07269 } 07270 continue; 07271 07272 } else if (!strncmp(a, red_fmtp, strlen(red_fmtp))) { 07273 /* count numbers of generations in fmtp */ 07274 red_cp = &red_fmtp[strlen(red_fmtp)]; 07275 strncpy(red_fmtp, a, 100); 07276 07277 sscanf(red_cp, "%u", &red_data_pt[red_num_gen]); 07278 red_cp = strtok(red_cp, "/"); 07279 while (red_cp && red_num_gen++ < RED_MAX_GENERATION) { 07280 sscanf(red_cp, "%u", &red_data_pt[red_num_gen]); 07281 red_cp = strtok(NULL, "/"); 07282 } 07283 red_cp = red_fmtp; 07284 07285 } else if (sscanf(a, "rtpmap: %u %127[^/]/", &codec, mimeSubtype) == 2) { 07286 /* We have a rtpmap to handle */ 07287 07288 if (last_rtpmap_codec < SDP_MAX_RTPMAP_CODECS) { 07289 /* Note: should really look at the 'freq' and '#chans' params too */ 07290 /* Note: This should all be done in the context of the m= above */ 07291 if (!strncasecmp(mimeSubtype, "H26", 3) || !strncasecmp(mimeSubtype, "MP4", 3)) { /* Video */ 07292 if(ast_rtp_set_rtpmap_type(newvideortp, codec, "video", mimeSubtype, 0) != -1) { 07293 if (debug) 07294 ast_verbose("Found video description format %s for ID %d\n", mimeSubtype, codec); 07295 found_rtpmap_codecs[last_rtpmap_codec] = codec; 07296 last_rtpmap_codec++; 07297 } else { 07298 ast_rtp_unset_m_type(newvideortp, codec); 07299 if (debug) 07300 ast_verbose("Found unknown media description format %s for ID %d\n", mimeSubtype, codec); 07301 } 07302 } else if (!strncasecmp(mimeSubtype, "T140", 4)) { /* Text */ 07303 if (p->trtp) { 07304 /* ast_verbose("Adding t140 mimeSubtype to textrtp struct\n"); */ 07305 ast_rtp_set_rtpmap_type(newtextrtp, codec, "text", mimeSubtype, 0); 07306 } 07307 } else if (!strncasecmp(mimeSubtype, "RED", 3)) { /* Text with Redudancy */ 07308 if (p->trtp) { 07309 ast_rtp_set_rtpmap_type(newtextrtp, codec, "text", mimeSubtype, 0); 07310 red_pt = codec; 07311 sprintf(red_fmtp, "fmtp:%d ", red_pt); 07312 07313 if (debug) 07314 ast_verbose("Red submimetype has payload type: %d\n", red_pt); 07315 } 07316 } else { /* Must be audio?? */ 07317 if(ast_rtp_set_rtpmap_type(newaudiortp, codec, "audio", mimeSubtype, 07318 ast_test_flag(&p->flags[0], SIP_G726_NONSTANDARD) ? AST_RTP_OPT_G726_NONSTANDARD : 0) != -1) { 07319 if (debug) 07320 ast_verbose("Found audio description format %s for ID %d\n", mimeSubtype, codec); 07321 found_rtpmap_codecs[last_rtpmap_codec] = codec; 07322 last_rtpmap_codec++; 07323 } else { 07324 ast_rtp_unset_m_type(newaudiortp, codec); 07325 if (debug) 07326 ast_verbose("Found unknown media description format %s for ID %d\n", mimeSubtype, codec); 07327 } 07328 } 07329 } else { 07330 if (debug) 07331 ast_verbose("Discarded description format %s for ID %d\n", mimeSubtype, codec); 07332 } 07333 07334 } 07335 } 07336 07337 if (udptlportno != -1) { 07338 int found = 0, x; 07339 07340 old = 0; 07341 07342 /* Scan trough the a= lines for T38 attributes and set apropriate fileds */ 07343 iterator = req->sdp_start; 07344 while ((a = get_sdp_iterate(&iterator, req, "a"))[0] != '\0') { 07345 if ((sscanf(a, "T38FaxMaxBuffer:%d", &x) == 1)) { 07346 found = 1; 07347 ast_debug(3, "MaxBufferSize:%d\n", x); 07348 } else if ((sscanf(a, "T38MaxBitRate:%d", &x) == 1) || (sscanf(a, "T38FaxMaxRate:%d", &x) == 1)) { 07349 found = 1; 07350 ast_debug(3, "T38MaxBitRate: %d\n", x); 07351 switch (x) { 07352 case 14400: 07353 peert38capability |= T38FAX_RATE_14400 | T38FAX_RATE_12000 | T38FAX_RATE_9600 | T38FAX_RATE_7200 | T38FAX_RATE_4800 | T38FAX_RATE_2400; 07354 break; 07355 case 12000: 07356 peert38capability |= T38FAX_RATE_12000 | T38FAX_RATE_9600 | T38FAX_RATE_7200 | T38FAX_RATE_4800 | T38FAX_RATE_2400; 07357 break; 07358 case 9600: 07359 peert38capability |= T38FAX_RATE_9600 | T38FAX_RATE_7200 | T38FAX_RATE_4800 | T38FAX_RATE_2400; 07360 break; 07361 case 7200: 07362 peert38capability |= T38FAX_RATE_7200 | T38FAX_RATE_4800 | T38FAX_RATE_2400; 07363 break; 07364 case 4800: 07365 peert38capability |= T38FAX_RATE_4800 | T38FAX_RATE_2400; 07366 break; 07367 case 2400: 07368 peert38capability |= T38FAX_RATE_2400; 07369 break; 07370 } 07371 } else if ((sscanf(a, "T38FaxVersion:%d", &x) == 1)) { 07372 found = 1; 07373 ast_debug(3, "FaxVersion: %d\n", x); 07374 if (x == 0) 07375 peert38capability |= T38FAX_VERSION_0; 07376 else if (x == 1) 07377 peert38capability |= T38FAX_VERSION_1; 07378 } else if ((sscanf(a, "T38FaxMaxDatagram:%d", &x) == 1) || (sscanf(a, "T38MaxDatagram:%d", &x) == 1)) { 07379 found = 1; 07380 ast_debug(3, "FaxMaxDatagram: %d\n", x); 07381 ast_udptl_set_far_max_datagram(p->udptl, x); 07382 ast_udptl_set_local_max_datagram(p->udptl, x); 07383 } else if ((strncmp(a, "T38FaxFillBitRemoval", 20) == 0)) { 07384 found = 1; 07385 if(sscanf(a, "T38FaxFillBitRemoval:%d", &x) == 1) { 07386 ast_debug(3, "FillBitRemoval: %d\n", x); 07387 if(x == 1) 07388 peert38capability |= T38FAX_FILL_BIT_REMOVAL; 07389 } else { 07390 ast_debug(3, "FillBitRemoval\n"); 07391 peert38capability |= T38FAX_FILL_BIT_REMOVAL; 07392 } 07393 } else if ((strncmp(a, "T38FaxTranscodingMMR", 20) == 0)) { 07394 found = 1; 07395 if(sscanf(a, "T38FaxTranscodingMMR:%d", &x) == 1) { 07396 ast_debug(3, "Transcoding MMR: %d\n", x); 07397 if(x == 1) 07398 peert38capability |= T38FAX_TRANSCODING_MMR; 07399 } else { 07400 ast_debug(3, "Transcoding MMR\n"); 07401 peert38capability |= T38FAX_TRANSCODING_MMR; 07402 } 07403 } else if ((strncmp(a, "T38FaxTranscodingJBIG", 21) == 0)) { 07404 found = 1; 07405 if(sscanf(a, "T38FaxTranscodingJBIG:%d", &x) == 1) { 07406 ast_debug(3, "Transcoding JBIG: %d\n", x); 07407 if(x == 1) 07408 peert38capability |= T38FAX_TRANSCODING_JBIG; 07409 } else { 07410 ast_debug(3, "Transcoding JBIG\n"); 07411 peert38capability |= T38FAX_TRANSCODING_JBIG; 07412 } 07413 } else if ((sscanf(a, "T38FaxRateManagement:%255s", s) == 1)) { 07414 found = 1; 07415 ast_debug(3, "RateManagement: %s\n", s); 07416 if (!strcasecmp(s, "localTCF")) 07417 peert38capability |= T38FAX_RATE_MANAGEMENT_LOCAL_TCF; 07418 else if (!strcasecmp(s, "transferredTCF")) 07419 peert38capability |= T38FAX_RATE_MANAGEMENT_TRANSFERED_TCF; 07420 } else if ((sscanf(a, "T38FaxUdpEC:%255s", s) == 1)) { 07421 found = 1; 07422 ast_debug(3, "UDP EC: %s\n", s); 07423 if (!strcasecmp(s, "t38UDPRedundancy")) { 07424 peert38capability |= T38FAX_UDP_EC_REDUNDANCY; 07425 ast_udptl_set_error_correction_scheme(p->udptl, UDPTL_ERROR_CORRECTION_REDUNDANCY); 07426 } else if (!strcasecmp(s, "t38UDPFEC")) { 07427 peert38capability |= T38FAX_UDP_EC_FEC; 07428 ast_udptl_set_error_correction_scheme(p->udptl, UDPTL_ERROR_CORRECTION_FEC); 07429 } else { 07430 peert38capability |= T38FAX_UDP_EC_NONE; 07431 ast_udptl_set_error_correction_scheme(p->udptl, UDPTL_ERROR_CORRECTION_NONE); 07432 } 07433 } 07434 } 07435 if (found) { /* Some cisco equipment returns nothing beside c= and m= lines in 200 OK T38 SDP */ 07436 p->t38.peercapability = peert38capability; 07437 p->t38.jointcapability = (peert38capability & 255); /* Put everything beside supported speeds settings */ 07438 peert38capability &= (T38FAX_RATE_14400 | T38FAX_RATE_12000 | T38FAX_RATE_9600 | T38FAX_RATE_7200 | T38FAX_RATE_4800 | T38FAX_RATE_2400); 07439 p->t38.jointcapability |= (peert38capability & p->t38.capability); /* Put the lower of our's and peer's speed */ 07440 } 07441 if (debug) 07442 ast_debug(1, "Our T38 capability = (%d), peer T38 capability (%d), joint T38 capability (%d)\n", 07443 p->t38.capability, 07444 p->t38.peercapability, 07445 p->t38.jointcapability); 07446 07447 /* Remote party offers T38, we need to update state */ 07448 if (t38action == SDP_T38_ACCEPT) { 07449 if (p->t38.state == T38_LOCAL_REINVITE) 07450 change_t38_state(p, T38_ENABLED); 07451 } else if (t38action == SDP_T38_INITIATE) { 07452 if (p->owner && p->lastinvite) { 07453 change_t38_state(p, T38_PEER_REINVITE); /* T38 Offered in re-invite from remote party */ 07454 } else { 07455 change_t38_state(p, T38_PEER_DIRECT); /* T38 Offered directly from peer in first invite */ 07456 } 07457 } 07458 } else { 07459 change_t38_state(p, T38_DISABLED); 07460 } 07461 07462 /* Now gather all of the codecs that we are asked for: */ 07463 ast_rtp_get_current_formats(newaudiortp, &peercapability, &peernoncodeccapability); 07464 ast_rtp_get_current_formats(newvideortp, &vpeercapability, &vpeernoncodeccapability); 07465 ast_rtp_get_current_formats(newtextrtp, &tpeercapability, &tpeernoncodeccapability); 07466 07467 newjointcapability = p->capability & (peercapability | vpeercapability | tpeercapability); 07468 newpeercapability = (peercapability | vpeercapability | tpeercapability); 07469 newnoncodeccapability = p->noncodeccapability & peernoncodeccapability; 07470 07471 07472 if (debug) { 07473 /* shame on whoever coded this.... */ 07474 char s1[SIPBUFSIZE], s2[SIPBUFSIZE], s3[SIPBUFSIZE], s4[SIPBUFSIZE], s5[SIPBUFSIZE]; 07475 07476 ast_verbose("Capabilities: us - %s, peer - audio=%s/video=%s/text=%s, combined - %s\n", 07477 ast_getformatname_multiple(s1, SIPBUFSIZE, p->capability), 07478 ast_getformatname_multiple(s2, SIPBUFSIZE, peercapability), 07479 ast_getformatname_multiple(s3, SIPBUFSIZE, vpeercapability), 07480 ast_getformatname_multiple(s4, SIPBUFSIZE, tpeercapability), 07481 ast_getformatname_multiple(s5, SIPBUFSIZE, newjointcapability)); 07482 07483 ast_verbose("Non-codec capabilities (dtmf): us - %s, peer - %s, combined - %s\n", 07484 ast_rtp_lookup_mime_multiple(s1, SIPBUFSIZE, p->noncodeccapability, 0, 0), 07485 ast_rtp_lookup_mime_multiple(s2, SIPBUFSIZE, peernoncodeccapability, 0, 0), 07486 ast_rtp_lookup_mime_multiple(s3, SIPBUFSIZE, newnoncodeccapability, 0, 0)); 07487 } 07488 if (!newjointcapability) { 07489 /* If T.38 was not negotiated either, totally bail out... */ 07490 if (!p->t38.jointcapability || !udptlportno) { 07491 ast_log(LOG_NOTICE, "No compatible codecs, not accepting this offer!\n"); 07492 /* Do NOT Change current setting */ 07493 return -1; 07494 } else { 07495 ast_debug(3, "Have T.38 but no audio codecs, accepting offer anyway\n"); 07496 return 0; 07497 } 07498 } 07499 07500 /* We are now ready to change the sip session and p->rtp and p->vrtp with the offered codecs, since 07501 they are acceptable */ 07502 p->jointcapability = newjointcapability; /* Our joint codec profile for this call */ 07503 p->peercapability = newpeercapability; /* The other sides capability in latest offer */ 07504 p->jointnoncodeccapability = newnoncodeccapability; /* DTMF capabilities */ 07505 07506 if (p->jointcapability & AST_FORMAT_T140RED) { 07507 p->red = 1; 07508 rtp_red_init(p->trtp, 300, red_data_pt, 2); 07509 } else { 07510 p->red = 0; 07511 } 07512 07513 ast_rtp_pt_copy(p->rtp, newaudiortp); 07514 if (p->vrtp) 07515 ast_rtp_pt_copy(p->vrtp, newvideortp); 07516 if (p->trtp) 07517 ast_rtp_pt_copy(p->trtp, newtextrtp); 07518 07519 if (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO) { 07520 ast_clear_flag(&p->flags[0], SIP_DTMF); 07521 if (newnoncodeccapability & AST_RTP_DTMF) { 07522 /* XXX Would it be reasonable to drop the DSP at this point? XXX */ 07523 ast_set_flag(&p->flags[0], SIP_DTMF_RFC2833); 07524 /* Since RFC2833 is now negotiated we need to change some properties of the RTP stream */ 07525 ast_rtp_setdtmf(p->rtp, 1); 07526 ast_rtp_setdtmfcompensate(p->rtp, ast_test_flag(&p->flags[1], SIP_PAGE2_RFC2833_COMPENSATE)); 07527 } else { 07528 ast_set_flag(&p->flags[0], SIP_DTMF_INBAND); 07529 } 07530 } 07531 07532 /* Setup audio port number */ 07533 if (p->rtp && sin.sin_port) { 07534 ast_rtp_set_peer(p->rtp, &sin); 07535 if (debug) 07536 ast_verbose("Peer audio RTP is at port %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 07537 } 07538 07539 /* Setup video port number */ 07540 if (p->vrtp && vsin.sin_port) { 07541 ast_rtp_set_peer(p->vrtp, &vsin); 07542 if (debug) 07543 ast_verbose("Peer video RTP is at port %s:%d\n", ast_inet_ntoa(vsin.sin_addr), ntohs(vsin.sin_port)); 07544 } 07545 07546 /* Setup text port number */ 07547 if (p->trtp && tsin.sin_port) { 07548 ast_rtp_set_peer(p->trtp, &tsin); 07549 if (debug) 07550 ast_verbose("Peer text RTP is at port %s:%d\n", ast_inet_ntoa(tsin.sin_addr), ntohs(tsin.sin_port)); 07551 } 07552 07553 /* Ok, we're going with this offer */ 07554 ast_debug(2, "We're settling with these formats: %s\n", ast_getformatname_multiple(buf, SIPBUFSIZE, p->jointcapability)); 07555 07556 if (!p->owner) /* There's no open channel owning us so we can return here. For a re-invite or so, we proceed */ 07557 return 0; 07558 07559 ast_debug(4, "We have an owner, now see if we need to change this call\n"); 07560 07561 if (!(p->owner->nativeformats & p->jointcapability) && (p->jointcapability & AST_FORMAT_AUDIO_MASK)) { 07562 if (debug) { 07563 char s1[SIPBUFSIZE], s2[SIPBUFSIZE]; 07564 ast_debug(1, "Oooh, we need to change our audio formats since our peer supports only %s and not %s\n", 07565 ast_getformatname_multiple(s1, SIPBUFSIZE, p->jointcapability), 07566 ast_getformatname_multiple(s2, SIPBUFSIZE, p->owner->nativeformats)); 07567 } 07568 p->owner->nativeformats = ast_codec_choose(&p->prefs, p->jointcapability, 1) | (p->capability & vpeercapability) | (p->capability & tpeercapability); 07569 ast_set_read_format(p->owner, p->owner->readformat); 07570 ast_set_write_format(p->owner, p->owner->writeformat); 07571 } 07572 07573 if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD) && sin.sin_addr.s_addr && (!sendonly || sendonly == -1)) { 07574 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 07575 /* Activate a re-invite */ 07576 ast_queue_frame(p->owner, &ast_null_frame); 07577 /* Queue Manager Unhold event */ 07578 append_history(p, "Unhold", "%s", req->data->str); 07579 if (global_callevents) 07580 manager_event(EVENT_FLAG_CALL, "Hold", 07581 "Status: Off\r\n" 07582 "Channel: %s\r\n" 07583 "Uniqueid: %s\r\n", 07584 p->owner->name, 07585 p->owner->uniqueid); 07586 if (global_notifyhold) 07587 sip_peer_hold(p, FALSE); 07588 ast_clear_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD); /* Clear both flags */ 07589 } else if (!sin.sin_addr.s_addr || (sendonly && sendonly != -1)) { 07590 int already_on_hold = ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD); 07591 ast_queue_control_data(p->owner, AST_CONTROL_HOLD, 07592 S_OR(p->mohsuggest, NULL), 07593 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 07594 if (sendonly) 07595 ast_rtp_stop(p->rtp); 07596 /* RTCP needs to go ahead, even if we're on hold!!! */ 07597 /* Activate a re-invite */ 07598 ast_queue_frame(p->owner, &ast_null_frame); 07599 /* Queue Manager Hold event */ 07600 append_history(p, "Hold", "%s", req->data->str); 07601 if (global_callevents && !ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD)) { 07602 manager_event(EVENT_FLAG_CALL, "Hold", 07603 "Status: On\r\n" 07604 "Channel: %s\r\n" 07605 "Uniqueid: %s\r\n", 07606 p->owner->name, 07607 p->owner->uniqueid); 07608 } 07609 if (sendonly == 1) /* One directional hold (sendonly/recvonly) */ 07610 ast_set_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD_ONEDIR); 07611 else if (sendonly == 2) /* Inactive stream */ 07612 ast_set_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD_INACTIVE); 07613 else 07614 ast_set_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD_ACTIVE); 07615 if (global_notifyhold && !already_on_hold) 07616 sip_peer_hold(p, TRUE); 07617 } 07618 07619 return 0; 07620 }
| static struct sip_proxy* proxy_allocate | ( | char * | name, | |
| char * | port, | |||
| int | force | |||
| ) | [static] |
Allocate and initialize sip proxy.
Definition at line 2667 of file chan_sip.c.
References ao2_alloc, ast_copy_string(), ast_strlen_zero(), proxy_update(), and STANDARD_SIP_PORT.
Referenced by build_peer().
02668 { 02669 struct sip_proxy *proxy; 02670 proxy = ao2_alloc(sizeof(*proxy), NULL); 02671 if (!proxy) 02672 return NULL; 02673 proxy->force = force; 02674 ast_copy_string(proxy->name, name, sizeof(proxy->name)); 02675 proxy->ip.sin_port = htons((!ast_strlen_zero(port) ? atoi(port) : STANDARD_SIP_PORT)); 02676 proxy_update(proxy); 02677 return proxy; 02678 }
| static int proxy_update | ( | struct sip_proxy * | proxy | ) | [static] |
Resolve DNS srv name or host name in a sip_proxy structure
Definition at line 2650 of file chan_sip.c.
References ast_get_ip_or_srv(), ast_log(), FALSE, inet_aton(), sip_proxy::ip, sip_proxy::last_dnsupdate, LOG_WARNING, sip_proxy::name, and TRUE.
Referenced by proxy_allocate().
02651 { 02652 /* if it's actually an IP address and not a name, 02653 there's no need for a managed lookup */ 02654 if (!inet_aton(proxy->name, &proxy->ip.sin_addr)) { 02655 /* Ok, not an IP address, then let's check if it's a domain or host */ 02656 /* XXX Todo - if we have proxy port, don't do SRV */ 02657 if (ast_get_ip_or_srv(&proxy->ip, proxy->name, global_srvlookup ? "_sip._udp" : NULL) < 0) { 02658 ast_log(LOG_WARNING, "Unable to locate host '%s'\n", proxy->name); 02659 return FALSE; 02660 } 02661 } 02662 proxy->last_dnsupdate = time(NULL); 02663 return TRUE; 02664 }
| static int queue_request | ( | struct sip_pvt * | p, | |
| const struct sip_request * | req | |||
| ) | [static] |
Definition at line 19844 of file chan_sip.c.
References ast_calloc, AST_LIST_INSERT_TAIL, ast_sched_add(), copy_request(), dialog_ref(), dialog_unref(), sip_request::next, sip_pvt::request_queue, sip_pvt::request_queue_sched_id, sched, and scheduler_process_request_queue().
Referenced by handle_request_do().
19845 { 19846 struct sip_request *newreq; 19847 19848 if (!(newreq = ast_calloc(1, sizeof(*newreq)))) { 19849 return -1; 19850 } 19851 19852 copy_request(newreq, req); 19853 AST_LIST_INSERT_TAIL(&p->request_queue, newreq, next); 19854 if (p->request_queue_sched_id == -1) { 19855 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) { 19856 dialog_unref(p, "Decrement refcount due to sched_add failure"); 19857 } 19858 } 19859 19860 return 0; 19861 }
| static struct sip_peer * realtime_peer | ( | const char * | peername, | |
| struct sockaddr_in * | sin, | |||
| int | devstate_only | |||
| ) | [static] |
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 3945 of file chan_sip.c.
References ahp, ast_check_realtime(), ast_gethostbyname(), ast_inet_ntoa(), ast_load_realtime(), ast_variables_destroy(), hp, ipaddr, ast_variable::name, ast_variable::next, SENTINEL, ast_variable::value, and var.
03946 { 03947 struct sip_peer *peer; 03948 struct ast_variable *var = NULL; 03949 struct ast_variable *varregs = NULL; 03950 struct ast_variable *tmp; 03951 struct ast_config *peerlist = NULL; 03952 char ipaddr[INET_ADDRSTRLEN]; 03953 char portstring[6]; /*up to 5 digits plus null terminator*/ 03954 char *cat = NULL; 03955 unsigned short portnum; 03956 int realtimeregs = ast_check_realtime("sipregs"); 03957 03958 /* First check on peer name */ 03959 if (newpeername) { 03960 if (realtimeregs) 03961 varregs = ast_load_realtime("sipregs", "name", newpeername, SENTINEL); 03962 03963 var = ast_load_realtime("sippeers", "name", newpeername, "host", "dynamic", SENTINEL); 03964 if (!var && sin) 03965 var = ast_load_realtime("sippeers", "name", newpeername, "host", ast_inet_ntoa(sin->sin_addr), SENTINEL); 03966 if (!var) { 03967 var = ast_load_realtime("sippeers", "name", newpeername, SENTINEL); 03968 /*!\note 03969 * If this one loaded something, then we need to ensure that the host 03970 * field matched. The only reason why we can't have this as a criteria 03971 * is because we only have the IP address and the host field might be 03972 * set as a name (and the reverse PTR might not match). 03973 */ 03974 if (var && sin) { 03975 for (tmp = var; tmp; tmp = tmp->next) { 03976 if (!strcasecmp(tmp->name, "host")) { 03977 struct hostent *hp; 03978 struct ast_hostent ahp; 03979 if (!(hp = ast_gethostbyname(tmp->value, &ahp)) || (memcmp(&hp->h_addr, &sin->sin_addr, sizeof(hp->h_addr)))) { 03980 /* No match */ 03981 ast_variables_destroy(var); 03982 var = NULL; 03983 } 03984 break; 03985 } 03986 } 03987 } 03988 } 03989 } 03990 03991 if (!var && sin) { /* Then check on IP address for dynamic peers */ 03992 ast_copy_string(ipaddr, ast_inet_ntoa(sin->sin_addr), sizeof(ipaddr)); 03993 portnum = ntohs(sin->sin_port); 03994 sprintf(portstring, "%u", portnum); 03995 var = ast_load_realtime("sippeers", "host", ipaddr, "port", portstring, SENTINEL); /* First check for fixed IP hosts */ 03996 if (var) { 03997 if (realtimeregs) { 03998 newpeername = get_name_from_variable(var, newpeername); 03999 varregs = ast_load_realtime("sipregs", "name", newpeername, SENTINEL); 04000 } 04001 } else { 04002 if (realtimeregs) 04003 varregs = ast_load_realtime("sipregs", "ipaddr", ipaddr, "port", portstring, SENTINEL); /* Then check for registered hosts */ 04004 else 04005 var = ast_load_realtime("sippeers", "ipaddr", ipaddr, "port", portstring, SENTINEL); /* Then check for registered hosts */ 04006 if (varregs) { 04007 newpeername = get_name_from_variable(varregs, newpeername); 04008 var = ast_load_realtime("sippeers", "name", newpeername, SENTINEL); 04009 } 04010 } 04011 if (!var) { /*We couldn't match on ipaddress and port, so we need to check if port is insecure*/ 04012 peerlist = ast_load_realtime_multientry("sippeers", "host", ipaddr, SENTINEL); 04013 if (peerlist) { 04014 var = get_insecure_variable_from_config(peerlist); 04015 if(var) { 04016 if (realtimeregs) { 04017 newpeername = get_name_from_variable(var, newpeername); 04018 varregs = ast_load_realtime("sipregs", "name", newpeername, SENTINEL); 04019 } 04020 } else { /*var wasn't found in the list of "hosts", so try "ipaddr"*/ 04021 peerlist = NULL; 04022 cat = NULL; 04023 peerlist = ast_load_realtime_multientry("sippeers", "ipaddr", ipaddr, SENTINEL); 04024 if(peerlist) { 04025 var = get_insecure_variable_from_config(peerlist); 04026 if(var) { 04027 if (realtimeregs) { 04028 newpeername = get_name_from_variable(var, newpeername); 04029 varregs = ast_load_realtime("sipregs", "name", newpeername, SENTINEL); 04030 } 04031 } 04032 } 04033 } 04034 } else { 04035 if (realtimeregs) { 04036 peerlist = ast_load_realtime_multientry("sipregs", "ipaddr", ipaddr, SENTINEL); 04037 if (peerlist) { 04038 varregs = get_insecure_variable_from_config(peerlist); 04039 if (varregs) { 04040 newpeername = get_name_from_variable(varregs, newpeername); 04041 var = ast_load_realtime("sippeers", "name", newpeername, SENTINEL); 04042 } 04043 } 04044 } else { 04045 peerlist = ast_load_realtime_multientry("sippeers", "ipaddr", ipaddr, SENTINEL); 04046 if (peerlist) { 04047 var = get_insecure_variable_from_config(peerlist); 04048 if (var) { 04049 newpeername = get_name_from_variable(var, newpeername); 04050 varregs = ast_load_realtime("sipregs", "name", newpeername, SENTINEL); 04051 } 04052 } 04053 } 04054 } 04055 } 04056 } 04057 04058 if (!var) { 04059 if (peerlist) 04060 ast_config_destroy(peerlist); 04061 return NULL; 04062 } 04063 04064 for (tmp = var; tmp; tmp = tmp->next) { 04065 /* If this is type=user, then skip this object. */ 04066 if (!strcasecmp(tmp->name, "type") && 04067 !strcasecmp(tmp->value, "user")) { 04068 if(peerlist) 04069 ast_config_destroy(peerlist); 04070 else { 04071 ast_variables_destroy(var); 04072 ast_variables_destroy(varregs); 04073 } 04074 return NULL; 04075 } else if (!newpeername && !strcasecmp(tmp->name, "name")) { 04076 newpeername = tmp->value; 04077 } 04078 } 04079 04080 if (!newpeername) { /* Did not find peer in realtime */ 04081 ast_log(LOG_WARNING, "Cannot Determine peer name ip=%s\n", ipaddr); 04082 if(peerlist) 04083 ast_config_destroy(peerlist); 04084 else 04085 ast_variables_destroy(var); 04086 return NULL; 04087 } 04088 04089 04090 /* Peer found in realtime, now build it in memory */ 04091 peer = build_peer(newpeername, var, varregs, TRUE); 04092 if (!peer) { 04093 if(peerlist) 04094 ast_config_destroy(peerlist); 04095 else { 04096 ast_variables_destroy(var); 04097 ast_variables_destroy(varregs); 04098 } 04099 return NULL; 04100 } 04101 04102 ast_debug(3, "-REALTIME- loading peer from database to memory. Name: %s. Peer objects: %d\n", peer->name, rpeerobjs); 04103 04104 if (ast_test_flag(&global_flags[1], SIP_PAGE2_RTCACHEFRIENDS) && !devstate_only) { 04105 /* Cache peer */ 04106 ast_copy_flags(&peer->flags[1], &global_flags[1], SIP_PAGE2_RTAUTOCLEAR|SIP_PAGE2_RTCACHEFRIENDS); 04107 if (ast_test_flag(&global_flags[1], SIP_PAGE2_RTAUTOCLEAR)) { 04108 AST_SCHED_REPLACE_UNREF(peer->expire, sched, global_rtautoclear * 1000, expire_register, peer, 04109 unref_peer(_data, "remove registration ref"), 04110 unref_peer(peer, "remove registration ref"), 04111 ref_peer(peer, "add registration ref")); 04112 } 04113 ao2_t_link(peers, peer, "link peer into peers table"); 04114 if (peer->addr.sin_addr.s_addr) { 04115 ao2_t_link(peers_by_ip, peer, "link peer into peers_by_ip table"); 04116 } 04117 } 04118 peer->is_realtime = 1; 04119 if (peerlist) 04120 ast_config_destroy(peerlist); 04121 else { 04122 ast_variables_destroy(var); 04123 ast_variables_destroy(varregs); 04124 } 04125 04126 return peer; 04127 }
| static void realtime_update_peer | ( | const char * | peername, | |
| struct sockaddr_in * | sin, | |||
| const char * | username, | |||
| const char * | fullcontact, | |||
| const char * | useragent, | |||
| int | expirey, | |||
| int | deprecated_username, | |||
| int | lastms | |||
| ) | [static] |
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.
Definition at line 3749 of file chan_sip.c.
References ast_check_realtime(), ast_config_AST_SYSTEM_NAME, ast_copy_string(), ast_inet_ntoa(), ast_strlen_zero(), ast_update_realtime(), ipaddr, sip_settings::rtsave_sysname, SENTINEL, and sip_cfg.
03750 { 03751 char port[10]; 03752 char ipaddr[INET_ADDRSTRLEN]; 03753 char regseconds[20]; 03754 char *tablename = NULL; 03755 char str_lastms[20]; 03756 03757 const char *sysname = ast_config_AST_SYSTEM_NAME; 03758 char *syslabel = NULL; 03759 03760 time_t nowtime = time(NULL) + expirey; 03761 const char *fc = fullcontact ? "fullcontact" : NULL; 03762 03763 int realtimeregs = ast_check_realtime("sipregs"); 03764 03765 tablename = realtimeregs ? "sipregs" : "sippeers"; 03766 03767 03768 snprintf(str_lastms, sizeof(str_lastms), "%d", lastms); 03769 snprintf(regseconds, sizeof(regseconds), "%d", (int)nowtime); /* Expiration time */ 03770 ast_copy_string(ipaddr, ast_inet_ntoa(sin->sin_addr), sizeof(ipaddr)); 03771 snprintf(port, sizeof(port), "%d", ntohs(sin->sin_port)); 03772 03773 if (ast_strlen_zero(sysname)) /* No system name, disable this */ 03774 sysname = NULL; 03775 else if (sip_cfg.rtsave_sysname) 03776 syslabel = "regserver"; 03777 03778 if (fc) { 03779 ast_update_realtime(tablename, "name", peername, "ipaddr", ipaddr, 03780 "port", port, "regseconds", regseconds, 03781 deprecated_username ? "username" : "defaultuser", defaultuser, 03782 "useragent", useragent, "lastms", str_lastms, 03783 fc, fullcontact, syslabel, sysname, SENTINEL); /* note fc and syslabel _can_ be NULL */ 03784 } else { 03785 ast_update_realtime(tablename, "name", peername, "ipaddr", ipaddr, 03786 "port", port, "regseconds", regseconds, 03787 "useragent", useragent, "lastms", str_lastms, 03788 deprecated_username ? "username" : "defaultuser", defaultuser, 03789 syslabel, sysname, SENTINEL); /* note syslabel _can_ be NULL */ 03790 } 03791 }
| static void receive_message | ( | struct sip_pvt * | p, | |
| struct sip_request * | req | |||
| ) | [static] |
Receive SIP MESSAGE method messages.
Definition at line 12516 of file chan_sip.c.
References AST_FRAME_TEXT, ast_log(), ast_queue_frame(), ast_verbose, buf, sip_pvt::callid, DEFAULT_TRANS_TIMEOUT, f, FALSE, get_header(), get_msg_text(), LOG_WARNING, sip_pvt::owner, sip_debug_test_pvt(), sip_scheddestroy(), and transmit_response().
Referenced by handle_request_message().
12517 { 12518 char buf[1400]; 12519 struct ast_frame f; 12520 const char *content_type = get_header(req, "Content-Type"); 12521 12522 if (strncmp(content_type, "text/plain", strlen("text/plain"))) { /* No text/plain attachment */ 12523 transmit_response(p, "415 Unsupported Media Type", req); /* Good enough, or? */ 12524 if (!p->owner) 12525 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 12526 return; 12527 } 12528 12529 if (get_msg_text(buf, sizeof(buf), req, FALSE)) { 12530 ast_log(LOG_WARNING, "Unable to retrieve text from %s\n", p->callid); 12531 transmit_response(p, "202 Accepted", req); 12532 if (!p->owner) 12533 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 12534 return; 12535 } 12536 12537 if (p->owner) { 12538 if (sip_debug_test_pvt(p)) 12539 ast_verbose("SIP Text message received: '%s'\n", buf); 12540 memset(&f, 0, sizeof(f)); 12541 f.frametype = AST_FRAME_TEXT; 12542 f.subclass = 0; 12543 f.offset = 0; 12544 f.data.ptr = buf; 12545 f.datalen = strlen(buf); 12546 ast_queue_frame(p->owner, &f); 12547 transmit_response(p, "202 Accepted", req); /* We respond 202 accepted, since we relay the message */ 12548 return; 12549 } 12550 12551 /* Message outside of a call, we do not support that */ 12552 ast_log(LOG_WARNING, "Received message to %s from %s, dropped it...\n Content-Type:%s\n Message: %s\n", get_header(req, "To"), get_header(req, "From"), content_type, buf); 12553 transmit_response(p, "405 Method Not Allowed", req); 12554 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 12555 return; 12556 }
Definition at line 2497 of file chan_sip.c.
References ao2_t_ref.
Referenced by build_peer(), handle_request_subscribe(), handle_response_peerpoke(), parse_register_contact(), reg_source_db(), sip_poke_all_peers(), sip_poke_noanswer(), sip_poke_peer(), and sip_unregister().
02498 { 02499 ao2_t_ref(peer, 1, tag); 02500 return peer; 02501 }
maintain proper refcounts for a sip_pvt's outboundproxy
This function sets pvt's outboundproxy pointer to the one referenced by the proxy parameter. Because proxy may be a refcounted object, and because pvt's old outboundproxy may also be a refcounted object, we need to maintain the proper refcounts.
| pvt | The sip_pvt for which we wish to set the outboundproxy | |
| proxy | The sip_proxy which we will point pvt towards. |
Definition at line 2514 of file chan_sip.c.
References ao2_ref, global_outboundproxy, and sip_pvt::outboundproxy.
Referenced by __sip_ack(), create_addr(), create_addr_from_peer(), and transmit_register().
02515 { 02516 struct sip_proxy *old_obproxy = pvt->outboundproxy; 02517 /* Cool, now get the refs correct */ 02518 if (proxy && proxy != &global_outboundproxy) { 02519 ao2_ref(proxy, +1); 02520 } 02521 pvt->outboundproxy = proxy; 02522 if (old_obproxy && old_obproxy != &global_outboundproxy) { 02523 ao2_ref(old_obproxy, -1); 02524 } 02525 return proxy; 02526 }
| static const char * referstatus2str | ( | enum referstatus | rstatus | ) | [static] |
Convert transfer status to string.
Definition at line 2621 of file chan_sip.c.
References map_x_s(), and referstatusstrings.
Referenced by show_channels_cb().
02622 { 02623 return map_x_s(referstatusstrings, rstatus, ""); 02624 }
| static void reg_source_db | ( | struct sip_peer * | peer | ) | [static] |
Get registration details from Asterisk DB.
Definition at line 10442 of file chan_sip.c.
References sip_peer::addr, ast_copy_string(), ast_db_get(), ast_debug, ast_inet_ntoa(), ast_random(), AST_SCHED_REPLACE_UNREF, sip_request::data, sip_peer::expire, expire_register(), sip_peer::fullcontact, inet_aton(), sip_peer::name, sip_peer::pokeexpire, ref_peer(), register_peer_exten(), sip_peer::rt_fromcontact, sched, sip_poke_peer(), sip_poke_peer_s(), sipsock, strsep(), TRUE, unref_peer(), and sip_peer::username.
10443 { 10444 char data[256]; 10445 struct in_addr in; 10446 int expire; 10447 int port; 10448 char *scan, *addr, *port_str, *expiry_str, *username, *contact; 10449 10450 if (peer->rt_fromcontact) 10451 return; 10452 if (ast_db_get("SIP/Registry", peer->name, data, sizeof(data))) 10453 return; 10454 10455 scan = data; 10456 addr = strsep(&scan, ":"); 10457 port_str = strsep(&scan, ":"); 10458 expiry_str = strsep(&scan, ":"); 10459 username = strsep(&scan, ":"); 10460 contact = scan; /* Contact include sip: and has to be the last part of the database entry as long as we use : as a separator */ 10461 10462 if (!inet_aton(addr, &in)) 10463 return; 10464 10465 if (port_str) 10466 port = atoi(port_str); 10467 else 10468 return; 10469 10470 if (expiry_str) 10471 expire = atoi(expiry_str); 10472 else 10473 return; 10474 10475 if (username) 10476 ast_copy_string(peer->username, username, sizeof(peer->username)); 10477 if (contact) 10478 ast_copy_string(peer->fullcontact, contact, sizeof(peer->fullcontact)); 10479 10480 ast_debug(2, "SIP Seeding peer from astdb: '%s' at %s@%s:%d for %d\n", 10481 peer->name, peer->username, ast_inet_ntoa(in), port, expire); 10482 10483 memset(&peer->addr, 0, sizeof(peer->addr)); 10484 peer->addr.sin_family = AF_INET; 10485 peer->addr.sin_addr = in; 10486 peer->addr.sin_port = htons(port); 10487 if (sipsock < 0) { 10488 /* SIP isn't up yet, so schedule a poke only, pretty soon */ 10489 AST_SCHED_REPLACE_UNREF(peer->pokeexpire, sched, ast_random() % 5000 + 1, sip_poke_peer_s, peer, 10490 unref_peer(_data, "removing poke peer ref"), 10491 unref_peer(peer, "removing poke peer ref"), 10492 ref_peer(peer, "adding poke peer ref")); 10493 } else { 10494 sip_poke_peer(peer, 0); 10495 } 10496 AST_SCHED_REPLACE_UNREF(peer->expire, sched, (expire + 10) * 1000, expire_register, peer, 10497 unref_peer(_data, "remove registration ref"), 10498 unref_peer(peer, "remove registration ref"), 10499 ref_peer(peer, "add registration ref")); 10500 register_peer_exten(peer, TRUE); 10501 }
| static void register_peer_exten | ( | struct sip_peer * | peer, | |
| int | onoff | |||
| ) | [static] |
Automatically add peer extension to dial plan.
Definition at line 3794 of file chan_sip.c.
References ast_add_extension(), ast_context_find(), ast_context_remove_extension(), ast_copy_string(), ast_exists_extension(), ast_free_ptr, ast_log(), ast_strdup, ast_strlen_zero(), context, E_MATCH, ext, LOG_WARNING, sip_peer::name, pbx_find_extension(), sip_peer::regexten, S_OR, pbx_find_info::stacklen, and strsep().
03795 { 03796 char multi[256]; 03797 char *stringp, *ext, *context; 03798 struct pbx_find_info q = { .stacklen = 0 }; 03799 03800 /* XXX note that global_regcontext is both a global 'enable' flag and 03801 * the name of the global regexten context, if not specified 03802 * individually. 03803 */ 03804 if (ast_strlen_zero(global_regcontext)) 03805 return; 03806 03807 ast_copy_string(multi, S_OR(peer->regexten, peer->name), sizeof(multi)); 03808 stringp = multi; 03809 while ((ext = strsep(&stringp, "&"))) { 03810 if ((context = strchr(ext, '@'))) { 03811 *context++ = '\0'; /* split ext@context */ 03812 if (!ast_context_find(context)) { 03813 ast_log(LOG_WARNING, "Context %s must exist in regcontext= in sip.conf!\n", context); 03814 continue; 03815 } 03816 } else { 03817 context = global_regcontext; 03818 } 03819 if (onoff) { 03820 if (!ast_exists_extension(NULL, context, ext, 1, NULL)) { 03821 ast_add_extension(context, 1, ext, 1, NULL, NULL, "Noop", 03822 ast_strdup(peer->name), ast_free_ptr, "SIP"); 03823 } 03824 } else if (pbx_find_extension(NULL, NULL, &q, context, ext, 1, NULL, "", E_MATCH)) { 03825 ast_context_remove_extension(context, ext, 1, NULL); 03826 } 03827 } 03828 }
| static enum check_auth_result register_verify | ( | struct sip_pvt * | p, | |
| struct sockaddr_in * | sin, | |||
| struct sip_request * | req, | |||
| char * | uri | |||
| ) | [static] |
Verify registration of user
Definition at line 11253 of file chan_sip.c.
References sip_peer::addr, ao2_t_link, ast_apply_ha(), ast_copy_flags, ast_copy_string(), AST_DEVICE_UNKNOWN, ast_devstate_changed(), ast_inet_ntoa(), AST_LIST_EMPTY, ast_log(), ast_rtp_codec_setpref(), ast_set_flag, ast_string_field_set, ast_test_flag, ast_uri_decode(), AUTH_ACL_FAILED, AUTH_BAD_TRANSPORT, AUTH_NOT_FOUND, AUTH_PEER_NOT_DYNAMIC, AUTH_SECRET_FAILED, AUTH_UNKNOWN_DOMAIN, AUTH_USERNAME_MISMATCH, sip_peer::autoframing, sip_pvt::autoframing, build_contact(), check_auth(), check_request_transport, check_sip_domain(), EVENT_FLAG_SYSTEM, exten, FALSE, find_peer(), FINDPEERS, sip_peer::flags, sip_pvt::flags, get_header(), get_in_brackets(), sip_peer::ha, sip_peer::host_dynamic, sip_request::ignore, sip_pvt::initreq, sip_peer::lastmsgssent, LOG_ERROR, LOG_NOTICE, LOG_WARNING, manager_event, sip_peer::md5secret, sip_peer::name, name, parse_register_contact(), PARSE_REGISTER_FAILED, PARSE_REGISTER_QUERY, PARSE_REGISTER_UPDATE, peers_by_ip, sip_peer::prefs, remove_uri_parameters(), sip_pvt::rtp, sip_peer::secret, sip_cancel_destroy(), SIP_NAT, SIP_PAGE2_REGISTERTRYING, SIP_PAGE2_SUBSCRIBEMWIONLY, SIP_PENDINGBYE, SIP_REGISTER, temp_peer(), terminate_uri(), transmit_fake_auth_response(), transmit_response(), transmit_response_with_date(), TRUE, unref_peer(), update_peer(), and XMIT_UNRELIABLE.
11255 { 11256 enum check_auth_result res = AUTH_NOT_FOUND; 11257 struct sip_peer *peer; 11258 char tmp[256]; 11259 char *name, *c; 11260 char *domain; 11261 11262 terminate_uri(uri); /* warning, overwrite the string */ 11263 11264 ast_copy_string(tmp, get_header(req, "To"), sizeof(tmp)); 11265 if (pedanticsipchecking) 11266 ast_uri_decode(tmp); 11267 11268 c = get_in_brackets(tmp); 11269 c = remove_uri_parameters(c); 11270 11271 if (!strncasecmp(c, "sip:", 4)) { 11272 name = c + 4; 11273 } else if (!strncasecmp(c, "sips:", 5)) { 11274 name = c + 5; 11275 } else { 11276 name = c; 11277 ast_log(LOG_NOTICE, "Invalid to address: '%s' from %s (missing sip:) trying to use anyway...\n", c, ast_inet_ntoa(sin->sin_addr)); 11278 } 11279 11280 /* XXX here too we interpret a missing @domain as a name-only 11281 * URI, whereas the RFC says this is a domain-only uri. 11282 */ 11283 /* Strip off the domain name */ 11284 if ((c = strchr(name, '@'))) { 11285 *c++ = '\0'; 11286 domain = c; 11287 if ((c = strchr(domain, ':'))) /* Remove :port */ 11288 *c = '\0'; 11289 if (!AST_LIST_EMPTY(&domain_list)) { 11290 if (!check_sip_domain(domain, NULL, 0)) { 11291 transmit_response(p, "404 Not found (unknown domain)", &p->initreq); 11292 return AUTH_UNKNOWN_DOMAIN; 11293 } 11294 } 11295 } 11296 c = strchr(name, ';'); /* Remove any Username parameters */ 11297 if (c) 11298 *c = '\0'; 11299 11300 ast_string_field_set(p, exten, name); 11301 build_contact(p); 11302 peer = find_peer(name, NULL, TRUE, FINDPEERS, FALSE); 11303 if (!(peer && ast_apply_ha(peer->ha, sin))) { 11304 /* Peer fails ACL check */ 11305 if (peer) { 11306 unref_peer(peer, "register_verify: unref_peer: from find_peer operation"); 11307 peer = NULL; 11308 res = AUTH_ACL_FAILED; 11309 } else 11310 res = AUTH_NOT_FOUND; 11311 } 11312 11313 if (peer) { 11314 /* Set Frame packetization */ 11315 if (p->rtp) { 11316 ast_rtp_codec_setpref(p->rtp, &peer->prefs); 11317 p->autoframing = peer->autoframing; 11318 } 11319 if (!peer->host_dynamic) { 11320 ast_log(LOG_ERROR, "Peer '%s' is trying to register, but not configured as host=dynamic\n", peer->name); 11321 res = AUTH_PEER_NOT_DYNAMIC; 11322 } else { 11323 ast_copy_flags(&p->flags[0], &peer->flags[0], SIP_NAT); 11324 if (ast_test_flag(&p->flags[1], SIP_PAGE2_REGISTERTRYING)) 11325 transmit_response(p, "100 Trying", req); 11326 if (!(res = check_auth(p, req, peer->name, peer->secret, peer->md5secret, SIP_REGISTER, uri, XMIT_UNRELIABLE, req->ignore))) { 11327 if (sip_cancel_destroy(p)) 11328 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 11329 11330 if (check_request_transport(peer, req)) { 11331 ast_set_flag(&p->flags[0], SIP_PENDINGBYE); 11332 transmit_response_with_date(p, "403 Forbidden", req); 11333 res = AUTH_BAD_TRANSPORT; 11334 } else { 11335 11336 /* We have a successful registration attempt with proper authentication, 11337 now, update the peer */ 11338 switch (parse_register_contact(p, peer, req)) { 11339 case PARSE_REGISTER_FAILED: 11340 ast_log(LOG_WARNING, "Failed to parse contact info\n"); 11341 transmit_response_with_date(p, "400 Bad Request", req); 11342 peer->lastmsgssent = -1; 11343 res = 0; 11344 break; 11345 case PARSE_REGISTER_QUERY: 11346 transmit_response_with_date(p, "200 OK", req); 11347 peer->lastmsgssent = -1; 11348 res = 0; 11349 break; 11350 case PARSE_REGISTER_UPDATE: 11351 update_peer(peer, p->expiry); 11352 /* Say OK and ask subsystem to retransmit msg counter */ 11353 transmit_response_with_date(p, "200 OK", req); 11354 if (!ast_test_flag((&peer->flags[1]), SIP_PAGE2_SUBSCRIBEMWIONLY)) 11355 peer->lastmsgssent = -1; 11356 res = 0; 11357 break; 11358 } 11359 } 11360 11361 } 11362 } 11363 } 11364 if (!peer && autocreatepeer) { 11365 /* Create peer if we have autocreate mode enabled */ 11366 peer = temp_peer(name); 11367 if (peer) { 11368 ao2_t_link(peers, peer, "link peer into peer table"); 11369 if (peer->addr.sin_addr.s_addr) { 11370 ao2_t_link(peers_by_ip, peer, "link peer into peers-by-ip table"); 11371 } 11372 11373 if (sip_cancel_destroy(p)) 11374 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 11375 switch (parse_register_contact(p, peer, req)) { 11376 case PARSE_REGISTER_FAILED: 11377 ast_log(LOG_WARNING, "Failed to parse contact info\n"); 11378 transmit_response_with_date(p, "400 Bad Request", req); 11379 peer->lastmsgssent = -1; 11380 res = 0; 11381 break; 11382 case PARSE_REGISTER_QUERY: 11383 transmit_response_with_date(p, "200 OK", req); 11384 peer->lastmsgssent = -1; 11385 res = 0; 11386 break; 11387 case PARSE_REGISTER_UPDATE: 11388 /* Say OK and ask subsystem to retransmit msg counter */ 11389 transmit_response_with_date(p, "200 OK", req); 11390 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: SIP\r\nPeer: SIP/%s\r\nPeerStatus: Registered\r\nAddress: %s\r\nPort: %d\r\n", peer->name, ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port)); 11391 peer->lastmsgssent = -1; 11392 res = 0; 11393 break; 11394 } 11395 } 11396 } 11397 if (!peer && global_alwaysauthreject) { 11398 /* If we found a peer, we transmit a 100 Trying. Therefore, if we're 11399 * trying to avoid leaking information, we MUST also transmit the same 11400 * response when we DON'T find a peer. */ 11401 transmit_response(p, "100 Trying", req); 11402 /* Insert a fake delay between the 100 and the subsequent failure. */ 11403 sched_yield(); 11404 } 11405 if (!res) { 11406 ast_devstate_changed(AST_DEVICE_UNKNOWN, "SIP/%s", peer->name); 11407 } 11408 if (res < 0) { 11409 switch (res) { 11410 case AUTH_SECRET_FAILED: 11411 /* Wrong password in authentication. Go away, don't try again until you fixed it */ 11412 transmit_response(p, "403 Forbidden (Bad auth)", &p->initreq); 11413 if (global_authfailureevents) 11414 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: SIP\r\nPeer: SIP/%s\r\nPeerStatus: Rejected\r\nCause: AUTH_SECRET_FAILED\r\nAddress: %s\r\nPort: %d\r\n", 11415 name, ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port)); 11416 break; 11417 case AUTH_USERNAME_MISMATCH: 11418 /* Username and digest username does not match. 11419 Asterisk uses the From: username for authentication. We need the 11420 devices to use the same authentication user name until we support 11421 proper authentication by digest auth name */ 11422 transmit_response(p, "403 Authentication user name does not match account name", &p->initreq); 11423 if (global_authfailureevents) 11424 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: SIP\r\nPeer: SIP/%s\r\nPeerStatus: Rejected\r\nCause: AUTH_USERNAME_MISMATCH\r\nAddress: %s\r\nPort: %d\r\n", 11425 name, ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port)); 11426 break; 11427 case AUTH_NOT_FOUND: 11428 case AUTH_PEER_NOT_DYNAMIC: 11429 case AUTH_ACL_FAILED: 11430 if (global_alwaysauthreject) { 11431 transmit_fake_auth_response(p, SIP_REGISTER, &p->initreq, XMIT_UNRELIABLE); 11432 } else { 11433 /* URI not found */ 11434 if (res == AUTH_PEER_NOT_DYNAMIC) { 11435 transmit_response(p, "403 Forbidden", &p->initreq); 11436 if (global_authfailureevents) 11437 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: SIP\r\nPeer: SIP/%s\r\nPeerStatus: Rejected\r\nCause: AUTH_PEER_NOT_DYNAMIC\r\nAddress: %s\r\nPort: %d\r\n", 11438 name, ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port)); 11439 } 11440 else 11441 transmit_response(p, "404 Not found", &p->initreq); 11442 if (global_authfailureevents) 11443 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: SIP\r\nPeer: SIP/%s\r\nPeerStatus: Rejected\r\nCause: URI_NOT_FOUND\r\nAddress: %s\r\nPort: %d\r\n", 11444 name, ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port)); 11445 } 11446 break; 11447 case AUTH_BAD_TRANSPORT: 11448 default: 11449 break; 11450 } 11451 } 11452 if (peer) 11453 unref_peer(peer, "register_verify: unref_peer: tossing stack peer pointer at end of func"); 11454 11455 return res; 11456 }
| static struct sip_registry* registry_addref | ( | struct sip_registry * | reg, | |
| char * | tag | |||
| ) | [static] |
Add object reference to SIP registry.
Definition at line 2603 of file chan_sip.c.
References ast_debug, ASTOBJ_REF, sip_registry::hostname, and sip_registry::refcount.
Referenced by handle_response_register(), sip_send_all_registers(), and transmit_register().
02604 { 02605 ast_debug(3, "SIP Registry %s: refcount now %d\n", reg->hostname, reg->refcount + 1); 02606 return ASTOBJ_REF(reg); /* Add pointer to registry in packet */ 02607 }
| static void * registry_unref | ( | struct sip_registry * | reg, | |
| char * | tag | |||
| ) | [static] |
Definition at line 2595 of file chan_sip.c.
References ast_debug, ASTOBJ_UNREF, sip_registry::hostname, sip_registry::refcount, and sip_registry_destroy().
Referenced by __sip_destroy(), dialog_unlink_all(), handle_response_register(), sip_reg_timeout(), sip_register(), sip_registry_destroy(), sip_reregister(), sip_send_all_registers(), and transmit_register().
02596 { 02597 ast_debug(3, "SIP Registry %s: refcount now %d\n", reg->hostname, reg->refcount - 1); 02598 ASTOBJ_UNREF(reg, sip_registry_destroy); 02599 return NULL; 02600 }
| static const char * regstate2str | ( | enum sipregistrystate | regstate | ) | const [static] |
Convert registration state status to string.
Definition at line 9858 of file chan_sip.c.
References map_x_s(), and regstatestrings.
09859 { 09860 return map_x_s(regstatestrings, regstate, "Unknown"); 09861 }
| static int reload | ( | void | ) | [static] |
Part of Asterisk module interface.
Definition at line 23351 of file chan_sip.c.
References sip_reload().
23352 { 23353 if (sip_reload(0, 0, NULL)) 23354 return 0; 23355 return 1; 23356 }
| static int reload_config | ( | enum channelreloadreason | reason | ) | [static] |
Re-read SIP.conf config file.
< Type of address: IPv4
< Don't force proxy usage, use route: headers
< Keep track of hold status for a peer
< Match auth username if available instead of From: Default off.
< Default DTMF setting: RFC2833
< NAT support if requested by device with rport
< Allow re-invites
Definition at line 22051 of file chan_sip.c.
References ao2_t_callback, ast_clear_flag, ast_config_load, ast_debug, ast_free_ha(), ast_log(), AST_MAX_CONTEXT, ast_unload_realtime(), ASTOBJ_CONTAINER_DESTROYALL, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_RDLOCK, ASTOBJ_UNLOCK, authl, CHANNEL_MODULE_LOAD, clear_realm_authentication(), clear_sip_domains(), CONFIG_FLAG_FILEUNCHANGED, config_flags, CONFIG_STATUS_FILEUNCHANGED, context, default_tls_cfg, dialog_unlink_all(), dialog_unref(), dummy(), ast_tls_config::enabled, FALSE, global_contact_ha, ast_tcptls_session_args::local_address, LOG_NOTICE, OBJ_NODATA, peer_markall_func(), regl, sip_registry_destroy(), sip_tcp_desc, sip_tls_desc, STANDARD_SIP_PORT, STANDARD_TLS_PORT, and TRUE.
22052 { 22053 struct ast_config *cfg, *ucfg; 22054 struct ast_variable *v; 22055 struct sip_peer *peer; 22056 char *cat, *stringp, *context, *oldregcontext; 22057 char newcontexts[AST_MAX_CONTEXT], oldcontexts[AST_MAX_CONTEXT]; 22058 struct ast_flags dummy[2]; 22059 struct ast_flags config_flags = { reason == CHANNEL_MODULE_LOAD ? 0 : CONFIG_FLAG_FILEUNCHANGED }; 22060 int auto_sip_domains = FALSE; 22061 struct sockaddr_in old_bindaddr = bindaddr; 22062 int registry_count = 0, peer_count = 0; 22063 time_t run_start, run_end; 22064 22065 run_start = time(0); 22066 ast_unload_realtime("sipregs"); 22067 ast_unload_realtime("sippeers"); 22068 cfg = ast_config_load(config, config_flags); 22069 22070 /* We *must* have a config file otherwise stop immediately */ 22071 if (!cfg) { 22072 ast_log(LOG_NOTICE, "Unable to load config %s\n", config); 22073 return -1; 22074 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) { 22075 ucfg = ast_config_load("users.conf", config_flags); 22076 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) 22077 return 1; 22078 /* Must reread both files, because one changed */ 22079 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); 22080 cfg = ast_config_load(config, config_flags); 22081 } else { 22082 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); 22083 ucfg = ast_config_load("users.conf", config_flags); 22084 } 22085 22086 /* Initialize tcp sockets */ 22087 memset(&sip_tcp_desc.local_address, 0, sizeof(sip_tcp_desc.local_address)); 22088 memset(&sip_tls_desc.local_address, 0, sizeof(sip_tls_desc.local_address)); 22089 22090 ast_free_ha(global_contact_ha); 22091 global_contact_ha = NULL; 22092 22093 default_tls_cfg.enabled = FALSE; /* Default: Disable TLS */ 22094 22095 sip_tcp_desc.local_address.sin_port = htons(STANDARD_SIP_PORT); 22096 sip_tls_desc.local_address.sin_port = htons(STANDARD_TLS_PORT); 22097 22098 if (reason != CHANNEL_MODULE_LOAD) { 22099 ast_debug(4, "--------------- SIP reload started\n"); 22100 22101 clear_realm_authentication(authl); 22102 clear_sip_domains(); 22103 authl = NULL; 22104 22105 /* First, destroy all outstanding registry calls */ 22106 /* This is needed, since otherwise active registry entries will not be destroyed */ 22107 ASTOBJ_CONTAINER_TRAVERSE(®l, 1, do { /* regl is locked */ 22108 22109 /* avoid a deadlock in the unlink_all call, if iterator->call's (a dialog) registry entry 22110 is this registry entry. In other words, if the dialog we are pointing to points back to 22111 us, then if we get a lock on this object, and try to UNREF it, we will deadlock, because 22112 we already ... NO. This is not the problem. */ 22113 ASTOBJ_RDLOCK(iterator); /* now regl is locked, and the object is also locked */ 22114 if (iterator->call) { 22115 ast_debug(3, "Destroying active SIP dialog for registry %s@%s\n", iterator->username, iterator->hostname); 22116 /* This will also remove references to the registry */ 22117 dialog_unlink_all(iterator->call, TRUE, TRUE); 22118 iterator->call = dialog_unref(iterator->call, "remove iterator->call from registry traversal"); 22119 /* iterator->call = sip_destroy(iterator->call); */ 22120 } 22121 ASTOBJ_UNLOCK(iterator); 22122 22123 } while(0)); 22124 22125 /* Then, actually destroy users and registry */ 22126 ASTOBJ_CONTAINER_DESTROYALL(®l, sip_registry_destroy); 22127 ast_debug(4, "--------------- Done destroying registry list\n"); 22128 ao2_t_callback(peers, OBJ_NODATA, peer_markall_func, 0, "callback to mark all peers"); 22129 } 22130 22131 /* Reset certificate handling for TLS sessions */ 22132 if (reason != CHANNEL_MODULE_LOAD) { 22133 ast_free(default_tls_cfg.certfile); 22134 ast_free(default_tls_cfg.cipher); 22135 ast_free(default_tls_cfg.cafile); 22136 ast_free(default_tls_cfg.capath); 22137 } 22138 default_tls_cfg.certfile = ast_strdup(AST_CERTFILE); /*XXX Not sure if this is useful */ 22139 default_tls_cfg.cipher = ast_strdup(""); 22140 default_tls_cfg.cafile = ast_strdup(""); 22141 default_tls_cfg.capath = ast_strdup(""); 22142 22143 /* Initialize copy of current global_regcontext for later use in removing stale contexts */ 22144 ast_copy_string(oldcontexts, global_regcontext, sizeof(oldcontexts)); 22145 oldregcontext = oldcontexts; 22146 22147 /* Clear all flags before setting default values */ 22148 /* Preserve debugging settings for console */ 22149 sipdebug &= sip_debug_console; 22150 ast_clear_flag(&global_flags[0], AST_FLAGS_ALL); 22151 ast_clear_flag(&global_flags[1], AST_FLAGS_ALL); 22152 22153 /* Reset IP addresses */ 22154 memset(&bindaddr, 0, sizeof(bindaddr)); 22155 memset(&stunaddr, 0, sizeof(stunaddr)); 22156 memset(&internip, 0, sizeof(internip)); 22157 22158 /* Free memory for local network address mask */ 22159 ast_free_ha(localaddr); 22160 memset(&localaddr, 0, sizeof(localaddr)); 22161 memset(&externip, 0, sizeof(externip)); 22162 memset(&default_prefs, 0 , sizeof(default_prefs)); 22163 memset(&global_outboundproxy, 0, sizeof(struct sip_proxy)); 22164 global_outboundproxy.ip.sin_port = htons(STANDARD_SIP_PORT); 22165 global_outboundproxy.ip.sin_family = AF_INET; /*!< Type of address: IPv4 */ 22166 global_outboundproxy.force = FALSE; /*!< Don't force proxy usage, use route: headers */ 22167 ourport_tcp = STANDARD_SIP_PORT; 22168 ourport_tls = STANDARD_TLS_PORT; 22169 bindaddr.sin_port = htons(STANDARD_SIP_PORT); 22170 global_srvlookup = DEFAULT_SRVLOOKUP; 22171 global_tos_sip = DEFAULT_TOS_SIP; 22172 global_tos_audio = DEFAULT_TOS_AUDIO; 22173 global_tos_video = DEFAULT_TOS_VIDEO; 22174 global_tos_text = DEFAULT_TOS_TEXT; 22175 global_cos_sip = DEFAULT_COS_SIP; 22176 global_cos_audio = DEFAULT_COS_AUDIO; 22177 global_cos_video = DEFAULT_COS_VIDEO; 22178 global_cos_text = DEFAULT_COS_TEXT; 22179 22180 externhost[0] = '\0'; /* External host name (for behind NAT DynDNS support) */ 22181 externexpire = 0; /* Expiration for DNS re-issuing */ 22182 externrefresh = 10; 22183 22184 /* Reset channel settings to default before re-configuring */ 22185 allow_external_domains = DEFAULT_ALLOW_EXT_DOM; /* Allow external invites */ 22186 global_regcontext[0] = '\0'; 22187 global_regextenonqualify = DEFAULT_REGEXTENONQUALIFY; 22188 global_notifyringing = DEFAULT_NOTIFYRINGING; 22189 global_notifyhold = FALSE; /*!< Keep track of hold status for a peer */ 22190 global_directrtpsetup = FALSE; /* Experimental feature, disabled by default */ 22191 global_alwaysauthreject = 0; 22192 global_allowsubscribe = FALSE; 22193 snprintf(global_useragent, sizeof(global_useragent), "%s %s", DEFAULT_USERAGENT, ast_get_version()); 22194 snprintf(global_sdpsession, sizeof(global_sdpsession), "%s %s", DEFAULT_SDPSESSION, ast_get_version()); 22195 snprintf(global_sdpowner, sizeof(global_sdpowner), "%s", DEFAULT_SDPOWNER); 22196 ast_copy_string(default_notifymime, DEFAULT_NOTIFYMIME, sizeof(default_notifymime)); 22197 ast_copy_string(global_realm, S_OR(ast_config_AST_SYSTEM_NAME, DEFAULT_REALM), sizeof(global_realm)); 22198 ast_copy_string(default_callerid, DEFAULT_CALLERID, sizeof(default_callerid)); 22199 compactheaders = DEFAULT_COMPACTHEADERS; 22200 global_reg_timeout = DEFAULT_REGISTRATION_TIMEOUT; 22201 global_regattempts_max = 0; 22202 pedanticsipchecking = DEFAULT_PEDANTIC; 22203 autocreatepeer = DEFAULT_AUTOCREATEPEER; 22204 global_autoframing = 0; 22205 global_allowguest = DEFAULT_ALLOWGUEST; 22206 global_callcounter = DEFAULT_CALLCOUNTER; 22207 global_match_auth_username = FALSE; /*!< Match auth username if available instead of From: Default off. */ 22208 global_rtptimeout = 0; 22209 global_rtpholdtimeout = 0; 22210 global_rtpkeepalive = 0; 22211 global_allowtransfer = TRANSFER_OPENFORALL; /* Merrily accept all transfers by default */ 22212 global_rtautoclear = 120; 22213 ast_set_flag(&global_flags[1], SIP_PAGE2_ALLOWSUBSCRIBE); /* Default for all devices: TRUE */ 22214 ast_set_flag(&global_flags[1], SIP_PAGE2_ALLOWOVERLAP); /* Default for all devices: TRUE */ 22215 sip_cfg.peer_rtupdate = TRUE; 22216 22217 /* Session-Timers */ 22218 global_st_mode = SESSION_TIMER_MODE_ACCEPT; 22219 global_st_refresher = SESSION_TIMER_REFRESHER_UAS; 22220 global_min_se = DEFAULT_MIN_SE; 22221 global_max_se = DEFAULT_MAX_SE; 22222 22223 /* Initialize some reasonable defaults at SIP reload (used both for channel and as default for devices */ 22224 ast_copy_string(default_context, DEFAULT_CONTEXT, sizeof(default_context)); 22225 default_subscribecontext[0] = '\0'; 22226 default_language[0] = '\0'; 22227 default_fromdomain[0] = '\0'; 22228 default_qualify = DEFAULT_QUALIFY; 22229 default_maxcallbitrate = DEFAULT_MAX_CALL_BITRATE; 22230 ast_copy_string(default_mohinterpret, DEFAULT_MOHINTERPRET, sizeof(default_mohinterpret)); 22231 ast_copy_string(default_mohsuggest, DEFAULT_MOHSUGGEST, sizeof(default_mohsuggest)); 22232 ast_copy_string(default_vmexten, DEFAULT_VMEXTEN, sizeof(default_vmexten)); 22233 ast_set_flag(&global_flags[0], SIP_DTMF_RFC2833); /*!< Default DTMF setting: RFC2833 */ 22234 ast_set_flag(&global_flags[0], SIP_NAT_RFC3581); /*!< NAT support if requested by device with rport */ 22235 ast_set_flag(&global_flags[0], SIP_CAN_REINVITE); /*!< Allow re-invites */ 22236 22237 /* Debugging settings, always default to off */ 22238 dumphistory = FALSE; 22239 recordhistory = FALSE; 22240 sipdebug &= ~sip_debug_config; 22241 22242 /* Misc settings for the channel */ 22243 global_relaxdtmf = FALSE; 22244 global_callevents = FALSE; 22245 global_authfailureevents = FALSE; 22246 global_t1 = SIP_TIMER_T1; 22247 global_timer_b = 64 * SIP_TIMER_T1; 22248 global_t1min = DEFAULT_T1MIN; 22249 global_qualifyfreq = DEFAULT_QUALIFYFREQ; 22250 22251 global_matchexterniplocally = FALSE; 22252 22253 /* Copy the default jb config over global_jbconf */ 22254 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf)); 22255 22256 ast_clear_flag(&global_flags[1], SIP_PAGE2_VIDEOSUPPORT | SIP_PAGE2_VIDEOSUPPORT_ALWAYS); 22257 ast_clear_flag(&global_flags[1], SIP_PAGE2_TEXTSUPPORT); 22258 22259 22260 /* Read the [general] config section of sip.conf (or from realtime config) */ 22261 for (v = ast_variable_browse(cfg, "general"); v; v = v->next) { 22262 if (handle_common_options(&global_flags[0], &dummy[0], v)) 22263 continue; 22264 /* handle jb conf */ 22265 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) 22266 continue; 22267 22268 if (!strcasecmp(v->name, "context")) { 22269 ast_copy_string(default_context, v->value, sizeof(default_context)); 22270 } else if (!strcasecmp(v->name, "subscribecontext")) { 22271 ast_copy_string(default_subscribecontext, v->value, sizeof(default_subscribecontext)); 22272 } else if (!strcasecmp(v->name, "callcounter")) { 22273 global_callcounter = ast_true(v->value) ? 1 : 0; 22274 } else if (!strcasecmp(v->name, "allowguest")) { 22275 global_allowguest = ast_true(v->value) ? 1 : 0; 22276 } else if (!strcasecmp(v->name, "realm")) { 22277 ast_copy_string(global_realm, v->value, sizeof(global_realm)); 22278 } else if (!strcasecmp(v->name, "useragent")) { 22279 ast_copy_string(global_useragent, v->value, sizeof(global_useragent)); 22280 ast_debug(1, "Setting SIP channel User-Agent Name to %s\n", global_useragent); 22281 } else if (!strcasecmp(v->name, "sdpsession")) { 22282 ast_copy_string(global_sdpsession, v->value, sizeof(global_sdpsession)); 22283 } else if (!strcasecmp(v->name, "sdpowner")) { 22284 /* Field cannot contain spaces */ 22285 if (!strstr(v->value, " ")) 22286 ast_copy_string(global_sdpowner, v->value, sizeof(global_sdpowner)); 22287 else 22288 ast_log(LOG_WARNING, "'%s' must not contain spaces at line %d. Using default.\n", v->value, v->lineno); 22289 } else if (!strcasecmp(v->name, "allowtransfer")) { 22290 global_allowtransfer = ast_true(v->value) ? TRANSFER_OPENFORALL : TRANSFER_CLOSED; 22291 } else if (!strcasecmp(v->name, "rtcachefriends")) { 22292 ast_set2_flag(&global_flags[1], ast_true(v->value), SIP_PAGE2_RTCACHEFRIENDS); 22293 } else if (!strcasecmp(v->name, "rtsavesysname")) { 22294 sip_cfg.rtsave_sysname = ast_true(v->value); 22295 } else if (!strcasecmp(v->name, "rtupdate")) { 22296 sip_cfg.peer_rtupdate = ast_true(v->value); 22297 } else if (!strcasecmp(v->name, "ignoreregexpire")) { 22298 sip_cfg.ignore_regexpire = ast_true(v->value); 22299 } else if (!strcasecmp(v->name, "timert1")) { 22300 /* Defaults to 500ms, but RFC 3261 states that it is recommended 22301 * for the value to be set higher, though a lower value is only 22302 * allowed on private networks unconnected to the Internet. */ 22303 global_t1 = atoi(v->value); 22304 /* Note that timer B is dependent on the value of T1 */ 22305 global_timer_b = global_t1 * 64; 22306 } else if (!strcasecmp(v->name, "t1min")) { 22307 global_t1min = atoi(v->value); 22308 } else if (!strcasecmp(v->name, "tcpenable")) { 22309 sip_tcp_desc.local_address.sin_family = ast_false(v->value) ? 0 : AF_INET; 22310 ast_debug(2, "Enabling TCP socket for listening\n"); 22311 } else if (!strcasecmp(v->name, "tcpbindaddr")) { 22312 int family = sip_tcp_desc.local_address.sin_family; 22313 if (ast_parse_arg(v->value, PARSE_INADDR, &sip_tcp_desc.local_address)) 22314 ast_log(LOG_WARNING, "Invalid %s '%s' at line %d of %s\n", v->name, v->value, v->lineno, config); 22315 sip_tcp_desc.local_address.sin_family = family; 22316 ast_debug(2, "Setting TCP socket address to %s\n", v->value); 22317 } else if (!strcasecmp(v->name, "tlsenable")) { 22318 default_tls_cfg.enabled = ast_true(v->value) ? TRUE : FALSE; 22319 sip_tls_desc.local_address.sin_family = AF_INET; 22320 } else if (!strcasecmp(v->name, "tlscertfile")) { 22321 ast_free(default_tls_cfg.certfile); 22322 default_tls_cfg.certfile = ast_strdup(v->value); 22323 } else if (!strcasecmp(v->name, "tlscipher")) { 22324 ast_free(default_tls_cfg.cipher); 22325 default_tls_cfg.cipher = ast_strdup(v->value); 22326 } else if (!strcasecmp(v->name, "tlscafile")) { 22327 ast_free(default_tls_cfg.cafile); 22328 default_tls_cfg.cafile = ast_strdup(v->value); 22329 } else if (!strcasecmp(v->name, "tlscapath")) { 22330 ast_free(default_tls_cfg.capath); 22331 default_tls_cfg.capath = ast_strdup(v->value); 22332 } else if (!strcasecmp(v->name, "tlsverifyclient")) { 22333 ast_set2_flag(&default_tls_cfg.flags, ast_true(v->value), AST_SSL_VERIFY_CLIENT); 22334 } else if (!strcasecmp(v->name, "tlsdontverifyserver")) { 22335 ast_set2_flag(&default_tls_cfg.flags, ast_true(v->value), AST_SSL_DONT_VERIFY_SERVER); 22336 } else if (!strcasecmp(v->name, "tlsbindaddr")) { 22337 if (ast_parse_arg(v->value, PARSE_INADDR, &sip_tls_desc.local_address)) 22338 ast_log(LOG_WARNING, "Invalid %s '%s' at line %d of %s\n", v->name, v->value, v->lineno, config); 22339 } else if (!strcasecmp(v->name, "dynamic_exclude_static") || !strcasecmp(v->name, "dynamic_excludes_static")) { 22340 global_dynamic_exclude_static = ast_true(v->value); 22341 } else if (!strcasecmp(v->name, "contactpermit") || !strcasecmp(v->name, "contactdeny")) { 22342 int ha_error = 0; 22343 global_contact_ha = ast_append_ha(v->name + 7, v->value, global_contact_ha, &ha_error); 22344 if (ha_error) { 22345 ast_log(LOG_ERROR, "Bad ACL entry in configuration line %d : %s\n", v->lineno, v->value); 22346 } 22347 } else if (!strcasecmp(v->name, "rtautoclear")) { 22348 int i = atoi(v->value); 22349 if (i > 0) 22350 global_rtautoclear = i; 22351 else 22352 i = 0; 22353 ast_set2_flag(&global_flags[1], i || ast_true(v->value), SIP_PAGE2_RTAUTOCLEAR); 22354 } else if (!strcasecmp(v->name, "usereqphone")) { 22355 ast_set2_flag(&global_flags[0], ast_true(v->value), SIP_USEREQPHONE); 22356 } else if (!strcasecmp(v->name, "relaxdtmf")) { 22357 global_relaxdtmf = ast_true(v->value); 22358 } else if (!strcasecmp(v->name, "vmexten")) { 22359 ast_copy_string(default_vmexten, v->value, sizeof(default_vmexten)); 22360 } else if (!strcasecmp(v->name, "rtptimeout")) { 22361 if ((sscanf(v->value, "%d", &global_rtptimeout) != 1) || (global_rtptimeout < 0)) { 22362 ast_log(LOG_WARNING, "'%s' is not a valid RTP hold time at line %d. Using default.\n", v->value, v->lineno); 22363 global_rtptimeout = 0; 22364 } 22365 } else if (!strcasecmp(v->name, "rtpholdtimeout")) { 22366 if ((sscanf(v->value, "%d", &global_rtpholdtimeout) != 1) || (global_rtpholdtimeout < 0)) { 22367 ast_log(LOG_WARNING, "'%s' is not a valid RTP hold time at line %d. Using default.\n", v->value, v->lineno); 22368 global_rtpholdtimeout = 0; 22369 } 22370 } else if (!strcasecmp(v->name, "rtpkeepalive")) { 22371 if ((sscanf(v->value, "%d", &global_rtpkeepalive) != 1) || (global_rtpkeepalive < 0)) { 22372 ast_log(LOG_WARNING, "'%s' is not a valid RTP keepalive time at line %d. Using default.\n", v->value, v->lineno); 22373 global_rtpkeepalive = 0; 22374 } 22375 } else if (!strcasecmp(v->name, "compactheaders")) { 22376 compactheaders = ast_true(v->value); 22377 } else if (!strcasecmp(v->name, "notifymimetype")) { 22378 ast_copy_string(default_notifymime, v->value, sizeof(default_notifymime)); 22379 } else if (!strcasecmp(v->name, "directrtpsetup")) { 22380 global_directrtpsetup = ast_true(v->value); 22381 } else if (!strcasecmp(v->name, "notifyringing")) { 22382 global_notifyringing = ast_true(v->value); 22383 } else if (!strcasecmp(v->name, "notifyhold")) { 22384 global_notifyhold = ast_true(v->value); 22385 } else if (!strcasecmp(v->name, "alwaysauthreject")) { 22386 global_alwaysauthreject = ast_true(v->value); 22387 } else if (!strcasecmp(v->name, "mohinterpret")) { 22388 ast_copy_string(default_mohinterpret, v->value, sizeof(default_mohinterpret)); 22389 } else if (!strcasecmp(v->name, "mohsuggest")) { 22390 ast_copy_string(default_mohsuggest, v->value, sizeof(default_mohsuggest)); 22391 } else if (!strcasecmp(v->name, "language")) { 22392 ast_copy_string(default_language, v->value, sizeof(default_language)); 22393 } else if (!strcasecmp(v->name, "regcontext")) { 22394 ast_copy_string(newcontexts, v->value, sizeof(newcontexts)); 22395 stringp = newcontexts; 22396 /* Let's remove any contexts that are no longer defined in regcontext */ 22397 cleanup_stale_contexts(stringp, oldregcontext); 22398 /* Create contexts if they don't exist already */ 22399 while ((context = strsep(&stringp, "&"))) { 22400 ast_copy_string(used_context, context, sizeof(used_context)); 22401 ast_context_find_or_create(NULL, NULL, context, "SIP"); 22402 } 22403 ast_copy_string(global_regcontext, v->value, sizeof(global_regcontext)); 22404 } else if (!strcasecmp(v->name, "regextenonqualify")) { 22405 global_regextenonqualify = ast_true(v->value); 22406 } else if (!strcasecmp(v->name, "callerid")) { 22407 ast_copy_string(default_callerid, v->value, sizeof(default_callerid)); 22408 } else if (!strcasecmp(v->name, "fromdomain")) { 22409 ast_copy_string(default_fromdomain, v->value, sizeof(default_fromdomain)); 22410 } else if (!strcasecmp(v->name, "outboundproxy")) { 22411 int portnum; 22412 char *tok, *proxyname; 22413 22414 if (ast_strlen_zero(v->value)) { 22415 ast_log(LOG_WARNING, "no value given for outbound proxy on line %d of sip.conf.", v->lineno); 22416 continue; 22417 } 22418 22419 tok = ast_skip_blanks(strtok(ast_strdupa(v->value), ",")); 22420 22421 sip_parse_host(tok, v->lineno, &proxyname, &portnum, &global_outboundproxy.transport); 22422 22423 global_outboundproxy.ip.sin_port = htons(portnum); 22424 22425 if ((tok = strtok(NULL, ","))) { 22426 global_outboundproxy.force = !strncasecmp(ast_skip_blanks(tok), "force", 5); 22427 } else { 22428 global_outboundproxy.force = FALSE; 22429 } 22430 22431 if (ast_strlen_zero(proxyname)) { 22432 ast_log(LOG_WARNING, "you must specify a name for the outboundproxy on line %d of sip.conf.", v->lineno); 22433 global_outboundproxy.name[0] = '\0'; 22434 continue; 22435 } 22436 22437 ast_copy_string(global_outboundproxy.name, proxyname, sizeof(global_outboundproxy.name)); 22438 22439 proxy_update(&global_outboundproxy); 22440 } else if (!strcasecmp(v->name, "autocreatepeer")) { 22441 autocreatepeer = ast_true(v->value); 22442 } else if (!strcasecmp(v->name, "match_auth_username")) { 22443 global_match_auth_username = ast_true(v->value); 22444 } else if (!strcasecmp(v->name, "srvlookup")) { 22445 global_srvlookup = ast_true(v->value); 22446 } else if (!strcasecmp(v->name, "pedantic")) { 22447 pedanticsipchecking = ast_true(v->value); 22448 } else if (!strcasecmp(v->name, "maxexpirey") || !strcasecmp(v->name, "maxexpiry")) { 22449 max_expiry = atoi(v->value); 22450 if (max_expiry < 1) 22451 max_expiry = DEFAULT_MAX_EXPIRY; 22452 } else if (!strcasecmp(v->name, "minexpirey") || !strcasecmp(v->name, "minexpiry")) { 22453 min_expiry = atoi(v->value); 22454 if (min_expiry < 1) 22455 min_expiry = DEFAULT_MIN_EXPIRY; 22456 } else if (!strcasecmp(v->name, "defaultexpiry") || !strcasecmp(v->name, "defaultexpirey")) { 22457 default_expiry = atoi(v->value); 22458 if (default_expiry < 1) 22459 default_expiry = DEFAULT_DEFAULT_EXPIRY; 22460 } else if (!strcasecmp(v->name, "sipdebug")) { 22461 if (ast_true(v->value)) 22462 sipdebug |= sip_debug_config; 22463 } else if (!strcasecmp(v->name, "dumphistory")) { 22464 dumphistory = ast_true(v->value); 22465 } else if (!strcasecmp(v->name, "recordhistory")) { 22466 recordhistory = ast_true(v->value); 22467 } else if (!strcasecmp(v->name, "registertimeout")) { 22468 global_reg_timeout = atoi(v->value); 22469 if (global_reg_timeout < 1) 22470 global_reg_timeout = DEFAULT_REGISTRATION_TIMEOUT; 22471 } else if (!strcasecmp(v->name, "registerattempts")) { 22472 global_regattempts_max = atoi(v->value); 22473 } else if (!strcasecmp(v->name, "stunaddr")) { 22474 stunaddr.sin_port = htons(3478); 22475 if (ast_parse_arg(v->value, PARSE_INADDR, &stunaddr)) 22476 ast_log(LOG_WARNING, "Invalid STUN server address: %s\n", v->value); 22477 externexpire = time(NULL); 22478 } else if (!strcasecmp(v->name, "bindaddr") || !strcasecmp(v->name, "udpbindaddr")) { 22479 if (ast_parse_arg(v->value, PARSE_INADDR, &bindaddr)) 22480 ast_log(LOG_WARNING, "Invalid address: %s\n", v->value); 22481 } else if (!strcasecmp(v->name, "localnet")) { 22482 struct ast_ha *na; 22483 int ha_error = 0; 22484 22485 if (!(na = ast_append_ha("d", v->value, localaddr, &ha_error))) 22486 ast_log(LOG_WARNING, "Invalid localnet value: %s\n", v->value); 22487 else 22488 localaddr = na; 22489 if (ha_error) 22490 ast_log(LOG_ERROR, "Bad localnet configuration value line %d : %s\n", v->lineno, v->value); 22491 } else if (!strcasecmp(v->name, "externip")) { 22492 if (ast_parse_arg(v->value, PARSE_INADDR, &externip)) 22493 ast_log(LOG_WARNING, "Invalid address for externip keyword: %s\n", v->value); 22494 externexpire = 0; 22495 /* If no port was specified use the value of bindport */ 22496 if (!externip.sin_port) 22497 externip.sin_port = bindaddr.sin_port; 22498 } else if (!strcasecmp(v->name, "externhost")) { 22499 ast_copy_string(externhost, v->value, sizeof(externhost)); 22500 if (ast_parse_arg(externhost, PARSE_INADDR, &externip)) 22501 ast_log(LOG_WARNING, "Invalid address for externhost keyword: %s\n", externhost); 22502 externexpire = time(NULL); 22503 /* If no port was specified use the value of bindport */ 22504 if (!externip.sin_port) 22505 externip.sin_port = bindaddr.sin_port; 22506 } else if (!strcasecmp(v->name, "externrefresh")) { 22507 if (sscanf(v->value, "%d", &externrefresh) != 1) { 22508 ast_log(LOG_WARNING, "Invalid externrefresh value '%s', must be an integer >0 at line %d\n", v->value, v->lineno); 22509 externrefresh = 10; 22510 } 22511 } else if (!strcasecmp(v->name, "allow")) { 22512 int error = ast_parse_allow_disallow(&default_prefs, &global_capability, v->value, TRUE); 22513 if (error) 22514 ast_log(LOG_WARNING, "Codec configuration errors found in line %d : %s = %s\n", v->lineno, v->name, v->value); 22515 } else if (!strcasecmp(v->name, "disallow")) { 22516 int error = ast_parse_allow_disallow(&default_prefs, &global_capability, v->value, FALSE); 22517 if (error) 22518 ast_log(LOG_WARNING, "Codec configuration errors found in line %d : %s = %s\n", v->lineno, v->name, v->value); 22519 } else if (!strcasecmp(v->name, "autoframing")) { 22520 global_autoframing = ast_true(v->value); 22521 } else if (!strcasecmp(v->name, "allowexternaldomains")) { 22522 allow_external_domains = ast_true(v->value); 22523 } else if (!strcasecmp(v->name, "autodomain")) { 22524 auto_sip_domains = ast_true(v->value); 22525 } else if (!strcasecmp(v->name, "domain")) { 22526 char *domain = ast_strdupa(v->value); 22527 char *cntx = strchr(domain, ','); 22528 22529 if (cntx) 22530 *cntx++ = '\0'; 22531 22532 if (ast_strlen_zero(cntx)) 22533 ast_debug(1, "No context specified at line %d for domain '%s'\n", v->lineno, domain); 22534 if (ast_strlen_zero(domain)) 22535 ast_log(LOG_WARNING, "Empty domain specified at line %d\n", v->lineno); 22536 else 22537 add_sip_domain(ast_strip(domain), SIP_DOMAIN_CONFIG, cntx ? ast_strip(cntx) : ""); 22538 } else if (!strcasecmp(v->name, "register")) { 22539 if (sip_register(v->value, v->lineno) == 0) 22540 registry_count++; 22541 } else if (!strcasecmp(v->name, "tos_sip")) { 22542 if (ast_str2tos(v->value, &global_tos_sip)) 22543 ast_log(LOG_WARNING, "Invalid tos_sip value at line %d, refer to QoS documentation\n", v->lineno); 22544 } else if (!strcasecmp(v->name, "tos_audio")) { 22545 if (ast_str2tos(v->value, &global_tos_audio)) 22546 ast_log(LOG_WARNING, "Invalid tos_audio value at line %d, refer to QoS documentation\n", v->lineno); 22547 } else if (!strcasecmp(v->name, "tos_video")) { 22548 if (ast_str2tos(v->value, &global_tos_video)) 22549 ast_log(LOG_WARNING, "Invalid tos_video value at line %d, refer to QoS documentation\n", v->lineno); 22550 } else if (!strcasecmp(v->name, "tos_text")) { 22551 if (ast_str2tos(v->value, &global_tos_text)) 22552 ast_log(LOG_WARNING, "Invalid tos_text value at line %d, refer to QoS documentation\n", v->lineno); 22553 } else if (!strcasecmp(v->name, "cos_sip")) { 22554 if (ast_str2cos(v->value, &global_cos_sip)) 22555 ast_log(LOG_WARNING, "Invalid cos_sip value at line %d, refer to QoS documentation\n", v->lineno); 22556 } else if (!strcasecmp(v->name, "cos_audio")) { 22557 if (ast_str2cos(v->value, &global_cos_audio)) 22558 ast_log(LOG_WARNING, "Invalid cos_audio value at line %d, refer to QoS documentation\n", v->lineno); 22559 } else if (!strcasecmp(v->name, "cos_video")) { 22560 if (ast_str2cos(v->value, &global_cos_video)) 22561 ast_log(LOG_WARNING, "Invalid cos_video value at line %d, refer to QoS documentation\n", v->lineno); 22562 } else if (!strcasecmp(v->name, "cos_text")) { 22563 if (ast_str2cos(v->value, &global_cos_text)) 22564 ast_log(LOG_WARNING, "Invalid cos_text value at line %d, refer to QoS documentation\n", v->lineno); 22565 } else if (!strcasecmp(v->name, "bindport")) { 22566 int i; 22567 if (sscanf(v->value, "%d", &i) == 1) { 22568 bindaddr.sin_port = htons(i); 22569 } else { 22570 ast_log(LOG_WARNING, "Invalid port number '%s' at line %d of %s\n", v->value, v->lineno, config); 22571 } 22572 } else if (!strcasecmp(v->name, "hash_user")) { 22573 int i; 22574 if (sscanf(v->value, "%d", &i) == 1 && i > 2) { 22575 hash_user_size = i; 22576 } else { 22577 ast_log(LOG_WARNING, "Invalid hash_user size '%s' at line %d of %s -- should be much larger than 2\n", v->value, v->lineno, config); 22578 } 22579 } else if (!strcasecmp(v->name, "hash_peer")) { 22580 int i; 22581 if (sscanf(v->value, "%d", &i) == 1 && i > 2) { 22582 hash_peer_size = i; 22583 } else { 22584 ast_log(LOG_WARNING, "Invalid hash_peer size '%s' at line %d of %s -- should be much larger than 2\n", v->value, v->lineno, config); 22585 } 22586 } else if (!strcasecmp(v->name, "hash_dialog")) { 22587 int i; 22588 if (sscanf(v->value, "%d", &i) == 1 && i > 2) { 22589 hash_dialog_size = i; 22590 } else { 22591 ast_log(LOG_WARNING, "Invalid hash_dialog size '%s' at line %d of %s -- should be much larger than 2\n", v->value, v->lineno, config); 22592 } 22593 } else if (!strcasecmp(v->name, "qualify")) { 22594 if (!strcasecmp(v->value, "no")) { 22595 default_qualify = 0; 22596 } else if (!strcasecmp(v->value, "yes")) { 22597 default_qualify = DEFAULT_MAXMS; 22598 } else if (sscanf(v->value, "%d", &default_qualify) != 1) { 22599 ast_log(LOG_WARNING, "Qualification default should be 'yes', 'no', or a number of milliseconds at line %d of sip.conf\n", v->lineno); 22600 default_qualify = 0; 22601 } 22602 } else if (!strcasecmp(v->name, "qualifyfreq")) { 22603 int i; 22604 if (sscanf(v->value, "%d", &i) == 1) 22605 global_qualifyfreq = i * 1000; 22606 else { 22607 ast_log(LOG_WARNING, "Invalid qualifyfreq number '%s' at line %d of %s\n", v->value, v->lineno, config); 22608 global_qualifyfreq = DEFAULT_QUALIFYFREQ; 22609 } 22610 } else if (!strcasecmp(v->name, "callevents")) { 22611 global_callevents = ast_true(v->value); 22612 } else if (!strcasecmp(v->name, "authfailureevents")) { 22613 global_authfailureevents = ast_true(v->value); 22614 } else if (!strcasecmp(v->name, "maxcallbitrate")) { 22615 default_maxcallbitrate = atoi(v->value); 22616 if (default_maxcallbitrate < 0) 22617 default_maxcallbitrate = DEFAULT_MAX_CALL_BITRATE; 22618 } else if (!strcasecmp(v->name, "matchexterniplocally")) { 22619 global_matchexterniplocally = ast_true(v->value); 22620 } else if (!strcasecmp(v->name, "session-timers")) { 22621 int i = (int) str2stmode(v->value); 22622 if (i < 0) { 22623 ast_log(LOG_WARNING, "Invalid session-timers '%s' at line %d of %s\n", v->value, v->lineno, config); 22624 global_st_mode = SESSION_TIMER_MODE_ACCEPT; 22625 } else { 22626 global_st_mode = i; 22627 } 22628 } else if (!strcasecmp(v->name, "session-expires")) { 22629 if (sscanf(v->value, "%d", &global_max_se) != 1) { 22630 ast_log(LOG_WARNING, "Invalid session-expires '%s' at line %d of %s\n", v->value, v->lineno, config); 22631 global_max_se = DEFAULT_MAX_SE; 22632 } 22633 } else if (!strcasecmp(v->name, "session-minse")) { 22634 if (sscanf(v->value, "%d", &global_min_se) != 1) { 22635 ast_log(LOG_WARNING, "Invalid session-minse '%s' at line %d of %s\n", v->value, v->lineno, config); 22636 global_min_se = DEFAULT_MIN_SE; 22637 } 22638 if (global_min_se < 90) { 22639 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); 22640 global_min_se = DEFAULT_MIN_SE; 22641 } 22642 } else if (!strcasecmp(v->name, "session-refresher")) { 22643 int i = (int) str2strefresher(v->value); 22644 if (i < 0) { 22645 ast_log(LOG_WARNING, "Invalid session-refresher '%s' at line %d of %s\n", v->value, v->lineno, config); 22646 global_st_refresher = SESSION_TIMER_REFRESHER_UAS; 22647 } else { 22648 global_st_refresher = i; 22649 } 22650 } 22651 } 22652 22653 if (!allow_external_domains && AST_LIST_EMPTY(&domain_list)) { 22654 ast_log(LOG_WARNING, "To disallow external domains, you need to configure local SIP domains.\n"); 22655 allow_external_domains = 1; 22656 } 22657 22658 /* Build list of authentication to various SIP realms, i.e. service providers */ 22659 for (v = ast_variable_browse(cfg, "authentication"); v ; v = v->next) { 22660 /* Format for authentication is auth = username:password@realm */ 22661 if (!strcasecmp(v->name, "auth")) 22662 authl = add_realm_authentication(authl, v->value, v->lineno); 22663 } 22664 22665 if (ucfg) { 22666 struct ast_variable *gen; 22667 int genhassip, genregistersip; 22668 const char *hassip, *registersip; 22669 22670 genhassip = ast_true(ast_variable_retrieve(ucfg, "general", "hassip")); 22671 genregistersip = ast_true(ast_variable_retrieve(ucfg, "general", "registersip")); 22672 gen = ast_variable_browse(ucfg, "general"); 22673 cat = ast_category_browse(ucfg, NULL); 22674 while (cat) { 22675 if (strcasecmp(cat, "general")) { 22676 hassip = ast_variable_retrieve(ucfg, cat, "hassip"); 22677 registersip = ast_variable_retrieve(ucfg, cat, "registersip"); 22678 if (ast_true(hassip) || (!hassip && genhassip)) { 22679 peer = build_peer(cat, gen, ast_variable_browse(ucfg, cat), 0); 22680 if (peer) { 22681 ao2_t_link(peers, peer, "link peer into peer table"); 22682 if ((peer->type & SIP_TYPE_PEER) && peer->addr.sin_addr.s_addr) { 22683 ao2_t_link(peers_by_ip, peer, "link peer into peers_by_ip table"); 22684 } 22685 22686 unref_peer(peer, "unref_peer: from reload_config"); 22687 peer_count++; 22688 } 22689 } 22690 if (ast_true(registersip) || (!registersip && genregistersip)) { 22691 char tmp[256]; 22692 const char *host = ast_variable_retrieve(ucfg, cat, "host"); 22693 const char *username = ast_variable_retrieve(ucfg, cat, "username"); 22694 const char *secret = ast_variable_retrieve(ucfg, cat, "secret"); 22695 const char *contact = ast_variable_retrieve(ucfg, cat, "contact"); 22696 if (!host) 22697 host = ast_variable_retrieve(ucfg, "general", "host"); 22698 if (!username) 22699 username = ast_variable_retrieve(ucfg, "general", "username"); 22700 if (!secret) 22701 secret = ast_variable_retrieve(ucfg, "general", "secret"); 22702 if (!contact) 22703 contact = "s"; 22704 if (!ast_strlen_zero(username) && !ast_strlen_zero(host)) { 22705 if (!ast_strlen_zero(secret)) 22706 snprintf(tmp, sizeof(tmp), "%s:%s@%s/%s", username, secret, host, contact); 22707 else 22708 snprintf(tmp, sizeof(tmp), "%s@%s/%s", username, host, contact); 22709 if (sip_register(tmp, 0) == 0) 22710 registry_count++; 22711 } 22712 } 22713 } 22714 cat = ast_category_browse(ucfg, cat); 22715 } 22716 ast_config_destroy(ucfg); 22717 } 22718 22719 22720 /* Load peers, users and friends */ 22721 cat = NULL; 22722 while ( (cat = ast_category_browse(cfg, cat)) ) { 22723 const char *utype; 22724 if (!strcasecmp(cat, "general") || !strcasecmp(cat, "authentication")) 22725 continue; 22726 utype = ast_variable_retrieve(cfg, cat, "type"); 22727 if (!utype) { 22728 ast_log(LOG_WARNING, "Section '%s' lacks type\n", cat); 22729 continue; 22730 } else { 22731 if (!strcasecmp(utype, "user")) { 22732 ; 22733 } else if (!strcasecmp(utype, "friend")) { 22734 ; 22735 } else if (!strcasecmp(utype, "peer")) { 22736 ; 22737 } else { 22738 ast_log(LOG_WARNING, "Unknown type '%s' for '%s' in %s\n", utype, cat, "sip.conf"); 22739 continue; 22740 } 22741 peer = build_peer(cat, ast_variable_browse(cfg, cat), NULL, 0); 22742 if (peer) { 22743 ao2_t_link(peers, peer, "link peer into peers table"); 22744 if ((peer->type & SIP_TYPE_PEER) && peer->addr.sin_addr.s_addr) { 22745 ao2_t_link(peers_by_ip, peer, "link peer into peers_by_ip table"); 22746 } 22747 unref_peer(peer, "unref the result of the build_peer call. Now, the links from the tables are the only ones left."); 22748 peer_count++; 22749 } 22750 } 22751 } 22752 22753 /* Set UDP address and open socket */ 22754 bindaddr.sin_family = AF_INET; 22755 internip = bindaddr; 22756 if (ast_find_ourip(&internip.sin_addr, bindaddr)) { 22757 ast_log(LOG_WARNING, "Unable to get own IP address, SIP disabled\n"); 22758 ast_config_destroy(cfg); 22759 return 0; 22760 } 22761 ast_mutex_lock(&netlock); 22762 if ((sipsock > -1) && (memcmp(&old_bindaddr, &bindaddr, sizeof(struct sockaddr_in)))) { 22763 close(sipsock); 22764 sipsock = -1; 22765 } 22766 if (sipsock < 0) { 22767 sipsock = socket(AF_INET, SOCK_DGRAM, 0); 22768 if (sipsock < 0) { 22769 ast_log(LOG_WARNING, "Unable to create SIP socket: %s\n", strerror(errno)); 22770 ast_config_destroy(cfg); 22771 return -1; 22772 } else { 22773 /* Allow SIP clients on the same host to access us: */ 22774 const int reuseFlag = 1; 22775 22776 setsockopt(sipsock, SOL_SOCKET, SO_REUSEADDR, 22777 (const char*)&reuseFlag, 22778 sizeof reuseFlag); 22779 22780 ast_enable_packet_fragmentation(sipsock); 22781 22782 if (bind(sipsock, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) < 0) { 22783 ast_log(LOG_WARNING, "Failed to bind to %s:%d: %s\n", 22784 ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port), 22785 strerror(errno)); 22786 close(sipsock); 22787 sipsock = -1; 22788 } else { 22789 ast_verb(2, "SIP Listening on %s:%d\n", 22790 ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port)); 22791 ast_netsock_set_qos(sipsock, global_tos_sip, global_cos_sip, "SIP"); 22792 } 22793 } 22794 } 22795 if (stunaddr.sin_addr.s_addr != 0) { 22796 ast_debug(1, "stun to %s:%d\n", 22797 ast_inet_ntoa(stunaddr.sin_addr) , ntohs(stunaddr.sin_port)); 22798 ast_stun_request(sipsock, &stunaddr, 22799 NULL, &externip); 22800 ast_debug(1, "STUN sees us at %s:%d\n", 22801 ast_inet_ntoa(externip.sin_addr) , ntohs(externip.sin_port)); 22802 } 22803 ast_mutex_unlock(&netlock); 22804 22805 /* Start TCP server */ 22806 ast_tcptls_server_start(&sip_tcp_desc); 22807 22808 /* Start TLS server if needed */ 22809 memcpy(sip_tls_desc.tls_cfg, &default_tls_cfg, sizeof(default_tls_cfg)); 22810 22811 if (ast_ssl_setup(sip_tls_desc.tls_cfg)) 22812 ast_tcptls_server_start(&sip_tls_desc); 22813 else if (sip_tls_desc.tls_cfg->enabled) { 22814 sip_tls_desc.tls_cfg = NULL; 22815 ast_log(LOG_WARNING, "SIP TLS server did not load because of errors.\n"); 22816 } 22817 22818 22819 /* Add default domains - host name, IP address and IP:port 22820 * Only do this if user added any sip domain with "localdomains" 22821 * In order to *not* break backwards compatibility 22822 * Some phones address us at IP only, some with additional port number 22823 */ 22824 if (auto_sip_domains) { 22825 char temp[MAXHOSTNAMELEN]; 22826 22827 /* First our default IP address */ 22828 if (bindaddr.sin_addr.s_addr) 22829 add_sip_domain(ast_inet_ntoa(bindaddr.sin_addr), SIP_DOMAIN_AUTO, NULL); 22830 else 22831 ast_log(LOG_NOTICE, "Can't add wildcard IP address to domain list, please add IP address to domain manually.\n"); 22832 22833 /* If TCP is running on a different IP than UDP, then add it too */ 22834 if (sip_tcp_desc.local_address.sin_addr.s_addr && !inaddrcmp(&bindaddr, &sip_tcp_desc.local_address)) 22835 add_sip_domain(ast_inet_ntoa(sip_tcp_desc.local_address.sin_addr), SIP_DOMAIN_AUTO, NULL); 22836 22837 /* If TLS is running on a differen IP than UDP and TCP, then add that too */ 22838 if (sip_tls_desc.local_address.sin_addr.s_addr && !inaddrcmp(&bindaddr, &sip_tls_desc.local_address) && inaddrcmp(&sip_tcp_desc.local_address, &sip_tls_desc.local_address)) 22839 add_sip_domain(ast_inet_ntoa(sip_tls_desc.local_address.sin_addr), SIP_DOMAIN_AUTO, NULL); 22840 22841 /* Our extern IP address, if configured */ 22842 if (externip.sin_addr.s_addr) 22843 add_sip_domain(ast_inet_ntoa(externip.sin_addr), SIP_DOMAIN_AUTO, NULL); 22844 22845 /* Extern host name (NAT traversal support) */ 22846 if (!ast_strlen_zero(externhost)) 22847 add_sip_domain(externhost, SIP_DOMAIN_AUTO, NULL); 22848 22849 /* Our host name */ 22850 if (!gethostname(temp, sizeof(temp))) 22851 add_sip_domain(temp, SIP_DOMAIN_AUTO, NULL); 22852 } 22853 22854 /* Release configuration from memory */ 22855 ast_config_destroy(cfg); 22856 22857 /* Load the list of manual NOTIFY types to support */ 22858 if (notify_types) 22859 ast_config_destroy(notify_types); 22860 notify_types = ast_config_load(notify_config, config_flags); 22861 22862 /* Done, tell the manager */ 22863 manager_event(EVENT_FLAG_SYSTEM, "ChannelReload", "ChannelType: SIP\r\nReloadReason: %s\r\nRegistry_Count: %d\r\nPeer_Count: %d\r\n", channelreloadreason2txt(reason), registry_count, peer_count); 22864 run_end = time(0); 22865 ast_debug(4, "SIP reload_config done...Runtime= %d sec\n", (int)(run_end-run_start)); 22866 22867 return 0; 22868 }
| static char * remove_uri_parameters | ( | char * | uri | ) | [static] |
Definition at line 9112 of file chan_sip.c.
Referenced by extract_uri(), parse_moved_contact(), register_verify(), reqprep(), and transmit_state_notify().
09113 { 09114 char *atsign; 09115 atsign = strchr(uri, '@'); /* First, locate the at sign */ 09116 if (!atsign) 09117 atsign = uri; /* Ok hostname only, let's stick with the rest */ 09118 atsign = strchr(atsign, ';'); /* Locate semi colon */ 09119 if (atsign) 09120 *atsign = '\0'; /* Kill at the semi colon */ 09121 return uri; 09122 }
| static void replace_cid | ( | struct sip_pvt * | p, | |
| const char * | rpid_num, | |||
| const char * | calleridname | |||
| ) | [static] |
helper function for check_{user|peer}_ok()
Definition at line 12192 of file chan_sip.c.
References ast_is_shrinkable_phonenumber(), ast_shrink_phone_number(), ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, cid_name, cid_num, sip_pvt::flags, and SIP_TRUSTRPID.
Referenced by check_peer_ok(), and check_user_full().
12193 { 12194 /* replace callerid if rpid found, and not restricted */ 12195 if (!ast_strlen_zero(rpid_num) && ast_test_flag(&p->flags[0], SIP_TRUSTRPID)) { 12196 char *tmp = ast_strdupa(rpid_num); /* XXX the copy can be done later */ 12197 if (!ast_strlen_zero(calleridname)) 12198 ast_string_field_set(p, cid_name, calleridname); 12199 if (ast_is_shrinkable_phonenumber(tmp)) 12200 ast_shrink_phone_number(tmp); 12201 ast_string_field_set(p, cid_num, tmp); 12202 } 12203 }
| static int reply_digest | ( | struct sip_pvt * | p, | |
| struct sip_request * | req, | |||
| char * | header, | |||
| int | sipmethod, | |||
| char * | digest, | |||
| int | digest_len | |||
| ) | [static] |
reply to authentication for outbound registrations
Definition at line 15288 of file chan_sip.c.
References ast_copy_string(), ast_log(), ast_skip_blanks(), ast_string_field_ptr_set, ast_string_field_set, ast_strlen_zero(), build_reply_digest(), sip_pvt::domain, get_header(), LOG_WARNING, sip_registry::nonce, sip_pvt::nonce, sip_registry::noncecount, sip_pvt::noncecount, sip_registry::opaque, sip_pvt::opaque, sip_registry::qop, sip_pvt::qop, sip_registry::realm, sip_pvt::realm, sip_pvt::registry, and strsep().
Referenced by do_proxy_auth(), and do_register_auth().
15289 { 15290 char tmp[512]; 15291 char *c; 15292 char oldnonce[256]; 15293 15294 /* table of recognised keywords, and places where they should be copied */ 15295 const struct x { 15296 const char *key; 15297 const ast_string_field *field; 15298 } *i, keys[] = { 15299 { "realm=", &p->realm }, 15300 { "nonce=", &p->nonce }, 15301 { "opaque=", &p->opaque }, 15302 { "qop=", &p->qop }, 15303 { "domain=", &p->domain }, 15304 { NULL, 0 }, 15305 }; 15306 15307 ast_copy_string(tmp, get_header(req, header), sizeof(tmp)); 15308 if (ast_strlen_zero(tmp)) 15309 return -1; 15310 if (strncasecmp(tmp, "Digest ", strlen("Digest "))) { 15311 ast_log(LOG_WARNING, "missing Digest.\n"); 15312 return -1; 15313 } 15314 c = tmp + strlen("Digest "); 15315 ast_copy_string(oldnonce, p->nonce, sizeof(oldnonce)); 15316 while (c && *(c = ast_skip_blanks(c))) { /* lookup for keys */ 15317 for (i = keys; i->key != NULL; i++) { 15318 char *src, *separator; 15319 if (strncasecmp(c, i->key, strlen(i->key)) != 0) 15320 continue; 15321 /* Found. Skip keyword, take text in quotes or up to the separator. */ 15322 c += strlen(i->key); 15323 if (*c == '"') { 15324 src = ++c; 15325 separator = "\""; 15326 } else { 15327 src = c; 15328 separator = ","; 15329 } 15330 strsep(&c, separator); /* clear separator and move ptr */ 15331 ast_string_field_ptr_set(p, i->field, src); 15332 break; 15333 } 15334 if (i->key == NULL) /* not found, try ',' */ 15335 strsep(&c, ","); 15336 } 15337 /* Reset nonce count */ 15338 if (strcmp(p->nonce, oldnonce)) 15339 p->noncecount = 0; 15340 15341 /* Save auth data for following registrations */ 15342 if (p->registry) { 15343 struct sip_registry *r = p->registry; 15344 15345 if (strcmp(r->nonce, p->nonce)) { 15346 ast_string_field_set(r, realm, p->realm); 15347 ast_string_field_set(r, nonce, p->nonce); 15348 ast_string_field_set(r, domain, p->domain); 15349 ast_string_field_set(r, opaque, p->opaque); 15350 ast_string_field_set(r, qop, p->qop); 15351 r->noncecount = 0; 15352 } 15353 } 15354 return build_reply_digest(p, sipmethod, digest, digest_len); 15355 }
| static int reqprep | ( | struct sip_request * | req, | |
| struct sip_pvt * | p, | |||
| int | sipmethod, | |||
| int | seqno, | |||
| int | newbranch | |||
| ) | [static] |
Initialize a SIP request message (not the initial one in a dialog).
< Strict routing flag
Definition at line 8029 of file chan_sip.c.
References add_header(), add_route(), ast_copy_string(), ast_debug, ast_random(), ast_string_field_set, ast_strlen_zero(), ast_test_flag, sip_pvt::branch, build_via(), sip_pvt::callid, copy_header(), DEFAULT_MAX_FORWARDS, FALSE, sip_pvt::flags, get_header(), get_in_brackets(), sip_route::hop, init_req(), sip_pvt::initreq, sip_pvt::invite_branch, sip_pvt::lastmsg, sip_route::next, sip_pvt::ocseq, sip_pvt::okcontacturi, sip_pvt::our_contact, remove_uri_parameters(), REQ_OFFSET_TO_STR, sip_request::rlPart2, sip_pvt::route, sip_pvt::rpid, set_destination(), SIP_ACK, SIP_BYE, SIP_CANCEL, SIP_INVITE, SIP_MESSAGE, sip_methods, SIP_OUTGOING, sip_st_dlg::st_active, sip_st_dlg::st_active_peer_ua, st_get_se(), sip_st_dlg::st_interval, sip_st_dlg::st_ref, sip_pvt::stimer, strcasestr(), strefresher2str(), sip_pvt::tag, text, cfsip_methods::text, sip_pvt::theirtag, TRUE, sip_pvt::uri, url, sip_pvt::url, and sip_pvt::via.
08030 { 08031 struct sip_request *orig = &p->initreq; 08032 char stripped[80]; 08033 char tmp[80]; 08034 char newto[256]; 08035 const char *c; 08036 const char *ot, *of; 08037 int is_strict = FALSE; /*!< Strict routing flag */ 08038 int is_outbound = ast_test_flag(&p->flags[0], SIP_OUTGOING); /* Session direction */ 08039 08040 memset(req, 0, sizeof(struct sip_request)); 08041 08042 snprintf(p->lastmsg, sizeof(p->lastmsg), "Tx: %s", sip_methods[sipmethod].text); 08043 08044 if (!seqno) { 08045 p->ocseq++; 08046 seqno = p->ocseq; 08047 } 08048 08049 if (sipmethod == SIP_CANCEL || sipmethod == SIP_INVITE) { 08050 p->branch = p->invite_branch; 08051 build_via(p); 08052 } else if (newbranch) { 08053 p->branch ^= ast_random(); 08054 build_via(p); 08055 } 08056 08057 /* Check for strict or loose router */ 08058 if (p->route && !ast_strlen_zero(p->route->hop) && strstr(p->route->hop, ";lr") == NULL) { 08059 is_strict = TRUE; 08060 if (sipdebug) 08061 ast_debug(1, "Strict routing enforced for session %s\n", p->callid); 08062 } 08063 08064 if (sipmethod == SIP_CANCEL) 08065 c = REQ_OFFSET_TO_STR(&p->initreq, rlPart2); /* Use original URI */ 08066 else if (sipmethod == SIP_ACK) { 08067 /* Use URI from Contact: in 200 OK (if INVITE) 08068 (we only have the contacturi on INVITEs) */ 08069 if (!ast_strlen_zero(p->okcontacturi)) 08070 c = is_strict ? p->route->hop : p->okcontacturi; 08071 else 08072 c = REQ_OFFSET_TO_STR(&p->initreq, rlPart2); 08073 } else if (!ast_strlen_zero(p->okcontacturi)) 08074 c = is_strict ? p->route->hop : p->okcontacturi; /* Use for BYE or REINVITE */ 08075 else if (!ast_strlen_zero(p->uri)) 08076 c = p->uri; 08077 else { 08078 char *n; 08079 /* We have no URI, use To: or From: header as URI (depending on direction) */ 08080 ast_copy_string(stripped, get_header(orig, is_outbound ? "To" : "From"), 08081 sizeof(stripped)); 08082 n = get_in_brackets(stripped); 08083 c = remove_uri_parameters(n); 08084 } 08085 init_req(req, sipmethod, c); 08086 08087 snprintf(tmp, sizeof(tmp), "%d %s", seqno, sip_methods[sipmethod].text); 08088 08089 add_header(req, "Via", p->via); 08090 if (p->route) { 08091 set_destination(p, p->route->hop); 08092 add_route(req, is_strict ? p->route->next : p->route); 08093 } 08094 add_header(req, "Max-Forwards", DEFAULT_MAX_FORWARDS); 08095 08096 ot = get_header(orig, "To"); 08097 of = get_header(orig, "From"); 08098 08099 /* Add tag *unless* this is a CANCEL, in which case we need to send it exactly 08100 as our original request, including tag (or presumably lack thereof) */ 08101 if (!strcasestr(ot, "tag=") && sipmethod != SIP_CANCEL) { 08102 /* Add the proper tag if we don't have it already. If they have specified 08103 their tag, use it. Otherwise, use our own tag */ 08104 if (is_outbound && !ast_strlen_zero(p->theirtag)) 08105 snprintf(newto, sizeof(newto), "%s;tag=%s", ot, p->theirtag); 08106 else if (!is_outbound) 08107 snprintf(newto, sizeof(newto), "%s;tag=%s", ot, p->tag); 08108 else 08109 snprintf(newto, sizeof(newto), "%s", ot); 08110 ot = newto; 08111 } 08112 08113 if (is_outbound) { 08114 add_header(req, "From", of); 08115 add_header(req, "To", ot); 08116 } else { 08117 add_header(req, "From", ot); 08118 add_header(req, "To", of); 08119 } 08120 /* Do not add Contact for MESSAGE, BYE and Cancel requests */ 08121 if (sipmethod != SIP_BYE && sipmethod != SIP_CANCEL && sipmethod != SIP_MESSAGE) 08122 add_header(req, "Contact", p->our_contact); 08123 08124 copy_header(req, orig, "Call-ID"); 08125 add_header(req, "CSeq", tmp); 08126 08127 if (!ast_strlen_zero(global_useragent)) 08128 add_header(req, "User-Agent", global_useragent); 08129 08130 if (!ast_strlen_zero(p->rpid)) 08131 add_header(req, "Remote-Party-ID", p->rpid); 08132 08133 if (!ast_strlen_zero(p->url)) { 08134 add_header(req, "Access-URL", p->url); 08135 ast_string_field_set(p, url, NULL); 08136 } 08137 08138 /* Add Session-Timers related headers if the feature is active for this session. 08139 An exception to this behavior is the ACK request. Since Asterisk never requires 08140 session-timers support from a remote end-point (UAS) in an INVITE, it must 08141 not send 'Require: timer' header in the ACK request. 08142 This should only be added in the INVITE transactions, not MESSAGE or REFER or other 08143 in-dialog messages. 08144 */ 08145 if (p->stimer && p->stimer->st_active == TRUE && p->stimer->st_active_peer_ua == TRUE 08146 && sipmethod == SIP_INVITE) { 08147 char se_hdr[256]; 08148 snprintf(se_hdr, sizeof(se_hdr), "%d;refresher=%s", p->stimer->st_interval, 08149 strefresher2str(p->stimer->st_ref)); 08150 add_header(req, "Require", "timer"); 08151 add_header(req, "Session-Expires", se_hdr); 08152 snprintf(se_hdr, sizeof(se_hdr), "%d", st_get_se(p, FALSE)); 08153 add_header(req, "Min-SE", se_hdr); 08154 } 08155 08156 return 0; 08157 }
| static int resp_needs_contact | ( | const char * | msg, | |
| enum sipmethod | method | |||
| ) | [inline, static] |
Test if this response needs a contact header.
Definition at line 7904 of file chan_sip.c.
References SIP_ACK, SIP_BYE, SIP_CANCEL, SIP_INFO, SIP_INVITE, SIP_MESSAGE, SIP_NOTIFY, SIP_OPTIONS, SIP_PING, SIP_PRACK, SIP_PUBLISH, SIP_REFER, SIP_REGISTER, SIP_SUBSCRIBE, and SIP_UPDATE.
Referenced by respprep().
07904 { 07905 /* Requirements for Contact header inclusion in responses generated 07906 * from the header tables found in the following RFCs. Where the 07907 * Contact header was marked mandatory (m) or optional (o) this 07908 * function returns 1. 07909 * 07910 * - RFC 3261 (ACK, BYE, CANCEL, INVITE, OPTIONS, REGISTER) 07911 * - RFC 2976 (INFO) 07912 * - RFC 3262 (PRACK) 07913 * - RFC 3265 (SUBSCRIBE, NOTIFY) 07914 * - RFC 3311 (UPDATE) 07915 * - RFC 3428 (MESSAGE) 07916 * - RFC 3515 (REFER) 07917 * - RFC 3903 (PUBLISH) 07918 */ 07919 07920 switch (method) { 07921 /* 1xx, 2xx, 3xx, 485 */ 07922 case SIP_INVITE: 07923 case SIP_UPDATE: 07924 case SIP_SUBSCRIBE: 07925 case SIP_NOTIFY: 07926 if ((msg[0] >= '1' && msg[0] <= '3') || !strncmp(msg, "485", 3)) 07927 return 1; 07928 break; 07929 07930 /* 2xx, 3xx, 485 */ 07931 case SIP_REGISTER: 07932 case SIP_OPTIONS: 07933 if (msg[0] == '2' || msg[0] == '3' || !strncmp(msg, "485", 3)) 07934 return 1; 07935 break; 07936 07937 /* 3xx, 485 */ 07938 case SIP_BYE: 07939 case SIP_PRACK: 07940 case SIP_MESSAGE: 07941 case SIP_PUBLISH: 07942 if (msg[0] == '3' || !strncmp(msg, "485", 3)) 07943 return 1; 07944 break; 07945 07946 /* 2xx, 3xx, 4xx, 5xx, 6xx */ 07947 case SIP_REFER: 07948 if (msg[0] >= '2' && msg[0] <= '6') 07949 return 1; 07950 break; 07951 07952 /* contact will not be included for everything else */ 07953 case SIP_ACK: 07954 case SIP_CANCEL: 07955 case SIP_INFO: 07956 case SIP_PING: 07957 default: 07958 return 0; 07959 } 07960 return 0; 07961 }
| static int respprep | ( | struct sip_request * | resp, | |
| struct sip_pvt * | p, | |||
| const char * | msg, | |||
| const struct sip_request * | req | |||
| ) | [static] |
Prepare SIP response packet.
Definition at line 7965 of file chan_sip.c.
References add_header(), ALLOWED_METHODS, ast_copy_string(), ast_string_field_set, ast_strlen_zero(), ast_test_flag, copy_all_header(), copy_header(), copy_via_headers(), sip_pvt::expiry, sip_pvt::flags, get_header(), init_resp(), sip_pvt::method, sip_pvt::our_contact, resp_needs_contact(), SIP_INVITE, SIP_OUTGOING, SIP_REGISTER, SIP_SUBSCRIBE, SIPBUFSIZE, sip_st_dlg::st_active, sip_st_dlg::st_active_peer_ua, sip_st_dlg::st_interval, sip_st_dlg::st_ref, sip_pvt::stimer, strcasestr(), strefresher2str(), SUPPORTED_EXTENSIONS, sip_pvt::tag, sip_pvt::theirtag, TRUE, url, and sip_pvt::url.
07966 { 07967 char newto[256]; 07968 const char *ot; 07969 07970 init_resp(resp, msg); 07971 copy_via_headers(p, resp, req, "Via"); 07972 if (msg[0] == '1' || msg[0] == '2') 07973 copy_all_header(resp, req, "Record-Route"); 07974 copy_header(resp, req, "From"); 07975 ot = get_header(req, "To"); 07976 if (!strcasestr(ot, "tag=") && strncmp(msg, "100", 3)) { 07977 /* Add the proper tag if we don't have it already. If they have specified 07978 their tag, use it. Otherwise, use our own tag */ 07979 if (!ast_strlen_zero(p->theirtag) && ast_test_flag(&p->flags[0], SIP_OUTGOING)) 07980 snprintf(newto, sizeof(newto), "%s;tag=%s", ot, p->theirtag); 07981 else if (p->tag && !ast_test_flag(&p->flags[0], SIP_OUTGOING)) 07982 snprintf(newto, sizeof(newto), "%s;tag=%s", ot, p->tag); 07983 else 07984 ast_copy_string(newto, ot, sizeof(newto)); 07985 ot = newto; 07986 } 07987 add_header(resp, "To", ot); 07988 copy_header(resp, req, "Call-ID"); 07989 copy_header(resp, req, "CSeq"); 07990 if (!ast_strlen_zero(global_useragent)) 07991 add_header(resp, "Server", global_useragent); 07992 add_header(resp, "Allow", ALLOWED_METHODS); 07993 add_header(resp, "Supported", SUPPORTED_EXTENSIONS); 07994 07995 /* If this is an invite, add Session-Timers related headers if the feature is active for this session */ 07996 if (p->method == SIP_INVITE && p->stimer && p->stimer->st_active == TRUE && p->stimer->st_active_peer_ua == TRUE) { 07997 char se_hdr[256]; 07998 snprintf(se_hdr, sizeof(se_hdr), "%d;refresher=%s", p->stimer->st_interval, 07999 strefresher2str(p->stimer->st_ref)); 08000 add_header(resp, "Require", "timer"); 08001 add_header(resp, "Session-Expires", se_hdr); 08002 } 08003 08004 if (msg[0] == '2' && (p->method == SIP_SUBSCRIBE || p->method == SIP_REGISTER)) { 08005 /* For registration responses, we also need expiry and 08006 contact info */ 08007 char tmp[256]; 08008 08009 snprintf(tmp, sizeof(tmp), "%d", p->expiry); 08010 add_header(resp, "Expires", tmp); 08011 if (p->expiry) { /* Only add contact if we have an expiry time */ 08012 char contact[SIPBUFSIZE]; 08013 snprintf(contact, sizeof(contact), "%s;expires=%d", p->our_contact, p->expiry); 08014 add_header(resp, "Contact", contact); /* Not when we unregister */ 08015 } 08016 } else if (!ast_strlen_zero(p->our_contact) && resp_needs_contact(msg, p->method)) { 08017 add_header(resp, "Contact", p->our_contact); 08018 } 08019 08020 if (!ast_strlen_zero(p->url)) { 08021 add_header(resp, "Access-URL", p->url); 08022 ast_string_field_set(p, url, NULL); 08023 } 08024 08025 return 0; 08026 }
| static int restart_monitor | ( | void | ) | [static] |
Start the channel monitor thread.
Definition at line 20419 of file chan_sip.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create_background, AST_PTHREADT_NULL, AST_PTHREADT_STOP, do_monitor(), LOG_ERROR, LOG_WARNING, and monlock.
20420 { 20421 /* If we're supposed to be stopped -- stay stopped */ 20422 if (monitor_thread == AST_PTHREADT_STOP) 20423 return 0; 20424 ast_mutex_lock(&monlock); 20425 if (monitor_thread == pthread_self()) { 20426 ast_mutex_unlock(&monlock); 20427 ast_log(LOG_WARNING, "Cannot kill myself\n"); 20428 return -1; 20429 } 20430 if (monitor_thread != AST_PTHREADT_NULL) { 20431 /* Wake up the thread */ 20432 pthread_kill(monitor_thread, SIGURG); 20433 } else { 20434 /* Start a new monitor */ 20435 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) { 20436 ast_mutex_unlock(&monlock); 20437 ast_log(LOG_ERROR, "Unable to start monitor thread.\n"); 20438 return -1; 20439 } 20440 } 20441 ast_mutex_unlock(&monlock); 20442 return 0; 20443 }
| static void restart_session_timer | ( | struct sip_pvt * | p | ) | [static] |
Session-Timers: Restart session timer.
Definition at line 20447 of file chan_sip.c.
References ast_debug, ast_log(), AST_SCHED_DEL_UNREF, sip_pvt::callid, dialog_unref(), LOG_WARNING, sched, sip_st_dlg::st_active, sip_st_dlg::st_schedid, start_session_timer(), sip_pvt::stimer, and TRUE.
Referenced by handle_request_invite().
20448 { 20449 if (!p->stimer) { 20450 ast_log(LOG_WARNING, "Null stimer in restart_session_timer - %s\n", p->callid); 20451 return; 20452 } 20453 20454 if (p->stimer->st_active == TRUE) { 20455 AST_SCHED_DEL_UNREF(sched, p->stimer->st_schedid, 20456 dialog_unref(p, "Removing session timer ref")); 20457 ast_debug(2, "Session timer stopped: %d - %s\n", p->stimer->st_schedid, p->callid); 20458 start_session_timer(p); 20459 } 20460 }
| static int retrans_pkt | ( | const void * | data | ) | [static] |
Retransmit SIP message if no answer (Called from scheduler).
Definition at line 3022 of file chan_sip.c.
References __sip_xmit(), append_history, AST_CAUSE_NO_USER_RESPONSE, AST_CAUSE_PROTOCOL_ERROR, ast_channel_trylock, ast_channel_unlock, ast_debug, ast_free, ast_inet_ntoa(), ast_log(), ast_queue_hangup_with_cause(), ast_verbose, sip_pvt::callid, sip_pkt::data, DEFAULT_RETRANS, dialog_unref(), ast_channel::hangupcause, sip_pkt::is_fatal, sip_pkt::is_resp, LOG_WARNING, MAX_RETRANS, sip_pkt::method, sip_pvt::needdestroy, sip_pkt::next, sip_pvt::owner, sip_pkt::owner, sip_pkt::packetlen, sip_pvt::packets, sip_pkt::retrans, sip_pkt::retransid, sip_pkt::seqno, sip_alreadygone(), SIP_BYE, sip_debug_test_pvt(), SIP_INVITE, sip_methods, sip_nat_mode(), SIP_OPTIONS, sip_pvt_lock, sip_pvt_unlock, sip_real_dst(), SIP_REGISTER, ast_str::str, sip_pkt::timer_a, sip_pkt::timer_t1, UNLINK, and XMIT_ERROR.
03023 { 03024 struct sip_pkt *pkt = (struct sip_pkt *)data, *prev, *cur = NULL; 03025 int reschedule = DEFAULT_RETRANS; 03026 int xmitres = 0; 03027 03028 /* Lock channel PVT */ 03029 sip_pvt_lock(pkt->owner); 03030 03031 if (pkt->retrans < MAX_RETRANS) { 03032 pkt->retrans++; 03033 if (!pkt->timer_t1) { /* Re-schedule using timer_a and timer_t1 */ 03034 if (sipdebug) 03035 ast_debug(4, "SIP TIMER: Not rescheduling id #%d:%s (Method %d) (No timer T1)\n", pkt->retransid, sip_methods[pkt->method].text, pkt->method); 03036 } else { 03037 int siptimer_a; 03038 03039 if (sipdebug) 03040 ast_debug(4, "SIP TIMER: Rescheduling retransmission #%d (%d) %s - %d\n", pkt->retransid, pkt->retrans, sip_methods[pkt->method].text, pkt->method); 03041 if (!pkt->timer_a) 03042 pkt->timer_a = 2 ; 03043 else 03044 pkt->timer_a = 2 * pkt->timer_a; 03045 03046 /* For non-invites, a maximum of 4 secs */ 03047 siptimer_a = pkt->timer_t1 * pkt->timer_a; /* Double each time */ 03048 if (pkt->method != SIP_INVITE && siptimer_a > 4000) 03049 siptimer_a = 4000; 03050 03051 /* Reschedule re-transmit */ 03052 reschedule = siptimer_a; 03053 ast_debug(4, "** SIP timers: Rescheduling retransmission %d to %d ms (t1 %d ms (Retrans id #%d)) \n", pkt->retrans +1, siptimer_a, pkt->timer_t1, pkt->retransid); 03054 } 03055 03056 if (sip_debug_test_pvt(pkt->owner)) { 03057 const struct sockaddr_in *dst = sip_real_dst(pkt->owner); 03058 ast_verbose("Retransmitting #%d (%s) to %s:%d:\n%s\n---\n", 03059 pkt->retrans, sip_nat_mode(pkt->owner), 03060 ast_inet_ntoa(dst->sin_addr), 03061 ntohs(dst->sin_port), pkt->data->str); 03062 } 03063 03064 append_history(pkt->owner, "ReTx", "%d %s", reschedule, pkt->data->str); 03065 xmitres = __sip_xmit(pkt->owner, pkt->data, pkt->packetlen); 03066 sip_pvt_unlock(pkt->owner); 03067 if (xmitres == XMIT_ERROR) 03068 ast_log(LOG_WARNING, "Network error on retransmit in dialog %s\n", pkt->owner->callid); 03069 else 03070 return reschedule; 03071 } 03072 /* Too many retries */ 03073 if (pkt->owner && pkt->method != SIP_OPTIONS && xmitres == 0) { 03074 if (pkt->is_fatal || sipdebug) /* Tell us if it's critical or if we're debugging */ 03075 ast_log(LOG_WARNING, "Maximum retries exceeded on transmission %s for seqno %d (%s %s) -- See doc/sip-retransmit.txt.\n", 03076 pkt->owner->callid, pkt->seqno, 03077 pkt->is_fatal ? "Critical" : "Non-critical", pkt->is_resp ? "Response" : "Request"); 03078 } else if (pkt->method == SIP_OPTIONS && sipdebug) { 03079 ast_log(LOG_WARNING, "Cancelling retransmit of OPTIONs (call id %s) -- See doc/sip-retransmit.txt.\n", pkt->owner->callid); 03080 03081 } 03082 if (xmitres == XMIT_ERROR) { 03083 ast_log(LOG_WARNING, "Transmit error :: Cancelling transmission on Call ID %s\n", pkt->owner->callid); 03084 append_history(pkt->owner, "XmitErr", "%s", pkt->is_fatal ? "(Critical)" : "(Non-critical)"); 03085 } else 03086 append_history(pkt->owner, "MaxRetries", "%s", pkt->is_fatal ? "(Critical)" : "(Non-critical)"); 03087 03088 pkt->retransid = -1; 03089 03090 if (pkt->is_fatal) { 03091 while(pkt->owner->owner && ast_channel_trylock(pkt->owner->owner)) { 03092 sip_pvt_unlock(pkt->owner); /* SIP_PVT, not channel */ 03093 usleep(1); 03094 sip_pvt_lock(pkt->owner); 03095 } 03096 03097 if (pkt->owner->owner && !pkt->owner->owner->hangupcause) 03098 pkt->owner->owner->hangupcause = AST_CAUSE_NO_USER_RESPONSE; 03099 03100 if (pkt->owner->owner) { 03101 sip_alreadygone(pkt->owner); 03102 ast_log(LOG_WARNING, "Hanging up call %s - no reply to our critical packet (see doc/sip-retransmit.txt).\n", pkt->owner->callid); 03103 ast_queue_hangup_with_cause(pkt->owner->owner, AST_CAUSE_PROTOCOL_ERROR); 03104 ast_channel_unlock(pkt->owner->owner); 03105 } else { 03106 /* If no channel owner, destroy now */ 03107 03108 /* Let the peerpoke system expire packets when the timer expires for poke_noanswer */ 03109 if (pkt->method != SIP_OPTIONS && pkt->method != SIP_REGISTER) { 03110 pkt->owner->needdestroy = 1; 03111 sip_alreadygone(pkt->owner); 03112 append_history(pkt->owner, "DialogKill", "Killing this failed dialog immediately"); 03113 } 03114 } 03115 } 03116 03117 if (pkt->method == SIP_BYE) { 03118 /* We're not getting answers on SIP BYE's. Tear down the call anyway. */ 03119 if (pkt->owner->owner) 03120 ast_channel_unlock(pkt->owner->owner); 03121 append_history(pkt->owner, "ByeFailure", "Remote peer doesn't respond to bye. Destroying call anyway."); 03122 pkt->owner->needdestroy = 1; 03123 } 03124 03125 /* Remove the packet */ 03126 for (prev = NULL, cur = pkt->owner->packets; cur; prev = cur, cur = cur->next) { 03127 if (cur == pkt) { 03128 UNLINK(cur, pkt->owner->packets, prev); 03129 sip_pvt_unlock(pkt->owner); 03130 if (pkt->owner) 03131 pkt->owner = dialog_unref(pkt->owner,"pkt is being freed, its dialog ref is dead now"); 03132 if (pkt->data) 03133 ast_free(pkt->data); 03134 pkt->data = NULL; 03135 ast_free(pkt); 03136 return 0; 03137 } 03138 } 03139 /* error case */ 03140 ast_log(LOG_WARNING, "Weird, couldn't find packet owner!\n"); 03141 sip_pvt_unlock(pkt->owner); 03142 return 0; 03143 }
| static int scheduler_process_request_queue | ( | const void * | data | ) | [static] |
Definition at line 19789 of file chan_sip.c.
References ast_channel_trylock, sip_pvt::owner, sip_pvt_lock, and sip_pvt_unlock.
Referenced by queue_request().
19790 { 19791 struct sip_pvt *p = (struct sip_pvt *) data; 19792 int recount = 0; 19793 int nounlock = 0; 19794 int lockretry; 19795 19796 for (lockretry = 10; lockretry > 0; lockretry--) { 19797 sip_pvt_lock(p); 19798 19799 /* lock the owner if it has one -- we may need it */ 19800 /* because this is deadlock-prone, we need to try and unlock if failed */ 19801 if (!p->owner || !ast_channel_trylock(p->owner)) { 19802 break; /* locking succeeded */ 19803 } 19804 19805 if (lockretry != 1) { 19806 sip_pvt_unlock(p); 19807 /* Sleep for a very short amount of time */ 19808 usleep(1); 19809 } 19810 } 19811 19812 if (!lockretry) { 19813 int retry = !AST_LIST_EMPTY(&p->request_queue); 19814 19815 /* we couldn't get the owner lock, which is needed to process 19816 the queued requests, so return a non-zero value, which will 19817 cause the scheduler to run this request again later if there 19818 still requests to be processed 19819 */ 19820 sip_pvt_unlock(p); 19821 if (!retry) { 19822 dialog_unref(p, "The ref to a dialog passed to this sched callback is going out of scope; unref it."); 19823 } 19824 return retry; 19825 }; 19826 19827 process_request_queue(p, &recount, &nounlock); 19828 p->request_queue_sched_id = -1; 19829 19830 if (p->owner && !nounlock) { 19831 ast_channel_unlock(p->owner); 19832 } 19833 sip_pvt_unlock(p); 19834 19835 if (recount) { 19836 ast_update_use_count(); 19837 } 19838 19839 dialog_unref(p, "The ref to a dialog passed to this sched callback is going out of scope; unref it."); 19840 19841 return 0; 19842 }
| static int send_request | ( | struct sip_pvt * | p, | |
| struct sip_request * | req, | |||
| enum xmittype | reliable, | |||
| int | seqno | |||
| ) | [static] |
Send SIP Request to the other part of the dialogue.
Definition at line 3461 of file chan_sip.c.
References __sip_reliable_xmit(), __sip_xmit(), add_blank(), append_history, ast_free, ast_inet_ntoa(), ast_test_flag, ast_verbose, sip_request::data, sip_pvt::do_history, sip_pvt::flags, get_header(), sip_proxy::ip, sip_request::len, sip_request::method, sip_pvt::outboundproxy, parse_copy(), sip_pvt::recv, sip_request::rlPart1, sip_pvt::sa, sip_debug_test_pvt(), sip_methods, SIP_NAT_ROUTE, ast_str::str, and XMIT_CRITICAL.
03462 { 03463 int res; 03464 03465 /* If we have an outbound proxy, reset peer address 03466 Only do this once. 03467 */ 03468 if (p->outboundproxy) { 03469 p->sa = p->outboundproxy->ip; 03470 } 03471 03472 add_blank(req); 03473 if (sip_debug_test_pvt(p)) { 03474 if (ast_test_flag(&p->flags[0], SIP_NAT_ROUTE)) 03475 ast_verbose("%sTransmitting (NAT) to %s:%d:\n%s\n---\n", reliable ? "Reliably " : "", ast_inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port), req->data->str); 03476 else 03477 ast_verbose("%sTransmitting (no NAT) to %s:%d:\n%s\n---\n", reliable ? "Reliably " : "", ast_inet_ntoa(p->sa.sin_addr), ntohs(p->sa.sin_port), req->data->str); 03478 } 03479 if (p->do_history) { 03480 struct sip_request tmp = { .rlPart1 = 0, }; 03481 parse_copy(&tmp, req); 03482 append_history(p, reliable ? "TxReqRel" : "TxReq", "%s / %s - %s", tmp.data->str, get_header(&tmp, "CSeq"), sip_methods[tmp.method].text); 03483 ast_free(tmp.data); 03484 } 03485 res = (reliable) ? 03486 __sip_reliable_xmit(p, seqno, 0, req->data, req->len, (reliable == XMIT_CRITICAL), req->method) : 03487 __sip_xmit(p, req->data, req->len); 03488 if (req->data) { 03489 ast_free(req->data); 03490 req->data = NULL; 03491 } 03492 return res; 03493 }
| static int send_response | ( | struct sip_pvt * | p, | |
| struct sip_request * | req, | |||
| enum xmittype | reliable, | |||
| int | seqno | |||
| ) | [static] |
Transmit response on SIP request.
Definition at line 3430 of file chan_sip.c.
References __sip_reliable_xmit(), __sip_xmit(), add_blank(), append_history, ast_free, ast_inet_ntoa(), ast_verbose, sip_request::data, sip_pvt::do_history, get_header(), sip_request::len, sip_request::method, parse_copy(), REQ_OFFSET_TO_STR, sip_request::rlPart1, sip_request::rlPart2, sip_debug_test_pvt(), sip_methods, sip_nat_mode(), sip_real_dst(), SIP_RESPONSE, SIP_UNKNOWN, ast_str::str, cfsip_methods::text, and XMIT_CRITICAL.
03431 { 03432 int res; 03433 03434 add_blank(req); 03435 if (sip_debug_test_pvt(p)) { 03436 const struct sockaddr_in *dst = sip_real_dst(p); 03437 03438 ast_verbose("\n<--- %sTransmitting (%s) to %s:%d --->\n%s\n<------------>\n", 03439 reliable ? "Reliably " : "", sip_nat_mode(p), 03440 ast_inet_ntoa(dst->sin_addr), 03441 ntohs(dst->sin_port), req->data->str); 03442 } 03443 if (p->do_history) { 03444 struct sip_request tmp = { .rlPart1 = 0, }; 03445 parse_copy(&tmp, req); 03446 append_history(p, reliable ? "TxRespRel" : "TxResp", "%s / %s - %s", tmp.data->str, get_header(&tmp, "CSeq"), 03447 (tmp.method == SIP_RESPONSE || tmp.method == SIP_UNKNOWN) ? REQ_OFFSET_TO_STR(&tmp, rlPart2) : sip_methods[tmp.method].text); 03448 ast_free(tmp.data); 03449 } 03450 res = (reliable) ? 03451 __sip_reliable_xmit(p, seqno, 1, req->data, req->len, (reliable == XMIT_CRITICAL), req->method) : 03452 __sip_xmit(p, req->data, req->len); 03453 ast_free(req->data); 03454 req->data = NULL; 03455 if (res > 0) 03456 return 0; 03457 return res; 03458 }
| static int set_address_from_contact | ( | struct sip_pvt * | pvt | ) | [static] |
Change the other partys IP address based on given contact.
Definition at line 10568 of file chan_sip.c.
References __set_address_from_contact(), ast_test_flag, sip_pvt::flags, sip_pvt::fullcontact, sip_pvt::recv, sip_pvt::sa, SIP_NAT_ROUTE, SIP_TRANSPORT_TLS, sip_pvt::socket, and sip_socket::type.
Referenced by handle_response_invite().
10569 { 10570 if (ast_test_flag(&pvt->flags[0], SIP_NAT_ROUTE)) { 10571 /* NAT: Don't trust the contact field. Just use what they came to us 10572 with. */ 10573 pvt->sa = pvt->recv; 10574 return 0; 10575 } 10576 10577 return __set_address_from_contact(pvt->fullcontact, &pvt->sa, pvt->socket.type == SIP_TRANSPORT_TLS ? 1 : 0); 10578 }
| static void set_destination | ( | struct sip_pvt * | p, | |
| char * | uri | |||
| ) | [static] |
Set destination from SIP URI.
Definition at line 7810 of file chan_sip.c.
References ahp, ast_copy_string(), ast_gethostbyname(), ast_inet_ntoa(), ast_log(), ast_verbose, sip_request::debug, hostname, hp, LOG_WARNING, sip_pvt::sa, sip_debug_test_pvt(), and STANDARD_SIP_PORT.
Referenced by reqprep().
07811 { 07812 char *h, *maddr, hostname[256]; 07813 int port, hn; 07814 struct hostent *hp; 07815 struct ast_hostent ahp; 07816 int debug=sip_debug_test_pvt(p); 07817 07818 /* Parse uri to h (host) and port - uri is already just the part inside the <> */ 07819 /* general form we are expecting is sip[s]:username[:password][;parameter]@host[:port][;...] */ 07820 07821 if (debug) 07822 ast_verbose("set_destination: Parsing <%s> for address/port to send to\n", uri); 07823 07824 /* Find and parse hostname */ 07825 h = strchr(uri, '@'); 07826 if (h) 07827 ++h; 07828 else { 07829 h = uri; 07830 if (!strncasecmp(h, "sip:", 4)) 07831 h += 4; 07832 else if (!strncasecmp(h, "sips:", 5)) 07833 h += 5; 07834 } 07835 hn = strcspn(h, ":;>") + 1; 07836 if (hn > sizeof(hostname)) 07837 hn = sizeof(hostname); 07838 ast_copy_string(hostname, h, hn); 07839 /* XXX bug here if string has been trimmed to sizeof(hostname) */ 07840 h += hn - 1; 07841 07842 /* Is "port" present? if not default to STANDARD_SIP_PORT */ 07843 if (*h == ':') { 07844 /* Parse port */ 07845 ++h; 07846 port = strtol(h, &h, 10); 07847 } 07848 else 07849 port = STANDARD_SIP_PORT; 07850 07851 /* Got the hostname:port - but maybe there's a "maddr=" to override address? */ 07852 maddr = strstr(h, "maddr="); 07853 if (maddr) { 07854 maddr += 6; 07855 hn = strspn(maddr, "0123456789.") + 1; 07856 if (hn > sizeof(hostname)) 07857 hn = sizeof(hostname); 07858 ast_copy_string(hostname, maddr, hn); 07859 } 07860 07861 hp = ast_gethostbyname(hostname, &ahp); 07862 if (hp == NULL) { 07863 ast_log(LOG_WARNING, "Can't find address for host '%s'\n", hostname); 07864 return; 07865 } 07866 p->sa.sin_family = AF_INET; 07867 memcpy(&p->sa.sin_addr, hp->h_addr, sizeof(p->sa.sin_addr)); 07868 p->sa.sin_port = htons(port); 07869 if (debug) 07870 ast_verbose("set_destination: set destination to %s, port %d\n", ast_inet_ntoa(p->sa.sin_addr), port); 07871 }
| static void set_insecure_flags | ( | struct ast_flags * | flags, | |
| const char * | value, | |||
| int | lineno | |||
| ) | [static] |
Parse insecure= setting in sip.conf and set flags according to setting.
Definition at line 21152 of file chan_sip.c.
References ast_copy_string(), ast_false(), ast_log(), ast_set_flag, ast_strlen_zero(), buf, ast_channel::flags, LOG_WARNING, ast_channel::next, SIP_INSECURE_INVITE, SIP_INSECURE_PORT, and strsep().
Referenced by get_insecure_variable_from_config(), and handle_common_options().
21153 { 21154 if (ast_strlen_zero(value)) 21155 return; 21156 21157 if (!ast_false(value)) { 21158 char buf[64]; 21159 char *word, *next; 21160 21161 ast_copy_string(buf, value, sizeof(buf)); 21162 next = buf; 21163 while ((word = strsep(&next, ","))) { 21164 if (!strcasecmp(word, "port")) 21165 ast_set_flag(&flags[0], SIP_INSECURE_PORT); 21166 else if (!strcasecmp(word, "invite")) 21167 ast_set_flag(&flags[0], SIP_INSECURE_INVITE); 21168 else 21169 ast_log(LOG_WARNING, "Unknown insecure mode '%s' on line %d\n", value, lineno); 21170 } 21171 } 21172 }
| static void set_peer_defaults | ( | struct sip_peer * | peer | ) | [static] |
Set peer defaults before configuring specific configurations.
Definition at line 21472 of file chan_sip.c.
References sip_peer::addr, sip_peer::allowtransfer, ast_copy_flags, sip_peer::autoframing, sip_peer::call_limit, sip_peer::callgroup, sip_peer::capability, sip_peer::cid_name, sip_peer::cid_num, clear_peer_mailboxes(), sip_peer::context, sip_peer::defaddr, default_prefs, sip_peer::expire, sip_socket::fd, sip_peer::flags, sip_peer::fromdomain, sip_peer::fromuser, global_flags, sip_peer::language, sip_peer::maxcallbitrate, sip_peer::maxms, sip_peer::md5secret, sip_peer::mohinterpret, sip_peer::mohsuggest, sip_peer::pickupgroup, sip_peer::pokeexpire, sip_peer::prefs, sip_peer::qualifyfreq, sip_peer::regexten, sip_peer::rtpholdtimeout, sip_peer::rtpkeepalive, sip_peer::rtptimeout, sip_peer::secret, SIP_FLAGS_TO_COPY, SIP_PAGE2_FLAGS_TO_COPY, SIP_TRANSPORT_UDP, SIP_TYPE_PEER, sip_peer::socket, sip_st_cfg::st_max_se, sip_st_cfg::st_min_se, sip_st_cfg::st_mode_oper, sip_st_cfg::st_ref, STANDARD_SIP_PORT, sip_peer::stimer, sip_peer::subscribecontext, sip_peer::timer_b, sip_peer::timer_t1, sip_peer::type, sip_socket::type, and sip_peer::vmexten.
Referenced by build_peer(), and temp_peer().
21473 { 21474 if (peer->expire == 0) { 21475 /* Don't reset expire or port time during reload 21476 if we have an active registration 21477 */ 21478 peer->expire = -1; 21479 peer->pokeexpire = -1; 21480 peer->addr.sin_port = htons(STANDARD_SIP_PORT); 21481 peer->socket.type = SIP_TRANSPORT_UDP; 21482 peer->socket.fd = -1; 21483 } 21484 peer->type = SIP_TYPE_PEER; 21485 ast_copy_flags(&peer->flags[0], &global_flags[0], SIP_FLAGS_TO_COPY); 21486 ast_copy_flags(&peer->flags[1], &global_flags[1], SIP_PAGE2_FLAGS_TO_COPY); 21487 strcpy(peer->context, default_context); 21488 strcpy(peer->subscribecontext, default_subscribecontext); 21489 strcpy(peer->language, default_language); 21490 strcpy(peer->mohinterpret, default_mohinterpret); 21491 strcpy(peer->mohsuggest, default_mohsuggest); 21492 peer->addr.sin_family = AF_INET; 21493 peer->defaddr.sin_family = AF_INET; 21494 peer->capability = global_capability; 21495 peer->maxcallbitrate = default_maxcallbitrate; 21496 peer->rtptimeout = global_rtptimeout; 21497 peer->rtpholdtimeout = global_rtpholdtimeout; 21498 peer->rtpkeepalive = global_rtpkeepalive; 21499 peer->allowtransfer = global_allowtransfer; 21500 peer->autoframing = global_autoframing; 21501 peer->qualifyfreq = global_qualifyfreq; 21502 if (global_callcounter) 21503 peer->call_limit=999; 21504 strcpy(peer->vmexten, default_vmexten); 21505 peer->secret[0] = '\0'; 21506 peer->md5secret[0] = '\0'; 21507 peer->cid_num[0] = '\0'; 21508 peer->cid_name[0] = '\0'; 21509 peer->fromdomain[0] = '\0'; 21510 peer->fromuser[0] = '\0'; 21511 peer->regexten[0] = '\0'; 21512 peer->callgroup = 0; 21513 peer->pickupgroup = 0; 21514 peer->maxms = default_qualify; 21515 peer->prefs = default_prefs; 21516 peer->stimer.st_mode_oper = global_st_mode; /* Session-Timers */ 21517 peer->stimer.st_ref = global_st_refresher; 21518 peer->stimer.st_min_se = global_min_se; 21519 peer->stimer.st_max_se = global_max_se; 21520 peer->timer_t1 = global_t1; 21521 peer->timer_b = global_timer_b; 21522 clear_peer_mailboxes(peer); 21523 }
| static void set_t38_capabilities | ( | struct sip_pvt * | p | ) | [static] |
Set the global T38 capabilities on a SIP dialog structure.
Definition at line 4273 of file chan_sip.c.
References ast_udptl_get_error_correction_scheme(), t38properties::capability, sip_pvt::t38, T38FAX_RATE_MANAGEMENT_TRANSFERED_TCF, T38FAX_UDP_EC_FEC, T38FAX_UDP_EC_NONE, T38FAX_UDP_EC_REDUNDANCY, sip_pvt::udptl, UDPTL_ERROR_CORRECTION_FEC, UDPTL_ERROR_CORRECTION_NONE, and UDPTL_ERROR_CORRECTION_REDUNDANCY.
Referenced by create_addr_from_peer(), and sip_alloc().
04274 { 04275 p->t38.capability = global_t38_capability; 04276 if (p->udptl) { 04277 if (ast_udptl_get_error_correction_scheme(p->udptl) == UDPTL_ERROR_CORRECTION_FEC ) 04278 p->t38.capability |= T38FAX_UDP_EC_FEC; 04279 else if (ast_udptl_get_error_correction_scheme(p->udptl) == UDPTL_ERROR_CORRECTION_REDUNDANCY ) 04280 p->t38.capability |= T38FAX_UDP_EC_REDUNDANCY; 04281 else if (ast_udptl_get_error_correction_scheme(p->udptl) == UDPTL_ERROR_CORRECTION_NONE ) 04282 p->t38.capability |= T38FAX_UDP_EC_NONE; 04283 p->t38.capability |= T38FAX_RATE_MANAGEMENT_TRANSFERED_TCF; 04284 } 04285 }
| static int show_channels_cb | ( | void * | __cur, | |
| void * | __arg, | |||
| int | flags | |||
| ) | [static] |
callback for show channel|subscription
Definition at line 14411 of file chan_sip.c.
References ast_cli(), ast_extension_state2str(), ast_getformatname_multiple(), ast_inet_ntoa(), ast_str_alloca, ast_test_flag, sip_pvt::callid, sip_pvt::cid_num, cli_yesno(), sip_pvt::expiry, __show_chan_arg::fd, sip_pvt::flags, FORMAT, FORMAT4, sip_pvt::lastmsg, sip_pvt::laststate, ast_channel::nativeformats, sip_pvt::needdestroy, NONE, __show_chan_arg::numchans, sip_pvt::owner, peer_mailboxes_to_str(), sip_pvt::refer, referstatus2str(), sip_pvt::relatedpeer, S_OR, SIP_PAGE2_CALL_ONHOLD, sip_real_dst(), SIPBUFSIZE, sip_refer::status, ast_str::str, sip_pvt::subscribed, sip_pvt::subscribeuri, subscription_type2str(), __show_chan_arg::subscriptions, and sip_pvt::username.
Referenced by sip_show_channels().
14412 { 14413 struct sip_pvt *cur = __cur; 14414 struct __show_chan_arg *arg = __arg; 14415 const struct sockaddr_in *dst = sip_real_dst(cur); 14416 14417 /* XXX indentation preserved to reduce diff. Will be fixed later */ 14418 if (cur->subscribed == NONE && !arg->subscriptions) { 14419 /* set if SIP transfer in progress */ 14420 const char *referstatus = cur->refer ? referstatus2str(cur->refer->status) : ""; 14421 char formatbuf[SIPBUFSIZE/2]; 14422 14423 ast_cli(arg->fd, FORMAT, ast_inet_ntoa(dst->sin_addr), 14424 S_OR(cur->username, S_OR(cur->cid_num, "(None)")), 14425 cur->callid, 14426 ast_getformatname_multiple(formatbuf, sizeof(formatbuf), cur->owner ? cur->owner->nativeformats : 0), 14427 cli_yesno(ast_test_flag(&cur->flags[1], SIP_PAGE2_CALL_ONHOLD)), 14428 cur->needdestroy ? "(d)" : "", 14429 cur->lastmsg , 14430 referstatus 14431 ); 14432 arg->numchans++; 14433 } 14434 if (cur->subscribed != NONE && arg->subscriptions) { 14435 struct ast_str *mailbox_str = ast_str_alloca(512); 14436 if (cur->subscribed == MWI_NOTIFICATION && cur->relatedpeer) 14437 peer_mailboxes_to_str(&mailbox_str, cur->relatedpeer); 14438 ast_cli(arg->fd, FORMAT4, ast_inet_ntoa(dst->sin_addr), 14439 S_OR(cur->username, S_OR(cur->cid_num, "(None)")), 14440 cur->callid, 14441 /* the 'complete' exten/context is hidden in the refer_to field for subscriptions */ 14442 cur->subscribed == MWI_NOTIFICATION ? "--" : cur->subscribeuri, 14443 cur->subscribed == MWI_NOTIFICATION ? "<none>" : ast_extension_state2str(cur->laststate), 14444 subscription_type2str(cur->subscribed), 14445 cur->subscribed == MWI_NOTIFICATION ? S_OR(mailbox_str->str, "<none>") : "<none>", 14446 cur->expiry 14447 ); 14448 arg->numchans++; 14449 } 14450 return 0; /* don't care, we scan all channels */ 14451 }
| static int show_chanstats_cb | ( | void * | __cur, | |
| void * | __arg, | |||
| int | flags | |||
| ) | [static] |
Callback for show_chanstats.
Definition at line 14092 of file chan_sip.c.
References ast_cli(), ast_inet_ntoa(), ast_rtp_get_qosvalue(), AST_RTP_RXCOUNT, AST_RTP_RXJITTER, AST_RTP_RXPLOSS, AST_RTP_TXCOUNT, AST_RTP_TXJITTER, AST_RTP_TXPLOSS, ast_tvdiff_ms(), ast_tvnow(), ast_tvzero(), sip_pvt::callid, ast_channel::cdr, __show_chan_arg::fd, FORMAT, sip_pvt::invitestate, invitestate2string, NONE, __show_chan_arg::numchans, sip_pvt::owner, sip_pvt::rtp, sip_pvt::sa, ast_cdr::start, and sip_pvt::subscribed.
Referenced by sip_show_channelstats().
14093 { 14094 #define FORMAT2 "%-15.15s %-11.11s %-8.8s %-10.10s %-10.10s (%-2.2s) %-6.6s %-10.10s %-10.10s ( %%) %-6.6s\n" 14095 #define FORMAT "%-15.15s %-11.11s %-8.8s %-10.10u%-1.1s %-10.10u (%-2.2u%%) %-6.6u %-10.10u%-1.1s %-10.10u (%-2.2u%%) %-6.6u\n" 14096 struct sip_pvt *cur = __cur; 14097 unsigned int rxcount; 14098 unsigned int txcount; 14099 char durbuf[10]; 14100 int duration; 14101 int durh, durm, durs; 14102 struct ast_channel *c = cur->owner; 14103 struct __show_chan_arg *arg = __arg; 14104 int fd = arg->fd; 14105 14106 14107 if (cur->subscribed != NONE) /* Subscriptions */ 14108 return 0; /* don't care, we scan all channels */ 14109 14110 if (!cur->rtp) { 14111 if (sipdebug) 14112 ast_cli(fd, "%-15.15s %-11.11s (inv state: %s) -- %s\n", ast_inet_ntoa(cur->sa.sin_addr), cur->callid, invitestate2string[cur->invitestate].desc, "-- No RTP active"); 14113 return 0; /* don't care, we scan all channels */ 14114 } 14115 rxcount = ast_rtp_get_qosvalue(cur->rtp, AST_RTP_RXCOUNT); 14116 txcount = ast_rtp_get_qosvalue(cur->rtp, AST_RTP_TXCOUNT); 14117 14118 /* Find the duration of this channel */ 14119 if (c && c->cdr && !ast_tvzero(c->cdr->start)) { 14120 duration = (int)(ast_tvdiff_ms(ast_tvnow(), c->cdr->start) / 1000); 14121 durh = duration / 3600; 14122 durm = (duration % 3600) / 60; 14123 durs = duration % 60; 14124 snprintf(durbuf, sizeof(durbuf), "%02d:%02d:%02d", durh, durm, durs); 14125 } else { 14126 durbuf[0] = '\0'; 14127 } 14128 /* Print stats for every call with RTP */ 14129 ast_cli(fd, FORMAT, 14130 ast_inet_ntoa(cur->sa.sin_addr), 14131 cur->callid, 14132 durbuf, 14133 rxcount > (unsigned int) 100000 ? (unsigned int) (rxcount)/(unsigned int) 1000 : rxcount, 14134 rxcount > (unsigned int) 100000 ? "K":" ", 14135 ast_rtp_get_qosvalue(cur->rtp, AST_RTP_RXPLOSS), 14136 rxcount > ast_rtp_get_qosvalue(cur->rtp, AST_RTP_RXPLOSS) ? (unsigned int) (ast_rtp_get_qosvalue(cur->rtp, AST_RTP_RXPLOSS) / rxcount * 100) : 0, 14137 ast_rtp_get_qosvalue(cur->rtp, AST_RTP_RXJITTER), 14138 txcount > (unsigned int) 100000 ? (unsigned int) (txcount)/(unsigned int) 1000 : txcount, 14139 txcount > (unsigned int) 100000 ? "K":" ", 14140 ast_rtp_get_qosvalue(cur->rtp, AST_RTP_TXPLOSS), 14141 txcount > ast_rtp_get_qosvalue(cur->rtp, AST_RTP_TXPLOSS) ? (unsigned int) (ast_rtp_get_qosvalue(cur->rtp, AST_RTP_TXPLOSS)/ txcount * 100) : 0, 14142 ast_rtp_get_qosvalue(cur->rtp, AST_RTP_TXJITTER) 14143 ); 14144 arg->numchans++; 14145 14146 return 0; /* don't care, we scan all channels */ 14147 }
| static int sip_addheader | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Add a SIP header to an outbound INVITE.
Definition at line 23138 of file chan_sip.c.
References ast_channel_lock, ast_channel_unlock, ast_debug, ast_get_encoded_str(), ast_log(), ast_strlen_zero(), chan, FALSE, inbuf(), len(), LOG_WARNING, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), and TRUE.
Referenced by load_module().
23139 { 23140 int no = 0; 23141 int ok = FALSE; 23142 char varbuf[30]; 23143 char *inbuf = data, *subbuf; 23144 23145 if (ast_strlen_zero(inbuf)) { 23146 ast_log(LOG_WARNING, "This application requires the argument: Header\n"); 23147 return 0; 23148 } 23149 ast_channel_lock(chan); 23150 23151 /* Check for headers */ 23152 while (!ok && no <= 50) { 23153 no++; 23154 snprintf(varbuf, sizeof(varbuf), "__SIPADDHEADER%.2d", no); 23155 23156 /* Compare without the leading underscores */ 23157 if ((pbx_builtin_getvar_helper(chan, (const char *) varbuf + 2) == (const char *) NULL)) { 23158 ok = TRUE; 23159 } 23160 } 23161 if (ok) { 23162 size_t len = strlen(inbuf); 23163 subbuf = alloca(len + 1); 23164 ast_get_encoded_str(inbuf, subbuf, len + 1); 23165 pbx_builtin_setvar_helper(chan, varbuf, subbuf); 23166 if (sipdebug) { 23167 ast_debug(1, "SIP Header added \"%s\" as %s\n", inbuf, varbuf); 23168 } 23169 } else { 23170 ast_log(LOG_WARNING, "Too many SIP headers added, max 50\n"); 23171 } 23172 ast_channel_unlock(chan); 23173 return 0; 23174 }
| static struct sip_pvt * sip_alloc | ( | ast_string_field | callid, | |
| struct sockaddr_in * | sin, | |||
| int | useglobal_nat, | |||
| const int | intended_method | |||
| ) | [static] |
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.
Definition at line 6213 of file chan_sip.c.
References ao2_t_alloc, ao2_t_link, ao2_t_ref, ast_copy_flags, ast_debug, AST_LIST_HEAD_INIT_NOLOCK, ast_log(), ast_random(), ast_rtp_codec_setpref(), AST_RTP_DTMF, ast_rtp_new_with_bindaddr(), ast_rtp_set_rtpholdtimeout(), ast_rtp_set_rtpkeepalive(), ast_rtp_set_rtptimeout(), ast_rtp_setdtmf(), ast_rtp_setdtmfcompensate(), ast_rtp_setqos(), ast_sip_ouraddrfor(), ast_string_field_init, ast_string_field_set, ast_test_flag, ast_udptl_new_with_bindaddr(), ast_udptl_setqos(), ast_variables_destroy(), build_callid_pvt(), build_via(), context, default_prefs, dialogs, do_setnat(), errno, sip_pvt::fromdomain, global_flags, INITIAL_CSEQ, io, LOG_WARNING, make_our_tag(), mohinterpret, mohsuggest, NONE, parkinglot, sched, set_t38_capabilities(), sip_destroy_fn(), SIP_DTMF, SIP_DTMF_AUTO, SIP_DTMF_RFC2833, SIP_FLAGS_TO_COPY, sip_methods, SIP_NAT, SIP_NAT_ROUTE, SIP_OPTIONS, SIP_PAGE2_FLAGS_TO_COPY, SIP_PAGE2_RFC2833_COMPENSATE, SIP_PAGE2_T38SUPPORT, SIP_PAGE2_TEXTSUPPORT, SIP_PAGE2_VIDEOSUPPORT, SIP_REGISTER, SIP_TRANSPORT_UDP, cfsip_methods::text, and TRUE.
Referenced by find_call(), manager_sipnotify(), sip_cli_notify(), sip_poke_peer(), sip_request_call(), sip_send_mwi_to_peer(), and transmit_register().
06215 { 06216 struct sip_pvt *p; 06217 06218 if (!(p = ao2_t_alloc(sizeof(*p), sip_destroy_fn, "allocate a dialog(pvt) struct"))) 06219 return NULL; 06220 06221 if (ast_string_field_init(p, 512)) { 06222 ao2_t_ref(p, -1, "failed to string_field_init, drop p"); 06223 return NULL; 06224 } 06225 06226 p->socket.fd = -1; 06227 p->socket.type = SIP_TRANSPORT_UDP; 06228 p->method = intended_method; 06229 p->initid = -1; 06230 p->waitid = -1; 06231 p->autokillid = -1; 06232 p->request_queue_sched_id = -1; 06233 p->t38id = -1; 06234 p->subscribed = NONE; 06235 p->stateid = -1; 06236 p->sessionversion_remote = -1; 06237 p->session_modify = TRUE; 06238 p->stimer = NULL; 06239 p->prefs = default_prefs; /* Set default codecs for this call */ 06240 06241 if (intended_method != SIP_OPTIONS) { /* Peerpoke has it's own system */ 06242 p->timer_t1 = global_t1; /* Default SIP retransmission timer T1 (RFC 3261) */ 06243 p->timer_b = global_timer_b; /* Default SIP transaction timer B (RFC 3261) */ 06244 } 06245 06246 if (!sin) 06247 p->ourip = internip; 06248 else { 06249 p->sa = *sin; 06250 ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip); 06251 } 06252 06253 /* Copy global flags to this PVT at setup. */ 06254 ast_copy_flags(&p->flags[0], &global_flags[0], SIP_FLAGS_TO_COPY); 06255 ast_copy_flags(&p->flags[1], &global_flags[1], SIP_PAGE2_FLAGS_TO_COPY); 06256 06257 p->do_history = recordhistory; 06258 06259 p->branch = ast_random(); 06260 make_our_tag(p->tag, sizeof(p->tag)); 06261 p->ocseq = INITIAL_CSEQ; 06262 06263 if (sip_methods[intended_method].need_rtp) { 06264 p->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr); 06265 /* If the global videosupport flag is on, we always create a RTP interface for video */ 06266 if (ast_test_flag(&p->flags[1], SIP_PAGE2_VIDEOSUPPORT)) 06267 p->vrtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr); 06268 if (ast_test_flag(&p->flags[1], SIP_PAGE2_TEXTSUPPORT)) 06269 p->trtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr); 06270 if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT)) 06271 p->udptl = ast_udptl_new_with_bindaddr(sched, io, 0, bindaddr.sin_addr); 06272 if (!p->rtp|| (ast_test_flag(&p->flags[1], SIP_PAGE2_VIDEOSUPPORT) && !p->vrtp) 06273 || (ast_test_flag(&p->flags[1], SIP_PAGE2_TEXTSUPPORT) && !p->trtp)) { 06274 ast_log(LOG_WARNING, "Unable to create RTP audio %s%ssession: %s\n", 06275 ast_test_flag(&p->flags[1], SIP_PAGE2_VIDEOSUPPORT) ? "and video " : "", 06276 ast_test_flag(&p->flags[1], SIP_PAGE2_TEXTSUPPORT) ? "and text " : "", strerror(errno)); 06277 if (p->chanvars) { 06278 ast_variables_destroy(p->chanvars); 06279 p->chanvars = NULL; 06280 } 06281 ao2_t_ref(p, -1, "failed to create RTP audio session, drop p"); 06282 return NULL; 06283 } 06284 ast_rtp_setqos(p->rtp, global_tos_audio, global_cos_audio, "SIP RTP"); 06285 ast_rtp_setdtmf(p->rtp, ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833); 06286 ast_rtp_setdtmfcompensate(p->rtp, ast_test_flag(&p->flags[1], SIP_PAGE2_RFC2833_COMPENSATE)); 06287 ast_rtp_set_rtptimeout(p->rtp, global_rtptimeout); 06288 ast_rtp_set_rtpholdtimeout(p->rtp, global_rtpholdtimeout); 06289 ast_rtp_set_rtpkeepalive(p->rtp, global_rtpkeepalive); 06290 if (p->vrtp) { 06291 ast_rtp_setqos(p->vrtp, global_tos_video, global_cos_video, "SIP VRTP"); 06292 ast_rtp_setdtmf(p->vrtp, 0); 06293 ast_rtp_setdtmfcompensate(p->vrtp, 0); 06294 ast_rtp_set_rtptimeout(p->vrtp, global_rtptimeout); 06295 ast_rtp_set_rtpholdtimeout(p->vrtp, global_rtpholdtimeout); 06296 ast_rtp_set_rtpkeepalive(p->vrtp, global_rtpkeepalive); 06297 } 06298 if (p->trtp) { 06299 ast_rtp_setqos(p->trtp, global_tos_text, global_cos_text, "SIP TRTP"); 06300 ast_rtp_setdtmf(p->trtp, 0); 06301 ast_rtp_setdtmfcompensate(p->trtp, 0); 06302 } 06303 if (p->udptl) 06304 ast_udptl_setqos(p->udptl, global_tos_audio, global_cos_audio); 06305 p->maxcallbitrate = default_maxcallbitrate; 06306 p->autoframing = global_autoframing; 06307 ast_rtp_codec_setpref(p->rtp, &p->prefs); 06308 } 06309 06310 if (useglobal_nat && sin) { 06311 /* Setup NAT structure according to global settings if we have an address */ 06312 ast_copy_flags(&p->flags[0], &global_flags[0], SIP_NAT); 06313 p->recv = *sin; 06314 do_setnat(p, ast_test_flag(&p->flags[0], SIP_NAT) & SIP_NAT_ROUTE); 06315 } 06316 06317 if (p->method != SIP_REGISTER) 06318 ast_string_field_set(p, fromdomain, default_fromdomain); 06319 build_via(p); 06320 if (!callid) 06321 build_callid_pvt(p); 06322 else 06323 ast_string_field_set(p, callid, callid); 06324 /* Assign default music on hold class */ 06325 ast_string_field_set(p, mohinterpret, default_mohinterpret); 06326 ast_string_field_set(p, mohsuggest, default_mohsuggest); 06327 p->capability = global_capability; 06328 p->allowtransfer = global_allowtransfer; 06329 if ((ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833) || 06330 (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO)) 06331 p->noncodeccapability |= AST_RTP_DTMF; 06332 if (p->udptl) { 06333 ast_copy_flags(&p->t38.t38support, &p->flags[1], SIP_PAGE2_T38SUPPORT); 06334 set_t38_capabilities(p); 06335 p->t38.jointcapability = p->t38.capability; 06336 } 06337 ast_string_field_set(p, context, default_context); 06338 ast_string_field_set(p, parkinglot, default_parkinglot); 06339 06340 AST_LIST_HEAD_INIT_NOLOCK(&p->request_queue); 06341 06342 /* Add to active dialog list */ 06343 06344 ao2_t_link(dialogs, p, "link pvt into dialogs table"); 06345 06346 ast_debug(1, "Allocating new SIP dialog for %s - %s (%s)\n", callid ? callid : p->callid, sip_methods[intended_method].text, p->rtp ? "With RTP" : "No RTP"); 06347 return p; 06348 }
| static void sip_alreadygone | ( | struct sip_pvt * | dialog | ) | [static] |
Encapsulate setting of SIP_ALREADYGONE to be able to trace it with debugging.
Definition at line 2643 of file chan_sip.c.
References sip_pvt::alreadygone, ast_debug, and sip_pvt::callid.
Referenced by handle_request_bye(), handle_request_cancel(), handle_request_invite(), handle_request_refer(), handle_response(), handle_response_invite(), retrans_pkt(), sip_indicate(), and sip_sipredirect().
02644 { 02645 ast_debug(3, "Setting SIP_ALREADYGONE on dialog %s\n", dialog->callid); 02646 dialog->alreadygone = 1; 02647 }
| static int sip_answer | ( | struct ast_channel * | ast | ) | [static] |
sip_answer: Answer SIP call , send 200 OK on Invite Part of PBX interface
Definition at line 5333 of file chan_sip.c.
References ast_channel::_state, ast_debug, ast_rtp_new_source(), ast_set_flag, ast_setstate(), AST_STATE_UP, change_t38_state(), FALSE, ast_channel::name, SIP_PAGE2_DIALOG_ESTABLISHED, sip_pvt_lock, sip_pvt_unlock, T38_ENABLED, T38_PEER_DIRECT, ast_channel::tech_pvt, transmit_response_with_sdp(), try_suggested_sip_codec(), and XMIT_CRITICAL.
05334 { 05335 int res = 0; 05336 struct sip_pvt *p = ast->tech_pvt; 05337 05338 sip_pvt_lock(p); 05339 if (ast->_state != AST_STATE_UP) { 05340 try_suggested_sip_codec(p); 05341 05342 ast_setstate(ast, AST_STATE_UP); 05343 ast_debug(1, "SIP answering channel: %s\n", ast->name); 05344 if (p->t38.state == T38_PEER_DIRECT) { 05345 change_t38_state(p, T38_ENABLED); 05346 } 05347 ast_rtp_new_source(p->rtp); 05348 res = transmit_response_with_sdp(p, "200 OK", &p->initreq, XMIT_CRITICAL, FALSE); 05349 ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED); 05350 } 05351 sip_pvt_unlock(p); 05352 return res; 05353 }
| static int sip_call | ( | struct ast_channel * | ast, | |
| char * | dest, | |||
| int | timeout | |||
| ) | [static] |
Initiate SIP call from PBX used from the dial() application.
Definition at line 4566 of file chan_sip.c.
References ast_channel::_state, sip_invite_param::addsipheaders, AST_CAUSE_USER_BUSY, ast_debug, AST_FORMAT_AUDIO_MASK, AST_LIST_TRAVERSE, ast_log(), AST_SCHED_REPLACE_UNREF, ast_set_flag, AST_STATE_DOWN, AST_STATE_RESERVED, ast_string_field_set, ast_translate_available_formats(), ast_var_name(), ast_var_value(), auto_congest(), buf, sip_pvt::callingpres, t38properties::capability, sip_pvt::capability, ast_channel::cid, cid_name, sip_pvt::cid_name, ast_callerid::cid_pres, dialog_ref(), dialog_unref(), ast_var_t::entries, sip_pvt::flags, ast_channel::hangupcause, INC_CALL_RINGING, sip_pvt::initid, INV_CALLING, sip_pvt::invitestate, t38properties::jointcapability, sip_pvt::jointcapability, sip_pvt::jointnoncodeccapability, LOG_WARNING, ast_channel::name, sip_pvt::noncodeccapability, sip_pvt::options, sip_pvt::prefcodec, sip_invite_param::replaces, sched, SIP_INVITE, SIP_OUTGOING, SIPBUFSIZE, sip_pvt::t38, ast_channel::tech_pvt, sip_pvt::timer_b, sip_invite_param::transfer, transmit_invite(), update_call_counter(), sip_invite_param::uri_options, sip_pvt::username, ast_channel::varshead, sip_invite_param::vxml_url, and XMIT_ERROR.
04567 { 04568 int res; 04569 struct sip_pvt *p = ast->tech_pvt; /* chan is locked, so the reference cannot go away */ 04570 struct varshead *headp; 04571 struct ast_var_t *current; 04572 const char *referer = NULL; /* SIP referrer */ 04573 04574 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) { 04575 ast_log(LOG_WARNING, "sip_call called on %s, neither down nor reserved\n", ast->name); 04576 return -1; 04577 } 04578 04579 /* Check whether there is vxml_url, distinctive ring variables */ 04580 headp=&ast->varshead; 04581 AST_LIST_TRAVERSE(headp, current, entries) { 04582 /* Check whether there is a VXML_URL variable */ 04583 if (!p->options->vxml_url && !strcasecmp(ast_var_name(current), "VXML_URL")) { 04584 p->options->vxml_url = ast_var_value(current); 04585 } else if (!p->options->uri_options && !strcasecmp(ast_var_name(current), "SIP_URI_OPTIONS")) { 04586 p->options->uri_options = ast_var_value(current); 04587 } else if (!p->options->addsipheaders && !strncasecmp(ast_var_name(current), "SIPADDHEADER", strlen("SIPADDHEADER"))) { 04588 /* Check whether there is a variable with a name starting with SIPADDHEADER */ 04589 p->options->addsipheaders = 1; 04590 } else if (!strcasecmp(ast_var_name(current), "SIPTRANSFER")) { 04591 /* This is a transfered call */ 04592 p->options->transfer = 1; 04593 } else if (!strcasecmp(ast_var_name(current), "SIPTRANSFER_REFERER")) { 04594 /* This is the referrer */ 04595 referer = ast_var_value(current); 04596 } else if (!strcasecmp(ast_var_name(current), "SIPTRANSFER_REPLACES")) { 04597 /* We're replacing a call. */ 04598 p->options->replaces = ast_var_value(current); 04599 } 04600 } 04601 04602 res = 0; 04603 ast_set_flag(&p->flags[0], SIP_OUTGOING); 04604 04605 if (p->options->transfer) { 04606 char buf[SIPBUFSIZE/2]; 04607 04608 if (referer) { 04609 if (sipdebug) 04610 ast_debug(3, "Call for %s transfered by %s\n", p->username, referer); 04611 snprintf(buf, sizeof(buf)-1, "-> %s (via %s)", p->cid_name, referer); 04612 } else 04613 snprintf(buf, sizeof(buf)-1, "-> %s", p->cid_name); 04614 ast_string_field_set(p, cid_name, buf); 04615 } 04616 ast_debug(1, "Outgoing Call for %s\n", p->username); 04617 04618 res = update_call_counter(p, INC_CALL_RINGING); 04619 04620 if (res == -1) { 04621 ast->hangupcause = AST_CAUSE_USER_BUSY; 04622 return res; 04623 } 04624 p->callingpres = ast->cid.cid_pres; 04625 p->jointcapability = ast_translate_available_formats(p->capability, p->prefcodec); 04626 p->jointnoncodeccapability = p->noncodeccapability; 04627 04628 /* If there are no audio formats left to offer, punt */ 04629 if (!(p->jointcapability & AST_FORMAT_AUDIO_MASK)) { 04630 ast_log(LOG_WARNING, "No audio format found to offer. Cancelling call to %s\n", p->username); 04631 res = -1; 04632 } else { 04633 int xmitres; 04634 04635 p->t38.jointcapability = p->t38.capability; 04636 ast_debug(2, "Our T38 capability (%d), joint T38 capability (%d)\n", p->t38.capability, p->t38.jointcapability); 04637 04638 xmitres = transmit_invite(p, SIP_INVITE, 1, 2); 04639 if (xmitres == XMIT_ERROR) 04640 return -1; 04641 p->invitestate = INV_CALLING; 04642 04643 /* Initialize auto-congest time */ 04644 AST_SCHED_REPLACE_UNREF(p->initid, sched, p->timer_b, auto_congest, p, 04645 dialog_unref(_data, "dialog ptr dec when SCHED_REPLACE del op succeeded"), 04646 dialog_unref(p, "dialog ptr dec when SCHED_REPLACE add failed"), 04647 dialog_ref(p, "dialog ptr inc when SCHED_REPLACE add succeeded") ); 04648 } 04649 return res; 04650 }
| static int sip_cancel_destroy | ( | struct sip_pvt * | p | ) | [static] |
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.
Definition at line 3293 of file chan_sip.c.
References append_history, ast_sched_del(), sip_pvt::autokillid, dialog_unref(), and sched.
Referenced by cb_extensionstate(), handle_request_invite(), handle_request_subscribe(), handle_response(), handle_response_invite(), register_verify(), sip_hangup(), and sip_scheddestroy().
03294 { 03295 int res = 0; 03296 if (p->autokillid > -1) { 03297 int res3; 03298 03299 if (!(res3 = ast_sched_del(sched, p->autokillid))) { 03300 append_history(p, "CancelDestroy", ""); 03301 p->autokillid = -1; 03302 dialog_unref(p, "dialog unrefd because autokillid is de-sched'd"); 03303 } 03304 } 03305 return res; 03306 }
| static char * sip_cli_notify | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Cli command to send SIP notify to peer.
Definition at line 15110 of file chan_sip.c.
References ao2_t_link, ao2_t_unlink, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_log(), ast_set_flag, ast_sip_ouraddrfor(), ast_variable_browse(), build_callid_pvt(), build_via(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, ast_cli_entry::command, complete_sipnotify(), create_addr(), dialog_ref(), dialog_unlink_all(), dialog_unref(), dialogs, ast_cli_args::fd, sip_pvt::flags, ast_cli_args::line, LOG_WARNING, ast_cli_args::n, notify_types, sip_pvt::ourip, ast_cli_args::pos, sip_pvt::sa, sip_alloc(), SIP_NOTIFY, SIP_OUTGOING, sip_scheddestroy(), SIP_TRANS_TIMEOUT, transmit_notify_custom(), TRUE, ast_cli_entry::usage, and ast_cli_args::word.
15111 { 15112 struct ast_variable *varlist; 15113 int i; 15114 15115 switch (cmd) { 15116 case CLI_INIT: 15117 e->command = "sip notify"; 15118 e->usage = 15119 "Usage: sip notify <type> <peer> [<peer>...]\n" 15120 " Send a NOTIFY message to a SIP peer or peers\n" 15121 " Message types are defined in sip_notify.conf\n"; 15122 return NULL; 15123 case CLI_GENERATE: 15124 return complete_sipnotify(a->line, a->word, a->pos, a->n); 15125 } 15126 15127 if (a->argc < 4) 15128 return CLI_SHOWUSAGE; 15129 15130 if (!notify_types) { 15131 ast_cli(a->fd, "No %s file found, or no types listed there\n", notify_config); 15132 return CLI_FAILURE; 15133 } 15134 15135 varlist = ast_variable_browse(notify_types, a->argv[2]); 15136 15137 if (!varlist) { 15138 ast_cli(a->fd, "Unable to find notify type '%s'\n", a->argv[2]); 15139 return CLI_FAILURE; 15140 } 15141 15142 for (i = 3; i < a->argc; i++) { 15143 struct sip_pvt *p; 15144 15145 if (!(p = sip_alloc(NULL, NULL, 0, SIP_NOTIFY))) { 15146 ast_log(LOG_WARNING, "Unable to build sip pvt data for notify (memory/socket error)\n"); 15147 return CLI_FAILURE; 15148 } 15149 15150 if (create_addr(p, a->argv[i], NULL, 0)) { 15151 /* Maybe they're not registered, etc. */ 15152 dialog_unlink_all(p, TRUE, TRUE); 15153 dialog_unref(p, "unref dialog inside for loop" ); 15154 /* sip_destroy(p); */ 15155 ast_cli(a->fd, "Could not create address for '%s'\n", a->argv[i]); 15156 continue; 15157 } 15158 15159 /* Notify is outgoing call */ 15160 ast_set_flag(&p->flags[0], SIP_OUTGOING); 15161 15162 /* Recalculate our side, and recalculate Call ID */ 15163 ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip); 15164 build_via(p); 15165 ao2_t_unlink(dialogs, p, "About to change the callid -- remove the old name"); 15166 build_callid_pvt(p); 15167 ao2_t_link(dialogs, p, "Linking in new name"); 15168 ast_cli(a->fd, "Sending NOTIFY of type '%s' to '%s'\n", a->argv[2], a->argv[i]); 15169 dialog_ref(p, "bump the count of p, which transmit_sip_request will decrement."); 15170 sip_scheddestroy(p, SIP_TRANS_TIMEOUT); 15171 transmit_notify_custom(p, varlist); 15172 } 15173 15174 return CLI_SUCCESS; 15175 }
| static int sip_debug_test_addr | ( | const struct sockaddr_in * | addr | ) | [inline, static] |
See if we pass debug IP filter.
Definition at line 2782 of file chan_sip.c.
Referenced by check_peer_ok(), handle_request_do(), and sip_debug_test_pvt().
02783 { 02784 if (!sipdebug) 02785 return 0; 02786 if (debugaddr.sin_addr.s_addr) { 02787 if (((ntohs(debugaddr.sin_port) != 0) 02788 && (debugaddr.sin_port != addr->sin_port)) 02789 || (debugaddr.sin_addr.s_addr != addr->sin_addr.s_addr)) 02790 return 0; 02791 } 02792 return 1; 02793 }
| static int sip_debug_test_pvt | ( | struct sip_pvt * | p | ) | [inline, static] |
Test PVT for debugging output.
Definition at line 2811 of file chan_sip.c.
References sip_debug_test_addr(), and sip_real_dst().
Referenced by __sip_destroy(), add_sdp(), build_route(), check_via(), do_register_auth(), get_also_info(), get_destination(), get_rdnis(), get_refer_info(), handle_incoming(), process_sdp(), receive_message(), retrans_pkt(), send_request(), send_response(), set_destination(), sip_scheddestroy(), sip_sendhtml(), sip_sendtext(), and transmit_register().
02812 { 02813 if (!sipdebug) 02814 return 0; 02815 return sip_debug_test_addr(sip_real_dst(p)); 02816 }
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.
Definition at line 4956 of file chan_sip.c.
References __sip_destroy(), ast_debug, sip_pvt::callid, and TRUE.
Referenced by sip_destroy_fn().
04957 { 04958 ast_debug(3, "Destroying SIP dialog %s\n", p->callid); 04959 __sip_destroy(p, TRUE, TRUE); 04960 return NULL; 04961 }
| static void sip_destroy_fn | ( | void * | p | ) | [static] |
Definition at line 4946 of file chan_sip.c.
References sip_destroy().
Referenced by sip_alloc().
04947 { 04948 sip_destroy(p); 04949 }
| static void sip_destroy_peer | ( | struct sip_peer * | peer | ) | [static] |
Destroy peer object from memory.
Definition at line 3857 of file chan_sip.c.
References ao2_ref, ast_atomic_fetchadd_int(), ast_debug, ast_dnsmgr_release(), ast_free_ha(), ast_variables_destroy(), sip_peer::auth, sip_peer::call, sip_peer::chanvars, clear_peer_mailboxes(), clear_realm_authentication(), dialog_unlink_all(), dialog_unref(), sip_peer::dnsmgr, FALSE, sip_peer::ha, sip_peer::is_realtime, sip_peer::mwipvt, sip_peer::name, sip_peer::outboundproxy, register_peer_exten(), sip_peer::selfdestruct, sip_peer::socket, sip_socket::tcptls_session, and TRUE.
Referenced by sip_destroy_peer_fn().
03858 { 03859 ast_debug(3, "Destroying SIP peer %s\n", peer->name); 03860 if (peer->outboundproxy) 03861 ao2_ref(peer->outboundproxy, -1); 03862 peer->outboundproxy = NULL; 03863 03864 /* Delete it, it needs to disappear */ 03865 if (peer->call) { 03866 dialog_unlink_all(peer->call, TRUE, TRUE); 03867 peer->call = dialog_unref(peer->call, "peer->call is being unset"); 03868 } 03869 03870 03871 if (peer->mwipvt) { /* We have an active subscription, delete it */ 03872 dialog_unlink_all(peer->mwipvt, TRUE, TRUE); 03873 peer->mwipvt = dialog_unref(peer->mwipvt, "unreffing peer->mwipvt"); 03874 } 03875 03876 if (peer->chanvars) { 03877 ast_variables_destroy(peer->chanvars); 03878 peer->chanvars = NULL; 03879 } 03880 03881 register_peer_exten(peer, FALSE); 03882 ast_free_ha(peer->ha); 03883 if (peer->selfdestruct) 03884 ast_atomic_fetchadd_int(&apeerobjs, -1); 03885 else if (peer->is_realtime) { 03886 ast_atomic_fetchadd_int(&rpeerobjs, -1); 03887 ast_debug(3, "-REALTIME- peer Destroyed. Name: %s. Realtime Peer objects: %d\n", peer->name, rpeerobjs); 03888 } else 03889 ast_atomic_fetchadd_int(&speerobjs, -1); 03890 clear_realm_authentication(peer->auth); 03891 peer->auth = NULL; 03892 if (peer->dnsmgr) 03893 ast_dnsmgr_release(peer->dnsmgr); 03894 clear_peer_mailboxes(peer); 03895 03896 if (peer->socket.tcptls_session) { 03897 ao2_ref(peer->socket.tcptls_session, -1); 03898 peer->socket.tcptls_session = NULL; 03899 } 03900 }
| static void sip_destroy_peer_fn | ( | void * | peer | ) | [static] |
Definition at line 3851 of file chan_sip.c.
References sip_destroy_peer().
Referenced by build_peer(), and temp_peer().
03852 { 03853 sip_destroy_peer(peer); 03854 }
| static int sip_devicestate | ( | void * | data | ) | [static] |
Part of PBX channel interface.
For peers with call limit:
For peers without call limit:
Peers that does not have a known call and can't be reached by OPTIONS
If we return AST_DEVICE_UNKNOWN, the device state engine will try to find out a state by walking the channel list.
The queue system (app_queue.c) treats a member as "active" if devicestate is != AST_DEVICE_UNAVAILBALE && != AST_DEVICE_INVALID
When placing a call to the queue member, queue system sets a member to busy if != AST_DEVICE_NOT_INUSE and != AST_DEVICE_UNKNOWN
Definition at line 20909 of file chan_sip.c.
References sip_peer::addr, ast_debug, AST_DEVICE_BUSY, AST_DEVICE_INUSE, AST_DEVICE_INVALID, AST_DEVICE_NOT_INUSE, AST_DEVICE_ONHOLD, AST_DEVICE_RINGING, AST_DEVICE_RINGINUSE, AST_DEVICE_UNAVAILABLE, AST_DEVICE_UNKNOWN, ast_strdupa, sip_peer::busy_level, sip_peer::call_limit, sip_peer::defaddr, FALSE, find_peer(), FINDALLDEVICES, sip_peer::inRinging, sip_peer::inUse, sip_peer::lastms, sip_peer::maxms, sip_peer::onHold, TRUE, and unref_peer().
20910 { 20911 char *host; 20912 char *tmp; 20913 struct sip_peer *p; 20914 20915 int res = AST_DEVICE_INVALID; 20916 20917 /* make sure data is not null. Maybe unnecessary, but better be safe */ 20918 host = ast_strdupa(data ? data : ""); 20919 if ((tmp = strchr(host, '@'))) 20920 host = tmp + 1; 20921 20922 ast_debug(3, "Checking device state for peer %s\n", host); 20923 20924 /* If find_peer asks for a realtime peer, then this breaks rtautoclear. This 20925 * is because when a peer tries to autoexpire, the last thing it does is to 20926 * queue up an event telling the system that the devicestate has changed 20927 * (presumably to unavailable). If we ask for a realtime peer here, this would 20928 * load it BACK into memory, thus defeating the point of trying to clear dead 20929 * hosts out of memory. 20930 */ 20931 if ((p = find_peer(host, NULL, FALSE, FINDALLDEVICES, TRUE))) { 20932 if (p->addr.sin_addr.s_addr || p->defaddr.sin_addr.s_addr) { 20933 /* we have an address for the peer */ 20934 20935 /* Check status in this order 20936 - Hold 20937 - Ringing 20938 - Busy (enforced only by call limit) 20939 - Inuse (we have a call) 20940 - Unreachable (qualify) 20941 If we don't find any of these state, report AST_DEVICE_NOT_INUSE 20942 for registered devices */ 20943 20944 if (p->onHold) 20945 /* First check for hold or ring states */ 20946 res = AST_DEVICE_ONHOLD; 20947 else if (p->inRinging) { 20948 if (p->inRinging == p->inUse) 20949 res = AST_DEVICE_RINGING; 20950 else 20951 res = AST_DEVICE_RINGINUSE; 20952 } else if (p->call_limit && (p->inUse == p->call_limit)) 20953 /* check call limit */ 20954 res = AST_DEVICE_BUSY; 20955 else if (p->call_limit && p->busy_level && p->inUse >= p->busy_level) 20956 /* We're forcing busy before we've reached the call limit */ 20957 res = AST_DEVICE_BUSY; 20958 else if (p->call_limit && p->inUse) 20959 /* Not busy, but we do have a call */ 20960 res = AST_DEVICE_INUSE; 20961 else if (p->maxms && ((p->lastms > p->maxms) || (p->lastms < 0))) 20962 /* We don't have a call. Are we reachable at all? Requires qualify= */ 20963 res = AST_DEVICE_UNAVAILABLE; 20964 else /* Default reply if we're registered and have no other data */ 20965 res = AST_DEVICE_NOT_INUSE; 20966 } else { 20967 /* there is no address, it's unavailable */ 20968 res = AST_DEVICE_UNAVAILABLE; 20969 } 20970 unref_peer(p, "unref_peer, from sip_devicestate, release ref from find_peer"); 20971 } else { 20972 res = AST_DEVICE_UNKNOWN; 20973 } 20974 20975 return res; 20976 }
| static char * sip_do_debug | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Turn on SIP debugging (CLI command).
Definition at line 15067 of file chan_sip.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_sip_peer(), ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, sip_debug_console, sip_do_debug_ip(), sip_do_debug_peer(), strcasestr(), ast_cli_entry::usage, and ast_cli_args::word.
15068 { 15069 int oldsipdebug = sipdebug & sip_debug_console; 15070 char *what; 15071 15072 if (cmd == CLI_INIT) { 15073 e->command = "sip set debug {on|off|ip|peer}"; 15074 e->usage = 15075 "Usage: sip set debug {off|on|ip addr[:port]|peer peername}\n" 15076 " Globally disables dumping of SIP packets,\n" 15077 " or enables it either globally or for a (single)\n" 15078 " IP address or registered peer.\n"; 15079 return NULL; 15080 } else if (cmd == CLI_GENERATE) { 15081 if (a->pos == 4 && strcasestr(a->line, " peer")) /* XXX should check on argv too */ 15082 return complete_sip_peer(a->word, a->n, 0); 15083 return NULL; 15084 } 15085 15086 what = a->argv[e->args-1]; /* guaranteed to exist */ 15087 if (a->argc == e->args) { /* on/off */ 15088 if (!strcasecmp(what, "on")) { 15089 sipdebug |= sip_debug_console; 15090 sipdebug_text = 1; /*! \note this can be a special debug command - "sip debug text" or something */ 15091 memset(&debugaddr, 0, sizeof(debugaddr)); 15092 ast_cli(a->fd, "SIP Debugging %senabled\n", oldsipdebug ? "re-" : ""); 15093 return CLI_SUCCESS; 15094 } else if (!strcasecmp(what, "off")) { 15095 sipdebug &= ~sip_debug_console; 15096 sipdebug_text = 0; 15097 ast_cli(a->fd, "SIP Debugging Disabled\n"); 15098 return CLI_SUCCESS; 15099 } 15100 } else if (a->argc == e->args +1) {/* ip/peer */ 15101 if (!strcasecmp(what, "ip")) 15102 return sip_do_debug_ip(a->fd, a->argv[e->args]); 15103 else if (!strcasecmp(what, "peer")) 15104 return sip_do_debug_peer(a->fd, a->argv[e->args]); 15105 } 15106 return CLI_SHOWUSAGE; /* default, failure */ 15107 }
| static char * sip_do_debug_ip | ( | int | fd, | |
| char * | arg | |||
| ) | [static] |
Enable SIP Debugging for a single IP.
Definition at line 15017 of file chan_sip.c.
References ahp, ast_cli(), ast_gethostbyname(), ast_inet_ntoa(), CLI_SHOWUSAGE, CLI_SUCCESS, hp, sip_debug_console, and strsep().
Referenced by sip_do_debug().
15018 { 15019 struct hostent *hp; 15020 struct ast_hostent ahp; 15021 int port = 0; 15022 char *p; 15023 15024 p = arg; 15025 strsep(&p, ":"); 15026 if (p) 15027 port = atoi(p); 15028 hp = ast_gethostbyname(arg, &ahp); 15029 if (hp == NULL) 15030 return CLI_SHOWUSAGE; 15031 15032 debugaddr.sin_family = AF_INET; 15033 memcpy(&debugaddr.sin_addr, hp->h_addr, sizeof(debugaddr.sin_addr)); 15034 debugaddr.sin_port = htons(port); 15035 if (port == 0) 15036 ast_cli(fd, "SIP Debugging Enabled for IP: %s\n", ast_inet_ntoa(debugaddr.sin_addr)); 15037 else 15038 ast_cli(fd, "SIP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(debugaddr.sin_addr), port); 15039 15040 sipdebug |= sip_debug_console; 15041 15042 return CLI_SUCCESS; 15043 }
| static char * sip_do_debug_peer | ( | int | fd, | |
| char * | arg | |||
| ) | [static] |
Turn on SIP debugging for a given peer.
Definition at line 15046 of file chan_sip.c.
References sip_peer::addr, ast_cli(), ast_inet_ntoa(), CLI_SUCCESS, FALSE, find_peer(), FINDPEERS, sip_debug_console, TRUE, and unref_peer().
Referenced by sip_do_debug().
15047 { 15048 struct sip_peer *peer = find_peer(arg, NULL, TRUE, FINDPEERS, FALSE); 15049 if (!peer) 15050 ast_cli(fd, "No such peer '%s'\n", arg); 15051 else if (peer->addr.sin_addr.s_addr == 0) 15052 ast_cli(fd, "Unable to get IP address of peer '%s'\n", arg); 15053 else { 15054 debugaddr.sin_family = AF_INET; 15055 debugaddr.sin_addr = peer->addr.sin_addr; 15056 debugaddr.sin_port = peer->addr.sin_port; 15057 ast_cli(fd, "SIP Debugging Enabled for IP: %s:%d\n", 15058 ast_inet_ntoa(debugaddr.sin_addr), ntohs(debugaddr.sin_port)); 15059 sipdebug |= sip_debug_console; 15060 } 15061 if (peer) 15062 unref_peer(peer, "sip_do_debug_peer: unref_peer, from find_peer call"); 15063 return CLI_SUCCESS; 15064 }
| static char * sip_do_history_deprecated | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Enable/Disable SIP History logging (CLI) - deprecated. use sip_set_history instead.
Definition at line 15178 of file chan_sip.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, FALSE, ast_cli_args::fd, TRUE, and ast_cli_entry::usage.
15179 { 15180 switch (cmd) { 15181 case CLI_INIT: 15182 e->command = "sip history [off]"; 15183 e->usage = 15184 "Usage: sip history [off]\n" 15185 " Enables/Disables recording of SIP dialog history for debugging purposes.\n" 15186 " Use 'sip show history' to view the history of a call number.\n"; 15187 return NULL; 15188 case CLI_GENERATE: 15189 return NULL; 15190 } 15191 15192 if (a->argc < 2 || a->argc > 3) { 15193 return CLI_SHOWUSAGE; 15194 } 15195 if (a->argc == 2) { 15196 recordhistory = TRUE; 15197 ast_cli(a->fd, "SIP History Recording Enabled (use 'sip show history')\n"); 15198 } else { 15199 if (strncasecmp(a->argv[2], "off", 3)) 15200 return CLI_SHOWUSAGE; 15201 recordhistory = FALSE; 15202 ast_cli(a->fd, "SIP History Recording Disabled\n"); 15203 } 15204 return CLI_SUCCESS; 15205 }
| static int sip_do_reload | ( | enum channelreloadreason | reason | ) | [static] |
Reload module.
Definition at line 23294 of file chan_sip.c.
References ao2_t_callback, ast_debug, ast_sched_dump(), OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, peer_is_marked(), reload_config(), sched, sip_poke_all_peers(), and sip_send_all_registers().
Referenced by do_monitor().
23295 { 23296 time_t start_poke, end_poke; 23297 23298 reload_config(reason); 23299 ast_sched_dump(sched); 23300 23301 start_poke = time(0); 23302 /* Prune peers who still are supposed to be deleted */ 23303 ao2_t_callback(peers, OBJ_NODATA | OBJ_UNLINK | OBJ_MULTIPLE, peer_is_marked, 0, 23304 "callback to remove marked peers"); 23305 23306 ast_debug(4, "--------------- Done destroying pruned peers\n"); 23307 23308 /* Send qualify (OPTIONS) to all peers */ 23309 sip_poke_all_peers(); 23310 23311 /* Register with all services */ 23312 sip_send_all_registers(); 23313 end_poke = time(0); 23314 23315 ast_debug(4, "do_reload finished. peer poke/prune reg contact time = %d sec.\n", (int)(end_poke-start_poke)); 23316 23317 ast_debug(4, "--------------- SIP reload done\n"); 23318 23319 return 0; 23320 }
| static int sip_dtmfmode | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Set the DTMFmode for an outbound SIP call (application).
Definition at line 23080 of file chan_sip.c.
References ast_channel_lock, ast_channel_unlock, ast_clear_flag, ast_dsp_free(), ast_dsp_new(), ast_dsp_set_features(), ast_log(), AST_RTP_DTMF, ast_rtp_setdtmf(), ast_set_flag, ast_test_flag, chan, DSP_FEATURE_DIGIT_DETECT, sip_pvt::flags, IS_SIP_TECH, sip_pvt::jointnoncodeccapability, LOG_WARNING, sip_pvt::rtp, SIP_DTMF, SIP_DTMF_INBAND, SIP_DTMF_INFO, SIP_DTMF_RFC2833, SIP_DTMF_SHORTINFO, sip_pvt_lock, sip_pvt_unlock, ast_channel::tech, ast_channel::tech_pvt, and sip_pvt::vad.
Referenced by load_module().
23081 { 23082 struct sip_pvt *p; 23083 char *mode = data; 23084 23085 if (!data) { 23086 ast_log(LOG_WARNING, "This application requires the argument: info, inband, rfc2833\n"); 23087 return 0; 23088 } 23089 ast_channel_lock(chan); 23090 if (!IS_SIP_TECH(chan->tech)) { 23091 ast_log(LOG_WARNING, "Call this application only on SIP incoming calls\n"); 23092 ast_channel_unlock(chan); 23093 return 0; 23094 } 23095 p = chan->tech_pvt; 23096 if (!p) { 23097 ast_channel_unlock(chan); 23098 return 0; 23099 } 23100 sip_pvt_lock(p); 23101 if (!strcasecmp(mode, "info")) { 23102 ast_clear_flag(&p->flags[0], SIP_DTMF); 23103 ast_set_flag(&p->flags[0], SIP_DTMF_INFO); 23104 p->jointnoncodeccapability &= ~AST_RTP_DTMF; 23105 } else if (!strcasecmp(mode, "shortinfo")) { 23106 ast_clear_flag(&p->flags[0], SIP_DTMF); 23107 ast_set_flag(&p->flags[0], SIP_DTMF_SHORTINFO); 23108 p->jointnoncodeccapability &= ~AST_RTP_DTMF; 23109 } else if (!strcasecmp(mode, "rfc2833")) { 23110 ast_clear_flag(&p->flags[0], SIP_DTMF); 23111 ast_set_flag(&p->flags[0], SIP_DTMF_RFC2833); 23112 p->jointnoncodeccapability |= AST_RTP_DTMF; 23113 } else if (!strcasecmp(mode, "inband")) { 23114 ast_clear_flag(&p->flags[0], SIP_DTMF); 23115 ast_set_flag(&p->flags[0], SIP_DTMF_INBAND); 23116 p->jointnoncodeccapability &= ~AST_RTP_DTMF; 23117 } else 23118 ast_log(LOG_WARNING, "I don't know about this dtmf mode: %s\n", mode); 23119 if (p->rtp) 23120 ast_rtp_setdtmf(p->rtp, ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833); 23121 if (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_INBAND) { 23122 if (!p->vad) { 23123 p->vad = ast_dsp_new(); 23124 ast_dsp_set_features(p->vad, DSP_FEATURE_DIGIT_DETECT); 23125 } 23126 } else { 23127 if (p->vad) { 23128 ast_dsp_free(p->vad); 23129 p->vad = NULL; 23130 } 23131 } 23132 sip_pvt_unlock(p); 23133 ast_channel_unlock(chan); 23134 return 0; 23135 }
| static void sip_dump_history | ( | struct sip_pvt * | dialog | ) | [static] |
Dump SIP history to debug log file at end of lifespan for SIP dialog.
Definition at line 14802 of file chan_sip.c.
References ast_debug, AST_LIST_TRAVERSE, ast_log(), sip_pvt::callid, sip_history::event, sip_pvt::history, sip_history::list, LOG_NOTICE, option_debug, and sip_pvt::subscribed.
Referenced by __sip_destroy().
14803 { 14804 int x = 0; 14805 struct sip_history *hist; 14806 static int errmsg = 0; 14807 14808 if (!dialog) 14809 return; 14810 14811 if (!option_debug && !sipdebug) { 14812 if (!errmsg) { 14813 ast_log(LOG_NOTICE, "You must have debugging enabled (SIP or Asterisk) in order to dump SIP history.\n"); 14814 errmsg = 1; 14815 } 14816 return; 14817 } 14818 14819 ast_debug(1, "\n---------- SIP HISTORY for '%s' \n", dialog->callid); 14820 if (dialog->subscribed) 14821 ast_debug(1, " * Subscription\n"); 14822 else 14823 ast_debug(1, " * SIP Call\n"); 14824 if (dialog->history) 14825 AST_LIST_TRAVERSE(dialog->history, hist, list) 14826 ast_debug(1, " %-3.3d. %s\n", ++x, hist->event); 14827 if (!x) 14828 ast_debug(1, "Call '%s' has no history\n", dialog->callid); 14829 ast_debug(1, "\n---------- END SIP HISTORY for '%s' \n", dialog->callid); 14830 }
| static int sip_fixup | ( | struct ast_channel * | oldchan, | |
| struct ast_channel * | newchan | |||
| ) | [static] |
sip_fixup: Fix up a channel: If a channel is consumed, this is called. Basically update any ->owner links
Definition at line 5470 of file chan_sip.c.
References append_history, ast_debug, AST_FLAG_ZOMBIE, ast_log(), ast_test_flag, sip_pvt::callid, LOG_WARNING, ast_channel::name, sip_pvt::owner, sip_pvt_lock, sip_pvt_unlock, sip_set_rtp_peer(), and ast_channel::tech_pvt.
05471 { 05472 int ret = -1; 05473 struct sip_pvt *p; 05474 05475 if (newchan && ast_test_flag(newchan, AST_FLAG_ZOMBIE)) 05476 ast_debug(1, "New channel is zombie\n"); 05477 if (oldchan && ast_test_flag(oldchan, AST_FLAG_ZOMBIE)) 05478 ast_debug(1, "Old channel is zombie\n"); 05479 05480 if (!newchan || !newchan->tech_pvt) { 05481 if (!newchan) 05482 ast_log(LOG_WARNING, "No new channel! Fixup of %s failed.\n", oldchan->name); 05483 else 05484 ast_log(LOG_WARNING, "No SIP tech_pvt! Fixup of %s failed.\n", oldchan->name); 05485 return -1; 05486 } 05487 p = newchan->tech_pvt; 05488 05489 sip_pvt_lock(p); 05490 append_history(p, "Masq", "Old channel: %s\n", oldchan->name); 05491 append_history(p, "Masq (cont)", "...new owner: %s\n", newchan->name); 05492 if (p->owner != oldchan) 05493 ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, p->owner); 05494 else { 05495 p->owner = newchan; 05496 /* Re-invite RTP back to Asterisk. Needed if channel is masqueraded out of a native 05497 RTP bridge (i.e., RTP not going through Asterisk): RTP bridge code might not be 05498 able to do this if the masquerade happens before the bridge breaks (e.g., AMI 05499 redirect of both channels). Note that a channel can not be masqueraded *into* 05500 a native bridge. So there is no danger that this breaks a native bridge that 05501 should stay up. */ 05502 sip_set_rtp_peer(newchan, NULL, NULL, 0, 0, 0); 05503 ret = 0; 05504 } 05505 ast_debug(3, "SIP Fixup: New owner for dialogue %s: %s (Old parent: %s)\n", p->callid, p->owner->name, oldchan->name); 05506 05507 sip_pvt_unlock(p); 05508 return ret; 05509 }
| static const char * sip_get_callid | ( | struct ast_channel * | chan | ) | [static] |
Deliver SIP call ID for the call.
Definition at line 3718 of file chan_sip.c.
References chan, and ast_channel::tech_pvt.
| static int sip_get_codec | ( | struct ast_channel * | chan | ) | [static] |
Return SIP UA's codec (part of the RTP interface).
Definition at line 23237 of file chan_sip.c.
References sip_pvt::capability, chan, sip_pvt::jointcapability, and ast_channel::tech_pvt.
23238 { 23239 struct sip_pvt *p = chan->tech_pvt; 23240 return p->jointcapability ? p->jointcapability : p->capability; 23241 }
| static enum ast_rtp_get_result sip_get_rtp_peer | ( | struct ast_channel * | chan, | |
| struct ast_rtp ** | rtp | |||
| ) | [static] |
Returns null if we can't reinvite audio (part of RTP interface).
Definition at line 22914 of file chan_sip.c.
References AST_JB_FORCED, AST_RTP_GET_FAILED, ast_rtp_getnat(), AST_RTP_TRY_NATIVE, AST_RTP_TRY_PARTIAL, ast_test_flag, chan, sip_pvt::flags, global_jbconf, sip_pvt::rtp, SIP_CAN_REINVITE, SIP_CAN_REINVITE_NAT, sip_pvt_lock, sip_pvt_unlock, and ast_channel::tech_pvt.
22915 { 22916 struct sip_pvt *p = NULL; 22917 enum ast_rtp_get_result res = AST_RTP_TRY_PARTIAL; 22918 22919 if (!(p = chan->tech_pvt)) 22920 return AST_RTP_GET_FAILED; 22921 22922 sip_pvt_lock(p); 22923 if (!(p->rtp)) { 22924 sip_pvt_unlock(p); 22925 return AST_RTP_GET_FAILED; 22926 } 22927 22928 *rtp = p->rtp; 22929 22930 if (ast_rtp_getnat(*rtp) && !ast_test_flag(&p->flags[0], SIP_CAN_REINVITE_NAT)) 22931 res = AST_RTP_TRY_PARTIAL; 22932 else if (ast_test_flag(&p->flags[0], SIP_CAN_REINVITE)) 22933 res = AST_RTP_TRY_NATIVE; 22934 else if (ast_test_flag(&global_jbconf, AST_JB_FORCED)) 22935 res = AST_RTP_GET_FAILED; 22936 22937 sip_pvt_unlock(p); 22938 22939 return res; 22940 }
| static enum ast_rtp_get_result sip_get_trtp_peer | ( | struct ast_channel * | chan, | |
| struct ast_rtp ** | rtp | |||
| ) | [static] |
Returns null if we can't reinvite text (part of RTP interface).
Definition at line 22968 of file chan_sip.c.
References AST_RTP_GET_FAILED, AST_RTP_TRY_NATIVE, AST_RTP_TRY_PARTIAL, ast_test_flag, chan, sip_pvt::flags, sip_pvt::rtp, SIP_CAN_REINVITE, sip_pvt_lock, sip_pvt_unlock, ast_channel::tech_pvt, and sip_pvt::trtp.
22969 { 22970 struct sip_pvt *p = NULL; 22971 enum ast_rtp_get_result res = AST_RTP_TRY_PARTIAL; 22972 22973 if (!(p = chan->tech_pvt)) 22974 return AST_RTP_GET_FAILED; 22975 22976 sip_pvt_lock(p); 22977 if (!(p->trtp)) { 22978 sip_pvt_unlock(p); 22979 return AST_RTP_GET_FAILED; 22980 } 22981 22982 *rtp = p->trtp; 22983 22984 if (ast_test_flag(&p->flags[0], SIP_CAN_REINVITE)) 22985 res = AST_RTP_TRY_NATIVE; 22986 22987 sip_pvt_unlock(p); 22988 22989 return res; 22990 }
| static struct ast_udptl * sip_get_udptl_peer | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 22870 of file chan_sip.c.
References ast_test_flag, chan, sip_pvt::flags, SIP_CAN_REINVITE, sip_pvt_lock, sip_pvt_unlock, ast_channel::tech_pvt, and sip_pvt::udptl.
22871 { 22872 struct sip_pvt *p; 22873 struct ast_udptl *udptl = NULL; 22874 22875 p = chan->tech_pvt; 22876 if (!p) 22877 return NULL; 22878 22879 sip_pvt_lock(p); 22880 if (p->udptl && ast_test_flag(&p->flags[0], SIP_CAN_REINVITE)) 22881 udptl = p->udptl; 22882 sip_pvt_unlock(p); 22883 return udptl; 22884 }
| static enum ast_rtp_get_result sip_get_vrtp_peer | ( | struct ast_channel * | chan, | |
| struct ast_rtp ** | rtp | |||
| ) | [static] |
Returns null if we can't reinvite video (part of RTP interface).
Definition at line 22943 of file chan_sip.c.
References AST_RTP_GET_FAILED, AST_RTP_TRY_NATIVE, AST_RTP_TRY_PARTIAL, ast_test_flag, chan, sip_pvt::flags, sip_pvt::rtp, SIP_CAN_REINVITE, sip_pvt_lock, sip_pvt_unlock, ast_channel::tech_pvt, and sip_pvt::vrtp.
22944 { 22945 struct sip_pvt *p = NULL; 22946 enum ast_rtp_get_result res = AST_RTP_TRY_PARTIAL; 22947 22948 if (!(p = chan->tech_pvt)) 22949 return AST_RTP_GET_FAILED; 22950 22951 sip_pvt_lock(p); 22952 if (!(p->vrtp)) { 22953 sip_pvt_unlock(p); 22954 return AST_RTP_GET_FAILED; 22955 } 22956 22957 *rtp = p->vrtp; 22958 22959 if (ast_test_flag(&p->flags[0], SIP_CAN_REINVITE)) 22960 res = AST_RTP_TRY_NATIVE; 22961 22962 sip_pvt_unlock(p); 22963 22964 return res; 22965 }
| static int sip_hangup | ( | struct ast_channel * | ast | ) | [static] |
sip_hangup: Hangup SIP call Part of PBX interface, called from ast_hangup
Definition at line 5126 of file chan_sip.c.
References __sip_pretend_ack(), ast_channel::_state, sip_pvt::alreadygone, sip_pvt::answered_elsewhere, append_history, ast_bridged_channel(), ast_cause2str(), ast_clear_flag, ast_debug, ast_dsp_free(), AST_FLAG_ANSWERED_ELSEWHERE, AST_FLAG_ZOMBIE, ast_log(), ast_module_unref(), ast_rtp_get_quality(), ast_rtp_set_vars(), AST_SCHED_DEL_UNREF, ast_set_flag, ast_state2str(), AST_STATE_UP, ast_strlen_zero(), ast_test_flag, sip_pvt::autokillid, sip_pvt::callid, DEC_CALL_LIMIT, DEFAULT_TRANS_TIMEOUT, dialog_unref(), FALSE, sip_pvt::flags, hangup_cause2sip(), ast_channel::hangupcause, sip_pvt::hangupcause, INV_CALLING, INV_CANCELLED, INV_COMPLETED, INV_TERMINATED, sip_pvt::invitestate, IS_SIP_TECH, LOG_WARNING, ast_channel::name, sip_pvt::needdestroy, sip_pvt::owner, pbx_builtin_setvar_helper(), sip_pvt::refer, sip_pvt::rtp, RTPQOS_SUMMARY, sched, SIP_BYE, SIP_CANCEL, sip_cancel_destroy(), SIP_DEFER_BYE_ON_TRANSFER, SIP_INC_COUNT, SIP_NEEDREINVITE, SIP_OUTGOING, SIP_PAGE2_CALL_ONHOLD, SIP_PENDINGBYE, sip_pvt_lock, sip_pvt_unlock, sip_scheddestroy(), stop_media_flows(), stop_session_timer(), ast_channel::tech, ast_channel::tech_pvt, transmit_request(), transmit_request_with_auth(), transmit_response_reliable(), TRUE, update_call_counter(), sip_pvt::username, sip_pvt::vad, and XMIT_RELIABLE.
05127 { 05128 struct sip_pvt *p = ast->tech_pvt; 05129 int needcancel = FALSE; 05130 int needdestroy = 0; 05131 struct ast_channel *oldowner = ast; 05132 05133 if (!p) { 05134 ast_debug(1, "Asked to hangup channel that was not connected\n"); 05135 return 0; 05136 } 05137 if (ast_test_flag(ast, AST_FLAG_ANSWERED_ELSEWHERE)) { 05138 ast_debug(1, "This call was answered elsewhere"); 05139 append_history(p, "Cancel", "Call answered elsewhere"); 05140 p->answered_elsewhere = TRUE; 05141 } 05142 05143 /* Store hangupcause locally in PVT so we still have it before disconnect */ 05144 if (p->owner) 05145 p->hangupcause = p->owner->hangupcause; 05146 05147 if (ast_test_flag(&p->flags[0], SIP_DEFER_BYE_ON_TRANSFER)) { 05148 if (ast_test_flag(&p->flags[0], SIP_INC_COUNT) || ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD)) { 05149 if (sipdebug) 05150 ast_debug(1, "update_call_counter(%s) - decrement call limit counter on hangup\n", p->username); 05151 update_call_counter(p, DEC_CALL_LIMIT); 05152 } 05153 ast_debug(4, "SIP Transfer: Not hanging up right now... Rescheduling hangup for %s.\n", p->callid); 05154 if (p->autokillid > -1 && sip_cancel_destroy(p)) 05155 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 05156 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 05157 ast_clear_flag(&p->flags[0], SIP_DEFER_BYE_ON_TRANSFER); /* Really hang up next time */ 05158 p->needdestroy = 0; 05159 p->owner->tech_pvt = dialog_unref(p->owner->tech_pvt, "unref p->owner->tech_pvt"); 05160 sip_pvt_lock(p); 05161 p->owner = NULL; /* Owner will be gone after we return, so take it away */ 05162 sip_pvt_unlock(p); 05163 return 0; 05164 } 05165 05166 if (ast_test_flag(ast, AST_FLAG_ZOMBIE)) { 05167 if (p->refer) 05168 ast_debug(1, "SIP Transfer: Hanging up Zombie channel %s after transfer ... Call-ID: %s\n", ast->name, p->callid); 05169 else 05170 ast_debug(1, "Hanging up zombie call. Be scared.\n"); 05171 } else 05172 ast_debug(1, "Hangup call %s, SIP callid %s\n", ast->name, p->callid); 05173 05174 sip_pvt_lock(p); 05175 if (ast_test_flag(&p->flags[0], SIP_INC_COUNT) || ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD)) { 05176 if (sipdebug) 05177 ast_debug(1, "update_call_counter(%s) - decrement call limit counter on hangup\n", p->username); 05178 update_call_counter(p, DEC_CALL_LIMIT); 05179 } 05180 05181 /* Determine how to disconnect */ 05182 if (p->owner != ast) { 05183 ast_log(LOG_WARNING, "Huh? We aren't the owner? Can't hangup call.\n"); 05184 sip_pvt_unlock(p); 05185 return 0; 05186 } 05187 /* If the call is not UP, we need to send CANCEL instead of BYE */ 05188 /* In case of re-invites, the call might be UP even though we have an incomplete invite transaction */ 05189 if (p->invitestate < INV_COMPLETED && p->owner->_state != AST_STATE_UP) { 05190 needcancel = TRUE; 05191 ast_debug(4, "Hanging up channel in state %s (not UP)\n", ast_state2str(ast->_state)); 05192 } 05193 05194 stop_media_flows(p); /* Immediately stop RTP, VRTP and UDPTL as applicable */ 05195 05196 append_history(p, needcancel ? "Cancel" : "Hangup", "Cause %s", p->owner ? ast_cause2str(p->hangupcause) : "Unknown"); 05197 05198 /* Disconnect */ 05199 if (p->vad) 05200 ast_dsp_free(p->vad); 05201 05202 p->owner = NULL; 05203 ast->tech_pvt = dialog_unref(ast->tech_pvt, "unref ast->tech_pvt"); 05204 05205 ast_module_unref(ast_module_info->self); 05206 /* Do not destroy this pvt until we have timeout or 05207 get an answer to the BYE or INVITE/CANCEL 05208 If we get no answer during retransmit period, drop the call anyway. 05209 (Sorry, mother-in-law, you can't deny a hangup by sending 05210 603 declined to BYE...) 05211 */ 05212 if (p->alreadygone) 05213 needdestroy = 1; /* Set destroy flag at end of this function */ 05214 else if (p->invitestate != INV_CALLING) 05215 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 05216 05217 /* Start the process if it's not already started */ 05218 if (!p->alreadygone && p->initreq.data && !ast_strlen_zero(p->initreq.data->str)) { 05219 if (needcancel) { /* Outgoing call, not up */ 05220 if (ast_test_flag(&p->flags[0], SIP_OUTGOING)) { 05221 /* stop retransmitting an INVITE that has not received a response */ 05222 __sip_pretend_ack(p); 05223 05224 /* if we can't send right now, mark it pending */ 05225 if (p->invitestate == INV_CALLING) { 05226 /* We can't send anything in CALLING state */ 05227 ast_set_flag(&p->flags[0], SIP_PENDINGBYE); 05228 /* Do we need a timer here if we don't hear from them at all? */ 05229 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 05230 append_history(p, "DELAY", "Not sending cancel, waiting for timeout"); 05231 } else { 05232 p->invitestate = INV_CANCELLED; 05233 /* Send a new request: CANCEL */ 05234 transmit_request(p, SIP_CANCEL, p->lastinvite, XMIT_RELIABLE, FALSE); 05235 /* Actually don't destroy us yet, wait for the 487 on our original 05236 INVITE, but do set an autodestruct just in case we never get it. */ 05237 needdestroy = 0; 05238 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 05239 } 05240 } else { /* Incoming call, not up */ 05241 const char *res; 05242 if (p->hangupcause && (res = hangup_cause2sip(p->hangupcause))) 05243 transmit_response_reliable(p, res, &p->initreq); 05244 else 05245 transmit_response_reliable(p, "603 Declined", &p->initreq); 05246 p->invitestate = INV_TERMINATED; 05247 } 05248 } else { /* Call is in UP state, send BYE */ 05249 if (p->stimer->st_active == TRUE) { 05250 stop_session_timer(p); 05251 } 05252 05253 if (!p->pendinginvite) { 05254 struct ast_channel *bridge = ast_bridged_channel(oldowner); 05255 char *audioqos = ""; 05256 char *videoqos = ""; 05257 char *textqos = ""; 05258 05259 if (p->rtp) 05260 ast_rtp_set_vars(oldowner, p->rtp); 05261 05262 if (bridge) { 05263 struct sip_pvt *q = bridge->tech_pvt; 05264 05265 if (IS_SIP_TECH(bridge->tech) && q && q->rtp) 05266 ast_rtp_set_vars(bridge, q->rtp); 05267 } 05268 05269 if (p->vrtp) 05270 videoqos = ast_rtp_get_quality(p->vrtp, NULL, RTPQOS_SUMMARY); 05271 if (p->trtp) 05272 textqos = ast_rtp_get_quality(p->trtp, NULL, RTPQOS_SUMMARY); 05273 /* Send a hangup */ 05274 transmit_request_with_auth(p, SIP_BYE, 0, XMIT_RELIABLE, 1); 05275 05276 /* Get RTCP quality before end of call */ 05277 if (p->do_history) { 05278 if (p->rtp) 05279 append_history(p, "RTCPaudio", "Quality:%s", audioqos); 05280 if (p->vrtp) 05281 append_history(p, "RTCPvideo", "Quality:%s", videoqos); 05282 if (p->trtp) 05283 append_history(p, "RTCPtext", "Quality:%s", textqos); 05284 } 05285 if (p->rtp && oldowner) 05286 pbx_builtin_setvar_helper(oldowner, "RTPAUDIOQOS", audioqos); 05287 if (p->vrtp && oldowner) 05288 pbx_builtin_setvar_helper(oldowner, "RTPVIDEOQOS", videoqos); 05289 if (p->trtp && oldowner) 05290 pbx_builtin_setvar_helper(oldowner, "RTPTEXTQOS", textqos); 05291 } else { 05292 /* Note we will need a BYE when this all settles out 05293 but we can't send one while we have "INVITE" outstanding. */ 05294 ast_set_flag(&p->flags[0], SIP_PENDINGBYE); 05295 ast_clear_flag(&p->flags[0], SIP_NEEDREINVITE); 05296 AST_SCHED_DEL_UNREF(sched, p->waitid, dialog_unref(p, "when you delete the waitid sched, you should dec the refcount for the stored dialog ptr")); 05297 if (sip_cancel_destroy(p)) 05298 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 05299 } 05300 } 05301 } 05302 if (needdestroy) 05303 p->needdestroy = 1; 05304 sip_pvt_unlock(p); 05305 return 0; 05306 }
| static int sip_indicate | ( | struct ast_channel * | ast, | |
| int | condition, | |||
| const void * | data, | |||
| size_t | datalen | |||
| ) | [static] |
Play indication to user With SIP a lot of indications is sent as messages, letting the device play the indication - busy signal, congestion etc.
Definition at line 5581 of file chan_sip.c.
References ast_channel::_state, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HOLD, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, AST_CONTROL_SRCUPDATE, AST_CONTROL_T38, AST_CONTROL_UNHOLD, AST_CONTROL_VIDUPDATE, ast_log(), ast_moh_start(), ast_moh_stop(), ast_rtp_new_source(), AST_SCHED_DEL_UNREF, ast_set_flag, AST_SOFTHANGUP_DEV, ast_softhangup_nolock(), AST_STATE_RING, AST_STATE_UP, AST_T38_NEGOTIATED, AST_T38_REFUSED, AST_T38_REQUEST_NEGOTIATE, AST_T38_REQUEST_TERMINATE, AST_T38_TERMINATED, ast_test_flag, change_t38_state(), dialog_unref(), FALSE, sip_pvt::flags, sip_pvt::initreq, INV_COMPLETED, INV_EARLY_MEDIA, INV_PROCEEDING, sip_pvt::invitestate, LOG_ERROR, LOG_WARNING, sip_pvt::mohinterpret, sip_pvt::novideo, sip_pvt::rtp, sched, sip_alreadygone(), SIP_NEEDREINVITE, SIP_OUTGOING, SIP_PAGE2_T38SUPPORT, SIP_PENDINGBYE, SIP_PROG_INBAND, SIP_PROG_INBAND_NEVER, SIP_PROG_INBAND_YES, SIP_PROGRESS_SENT, sip_pvt_lock, sip_pvt_unlock, SIP_RINGING, t38properties::state, sip_pvt::t38, T38_DISABLED, T38_ENABLED, T38_LOCAL_REINVITE, T38_PEER_REINVITE, sip_pvt::t38id, t38properties::t38support, ast_channel::tech_pvt, transmit_info_with_vidupdate(), transmit_reinvite_with_sdp(), transmit_response(), transmit_response_reliable(), transmit_response_with_sdp(), transmit_response_with_t38_sdp(), TRUE, sip_pvt::vrtp, XMIT_CRITICAL, and XMIT_UNRELIABLE.
05582 { 05583 struct sip_pvt *p = ast->tech_pvt; 05584 int res = 0; 05585 05586 sip_pvt_lock(p); 05587 switch(condition) { 05588 case AST_CONTROL_RINGING: 05589 if (ast->_state == AST_STATE_RING) { 05590 p->invitestate = INV_EARLY_MEDIA; 05591 if (!ast_test_flag(&p->flags[0], SIP_PROGRESS_SENT) || 05592 (ast_test_flag(&p->flags[0], SIP_PROG_INBAND) == SIP_PROG_INBAND_NEVER)) { 05593 /* Send 180 ringing if out-of-band seems reasonable */ 05594 transmit_response(p, "180 Ringing", &p->initreq); 05595 ast_set_flag(&p->flags[0], SIP_RINGING); 05596 if (ast_test_flag(&p->flags[0], SIP_PROG_INBAND) != SIP_PROG_INBAND_YES) 05597 break; 05598 } else { 05599 /* Well, if it's not reasonable, just send in-band */ 05600 } 05601 } 05602 res = -1; 05603 break; 05604 case AST_CONTROL_BUSY: 05605 if (ast->_state != AST_STATE_UP) { 05606 transmit_response_reliable(p, "486 Busy Here", &p->initreq); 05607 p->invitestate = INV_COMPLETED; 05608 sip_alreadygone(p); 05609 ast_softhangup_nolock(ast, AST_SOFTHANGUP_DEV); 05610 break; 05611 } 05612 res = -1; 05613 break; 05614 case AST_CONTROL_CONGESTION: 05615 if (ast->_state != AST_STATE_UP) { 05616 transmit_response_reliable(p, "503 Service Unavailable", &p->initreq); 05617 p->invitestate = INV_COMPLETED; 05618 sip_alreadygone(p); 05619 ast_softhangup_nolock(ast, AST_SOFTHANGUP_DEV); 05620 break; 05621 } 05622 res = -1; 05623 break; 05624 case AST_CONTROL_PROCEEDING: 05625 if ((ast->_state != AST_STATE_UP) && 05626 !ast_test_flag(&p->flags[0], SIP_PROGRESS_SENT) && 05627 !ast_test_flag(&p->flags[0], SIP_OUTGOING)) { 05628 transmit_response(p, "100 Trying", &p->initreq); 05629 p->invitestate = INV_PROCEEDING; 05630 break; 05631 } 05632 res = -1; 05633 break; 05634 case AST_CONTROL_PROGRESS: 05635 if ((ast->_state != AST_STATE_UP) && 05636 !ast_test_flag(&p->flags[0], SIP_PROGRESS_SENT) && 05637 !ast_test_flag(&p->flags[0], SIP_OUTGOING)) { 05638 p->invitestate = INV_EARLY_MEDIA; 05639 transmit_response_with_sdp(p, "183 Session Progress", &p->initreq, XMIT_UNRELIABLE, FALSE); 05640 ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT); 05641 break; 05642 } 05643 res = -1; 05644 break; 05645 case AST_CONTROL_HOLD: 05646 ast_rtp_new_source(p->rtp); 05647 ast_moh_start(ast, data, p->mohinterpret); 05648 break; 05649 case AST_CONTROL_UNHOLD: 05650 ast_rtp_new_source(p->rtp); 05651 ast_moh_stop(ast); 05652 break; 05653 case AST_CONTROL_VIDUPDATE: /* Request a video frame update */ 05654 if (p->vrtp && !p->novideo) { 05655 transmit_info_with_vidupdate(p); 05656 /* ast_rtcp_send_h261fur(p->vrtp); */ 05657 } else 05658 res = -1; 05659 break; 05660 case AST_CONTROL_T38: /* T38 control frame */ 05661 if (datalen != sizeof(enum ast_control_t38)) { 05662 ast_log(LOG_ERROR, "Invalid datalen for AST_CONTROL_T38. Expected %d, got %d\n", (int)sizeof(enum ast_control_t38), (int)datalen); 05663 } else { 05664 switch (*((enum ast_control_t38 *) data)) { 05665 case AST_T38_NEGOTIATED: 05666 case AST_T38_REQUEST_NEGOTIATE: /* Request T38 */ 05667 if (p->t38.state == T38_PEER_REINVITE) { 05668 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")); 05669 change_t38_state(p, T38_ENABLED); 05670 transmit_response_with_t38_sdp(p, "200 OK", &p->initreq, XMIT_CRITICAL); 05671 } else if (ast_test_flag(&p->t38.t38support, SIP_PAGE2_T38SUPPORT) && p->t38.state != T38_ENABLED) { 05672 change_t38_state(p, T38_LOCAL_REINVITE); 05673 if (!p->pendinginvite) { 05674 transmit_reinvite_with_sdp(p, TRUE, FALSE); 05675 } else if (!ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) { 05676 ast_set_flag(&p->flags[0], SIP_NEEDREINVITE); 05677 } 05678 } 05679 break; 05680 case AST_T38_TERMINATED: 05681 case AST_T38_REFUSED: 05682 case AST_T38_REQUEST_TERMINATE: /* Shutdown T38 */ 05683 if (p->t38.state == T38_PEER_REINVITE) { 05684 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")); 05685 change_t38_state(p, T38_DISABLED); 05686 transmit_response_reliable(p, "488 Not acceptable here", &p->initreq); 05687 } else if (p->t38.state == T38_ENABLED) 05688 transmit_reinvite_with_sdp(p, FALSE, FALSE); 05689 break; 05690 default: 05691 break; 05692 } 05693 } 05694 break; 05695 case AST_CONTROL_SRCUPDATE: 05696 ast_rtp_new_source(p->rtp); 05697 break; 05698 case -1: 05699 res = -1; 05700 break; 05701 default: 05702 ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", condition); 05703 res = -1; 05704 break; 05705 } 05706 sip_pvt_unlock(p); 05707 return res; 05708 }
| static const char * sip_nat_mode | ( | const struct sip_pvt * | p | ) | [static] |
Display SIP nat mode.
Definition at line 2805 of file chan_sip.c.
References ast_test_flag, sip_pvt::flags, SIP_NAT, and SIP_NAT_ROUTE.
Referenced by check_via(), retrans_pkt(), and send_response().
02806 { 02807 return ast_test_flag(&p->flags[0], SIP_NAT) & SIP_NAT_ROUTE ? "NAT" : "no NAT"; 02808 }
| static struct ast_channel* sip_new | ( | struct sip_pvt * | i, | |
| int | state, | |||
| const char * | title | |||
| ) | [static] |
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.
Definition at line 5716 of file chan_sip.c.
References accountcode, sip_pvt::accountcode, ast_channel::adsicpe, ast_channel::amaflags, sip_pvt::amaflags, append_history, AST_ADSI_UNAVAILABLE, ast_best_codec(), AST_CAUSE_SWITCH_CONGESTION, ast_channel_alloc(), ast_channel_set_fd(), ast_codec_choose(), ast_copy_string(), ast_debug, ast_dsp_new(), ast_dsp_set_digitmode(), ast_dsp_set_features(), AST_FORMAT_TEXT_MASK, AST_FORMAT_VIDEO_MASK, ast_getformatname_multiple(), ast_hangup(), ast_jb_configure(), ast_log(), ast_module_ref(), ast_pbx_start(), ast_rtcp_fd(), ast_rtp_fd(), AST_STATE_DOWN, AST_STATE_RING, ast_strdup, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_udptl_fd(), ast_uri_decode(), buf, sip_pvt::callgroup, ast_channel::callgroup, sip_pvt::callid, sip_pvt::callingpres, sip_pvt::capability, sip_pvt::chanvars, ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_dnid, sip_pvt::cid_name, sip_pvt::cid_num, ast_callerid::cid_pres, ast_callerid::cid_rdnis, ast_channel::context, sip_pvt::context, dialog_ref(), sip_pvt::do_history, sip_pvt::domain, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_RELAXDTMF, DSP_FEATURE_DIGIT_DETECT, EVENT_FLAG_SYSTEM, ast_channel::exten, sip_pvt::exten, sip_pvt::flags, sip_pvt::fromdomain, sip_pvt::fullcontact, global_jbconf, ast_channel::hangupcause, sip_pvt::jointcapability, language, sip_pvt::language, LOG_WARNING, manager_event, ast_channel::name, ast_variable::name, ast_channel::nativeformats, ast_variable::next, sip_pvt::owner, pbx_builtin_setvar_helper(), sip_pvt::pickupgroup, ast_channel::pickupgroup, sip_pvt::prefcodec, sip_pvt::prefs, ast_channel::priority, ast_channel::rawreadformat, ast_channel::rawwriteformat, sip_pvt::rdnis, ast_channel::readformat, ast_channel::rings, sip_pvt::rtp, SIP_DTMF, SIP_DTMF_AUTO, SIP_DTMF_INBAND, SIP_DTMF_INFO, SIP_DTMF_SHORTINFO, SIP_PAGE2_VIDEOSUPPORT, sip_pvt_lock, sip_pvt_unlock, sip_tech, sip_tech_info, SIPBUFSIZE, ast_channel::tech, ast_channel::tech_pvt, text, sip_pvt::trtp, sip_pvt::udptl, ast_channel::uniqueid, sip_pvt::uri, sip_pvt::vad, ast_variable::value, sip_pvt::vrtp, and ast_channel::writeformat.
Referenced by handle_request_invite(), and sip_request_call().
05717 { 05718 struct ast_channel *tmp; 05719 struct ast_variable *v = NULL; 05720 int fmt; 05721 int what; 05722 int video; 05723 int text; 05724 int needvideo = 0; 05725 int needtext = 0; 05726 char buf[SIPBUFSIZE]; 05727 char *decoded_exten; 05728 05729 { 05730 const char *my_name; /* pick a good name */ 05731 05732 if (title) 05733 my_name = title; 05734 else if ( (my_name = strchr(i->fromdomain, ':')) ) 05735 my_name++; /* skip ':' */ 05736 else 05737 my_name = i->fromdomain; 05738 05739 sip_pvt_unlock(i); 05740 /* Don't hold a sip pvt lock while we allocate a channel */ 05741 tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, "SIP/%s-%08x", my_name, (int)(long) i); 05742 05743 } 05744 if (!tmp) { 05745 ast_log(LOG_WARNING, "Unable to allocate AST channel structure for SIP channel\n"); 05746 sip_pvt_lock(i); 05747 return NULL; 05748 } 05749 sip_pvt_lock(i); 05750 05751 tmp->tech = ( ast_test_flag(&i->flags[0], SIP_DTMF) == SIP_DTMF_INFO || ast_test_flag(&i->flags[0], SIP_DTMF) == SIP_DTMF_SHORTINFO) ? &sip_tech_info : &sip_tech; 05752 05753 /* Select our native format based on codec preference until we receive 05754 something from another device to the contrary. */ 05755 if (i->jointcapability) { /* The joint capabilities of us and peer */ 05756 what = i->jointcapability; 05757 video = i->jointcapability & AST_FORMAT_VIDEO_MASK; 05758 text = i->jointcapability & AST_FORMAT_TEXT_MASK; 05759 } else if (i->capability) { /* Our configured capability for this peer */ 05760 what = i->capability; 05761 video = i->capability & AST_FORMAT_VIDEO_MASK; 05762 text = i->capability & AST_FORMAT_TEXT_MASK; 05763 } else { 05764 what = global_capability; /* Global codec support */ 05765 video = global_capability & AST_FORMAT_VIDEO_MASK; 05766 text = global_capability & AST_FORMAT_TEXT_MASK; 05767 } 05768 05769 /* Set the native formats for audio and merge in video */ 05770 tmp->nativeformats = ast_codec_choose(&i->prefs, what, 1) | video | text; 05771 ast_debug(3, "*** Our native formats are %s \n", ast_getformatname_multiple(buf, SIPBUFSIZE, tmp->nativeformats)); 05772 ast_debug(3, "*** Joint capabilities are %s \n", ast_getformatname_multiple(buf, SIPBUFSIZE, i->jointcapability)); 05773 ast_debug(3, "*** Our capabilities are %s \n", ast_getformatname_multiple(buf, SIPBUFSIZE, i->capability)); 05774 ast_debug(3, "*** AST_CODEC_CHOOSE formats are %s \n", ast_getformatname_multiple(buf, SIPBUFSIZE, ast_codec_choose(&i->prefs, what, 1))); 05775 if (i->prefcodec) 05776 ast_debug(3, "*** Our preferred formats from the incoming channel are %s \n", ast_getformatname_multiple(buf, SIPBUFSIZE, i->prefcodec)); 05777 05778 /* XXX Why are we choosing a codec from the native formats?? */ 05779 fmt = ast_best_codec(tmp->nativeformats); 05780 05781 /* If we have a prefcodec setting, we have an inbound channel that set a 05782 preferred format for this call. Otherwise, we check the jointcapability 05783 We also check for vrtp. If it's not there, we are not allowed do any video anyway. 05784 */ 05785 if (i->vrtp) { 05786 if (ast_test_flag(&i->flags[1], SIP_PAGE2_VIDEOSUPPORT)) 05787 needvideo = AST_FORMAT_VIDEO_MASK; 05788 else if (i->prefcodec) 05789 needvideo = i->prefcodec & AST_FORMAT_VIDEO_MASK; /* Outbound call */ 05790 else 05791 needvideo = i->jointcapability & AST_FORMAT_VIDEO_MASK; /* Inbound call */ 05792 } 05793 05794 if (i->trtp) { 05795 if (i->prefcodec) 05796 needtext = i->prefcodec & AST_FORMAT_TEXT_MASK; /* Outbound call */ 05797 else 05798 needtext = i->jointcapability & AST_FORMAT_TEXT_MASK; /* Inbound call */ 05799 } 05800 05801 if (needvideo) 05802 ast_debug(3, "This channel can handle video! HOLLYWOOD next!\n"); 05803 else 05804 ast_debug(3, "This channel will not be able to handle video.\n"); 05805 05806 if ((ast_test_flag(&i->flags[0], SIP_DTMF) == SIP_DTMF_INBAND) || (ast_test_flag(&i->flags[0], SIP_DTMF) == SIP_DTMF_AUTO)) { 05807 i->vad = ast_dsp_new(); 05808 ast_dsp_set_features(i->vad, DSP_FEATURE_DIGIT_DETECT); 05809 if (global_relaxdtmf) 05810 ast_dsp_set_digitmode(i->vad, DSP_DIGITMODE_DTMF | DSP_DIGITMODE_RELAXDTMF); 05811 } 05812 05813 /* Set file descriptors for audio, video, realtime text and UDPTL as needed */ 05814 if (i->rtp) { 05815 ast_channel_set_fd(tmp, 0, ast_rtp_fd(i->rtp)); 05816 ast_channel_set_fd(tmp, 1, ast_rtcp_fd(i->rtp)); 05817 } 05818 if (needvideo && i->vrtp) { 05819 ast_channel_set_fd(tmp, 2, ast_rtp_fd(i->vrtp)); 05820 ast_channel_set_fd(tmp, 3, ast_rtcp_fd(i->vrtp)); 05821 } 05822 if (needtext && i->trtp) 05823 ast_channel_set_fd(tmp, 4, ast_rtp_fd(i->trtp)); 05824 if (i->udptl) 05825 ast_channel_set_fd(tmp, 5, ast_udptl_fd(i->udptl)); 05826 05827 if (state == AST_STATE_RING) 05828 tmp->rings = 1; 05829 tmp->adsicpe = AST_ADSI_UNAVAILABLE; 05830 tmp->writeformat = fmt; 05831 tmp->rawwriteformat = fmt; 05832 tmp->readformat = fmt; 05833 tmp->rawreadformat = fmt; 05834 tmp->tech_pvt = dialog_ref(i, "sip_new: set chan->tech_pvt to i"); 05835 05836 tmp->callgroup = i->callgroup; 05837 tmp->pickupgroup = i->pickupgroup; 05838 tmp->cid.cid_pres = i->callingpres; 05839 if (!ast_strlen_zero(i->accountcode)) 05840 ast_string_field_set(tmp, accountcode, i->accountcode); 05841 if (i->amaflags) 05842 tmp->amaflags = i->amaflags; 05843 if (!ast_strlen_zero(i->language)) 05844 ast_string_field_set(tmp, language, i->language); 05845 i->owner = tmp; 05846 ast_module_ref(ast_module_info->self); 05847 ast_copy_string(tmp->context, i->context, sizeof(tmp->context)); 05848 /*Since it is valid to have extensions in the dialplan that have unescaped characters in them 05849 * we should decode the uri before storing it in the channel, but leave it encoded in the sip_pvt 05850 * structure so that there aren't issues when forming URI's 05851 */ 05852 decoded_exten = ast_strdupa(i->exten); 05853 ast_uri_decode(decoded_exten); 05854 ast_copy_string(tmp->exten, decoded_exten, sizeof(tmp->exten)); 05855 05856 /* Don't use ast_set_callerid() here because it will 05857 * generate an unnecessary NewCallerID event */ 05858 tmp->cid.cid_ani = ast_strdup(i->cid_num); 05859 if (!ast_strlen_zero(i->rdnis)) 05860 tmp->cid.cid_rdnis = ast_strdup(i->rdnis); 05861 05862 if (!ast_strlen_zero(i->exten) && strcmp(i->exten, "s")) 05863 tmp->cid.cid_dnid = ast_strdup(i->exten); 05864 05865 tmp->priority = 1; 05866 if (!ast_strlen_zero(i->uri)) 05867 pbx_builtin_setvar_helper(tmp, "SIPURI", i->uri); 05868 if (!ast_strlen_zero(i->domain)) 05869 pbx_builtin_setvar_helper(tmp, "SIPDOMAIN", i->domain); 05870 if (!ast_strlen_zero(i->callid)) 05871 pbx_builtin_setvar_helper(tmp, "SIPCALLID", i->callid); 05872 if (i->rtp) 05873 ast_jb_configure(tmp, &global_jbconf); 05874 05875 /* Set channel variables for this call from configuration */ 05876 for (v = i->chanvars ; v ; v = v->next) 05877 pbx_builtin_setvar_helper(tmp, v->name, v->value); 05878 05879 if (state != AST_STATE_DOWN && ast_pbx_start(tmp)) { 05880 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name); 05881 tmp->hangupcause = AST_CAUSE_SWITCH_CONGESTION; 05882 ast_hangup(tmp); 05883 tmp = NULL; 05884 } 05885 05886 if (i->do_history) 05887 append_history(i, "NewChan", "Channel %s - from %s", tmp->name, i->callid); 05888 05889 /* Inform manager user about new channel and their SIP call ID */ 05890 if (global_callevents) 05891 manager_event(EVENT_FLAG_SYSTEM, "ChannelUpdate", 05892 "Channel: %s\r\nUniqueid: %s\r\nChanneltype: %s\r\nSIPcallid: %s\r\nSIPfullcontact: %s\r\n", 05893 tmp->name, tmp->uniqueid, "SIP", i->callid, i->fullcontact); 05894 05895 return tmp; 05896 }
| static int sip_park | ( | struct ast_channel * | chan1, | |
| struct ast_channel * | chan2, | |||
| struct sip_request * | req, | |||
| int | seqno | |||
| ) | [static] |
Park a call using the subsystem in res_features.c This is executed in a separate thread.
Definition at line 16978 of file chan_sip.c.
References ast_channel::accountcode, ast_channel::amaflags, ast_calloc, AST_CAUSE_SWITCH_CONGESTION, ast_channel_alloc(), ast_channel_lock, ast_channel_masquerade(), ast_channel_trylock, ast_channel_unlock, ast_copy_string(), ast_debug, ast_do_masquerade(), ast_free, ast_hangup(), ast_log(), ast_pthread_create_detached_background, AST_STATE_DOWN, ast_channel::context, copy_request(), ast_channel::exten, ast_channel::hangupcause, LOG_WARNING, ast_channel::name, ast_channel::priority, ast_channel::readformat, sip_park_thread(), sip_pvt_lock, sip_pvt_unlock, ast_channel::tech_pvt, and ast_channel::writeformat.
Referenced by handle_request_refer().
16979 { 16980 struct sip_dual *d; 16981 struct ast_channel *transferee, *transferer; 16982 /* Chan2m: The transferer, chan1m: The transferee */ 16983 pthread_t th; 16984 16985 transferee = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan1->accountcode, chan1->exten, chan1->context, chan1->amaflags, "Parking/%s", chan1->name); 16986 transferer = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan2->accountcode, chan2->exten, chan2->context, chan2->amaflags, "SIPPeer/%s", chan2->name); 16987 if ((!transferer) || (!transferee)) { 16988 if (transferee) { 16989 transferee->hangupcause = AST_CAUSE_SWITCH_CONGESTION; 16990 ast_hangup(transferee); 16991 } 16992 if (transferer) { 16993 transferer->hangupcause = AST_CAUSE_SWITCH_CONGESTION; 16994 ast_hangup(transferer); 16995 } 16996 return -1; 16997 } 16998 16999 /* Make formats okay */ 17000 transferee->readformat = chan1->readformat; 17001 transferee->writeformat = chan1->writeformat; 17002 17003 /* Prepare for taking over the channel */ 17004 ast_channel_masquerade(transferee, chan1); 17005 17006 /* Setup the extensions and such */ 17007 ast_copy_string(transferee->context, chan1->context, sizeof(transferee->context)); 17008 ast_copy_string(transferee->exten, chan1->exten, sizeof(transferee->exten)); 17009 transferee->priority = chan1->priority; 17010 17011 /* We make a clone of the peer channel too, so we can play 17012 back the announcement */ 17013 17014 /* Make formats okay */ 17015 transferer->readformat = chan2->readformat; 17016 transferer->writeformat = chan2->writeformat; 17017 17018 /* Prepare for taking over the channel. Go ahead and grab this channel 17019 * lock here to avoid a deadlock with callbacks into the channel driver 17020 * that hold the channel lock and want the pvt lock. */ 17021 while (ast_channel_trylock(chan2)) { 17022 struct sip_pvt *pvt = chan2->tech_pvt; 17023 sip_pvt_unlock(pvt); 17024 usleep(1); 17025 sip_pvt_lock(pvt); 17026 } 17027 ast_channel_masquerade(transferer, chan2); 17028 ast_channel_unlock(chan2); 17029 17030 /* Setup the extensions and such */ 17031 ast_copy_string(transferer->context, chan2->context, sizeof(transferer->context)); 17032 ast_copy_string(transferer->exten, chan2->exten, sizeof(transferer->exten)); 17033 transferer->priority = chan2->priority; 17034 17035 ast_channel_lock(transferer); 17036 if (ast_do_masquerade(transferer)) { 17037 ast_log(LOG_WARNING, "Masquerade failed :(\n"); 17038 ast_channel_unlock(transferer); 17039 transferer->hangupcause = AST_CAUSE_SWITCH_CONGESTION; 17040 ast_hangup(transferer); 17041 return -1; 17042 } 17043 ast_channel_unlock(transferer); 17044 if (!transferer || !transferee) { 17045 if (!transferer) { 17046 ast_debug(1, "No transferer channel, giving up parking\n"); 17047 } 17048 if (!transferee) { 17049 ast_debug(1, "No transferee channel, giving up parking\n"); 17050 } 17051 return -1; 17052 } 17053 if ((d = ast_calloc(1, sizeof(*d)))) { 17054 17055 /* Save original request for followup */ 17056 copy_request(&d->req, req); 17057 d->chan1 = transferee; /* Transferee */ 17058 d->chan2 = transferer; /* Transferer */ 17059 d->seqno = seqno; 17060 if (ast_pthread_create_detached_background(&th, NULL, sip_park_thread, d) < 0) { 17061 /* Could not start thread */ 17062 if (d->req.data) 17063 ast_free(d->req.data); 17064 ast_free(d); /* We don't need it anymore. If thread is created, d will be free'd 17065 by sip_park_thread() */ 17066 return 0; 17067 } 17068 } 17069 return -1; 17070 }
| static void * sip_park_thread | ( | void * | stuff | ) | [static] |
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.
Definition at line 16906 of file chan_sip.c.
References append_history, AST_CAUSE_NORMAL_CLEARING, ast_channel_lock, ast_channel_unlock, ast_debug, ast_do_masquerade(), ast_free, ast_hangup(), ast_log(), ast_park_call(), buf, sip_dual::chan1, sip_dual::chan2, copy_request(), sip_request::data, ext, free, ast_channel::hangupcause, LOG_ERROR, LOG_WARNING, ast_channel::name, sip_dual::req, sip_dual::seqno, ast_channel::tech_pvt, transmit_message_with_text(), transmit_notify_with_sipfrag(), transmit_response(), and TRUE.
Referenced by sip_park().
16907 { 16908 struct ast_channel *transferee, *transferer; /* Chan1: The transferee, Chan2: The transferer */ 16909 struct sip_dual *d; 16910 struct sip_request req = {0,}; 16911 int ext; 16912 int res; 16913 16914 d = stuff; 16915 transferee = d->chan1; 16916 transferer = d->chan2; 16917 copy_request(&req, &d->req); 16918 16919 if (!transferee || !transferer) { 16920 ast_log(LOG_ERROR, "Missing channels for parking! Transferer %s Transferee %s\n", transferer ? "<available>" : "<missing>", transferee ? "<available>" : "<missing>" ); 16921 if (d->req.data) 16922 ast_free(d->req.data); 16923 free(d); 16924 return NULL; 16925 } 16926 ast_debug(4, "SIP Park: Transferer channel %s, Transferee %s\n", transferer->name, transferee->name); 16927 16928 ast_channel_lock(transferee); 16929 if (ast_do_masquerade(transferee)) { 16930 ast_log(LOG_WARNING, "Masquerade failed.\n"); 16931 transmit_response(transferer->tech_pvt, "503 Internal error", &req); 16932 ast_channel_unlock(transferee); 16933 if (d->req.data) 16934 ast_free(d->req.data); 16935 free(d); 16936 return NULL; 16937 } 16938 ast_channel_unlock(transferee); 16939 16940 res = ast_park_call(transferee, transferer, 0, &ext); 16941 16942 16943 #ifdef WHEN_WE_KNOW_THAT_THE_CLIENT_SUPPORTS_MESSAGE 16944 if (!res) { 16945 transmit_message_with_text(transferer->tech_pvt, "Unable to park call.\n"); 16946 } else { 16947 /* Then tell the transferer what happened */ 16948 sprintf(buf, "Call parked on extension '%d'", ext); 16949 transmit_message_with_text(transferer->tech_pvt, buf); 16950 } 16951 #endif 16952 16953 /* Any way back to the current call??? */ 16954 /* Transmit response to the REFER request */ 16955 transmit_response(transferer->tech_pvt, "202 Accepted", &req); 16956 if (!res) { 16957 /* Transfer succeeded */ 16958 append_history(transferer->tech_pvt, "SIPpark", "Parked call on %d", ext); 16959 transmit_notify_with_sipfrag(transferer->tech_pvt, d->seqno, "200 OK", TRUE); 16960 transferer->hangupcause = AST_CAUSE_NORMAL_CLEARING; 16961 ast_hangup(transferer); /* This will cause a BYE */ 16962 ast_debug(1, "SIP Call parked on extension '%d'\n", ext); 16963 } else { 16964 transmit_notify_with_sipfrag(transferer->tech_pvt, d->seqno, "503 Service Unavailable", TRUE); 16965 append_history(transferer->tech_pvt, "SIPpark", "Parking failed\n"); 16966 ast_debug(1, "SIP Call parked failed \n"); 16967 /* Do not hangup call */ 16968 } 16969 if (d->req.data) 16970 ast_free(d->req.data); 16971 free(d); 16972 return NULL; 16973 }
| static int sip_parse_host | ( | char * | line, | |
| int | lineno, | |||
| char ** | hostname, | |||
| int * | portnum, | |||
| enum sip_transport * | transport | |||
| ) | [static] |
Small function to parse a config line for a host with a transport i.e. tls://www.google.com:8056.
Definition at line 20140 of file chan_sip.c.
References ast_log(), LOG_NOTICE, SIP_TRANSPORT_TCP, SIP_TRANSPORT_TLS, SIP_TRANSPORT_UDP, STANDARD_SIP_PORT, and STANDARD_TLS_PORT.
Referenced by sip_register().
20141 { 20142 char *port; 20143 20144 if ((*hostname = strstr(line, "://"))) { 20145 *hostname += 3; 20146 20147 if (!strncasecmp(line, "tcp", 3)) 20148 *transport = SIP_TRANSPORT_TCP; 20149 else if (!strncasecmp(line, "tls", 3)) 20150 *transport = SIP_TRANSPORT_TLS; 20151 else if (!strncasecmp(line, "udp", 3)) 20152 *transport = SIP_TRANSPORT_UDP; 20153 else 20154 ast_log(LOG_NOTICE, "'%.3s' is not a valid transport type on line %d of sip.conf. defaulting to udp.\n", line, lineno); 20155 } else { 20156 *hostname = line; 20157 *transport = SIP_TRANSPORT_UDP; 20158 } 20159 20160 if ((line = strrchr(*hostname, '@'))) 20161 line++; 20162 else 20163 line = *hostname; 20164 20165 if ((port = strrchr(line, ':'))) { 20166 *port++ = '\0'; 20167 20168 if (!sscanf(port, "%u", portnum)) { 20169 ast_log(LOG_NOTICE, "'%s' is not a valid port number on line %d of sip.conf. using default.\n", port, lineno); 20170 port = NULL; 20171 } 20172 } 20173 20174 if (!port) { 20175 if (*transport & SIP_TRANSPORT_TLS) { 20176 *portnum = STANDARD_TLS_PORT; 20177 } else { 20178 *portnum = STANDARD_SIP_PORT; 20179 } 20180 } 20181 20182 return 0; 20183 }
| static void sip_peer_hold | ( | struct sip_pvt * | p, | |
| int | hold | |||
| ) | [static] |
Change onhold state of a peer using a pvt structure.
Definition at line 11065 of file chan_sip.c.
References ast_atomic_fetchadd_int(), AST_DEVICE_UNKNOWN, ast_devstate_changed(), FALSE, find_peer(), FINDALLDEVICES, sip_peer::name, sip_peer::onHold, sip_pvt::peername, and unref_peer().
Referenced by process_sdp(), and update_call_counter().
11066 { 11067 struct sip_peer *peer = find_peer(p->peername, NULL, 1, FINDALLDEVICES, FALSE); 11068 11069 if (!peer) 11070 return; 11071 11072 /* If they put someone on hold, increment the value... otherwise decrement it */ 11073 ast_atomic_fetchadd_int(&peer->onHold, (hold ? +1 : -1)); 11074 11075 /* Request device state update */ 11076 ast_devstate_changed(AST_DEVICE_UNKNOWN, "SIP/%s", peer->name); 11077 unref_peer(peer, "sip_peer_hold: from find_peer operation"); 11078 11079 return; 11080 }
| static void sip_poke_all_peers | ( | void | ) | [static] |
Send a poke to all known peers Space them out 100 ms apart XXX We might have a cool algorithm for this or use random - any suggestions?
Definition at line 23247 of file chan_sip.c.
References ao2_iterator_init(), ao2_lock(), ao2_t_iterator_next, ao2_unlock(), AST_SCHED_REPLACE_UNREF, sip_peer::pokeexpire, ref_peer(), sched, sip_poke_peer_s(), and unref_peer().
Referenced by load_module(), and sip_do_reload().
23248 { 23249 int ms = 0; 23250 struct ao2_iterator i; 23251 struct sip_peer *peer; 23252 23253 i = ao2_iterator_init(peers, 0); 23254 23255 if (!speerobjs) /* No peers, just give up */ 23256 return; 23257 23258 while ((peer = ao2_t_iterator_next(&i, "iterate thru peers table"))) { 23259 ao2_lock(peer); 23260 ms += 100; 23261 AST_SCHED_REPLACE_UNREF(peer->pokeexpire, sched, ms, sip_poke_peer_s, peer, 23262 unref_peer(_data, "removing poke peer ref"), 23263 unref_peer(peer, "removing poke peer ref"), 23264 ref_peer(peer, "adding poke peer ref")); 23265 ao2_unlock(peer); 23266 unref_peer(peer, "toss iterator peer ptr"); 23267 } 23268 }
| static int sip_poke_noanswer | ( | const void * | data | ) | [static] |
React to lack of answer to Qualify poke.
Definition at line 20754 of file chan_sip.c.
References ast_check_realtime(), AST_DEVICE_UNKNOWN, ast_devstate_changed(), ast_log(), AST_SCHED_REPLACE_UNREF, ast_update_realtime(), sip_peer::call, DEFAULT_FREQ_NOTOK, dialog_unlink_all(), dialog_unref(), EVENT_FLAG_SYSTEM, FALSE, sip_peer::lastms, LOG_NOTICE, manager_event, sip_peer::name, sip_settings::peer_rtupdate, sip_peer::pokeexpire, ref_peer(), register_peer_exten(), sched, SENTINEL, sip_cfg, sip_poke_peer_s(), TRUE, and unref_peer().
Referenced by sip_poke_peer(), and sip_show_sched().
20755 { 20756 struct sip_peer *peer = (struct sip_peer *)data; 20757 20758 peer->pokeexpire = -1; 20759 20760 if (peer->lastms > -1) { 20761 ast_log(LOG_NOTICE, "Peer '%s' is now UNREACHABLE! Last qualify: %d\n", peer->name, peer->lastms); 20762 if (sip_cfg.peer_rtupdate) { 20763 ast_update_realtime(ast_check_realtime("sipregs") ? "sipregs" : "sippeers", "name", peer->name, "lastms", "-1", SENTINEL); 20764 } 20765 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: SIP\r\nPeer: SIP/%s\r\nPeerStatus: Unreachable\r\nTime: %d\r\n", peer->name, -1); 20766 if (global_regextenonqualify) { 20767 register_peer_exten(peer, FALSE); 20768 } 20769 } 20770 20771 if (peer->call) { 20772 dialog_unlink_all(peer->call, TRUE, TRUE); 20773 peer->call = dialog_unref(peer->call, "unref dialog peer->call"); 20774 /* peer->call = sip_destroy(peer->call);*/ 20775 } 20776 20777 peer->lastms = -1; 20778 ast_devstate_changed(AST_DEVICE_UNKNOWN, "SIP/%s", peer->name); 20779 20780 /* Try again quickly */ 20781 AST_SCHED_REPLACE_UNREF(peer->pokeexpire, sched, 20782 DEFAULT_FREQ_NOTOK, sip_poke_peer_s, peer, 20783 unref_peer(_data, "removing poke peer ref"), 20784 unref_peer(peer, "removing poke peer ref"), 20785 ref_peer(peer, "adding poke peer ref")); 20786 20787 /* Release the ref held by the running scheduler entry */ 20788 unref_peer(peer, "release peer poke noanswer ref"); 20789 20790 return 0; 20791 }
| static int sip_poke_peer | ( | struct sip_peer * | peer, | |
| int | force | |||
| ) | [static] |
Check availability of peer, also keep NAT open.
Definition at line 20798 of file chan_sip.c.
References sip_peer::addr, ao2_t_link, ao2_t_unlink, ast_copy_flags, ast_copy_string(), ast_inet_ntoa(), ast_log(), AST_SCHED_DEL_UNREF, AST_SCHED_REPLACE_UNREF, ast_set_flag, ast_sip_ouraddrfor(), ast_string_field_set, ast_strlen_zero(), ast_tvnow(), build_callid_pvt(), build_via(), sip_peer::call, copy_socket_data(), dialog_ref(), dialog_unlink_all(), dialog_unref(), dialogs, sip_peer::flags, sip_pvt::flags, sip_pvt::fullcontact, sip_peer::fullcontact, sip_peer::lastms, LOG_NOTICE, sip_peer::maxms, sip_pvt::ourip, sip_peer::pokeexpire, sip_peer::ps, sip_pvt::recv, ref_peer(), sip_pvt::relatedpeer, sip_pvt::sa, sched, sip_alloc(), SIP_FLAGS_TO_COPY, SIP_INVITE, SIP_OPTIONS, SIP_OUTGOING, SIP_PAGE2_FLAGS_TO_COPY, sip_poke_noanswer(), sip_peer::socket, sip_pvt::socket, sip_pvt::tohost, sip_peer::tohost, transmit_invite(), TRUE, unref_peer(), sip_pvt::username, and XMIT_ERROR.
Referenced by _sip_qualify_peer(), build_peer(), parse_register_contact(), reg_source_db(), and sip_poke_peer_s().
20799 { 20800 struct sip_pvt *p; 20801 int xmitres = 0; 20802 20803 if ((!peer->maxms && !force) || !peer->addr.sin_addr.s_addr) { 20804 /* IF we have no IP, or this isn't to be monitored, return 20805 immediately after clearing things out */ 20806 AST_SCHED_DEL_UNREF(sched, peer->pokeexpire, 20807 unref_peer(peer, "removing poke peer ref")); 20808 20809 peer->lastms = 0; 20810 if (peer->call) { 20811 peer->call = dialog_unref(peer->call, "unref dialog peer->call"); 20812 } 20813 return 0; 20814 } 20815 if (peer->call) { 20816 if (sipdebug) { 20817 ast_log(LOG_NOTICE, "Still have a QUALIFY dialog active, deleting\n"); 20818 } 20819 dialog_unlink_all(peer->call, TRUE, TRUE); 20820 peer->call = dialog_unref(peer->call, "unref dialog peer->call"); 20821 /* peer->call = sip_destroy(peer->call); */ 20822 } 20823 if (!(p = sip_alloc(NULL, NULL, 0, SIP_OPTIONS))) { 20824 return -1; 20825 } 20826 peer->call = dialog_ref(p, "copy sip alloc from p to peer->call"); 20827 20828 p->sa = peer->addr; 20829 p->recv = peer->addr; 20830 copy_socket_data(&p->socket, &peer->socket); 20831 ast_copy_flags(&p->flags[0], &peer->flags[0], SIP_FLAGS_TO_COPY); 20832 ast_copy_flags(&p->flags[1], &peer->flags[1], SIP_PAGE2_FLAGS_TO_COPY); 20833 20834 /* Send OPTIONs to peer's fullcontact */ 20835 if (!ast_strlen_zero(peer->fullcontact)) 20836 ast_string_field_set(p, fullcontact, peer->fullcontact); 20837 20838 if (!ast_strlen_zero(peer->tohost)) 20839 ast_string_field_set(p, tohost, peer->tohost); 20840 else 20841 ast_string_field_set(p, tohost, ast_inet_ntoa(peer->addr.sin_addr)); 20842 20843 /* Recalculate our side, and recalculate Call ID */ 20844 ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip); 20845 build_via(p); 20846 ao2_t_unlink(dialogs, p, "About to change the callid -- remove the old name"); 20847 build_callid_pvt(p); 20848 ao2_t_link(dialogs, p, "Linking in under new name"); 20849 20850 AST_SCHED_DEL_UNREF(sched, peer->pokeexpire, 20851 unref_peer(peer, "removing poke peer ref")); 20852 20853 if (p->relatedpeer) 20854 p->relatedpeer = unref_peer(p->relatedpeer,"unsetting the relatedpeer field in the dialog, before it is set to something else."); 20855 p->relatedpeer = ref_peer(peer, "setting the relatedpeer field in the dialog"); 20856 ast_set_flag(&p->flags[0], SIP_OUTGOING); 20857 #ifdef VOCAL_DATA_HACK 20858 ast_copy_string(p->username, "__VOCAL_DATA_SHOULD_READ_THE_SIP_SPEC__", sizeof(p->username)); 20859 xmitres = transmit_invite(p, SIP_INVITE, 0, 2); /* sinks the p refcount */ 20860 #else 20861 xmitres = transmit_invite(p, SIP_OPTIONS, 0, 2); /* sinks the p refcount */ 20862 #endif 20863 peer->ps = ast_tvnow(); 20864 if (xmitres == XMIT_ERROR) { 20865 sip_poke_noanswer(peer); /* Immediately unreachable, network problems */ 20866 } else if (!force) { 20867 AST_SCHED_REPLACE_UNREF(peer->pokeexpire, sched, peer->maxms * 2, sip_poke_noanswer, peer, 20868 unref_peer(_data, "removing poke peer ref"), 20869 unref_peer(peer, "removing poke peer ref"), 20870 ref_peer(peer, "adding poke peer ref")); 20871 } 20872 dialog_unref(p, "unref dialog at end of sip_poke_peer, obtained from sip_alloc, just before it goes out of scope"); 20873 return 0; 20874 }
| static int sip_poke_peer_s | ( | const void * | data | ) | [static] |
Poke peer (send qualify to check if peer is alive and well).
Definition at line 10428 of file chan_sip.c.
References sip_peer::pokeexpire, sip_poke_peer(), and unref_peer().
Referenced by handle_response_peerpoke(), reg_source_db(), sip_poke_all_peers(), sip_poke_noanswer(), and sip_show_sched().
10429 { 10430 struct sip_peer *peer = (struct sip_peer *)data; 10431 10432 peer->pokeexpire = -1; 10433 10434 sip_poke_peer(peer, 0); 10435 10436 unref_peer(peer, "removing poke peer ref"); 10437 10438 return 0; 10439 }
| static int sip_prepare_socket | ( | struct sip_pvt * | p | ) | [static] |
Definition at line 20062 of file chan_sip.c.
References ast_tcptls_session_args::accept_fd, ao2_ref, ast_calloc, ast_copy_string(), ast_debug, ast_free, ast_pthread_create_background, ast_strlen_zero(), ast_tcptls_client_start(), default_tls_cfg, ast_tcptls_session_instance::fd, ast_tcptls_session_args::hostname, ast_tcptls_session_args::master, ast_tcptls_session_args::name, name, sip_pvt::outboundproxy, ast_tcptls_session_args::remote_address, s, sip_real_dst(), sip_tcp_locate(), sip_tcp_worker_fn(), SIP_TRANSPORT_TLS, SIP_TRANSPORT_UDP, sipsock, sip_pvt::socket, ast_tcptls_session_args::tls_cfg, sip_pvt::tohost, and sip_proxy::transport.
Referenced by __sip_xmit().
20063 { 20064 struct sip_socket *s = &p->socket; 20065 static const char name[] = "SIP socket"; 20066 struct ast_tcptls_session_instance *tcptls_session; 20067 struct ast_tcptls_session_args ca = { 20068 .name = name, 20069 .accept_fd = -1, 20070 }; 20071 20072 if (s->fd != -1) 20073 return s->fd; 20074 20075 if (p->outboundproxy && p->outboundproxy->transport) { 20076 s->type = p->outboundproxy->transport; 20077 } 20078 20079 if (s->type & SIP_TRANSPORT_UDP) { 20080 s->fd = sipsock; 20081 return s->fd; 20082 } 20083 20084 ca.remote_address = *(sip_real_dst(p)); 20085 20086 if ((tcptls_session = sip_tcp_locate(&ca.remote_address))) { /* Check if we have a thread handling a socket connected to this IP/port */ 20087 s->fd = tcptls_session->fd; 20088 if (s->tcptls_session) { 20089 ao2_ref(s->tcptls_session, -1); 20090 s->tcptls_session = NULL; 20091 } 20092 s->tcptls_session = tcptls_session; 20093 return s->fd; 20094 } 20095 20096 if (s->tcptls_session && s->tcptls_session->parent->tls_cfg) { 20097 ca.tls_cfg = s->tcptls_session->parent->tls_cfg; 20098 } else { 20099 if (s->type & SIP_TRANSPORT_TLS) { 20100 ca.tls_cfg = ast_calloc(1, sizeof(*ca.tls_cfg)); 20101 if (!ca.tls_cfg) 20102 return -1; 20103 memcpy(ca.tls_cfg, &default_tls_cfg, sizeof(*ca.tls_cfg)); 20104 if (!ast_strlen_zero(p->tohost)) 20105 ast_copy_string(ca.hostname, p->tohost, sizeof(ca.hostname)); 20106 } 20107 } 20108 20109 if (s->tcptls_session) { 20110 /* the pvt socket already has a server instance ... */ 20111 } else { 20112 s->tcptls_session = ast_tcptls_client_start(&ca); /* Start a client connection to this address */ 20113 } 20114 20115 if (!s->tcptls_session) { 20116 if (ca.tls_cfg) 20117 ast_free(ca.tls_cfg); 20118 return -1; 20119 } 20120 20121 s->fd = ca.accept_fd; 20122 20123 /* Give the new thread a reference */ 20124 ao2_ref(s->tcptls_session, +1); 20125 20126 if (ast_pthread_create_background(&ca.master, NULL, sip_tcp_worker_fn, s->tcptls_session)) { 20127 ast_debug(1, "Unable to launch '%s'.", ca.name); 20128 ao2_ref(s->tcptls_session, -1); 20129 close(ca.accept_fd); 20130 s->fd = ca.accept_fd = -1; 20131 } 20132 20133 return s->fd; 20134 }
| static char * sip_prune_realtime | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Remove temporary realtime objects from memory (CLI).
Definition at line 13312 of file chan_sip.c.
References sip_peer::addr, ao2_iterator_init(), ao2_lock(), ao2_t_callback, ao2_t_find, ao2_t_iterator_next, ao2_t_link, ao2_t_unlink, ao2_unlock(), ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_copy_string(), ast_test_flag, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_sip_peer(), FALSE, ast_cli_args::fd, sip_peer::flags, ast_cli_args::line, ast_cli_args::n, sip_peer::name, name, OBJ_MULTIPLE, OBJ_NODATA, OBJ_POINTER, OBJ_UNLINK, peer_is_marked(), peers_by_ip, ast_cli_args::pos, SIP_PAGE2_RTCACHEFRIENDS, strcasestr(), sip_peer::the_mark, TRUE, unref_peer(), ast_cli_entry::usage, and ast_cli_args::word.
13313 { 13314 struct sip_peer *peer, *pi; 13315 int prunepeer = FALSE; 13316 int multi = FALSE; 13317 char *name = NULL; 13318 regex_t regexbuf; 13319 struct ao2_iterator i; 13320 13321 if (cmd == CLI_INIT) { 13322 e->command = "sip prune realtime [peer|all] [all|like]"; 13323 e->usage = 13324 "Usage: sip prune realtime [peer [<name>|all|like <pattern>]|all]\n" 13325 " Prunes object(s) from the cache.\n" 13326 " Optional regular expression pattern is used to filter the objects.\n"; 13327 return NULL; 13328 } else if (cmd == CLI_GENERATE) { 13329 if (a->pos == 4) { 13330 if (strcasestr(a->line, "realtime peer")) 13331 return complete_sip_peer(a->word, a->n, SIP_PAGE2_RTCACHEFRIENDS); 13332 } 13333 return NULL; 13334 } 13335 switch (a->argc) { 13336 case 4: 13337 name = a->argv[3]; 13338 /* we accept a name in position 3, but keywords are not good. */ 13339 if (!strcasecmp(name, "peer") || !strcasecmp(name, "like")) 13340 return CLI_SHOWUSAGE; 13341 prunepeer = TRUE; 13342 if (!strcasecmp(name, "all")) { 13343 multi = TRUE; 13344 name = NULL; 13345 } 13346 /* else a single name, already set */ 13347 break; 13348 case 5: 13349 /* sip prune realtime {peer|like} name */ 13350 name = a->argv[4]; 13351 if (!strcasecmp(a->argv[3], "peer")) 13352 prunepeer = TRUE; 13353 else if (!strcasecmp(a->argv[3], "like")) { 13354 prunepeer = TRUE; 13355 multi = TRUE; 13356 } else 13357 return CLI_SHOWUSAGE; 13358 if (!strcasecmp(a->argv[4], "like")) 13359 return CLI_SHOWUSAGE; 13360 if (!multi && !strcasecmp(a->argv[4], "all")) { 13361 multi = TRUE; 13362 name = NULL; 13363 } 13364 break; 13365 case 6: 13366 name = a->argv[5]; 13367 multi = TRUE; 13368 /* sip prune realtime {peer} like name */ 13369 if (strcasecmp(a->argv[4], "like")) 13370 return CLI_SHOWUSAGE; 13371 if (!strcasecmp(a->argv[3], "peer")) { 13372 prunepeer = TRUE; 13373 } else 13374 return CLI_SHOWUSAGE; 13375 break; 13376 default: 13377 return CLI_SHOWUSAGE; 13378 } 13379 13380 if (multi && name) { 13381 if (regcomp(®exbuf, name, REG_EXTENDED | REG_NOSUB)) 13382 return CLI_SHOWUSAGE; 13383 } 13384 13385 if (multi) { 13386 if (prunepeer) { 13387 int pruned = 0; 13388 13389 i = ao2_iterator_init(peers, 0); 13390 while ((pi = ao2_t_iterator_next(&i, "iterate thru peers table"))) { 13391 ao2_lock(pi); 13392 if (name && regexec(®exbuf, pi->name, 0, NULL, 0)) { 13393 unref_peer(pi, "toss iterator peer ptr before continue"); 13394 ao2_unlock(pi); 13395 continue; 13396 }; 13397 if (ast_test_flag(&pi->flags[1], SIP_PAGE2_RTCACHEFRIENDS)) { 13398 pi->the_mark = 1; 13399 pruned++; 13400 } 13401 ao2_unlock(pi); 13402 unref_peer(pi, "toss iterator peer ptr"); 13403 } 13404 if (pruned) { 13405 ao2_t_callback(peers, OBJ_NODATA | OBJ_UNLINK | OBJ_MULTIPLE, peer_is_marked, 0, 13406 "initiating callback to remove marked peers"); 13407 ast_cli(a->fd, "%d peers pruned.\n", pruned); 13408 } else 13409 ast_cli(a->fd, "No peers found to prune.\n"); 13410 } 13411 } else { 13412 if (prunepeer) { 13413 struct sip_peer tmp; 13414 ast_copy_string(tmp.name, name, sizeof(tmp.name)); 13415 if ((peer = ao2_t_find(peers, &tmp, OBJ_POINTER | OBJ_UNLINK, "finding to unlink from peers"))) { 13416 if (peer->addr.sin_addr.s_addr) { 13417 ao2_t_unlink(peers_by_ip, peer, "unlinking peer from peers_by_ip also"); 13418 } 13419 if (!ast_test_flag(&peer->flags[1], SIP_PAGE2_RTCACHEFRIENDS)) { 13420 ast_cli(a->fd, "Peer '%s' is not a Realtime peer, cannot be pruned.\n", name); 13421 /* put it back! */ 13422 ao2_t_link(peers, peer, "link peer into peer table"); 13423 if (peer->addr.sin_addr.s_addr) { 13424 ao2_t_link(peers_by_ip, peer, "link peer into peers_by_ip table"); 13425 } 13426 13427 } else 13428 ast_cli(a->fd, "Peer '%s' pruned.\n", name); 13429 unref_peer(peer, "sip_prune_realtime: unref_peer: tossing temp peer ptr"); 13430 } else 13431 ast_cli(a->fd, "Peer '%s' not found.\n", name); 13432 } 13433 } 13434 13435 return CLI_SUCCESS; 13436 }
| static char * sip_qualify_peer | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Send an OPTIONS packet to a SIP peer.
Definition at line 13590 of file chan_sip.c.
References _sip_qualify_peer(), ast_cli_args::argc, ast_cli_args::argv, CLI_GENERATE, CLI_INIT, ast_cli_entry::command, complete_sip_show_peer(), ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.
13591 { 13592 switch (cmd) { 13593 case CLI_INIT: 13594 e->command = "sip qualify peer"; 13595 e->usage = 13596 "Usage: sip qualify peer <name> [load]\n" 13597 " Requests a response from one SIP peer and the current status.\n" 13598 " Option \"load\" forces lookup of peer in realtime storage.\n"; 13599 return NULL; 13600 case CLI_GENERATE: 13601 return complete_sip_show_peer(a->line, a->word, a->pos, a->n); 13602 } 13603 return _sip_qualify_peer(0, a->fd, NULL, NULL, a->argc, (const char **) a->argv); 13604 }
| static int sip_queryoption | ( | struct ast_channel * | chan, | |
| int | option, | |||
| void * | data, | |||
| int * | datalen | |||
| ) | [static] |
Query an option on a SIP dialog.
Definition at line 3496 of file chan_sip.c.
References ast_log(), AST_OPTION_T38_STATE, ast_test_flag, chan, LOG_ERROR, SIP_PAGE2_T38SUPPORT, sip_pvt_lock, sip_pvt_unlock, t38properties::state, sip_pvt::t38, T38_ENABLED, T38_LOCAL_REINVITE, T38_PEER_DIRECT, T38_PEER_REINVITE, T38_STATE_NEGOTIATED, T38_STATE_NEGOTIATING, T38_STATE_UNAVAILABLE, T38_STATE_UNKNOWN, t38properties::t38support, and ast_channel::tech_pvt.
03497 { 03498 int res = -1; 03499 enum ast_t38_state state = T38_STATE_UNAVAILABLE; 03500 struct sip_pvt *p = (struct sip_pvt *) chan->tech_pvt; 03501 03502 switch (option) { 03503 case AST_OPTION_T38_STATE: 03504 /* Make sure we got an ast_t38_state enum passed in */ 03505 if (*datalen != sizeof(enum ast_t38_state)) { 03506 ast_log(LOG_ERROR, "Invalid datalen for AST_OPTION_T38_STATE option. Expected %d, got %d\n", (int)sizeof(enum ast_t38_state), *datalen); 03507 return -1; 03508 } 03509 03510 sip_pvt_lock(p); 03511 03512 /* Now if T38 support is enabled we need to look and see what the current state is to get what we want to report back */ 03513 if (ast_test_flag(&p->t38.t38support, SIP_PAGE2_T38SUPPORT)) { 03514 switch (p->t38.state) { 03515 case T38_LOCAL_REINVITE: 03516 case T38_PEER_DIRECT: 03517 case T38_PEER_REINVITE: 03518 state = T38_STATE_NEGOTIATING; 03519 break; 03520 case T38_ENABLED: 03521 state = T38_STATE_NEGOTIATED; 03522 break; 03523 default: 03524 state = T38_STATE_UNKNOWN; 03525 } 03526 } 03527 03528 sip_pvt_unlock(p); 03529 03530 *((enum ast_t38_state *) data) = state; 03531 res = 0; 03532 03533 break; 03534 default: 03535 break; 03536 } 03537 03538 return res; 03539 }
| static struct ast_frame * sip_read | ( | struct ast_channel * | ast | ) | [static] |
Read SIP RTP from channel.
Definition at line 6113 of file chan_sip.c.
References ast_channel::_state, ast_bridged_channel(), ast_debug, AST_FRAME_VOICE, ast_null_frame, ast_set_flag, AST_STATE_UP, ast_test_flag, change_t38_state(), FALSE, sip_pvt::flags, ast_frame::frametype, INV_EARLY_MEDIA, sip_pvt::invitestate, sip_pvt::lastrtprx, ast_channel::name, sip_pvt::pendinginvite, SIP_GOTREFER, SIP_NEEDREINVITE, SIP_PAGE2_T38SUPPORT_UDPTL, SIP_PENDINGBYE, sip_pvt_lock, sip_pvt_unlock, sip_rtp_read(), t38properties::state, sip_pvt::t38, T38_DISABLED, T38_LOCAL_REINVITE, t38properties::t38support, ast_channel::tech_pvt, transmit_reinvite_with_sdp(), and TRUE.
06114 { 06115 struct ast_frame *fr; 06116 struct sip_pvt *p = ast->tech_pvt; 06117 int faxdetected = FALSE; 06118 06119 sip_pvt_lock(p); 06120 fr = sip_rtp_read(ast, p, &faxdetected); 06121 p->lastrtprx = time(NULL); 06122 06123 /* If we are NOT bridged to another channel, and we have detected fax tone we issue T38 re-invite to a peer */ 06124 /* If we are bridged then it is the responsibility of the SIP device to issue T38 re-invite if it detects CNG or fax preamble */ 06125 if (faxdetected && ast_test_flag(&p->t38.t38support, SIP_PAGE2_T38SUPPORT_UDPTL) && (p->t38.state == T38_DISABLED) && !(ast_bridged_channel(ast))) { 06126 if (!ast_test_flag(&p->flags[0], SIP_GOTREFER)) { 06127 if (!p->pendinginvite) { 06128 ast_debug(3, "Sending reinvite on SIP (%s) for T.38 negotiation.\n", ast->name); 06129 change_t38_state(p, T38_LOCAL_REINVITE); 06130 transmit_reinvite_with_sdp(p, TRUE, FALSE); 06131 } 06132 } else if (!ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) { 06133 ast_debug(3, "Deferring reinvite on SIP (%s) - it will be re-negotiated for T.38\n", ast->name); 06134 ast_set_flag(&p->flags[0], SIP_NEEDREINVITE); 06135 } 06136 } 06137 06138 /* Only allow audio through if they sent progress with SDP, or if the channel is actually answered */ 06139 if (fr && fr->frametype == AST_FRAME_VOICE && p->invitestate != INV_EARLY_MEDIA && ast->_state != AST_STATE_UP) { 06140 fr = &ast_null_frame; 06141 } 06142 06143 sip_pvt_unlock(p); 06144 06145 return fr; 06146 }
| static struct sockaddr_in * sip_real_dst | ( | const struct sip_pvt * | p | ) | [static] |
The real destination address for a write.
Definition at line 2796 of file chan_sip.c.
References ast_test_flag, sip_pvt::flags, sip_proxy::ip, sip_pvt::outboundproxy, sip_pvt::recv, sip_pvt::sa, SIP_NAT, and SIP_NAT_ROUTE.
Referenced by __sip_xmit(), check_via(), retrans_pkt(), send_response(), show_channels_cb(), sip_debug_test_pvt(), and sip_prepare_socket().
02797 { 02798 if (p->outboundproxy) 02799 return &p->outboundproxy->ip; 02800 02801 return ast_test_flag(&p->flags[0], SIP_NAT) & SIP_NAT_ROUTE ? &p->recv : &p->sa; 02802 }
| static int sip_refer_allocate | ( | struct sip_pvt * | p | ) | [static] |
Allocate SIP refer structure.
Definition at line 10208 of file chan_sip.c.
References ast_calloc, and sip_pvt::refer.
Referenced by get_also_info(), handle_request_invite(), handle_request_refer(), and transmit_refer().
10209 { 10210 p->refer = ast_calloc(1, sizeof(struct sip_refer)); 10211 return p->refer ? 1 : 0; 10212 }
| static int sip_reg_timeout | ( | const void * | data | ) | [static] |
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.
Definition at line 9906 of file chan_sip.c.
References __sip_pretend_ack(), ast_dnsmgr_refresh(), ast_log(), sip_registry::call, dialog_unref(), sip_registry::dnsmgr, EVENT_FLAG_SYSTEM, sip_registry::hostname, LOG_NOTICE, manager_event, sip_pvt::needdestroy, REG_STATE_FAILED, REG_STATE_UNREGISTERED, sip_registry::regattempts, sip_pvt::registry, registry_unref(), sip_registry::regstate, regstate2str(), sip_pvt_lock, sip_pvt_unlock, SIP_REGISTER, sip_registry::timeout, transmit_register(), and sip_registry::username.
Referenced by sip_show_sched(), and transmit_register().
09907 { 09908 09909 /* if we are here, our registration timed out, so we'll just do it over */ 09910 struct sip_registry *r = (struct sip_registry *)data; /* the ref count should have been bumped when the sched item was added */ 09911 struct sip_pvt *p; 09912 int res; 09913 09914 /* if we couldn't get a reference to the registry object, punt */ 09915 if (!r) 09916 return 0; 09917 09918 if (r->dnsmgr) { 09919 /* If the registration has timed out, maybe the IP changed. Force a refresh. */ 09920 ast_dnsmgr_refresh(r->dnsmgr); 09921 } 09922 09923 ast_log(LOG_NOTICE, " -- Registration for '%s@%s' timed out, trying again (Attempt #%d)\n", r->username, r->hostname, r->regattempts); 09924 /* If the initial tranmission failed, we may not have an existing dialog, 09925 * so it is possible that r->call == NULL. 09926 * Otherwise destroy it, as we have a timeout so we don't want it. 09927 */ 09928 if (r->call) { 09929 /* Unlink us, destroy old call. Locking is not relevant here because all this happens 09930 in the single SIP manager thread. */ 09931 p = r->call; 09932 sip_pvt_lock(p); 09933 p->needdestroy = 1; 09934 /* Pretend to ACK anything just in case */ 09935 __sip_pretend_ack(p); 09936 sip_pvt_unlock(p); 09937 09938 /* decouple the two objects */ 09939 /* p->registry == r, so r has 2 refs, and the unref won't take the object away */ 09940 if (p->registry) 09941 p->registry = registry_unref(p->registry, "p->registry unreffed"); 09942 r->call = dialog_unref(r->call, "unrefing r->call"); 09943 } 09944 /* If we have a limit, stop registration and give up */ 09945 if (global_regattempts_max && r->regattempts > global_regattempts_max) { 09946 /* Ok, enough is enough. Don't try any more */ 09947 /* We could add an external notification here... 09948 steal it from app_voicemail :-) */ 09949 ast_log(LOG_NOTICE, " -- Giving up forever trying to register '%s@%s'\n", r->username, r->hostname); 09950 r->regstate = REG_STATE_FAILED; 09951 } else { 09952 r->regstate = REG_STATE_UNREGISTERED; 09953 r->timeout = -1; 09954 res=transmit_register(r, SIP_REGISTER, NULL, NULL); 09955 } 09956 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)); 09957 registry_unref(r, "unreffing registry_unref r"); 09958 return 0; 09959 }
| static int sip_register | ( | const char * | value, | |
| int | lineno | |||
| ) | [static] |
Parse register=> line in sip.conf and add to registry.
Definition at line 6528 of file chan_sip.c.
References ast_atomic_fetchadd_int(), ast_calloc, ast_copy_string(), ast_free, ast_log(), ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ASTOBJ_CONTAINER_LINK, ASTOBJ_INIT, sip_registry::authuser, buf, sip_registry::callback, FALSE, hostname, INITIAL_CSEQ, LOG_ERROR, LOG_WARNING, registry_unref(), regl, secret, sip_parse_host(), SIP_TRANSPORT_UDP, sip_registry::transport, and sip_registry::username.
Referenced by build_peer().
06529 { 06530 struct sip_registry *reg; 06531 int portnum = 0; 06532 enum sip_transport transport = SIP_TRANSPORT_UDP; 06533 char buf[256] = ""; 06534 char *username = NULL; 06535 char *hostname=NULL, *secret=NULL, *authuser=NULL, *expire=NULL; 06536 char *callback=NULL; 06537 06538 if (!value) 06539 return -1; 06540 06541 ast_copy_string(buf, value, sizeof(buf)); 06542 06543 /* split [/contact][~expiry] */ 06544 expire = strchr(buf, '~'); 06545 if (expire) 06546 *expire++ = '\0'; 06547 callback = strrchr(buf, '/'); 06548 if (callback) 06549 *callback++ = '\0'; 06550 if (ast_strlen_zero(callback)) 06551 callback = "s"; 06552 06553 sip_parse_host(buf, lineno, &username, &portnum, &transport); 06554 06555 /* First split around the last '@' then parse the two components. */ 06556 hostname = strrchr(username, '@'); /* allow @ in the first part */ 06557 if (hostname) 06558 *hostname++ = '\0'; 06559 if (ast_strlen_zero(username) || ast_strlen_zero(hostname)) { 06560 ast_log(LOG_WARNING, "Format for registration is [transport://]user[:secret[:authuser]]@domain[:port][/extension][~expiry] at line %d\n", lineno); 06561 return -1; 06562 } 06563 /* split user[:secret[:authuser]] */ 06564 secret = strchr(username, ':'); 06565 if (secret) { 06566 *secret++ = '\0'; 06567 authuser = strchr(secret, ':'); 06568 if (authuser) 06569 *authuser++ = '\0'; 06570 } 06571 06572 if (!(reg = ast_calloc(1, sizeof(*reg)))) { 06573 ast_log(LOG_ERROR, "Out of memory. Can't allocate SIP registry entry\n"); 06574 return -1; 06575 } 06576 06577 if (ast_string_field_init(reg, 256)) { 06578 ast_log(LOG_ERROR, "Out of memory. Can't allocate SIP registry strings\n"); 06579 ast_free(reg); 06580 return -1; 06581 } 06582 06583 ast_atomic_fetchadd_int(®objs, 1); 06584 ASTOBJ_INIT(reg); 06585 ast_string_field_set(reg, callback, callback); 06586 if (!ast_strlen_zero(username)) 06587 ast_string_field_set(reg, username, username); 06588 if (hostname) 06589 ast_string_field_set(reg, hostname, hostname); 06590 if (authuser) 06591 ast_string_field_set(reg, authuser, authuser); 06592 if (secret) 06593 ast_string_field_set(reg, secret, secret); 06594 reg->transport = transport; 06595 reg->expire = -1; 06596 reg->expiry = (expire ? atoi(expire) : default_expiry); 06597 reg->timeout = -1; 06598 reg->refresh = reg->expiry; 06599 reg->portno = portnum; 06600 reg->callid_valid = FALSE; 06601 reg->ocseq = INITIAL_CSEQ; 06602 ASTOBJ_CONTAINER_LINK(®l, reg); /* Add the new registry entry to the list */ 06603 registry_unref(reg, "unref the reg pointer"); /* release the reference given by ASTOBJ_INIT. The container has another reference */ 06604 return 0; 06605 }
| static void sip_registry_destroy | ( | struct sip_registry * | reg | ) | [static] |
Destroy registry object Objects created with the register= statement in static configuration.
Definition at line 4654 of file chan_sip.c.
References ast_atomic_fetchadd_int(), ast_debug, ast_dnsmgr_release(), ast_free, AST_SCHED_DEL, ast_string_field_free_memory, sip_registry::call, dialog_unlink_all(), dialog_unref(), sip_registry::dnsmgr, sip_registry::expire, sip_registry::hostname, sip_pvt::registry, registry_unref(), sched, sip_registry::timeout, TRUE, and sip_registry::username.
Referenced by registry_unref(), reload_config(), and unload_module().
04655 { 04656 /* Really delete */ 04657 ast_debug(3, "Destroying registry entry for %s@%s\n", reg->username, reg->hostname); 04658 04659 if (reg->call) { 04660 /* Clear registry before destroying to ensure 04661 we don't get reentered trying to grab the registry lock */ 04662 reg->call->registry = registry_unref(reg->call->registry, "destroy reg->call->registry"); 04663 ast_debug(3, "Destroying active SIP dialog for registry %s@%s\n", reg->username, reg->hostname); 04664 dialog_unlink_all(reg->call, TRUE, TRUE); 04665 reg->call = dialog_unref(reg->call, "unref reg->call"); 04666 /* reg->call = sip_destroy(reg->call); */ 04667 } 04668 AST_SCHED_DEL(sched, reg->expire); 04669 AST_SCHED_DEL(sched, reg->timeout); 04670 04671 ast_string_field_free_memory(reg); 04672 ast_atomic_fetchadd_int(®objs, -1); 04673 ast_dnsmgr_release(reg->dnsmgr); 04674 ast_free(reg); 04675 }
| static int sip_reinvite_retry | ( | const void * | data | ) | [static] |
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.
Definition at line 15845 of file chan_sip.c.
References ast_set_flag, check_pendings(), dialog_unref(), SIP_NEEDREINVITE, sip_pvt_lock, and sip_pvt_unlock.
Referenced by handle_response_invite(), and sip_show_sched().
15846 { 15847 struct sip_pvt *p = (struct sip_pvt *) data; 15848 15849 sip_pvt_lock(p); /* called from schedule thread which requires a lock */ 15850 ast_set_flag(&p->flags[0], SIP_NEEDREINVITE); 15851 p->waitid = -1; 15852 check_pendings(p); 15853 sip_pvt_unlock(p); 15854 dialog_unref(p, "unref the dialog ptr from sip_reinvite_retry, because it held a dialog ptr"); 15855 return 0; 15856 }
| static char * sip_reload | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Force reload of module from cli.
Definition at line 23323 of file chan_sip.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_verbose, CHANNEL_CLI_RELOAD, CHANNEL_MODULE_RELOAD, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, restart_monitor(), sip_reload_lock, TRUE, and ast_cli_entry::usage.
Referenced by reload().
23324 { 23325 23326 switch (cmd) { 23327 case CLI_INIT: 23328 e->command = "sip reload"; 23329 e->usage = 23330 "Usage: sip reload\n" 23331 " Reloads SIP configuration from sip.conf\n"; 23332 return NULL; 23333 case CLI_GENERATE: 23334 return NULL; 23335 } 23336 23337 ast_mutex_lock(&sip_reload_lock); 23338 if (sip_reloading) 23339 ast_verbose("Previous SIP reload not yet done\n"); 23340 else { 23341 sip_reloading = TRUE; 23342 sip_reloadreason = (a && a->fd) ? CHANNEL_CLI_RELOAD : CHANNEL_MODULE_RELOAD; 23343 } 23344 ast_mutex_unlock(&sip_reload_lock); 23345 restart_monitor(); 23346 23347 return CLI_SUCCESS; 23348 }
| static struct ast_channel * sip_request_call | ( | const char * | type, | |
| int | format, | |||
| void * | data, | |||
| int * | cause | |||
| ) | [static] |
PBX interface function -build SIP pvt structure SIP calls initiated by the PBX arrive here.
* SIP Dial string syntax * SIP/exten@host!dnid * or SIP/host/exten!dnid * or SIP/host!dnid *
Definition at line 20988 of file chan_sip.c.
References ao2_t_link, ao2_t_unlink, ast_calloc, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL, AST_CAUSE_SWITCH_CONGESTION, AST_CAUSE_UNREGISTERED, ast_copy_string(), ast_debug, AST_FORMAT_AUDIO_MASK, ast_getformatname(), ast_getformatname_multiple(), ast_log(), ast_sip_ouraddrfor(), AST_STATE_DOWN, ast_string_field_set, ast_strlen_zero(), ast_update_use_count(), build_callid_pvt(), build_via(), create_addr(), dialog_unlink_all(), dialog_unref(), dialogs, EVENT_FLAG_SYSTEM, ext, sip_socket::fd, LOG_ERROR, LOG_NOTICE, LOG_WARNING, manager_event, sip_pvt::options, sip_pvt::outgoing_call, sip_pvt::peername, restart_monitor(), secret, sip_alloc(), SIP_INVITE, sip_new(), sip_pvt_lock, sip_pvt_unlock, SIP_TRANSPORT_TCP, SIP_TRANSPORT_TLS, SIP_TRANSPORT_UDP, sip_pvt::socket, TRUE, and sip_socket::type.
20989 { 20990 struct sip_pvt *p; 20991 struct ast_channel *tmpc = NULL; 20992 char *ext = NULL, *host; 20993 char tmp[256]; 20994 char *dest = data; 20995 char *dnid; 20996 char *secret = NULL; 20997 char *md5secret = NULL; 20998 char *authname = NULL; 20999 char *trans = NULL; 21000 enum sip_transport transport = 0; 21001 int oldformat = format; 21002 21003 /* mask request with some set of allowed formats. 21004 * XXX this needs to be fixed. 21005 * The original code uses AST_FORMAT_AUDIO_MASK, but it is 21006 * unclear what to use here. We have global_capabilities, which is 21007 * configured from sip.conf, and sip_tech.capabilities, which is 21008 * hardwired to all audio formats. 21009 */ 21010 format &= AST_FORMAT_AUDIO_MASK; 21011 if (!format) { 21012 ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format %s while capability is %s\n", ast_getformatname(oldformat), ast_getformatname(global_capability)); 21013 *cause = AST_CAUSE_BEARERCAPABILITY_NOTAVAIL; /* Can't find codec to connect to host */ 21014 return NULL; 21015 } 21016 ast_debug(1, "Asked to create a SIP channel with formats: %s\n", ast_getformatname_multiple(tmp, sizeof(tmp), oldformat)); 21017 21018 if (!(p = sip_alloc(NULL, NULL, 0, SIP_INVITE))) { 21019 ast_log(LOG_ERROR, "Unable to build sip pvt data for '%s' (Out of memory or socket error)\n", dest); 21020 *cause = AST_CAUSE_SWITCH_CONGESTION; 21021 return NULL; 21022 } 21023 21024 p->outgoing_call = TRUE; 21025 21026 if (!(p->options = ast_calloc(1, sizeof(*p->options)))) { 21027 dialog_unlink_all(p, TRUE, TRUE); 21028 dialog_unref(p, "unref dialog p from mem fail"); 21029 /* sip_destroy(p); */ 21030 ast_log(LOG_ERROR, "Unable to build option SIP data structure - Out of memory\n"); 21031 *cause = AST_CAUSE_SWITCH_CONGESTION; 21032 return NULL; 21033 } 21034 21035 /* Save the destination, the SIP dial string */ 21036 ast_copy_string(tmp, dest, sizeof(tmp)); 21037 21038 21039 /* Find DNID and take it away */ 21040 dnid = strchr(tmp, '!'); 21041 if (dnid != NULL) { 21042 *dnid++ = '\0'; 21043 ast_string_field_set(p, todnid, dnid); 21044 } 21045 21046 /* Find at sign - @ */ 21047 host = strchr(tmp, '@'); 21048 if (host) { 21049 *host++ = '\0'; 21050 ext = tmp; 21051 secret = strchr(ext, ':'); 21052 } 21053 if (secret) { 21054 *secret++ = '\0'; 21055 md5secret = strchr(secret, ':'); 21056 } 21057 if (md5secret) { 21058 *md5secret++ = '\0'; 21059 authname = strchr(md5secret, ':'); 21060 } 21061 if (authname) { 21062 *authname++ = '\0'; 21063 trans = strchr(authname, ':'); 21064 } 21065 if (trans) { 21066 *trans++ = '\0'; 21067 if (!strcasecmp(trans, "tcp")) 21068 transport = SIP_TRANSPORT_TCP; 21069 else if (!strcasecmp(trans, "tls")) 21070 transport = SIP_TRANSPORT_TLS; 21071 else { 21072 if (strcasecmp(trans, "udp")) 21073 ast_log(LOG_WARNING, "'%s' is not a valid transport option to Dial() for SIP calls, using udp by default.\n", trans); 21074 transport = SIP_TRANSPORT_UDP; 21075 } 21076 } else { /* use default */ 21077 transport = SIP_TRANSPORT_UDP; 21078 } 21079 21080 if (!host) { 21081 ext = strchr(tmp, '/'); 21082 if (ext) 21083 *ext++ = '\0'; 21084 host = tmp; 21085 } 21086 21087 p->socket.fd = -1; 21088 p->socket.type = transport; 21089 21090 /* We now have 21091 host = peer name, DNS host name or DNS domain (for SRV) 21092 ext = extension (user part of URI) 21093 dnid = destination of the call (applies to the To: header) 21094 */ 21095 if (create_addr(p, host, NULL, 1)) { 21096 *cause = AST_CAUSE_UNREGISTERED; 21097 ast_debug(3, "Cant create SIP call - target device not registered\n"); 21098 dialog_unlink_all(p, TRUE, TRUE); 21099 dialog_unref(p, "unref dialog p UNREGISTERED"); 21100 /* sip_destroy(p); */ 21101 return NULL; 21102 } 21103 if (ast_strlen_zero(p->peername) && ext) 21104 ast_string_field_set(p, peername, ext); 21105 /* Recalculate our side, and recalculate Call ID */ 21106 ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip); 21107 build_via(p); 21108 ao2_t_unlink(dialogs, p, "About to change the callid -- remove the old name"); 21109 build_callid_pvt(p); 21110 ao2_t_link(dialogs, p, "Linking in under new name"); 21111 21112 /* We have an extension to call, don't use the full contact here */ 21113 /* This to enable dialing registered peers with extension dialling, 21114 like SIP/peername/extension 21115 SIP/peername will still use the full contact 21116 */ 21117 if (ext) { 21118 ast_string_field_set(p, username, ext); 21119 ast_string_field_set(p, fullcontact, NULL); 21120 } 21121 if (secret && !ast_strlen_zero(secret)) 21122 ast_string_field_set(p, peersecret, secret); 21123 21124 if (md5secret && !ast_strlen_zero(md5secret)) 21125 ast_string_field_set(p, peermd5secret, md5secret); 21126 21127 if (authname && !ast_strlen_zero(authname)) 21128 ast_string_field_set(p, authname, authname); 21129 #if 0 21130 printf("Setting up to call extension '%s' at '%s'\n", ext ? ext : "<none>", host); 21131 #endif 21132 p->prefcodec = oldformat; /* Format for this call */ 21133 p->jointcapability = oldformat; 21134 sip_pvt_lock(p); 21135 tmpc = sip_new(p, AST_STATE_DOWN, host); /* Place the call */ 21136 if (global_callevents) 21137 manager_event(EVENT_FLAG_SYSTEM, "ChannelUpdate", 21138 "Channel: %s\r\nChanneltype: %s\r\nSIPcallid: %s\r\nSIPfullcontact: %s\r\nPeername: %s\r\n", 21139 p->owner? p->owner->name : "", "SIP", p->callid, p->fullcontact, p->peername); 21140 sip_pvt_unlock(p); 21141 if (!tmpc) { 21142 dialog_unlink_all(p, TRUE, TRUE); 21143 /* sip_destroy(p); */ 21144 } 21145 dialog_unref(p, "toss pvt ptr at end of sip_request_call"); 21146 ast_update_use_count(); 21147 restart_monitor(); 21148 return tmpc; 21149 }
| static int sip_reregister | ( | const void * | data | ) | [static] |
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.
Definition at line 9869 of file chan_sip.c.
References __sip_do_register(), append_history, ast_log(), sip_registry::call, sip_pvt::do_history, sip_registry::expire, sip_registry::hostname, LOG_NOTICE, registry_unref(), and sip_registry::username.
Referenced by handle_response_register(), sip_send_all_registers(), and sip_show_sched().
09870 { 09871 /* if we are here, we know that we need to reregister. */ 09872 struct sip_registry *r= (struct sip_registry *) data; 09873 09874 /* if we couldn't get a reference to the registry object, punt */ 09875 if (!r) 09876 return 0; 09877 09878 if (r->call && r->call->do_history) 09879 append_history(r->call, "RegistryRenew", "Account: %s@%s", r->username, r->hostname); 09880 /* Since registry's are only added/removed by the the monitor thread, this 09881 may be overkill to reference/dereference at all here */ 09882 if (sipdebug) 09883 ast_log(LOG_NOTICE, " -- Re-registration for %s@%s\n", r->username, r->hostname); 09884 09885 r->expire = -1; 09886 __sip_do_register(r); 09887 registry_unref(r, "unreg the re-registered"); 09888 return 0; 09889 }
| static struct ast_frame * sip_rtp_read | ( | struct ast_channel * | ast, | |
| struct sip_pvt * | p, | |||
| int * | faxdetect | |||
| ) | [static] |
Read RTP from network.
Definition at line 6033 of file chan_sip.c.
References ast_debug, ast_dsp_process(), AST_FORMAT_AUDIO_MASK, AST_FORMAT_TEXT_MASK, AST_FORMAT_VIDEO_MASK, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_getformatname(), ast_null_frame, ast_rtcp_read(), ast_rtp_read(), ast_set_read_format(), ast_set_write_format(), ast_test_flag, ast_udptl_read(), ast_verbose, f, ast_channel::fdno, sip_pvt::flags, sip_pvt::jointcapability, ast_channel::name, ast_channel::nativeformats, sip_pvt::owner, ast_channel::readformat, sip_pvt::rtp, SIP_DTMF, SIP_DTMF_INBAND, SIP_DTMF_RFC2833, SIP_PAGE2_T38SUPPORT_UDPTL, sip_pvt::t38, t38properties::t38support, sip_pvt::trtp, sip_pvt::udptl, sip_pvt::vad, sip_pvt::vrtp, and ast_channel::writeformat.
Referenced by sip_read().
06034 { 06035 /* Retrieve audio/etc from channel. Assumes p->lock is already held. */ 06036 struct ast_frame *f; 06037 06038 if (!p->rtp) { 06039 /* We have no RTP allocated for this channel */ 06040 return &ast_null_frame; 06041 } 06042 06043 switch(ast->fdno) { 06044 case 0: 06045 f = ast_rtp_read(p->rtp); /* RTP Audio */ 06046 break; 06047 case 1: 06048 f = ast_rtcp_read(p->rtp); /* RTCP Control Channel */ 06049 break; 06050 case 2: 06051 f = ast_rtp_read(p->vrtp); /* RTP Video */ 06052 break; 06053 case 3: 06054 f = ast_rtcp_read(p->vrtp); /* RTCP Control Channel for video */ 06055 break; 06056 case 4: 06057 f = ast_rtp_read(p->trtp); /* RTP Text */ 06058 if (sipdebug_text) { 06059 int i; 06060 unsigned char* arr = f->data.ptr; 06061 for (i=0; i < f->datalen; i++) 06062 ast_verbose("%c", (arr[i] > ' ' && arr[i] < '}') ? arr[i] : '.'); 06063 ast_verbose(" -> "); 06064 for (i=0; i < f->datalen; i++) 06065 ast_verbose("%02X ", arr[i]); 06066 ast_verbose("\n"); 06067 } 06068 break; 06069 case 5: 06070 f = ast_udptl_read(p->udptl); /* UDPTL for T.38 */ 06071 break; 06072 default: 06073 f = &ast_null_frame; 06074 } 06075 /* Don't forward RFC2833 if we're not supposed to */ 06076 if (f && (f->frametype == AST_FRAME_DTMF) && 06077 (ast_test_flag(&p->flags[0], SIP_DTMF) != SIP_DTMF_RFC2833)) 06078 return &ast_null_frame; 06079 06080 /* We already hold the channel lock */ 06081 if (!p->owner || (f && f->frametype != AST_FRAME_VOICE)) 06082 return f; 06083 06084 if (f && f->subclass != (p->owner->nativeformats & AST_FORMAT_AUDIO_MASK)) { 06085 if (!(f->subclass & p->jointcapability)) { 06086 ast_debug(1, "Bogus frame of format '%s' received from '%s'!\n", 06087 ast_getformatname(f->subclass), p->owner->name); 06088 return &ast_null_frame; 06089 } 06090 ast_debug(1, "Oooh, format changed to %d %s\n", 06091 f->subclass, ast_getformatname(f->subclass)); 06092 p->owner->nativeformats = (p->owner->nativeformats & (AST_FORMAT_VIDEO_MASK | AST_FORMAT_TEXT_MASK)) | f->subclass; 06093 ast_set_read_format(p->owner, p->owner->readformat); 06094 ast_set_write_format(p->owner, p->owner->writeformat); 06095 } 06096 06097 if (f && (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_INBAND) && p->vad) { 06098 f = ast_dsp_process(p->owner, p->vad, f); 06099 if (f && f->frametype == AST_FRAME_DTMF) { 06100 if (ast_test_flag(&p->t38.t38support, SIP_PAGE2_T38SUPPORT_UDPTL) && f->subclass == 'f') { 06101 ast_debug(1, "Fax CNG detected on %s\n", ast->name); 06102 *faxdetect = 1; 06103 } else { 06104 ast_debug(1, "* Detected inband DTMF '%c'\n", f->subclass); 06105 } 06106 } 06107 } 06108 06109 return f; 06110 }
| static void sip_scheddestroy | ( | struct sip_pvt * | p, | |
| int | ms | |||
| ) | [static] |
Schedule destruction of SIP dialog.
Definition at line 3267 of file chan_sip.c.
References __sip_autodestruct(), append_history, ast_log(), ast_sched_add(), ast_verbose, sip_pvt::autokillid, sip_pvt::callid, dialog_ref(), sip_pvt::do_history, LOG_WARNING, sip_pvt::method, sched, sip_cancel_destroy(), sip_debug_test_pvt(), sip_methods, sip_st_dlg::st_active, sip_st_dlg::st_schedid, sip_pvt::stimer, stop_session_timer(), sip_pvt::timer_b, sip_pvt::timer_t1, and TRUE.
Referenced by __sip_autodestruct(), cb_extensionstate(), check_auth(), check_pendings(), handle_incoming(), handle_invite_replaces(), handle_request_bye(), handle_request_cancel(), handle_request_info(), handle_request_invite(), handle_request_notify(), handle_request_options(), handle_request_register(), handle_request_subscribe(), handle_response_invite(), handle_response_register(), manager_sipnotify(), receive_message(), sip_cli_notify(), sip_hangup(), sip_send_mwi_to_peer(), sip_sipredirect(), and transmit_fake_auth_response().
03268 { 03269 if (ms < 0) { 03270 if (p->timer_t1 == 0) { 03271 p->timer_t1 = global_t1; /* Set timer T1 if not set (RFC 3261) */ 03272 p->timer_b = global_timer_b; /* Set timer B if not set (RFC 3261) */ 03273 } 03274 ms = p->timer_t1 * 64; 03275 } 03276 if (sip_debug_test_pvt(p)) 03277 ast_verbose("Scheduling destruction of SIP dialog '%s' in %d ms (Method: %s)\n", p->callid, ms, sip_methods[p->method].text); 03278 if (sip_cancel_destroy(p)) 03279 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 03280 03281 if (p->do_history) 03282 append_history(p, "SchedDestroy", "%d ms", ms); 03283 p->autokillid = ast_sched_add(sched, ms, __sip_autodestruct, dialog_ref(p, "setting ref as passing into ast_sched_add for __sip_autodestruct")); 03284 03285 if (p->stimer && p->stimer->st_active == TRUE && p->stimer->st_schedid > 0) 03286 stop_session_timer(p); 03287 }
| static void sip_send_all_registers | ( | void | ) | [static] |
Send all known registrations.
Definition at line 23271 of file chan_sip.c.
References AST_SCHED_REPLACE_UNREF, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_UNLOCK, ASTOBJ_WRLOCK, registry_addref(), registry_unref(), regl, sched, and sip_reregister().
Referenced by load_module(), and sip_do_reload().
23272 { 23273 int ms; 23274 int regspacing; 23275 if (!regobjs) 23276 return; 23277 regspacing = default_expiry * 1000/regobjs; 23278 if (regspacing > 100) 23279 regspacing = 100; 23280 ms = regspacing; 23281 ASTOBJ_CONTAINER_TRAVERSE(®l, 1, do { 23282 ASTOBJ_WRLOCK(iterator); 23283 ms += regspacing; 23284 AST_SCHED_REPLACE_UNREF(iterator->expire, sched, ms, sip_reregister, iterator, 23285 registry_unref(_data, "REPLACE sched del decs the refcount"), 23286 registry_unref(iterator, "REPLACE sched add failure decs the refcount"), 23287 registry_addref(iterator, "REPLACE sched add incs the refcount")); 23288 ASTOBJ_UNLOCK(iterator); 23289 } while (0) 23290 ); 23291 }
| static int sip_send_mwi_to_peer | ( | struct sip_peer * | peer, | |
| const struct ast_event * | event, | |||
| int | cache_only | |||
| ) | [static] |
Send message waiting indication to alert peer that they've got voicemail.
Definition at line 20211 of file chan_sip.c.
References sip_peer::addr, ao2_t_link, ao2_t_unlink, ast_app_inboxcount(), ast_event_get_ie_uint(), AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_OLDMSGS, ast_set_flag, ast_sip_ouraddrfor(), ast_str_alloca, ast_test_flag, build_callid_pvt(), build_via(), create_addr_from_peer(), sip_peer::defaddr, DEFAULT_TRANS_TIMEOUT, dialog_ref(), dialog_unlink_all(), dialog_unref(), dialogs, sip_pvt::flags, sip_peer::flags, get_cached_mwi(), sip_peer::mwipvt, sip_pvt::ourip, peer_mailboxes_to_str(), sip_pvt::sa, sip_alloc(), SIP_NOTIFY, SIP_OUTGOING, SIP_PAGE2_SUBSCRIBEMWIONLY, sip_scheddestroy(), sip_pvt::socket, ast_str::str, transmit_notify_with_mwi(), TRUE, sip_socket::type, and sip_peer::vmexten.
Referenced by build_peer(), handle_request_subscribe(), and mwi_event_cb().
20212 { 20213 /* Called with peerl lock, but releases it */ 20214 struct sip_pvt *p; 20215 int newmsgs = 0, oldmsgs = 0; 20216 20217 if (ast_test_flag((&peer->flags[1]), SIP_PAGE2_SUBSCRIBEMWIONLY) && !peer->mwipvt) 20218 return 0; 20219 20220 /* Do we have an IP address? If not, skip this peer */ 20221 if (!peer->addr.sin_addr.s_addr && !peer->defaddr.sin_addr.s_addr) 20222 return 0; 20223 20224 if (event) { 20225 newmsgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS); 20226 oldmsgs = ast_event_get_ie_uint(event, AST_EVENT_IE_OLDMSGS); 20227 } else if (!get_cached_mwi(peer, &newmsgs, &oldmsgs)) { 20228 /* got it! Don't keep looking. */ 20229 } else if (cache_only) { 20230 return 0; 20231 } else { /* Fall back to manually checking the mailbox */ 20232 struct ast_str *mailbox_str = ast_str_alloca(512); 20233 peer_mailboxes_to_str(&mailbox_str, peer); 20234 ast_app_inboxcount(mailbox_str->str, &newmsgs, &oldmsgs); 20235 } 20236 20237 if (peer->mwipvt) { 20238 /* Base message on subscription */ 20239 p = dialog_ref(peer->mwipvt, "sip_send_mwi_to_peer: Setting dialog ptr p from peer->mwipvt-- should this be done?"); 20240 } else { 20241 /* Build temporary dialog for this message */ 20242 if (!(p = sip_alloc(NULL, NULL, 0, SIP_NOTIFY))) 20243 return -1; 20244 /* If we don't set the socket type to 0, then create_addr_from_peer will fail immediately if the peer 20245 * uses any transport other than UDP. We set the type to 0 here and then let create_addr_from_peer copy 20246 * the peer's socket information to the sip_pvt we just allocated 20247 */ 20248 p->socket.type = 0; 20249 if (create_addr_from_peer(p, peer)) { 20250 /* Maybe they're not registered, etc. */ 20251 dialog_unlink_all(p, TRUE, TRUE); 20252 dialog_unref(p, "unref dialog p just created via sip_alloc"); 20253 /* sip_destroy(p); */ 20254 return 0; 20255 } 20256 /* Recalculate our side, and recalculate Call ID */ 20257 ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip); 20258 build_via(p); 20259 ao2_t_unlink(dialogs, p, "About to change the callid -- remove the old name"); 20260 build_callid_pvt(p); 20261 ao2_t_link(dialogs, p, "Linking in under new name"); 20262 /* Destroy this session after 32 secs */ 20263 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 20264 } 20265 20266 /* Send MWI */ 20267 ast_set_flag(&p->flags[0], SIP_OUTGOING); 20268 /* the following will decrement the refcount on p as it finishes */ 20269 transmit_notify_with_mwi(p, newmsgs, oldmsgs, peer->vmexten); 20270 dialog_unref(p, "unref dialog ptr p just before it goes out of scope at the end of sip_send_mwi_to_peer."); 20271 return 0; 20272 }
| static int sip_senddigit_begin | ( | struct ast_channel * | ast, | |
| char | digit | |||
| ) | [static] |
Definition at line 5511 of file chan_sip.c.
References ast_rtp_senddigit_begin(), ast_test_flag, sip_pvt::flags, sip_pvt::rtp, SIP_DTMF, SIP_DTMF_INBAND, SIP_DTMF_RFC2833, sip_pvt_lock, sip_pvt_unlock, and ast_channel::tech_pvt.
05512 { 05513 struct sip_pvt *p = ast->tech_pvt; 05514 int res = 0; 05515 05516 sip_pvt_lock(p); 05517 switch (ast_test_flag(&p->flags[0], SIP_DTMF)) { 05518 case SIP_DTMF_INBAND: 05519 res = -1; /* Tell Asterisk to generate inband indications */ 05520 break; 05521 case SIP_DTMF_RFC2833: 05522 if (p->rtp) 05523 ast_rtp_senddigit_begin(p->rtp, digit); 05524 break; 05525 default: 05526 break; 05527 } 05528 sip_pvt_unlock(p); 05529 05530 return res; 05531 }
| static int sip_senddigit_end | ( | struct ast_channel * | ast, | |
| char | digit, | |||
| unsigned int | duration | |||
| ) | [static] |
Send DTMF character on SIP channel within one call, we're able to transmit in many methods simultaneously.
Definition at line 5535 of file chan_sip.c.
References ast_rtp_senddigit_end(), ast_test_flag, sip_pvt::flags, SIP_DTMF, SIP_DTMF_INBAND, SIP_DTMF_INFO, SIP_DTMF_RFC2833, SIP_DTMF_SHORTINFO, sip_pvt_lock, sip_pvt_unlock, ast_channel::tech_pvt, and transmit_info_with_digit().
05536 { 05537 struct sip_pvt *p = ast->tech_pvt; 05538 int res = 0; 05539 05540 sip_pvt_lock(p); 05541 switch (ast_test_flag(&p->flags[0], SIP_DTMF)) { 05542 case SIP_DTMF_INFO: 05543 case SIP_DTMF_SHORTINFO: 05544 transmit_info_with_digit(p, digit, duration); 05545 break; 05546 case SIP_DTMF_RFC2833: 05547 if (p->rtp) 05548 ast_rtp_senddigit_end(p->rtp, digit); 05549 break; 05550 case SIP_DTMF_INBAND: 05551 res = -1; /* Tell Asterisk to stop inband indications */ 05552 break; 05553 } 05554 sip_pvt_unlock(p); 05555 05556 return res; 05557 }
| static int sip_sendhtml | ( | struct ast_channel * | chan, | |
| int | subclass, | |||
| const char * | data, | |||
| int | datalen | |||
| ) | [static] |
Send message with Access-URL header, if this is an HTML URL only!
Definition at line 3684 of file chan_sip.c.
References ast_channel::_state, ast_debug, AST_HTML_URL, ast_log(), ast_set_flag, AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, ast_string_field_build, ast_test_flag, chan, FALSE, sip_pvt::flags, sip_pvt::initreq, LOG_WARNING, sip_pvt::pendinginvite, sip_debug_test_pvt(), SIP_NEEDREINVITE, SIP_PENDINGBYE, ast_channel::tech_pvt, transmit_reinvite_with_sdp(), transmit_response(), and url.
03685 { 03686 struct sip_pvt *p = chan->tech_pvt; 03687 03688 if (subclass != AST_HTML_URL) 03689 return -1; 03690 03691 ast_string_field_build(p, url, "<%s>;mode=active", data); 03692 03693 if (sip_debug_test_pvt(p)) 03694 ast_debug(1, "Send URL %s, state = %d!\n", data, chan->_state); 03695 03696 switch (chan->_state) { 03697 case AST_STATE_RING: 03698 transmit_response(p, "100 Trying", &p->initreq); 03699 break; 03700 case AST_STATE_RINGING: 03701 transmit_response(p, "180 Ringing", &p->initreq); 03702 break; 03703 case AST_STATE_UP: 03704 if (!p->pendinginvite) { /* We are up, and have no outstanding invite */ 03705 transmit_reinvite_with_sdp(p, FALSE, FALSE); 03706 } else if (!ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) { 03707 ast_set_flag(&p->flags[0], SIP_NEEDREINVITE); 03708 } 03709 break; 03710 default: 03711 ast_log(LOG_WARNING, "Don't know how to send URI when state is %d!\n", chan->_state); 03712 } 03713 03714 return 0; 03715 }
| static int sip_sendtext | ( | struct ast_channel * | ast, | |
| const char * | text | |||
| ) | [static] |
Send SIP MESSAGE text within a call Called from PBX core sendtext() application.
Definition at line 3725 of file chan_sip.c.
References ast_verbose, sip_request::debug, ast_channel::name, sip_debug_test_pvt(), ast_channel::tech_pvt, and transmit_message_with_text().
03726 { 03727 struct sip_pvt *p = ast->tech_pvt; 03728 int debug = sip_debug_test_pvt(p); 03729 03730 if (debug) 03731 ast_verbose("Sending text %s on %s\n", text, ast->name); 03732 if (!p) 03733 return -1; 03734 /* NOT ast_strlen_zero, because a zero-length message is specifically 03735 * allowed by RFC 3428 (See section 10, Examples) */ 03736 if (!text) 03737 return 0; 03738 if (debug) 03739 ast_verbose("Really sending text %s on %s\n", text, ast->name); 03740 transmit_message_with_text(p, text); 03741 return 0; 03742 }
| static char * sip_set_history | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Enable/Disable SIP History logging (CLI).
Definition at line 15208 of file chan_sip.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, FALSE, ast_cli_args::fd, TRUE, and ast_cli_entry::usage.
15209 { 15210 switch (cmd) { 15211 case CLI_INIT: 15212 e->command = "sip set history {on|off}"; 15213 e->usage = 15214 "Usage: sip set history {on|off}\n" 15215 " Enables/Disables recording of SIP dialog history for debugging purposes.\n" 15216 " Use 'sip show history' to view the history of a call number.\n"; 15217 return NULL; 15218 case CLI_GENERATE: 15219 return NULL; 15220 } 15221 15222 if (a->argc != e->args) 15223 return CLI_SHOWUSAGE; 15224 15225 if (!strncasecmp(a->argv[e->args - 1], "on", 2)) { 15226 recordhistory = TRUE; 15227 ast_cli(a->fd, "SIP History Recording Enabled (use 'sip show history')\n"); 15228 } else if (!strncasecmp(a->argv[e->args - 1], "off", 3)) { 15229 recordhistory = FALSE; 15230 ast_cli(a->fd, "SIP History Recording Disabled\n"); 15231 } else { 15232 return CLI_SHOWUSAGE; 15233 } 15234 return CLI_SUCCESS; 15235 }
| static void sip_set_redirstr | ( | struct sip_pvt * | p, | |
| char * | reason | |||
| ) | [static] |
Translate referring cause.
Definition at line 11459 of file chan_sip.c.
References ast_string_field_set.
Referenced by get_rdnis().
11459 { 11460 11461 if (!strcmp(reason, "unknown")) { 11462 ast_string_field_set(p, redircause, "UNKNOWN"); 11463 } else if (!strcmp(reason, "user-busy")) { 11464 ast_string_field_set(p, redircause, "BUSY"); 11465 } else if (!strcmp(reason, "no-answer")) { 11466 ast_string_field_set(p, redircause, "NOANSWER"); 11467 } else if (!strcmp(reason, "unavailable")) { 11468 ast_string_field_set(p, redircause, "UNREACHABLE"); 11469 } else if (!strcmp(reason, "unconditional")) { 11470 ast_string_field_set(p, redircause, "UNCONDITIONAL"); 11471 } else if (!strcmp(reason, "time-of-day")) { 11472 ast_string_field_set(p, redircause, "UNKNOWN"); 11473 } else if (!strcmp(reason, "do-not-disturb")) { 11474 ast_string_field_set(p, redircause, "UNKNOWN"); 11475 } else if (!strcmp(reason, "deflection")) { 11476 ast_string_field_set(p, redircause, "UNKNOWN"); 11477 } else if (!strcmp(reason, "follow-me")) { 11478 ast_string_field_set(p, redircause, "UNKNOWN"); 11479 } else if (!strcmp(reason, "out-of-service")) { 11480 ast_string_field_set(p, redircause, "UNREACHABLE"); 11481 } else if (!strcmp(reason, "away")) { 11482 ast_string_field_set(p, redircause, "UNREACHABLE"); 11483 } else { 11484 ast_string_field_set(p, redircause, "UNKNOWN"); 11485 } 11486 }
| static int sip_set_rtp_peer | ( | struct ast_channel * | chan, | |
| struct ast_rtp * | rtp, | |||
| struct ast_rtp * | vrtp, | |||
| struct ast_rtp * | trtp, | |||
| int | codecs, | |||
| int | nat_active | |||
| ) | [static] |
Set the RTP peer for this call.
Definition at line 22993 of file chan_sip.c.
References ast_channel::_state, sip_pvt::alreadygone, append_history, ast_debug, ast_inet_ntoa(), ast_rtp_get_peer(), ast_set_flag, AST_STATE_UP, ast_test_flag, sip_pvt::callid, chan, sip_pvt::do_history, FALSE, sip_pvt::flags, sip_pvt::lastrtprx, sip_pvt::lastrtptx, sip_pvt::ourip, sip_pvt::pendinginvite, sip_pvt::redircodecs, sip_pvt::redirip, sip_pvt::rtp, SIP_CAN_REINVITE_NAT, SIP_DEFER_BYE_ON_TRANSFER, SIP_GOTREFER, SIP_NEEDREINVITE, SIP_PENDINGBYE, sip_pvt_lock, sip_pvt_unlock, ast_channel::tech_pvt, transmit_reinvite_with_sdp(), sip_pvt::tredirip, sip_pvt::trtp, sip_pvt::vredirip, and sip_pvt::vrtp.
Referenced by sip_fixup().
22994 { 22995 struct sip_pvt *p; 22996 int changed = 0; 22997 22998 p = chan->tech_pvt; 22999 if (!p) 23000 return -1; 23001 23002 /* Disable early RTP bridge */ 23003 if (chan->_state != AST_STATE_UP && !global_directrtpsetup) /* We are in early state */ 23004 return 0; 23005 23006 sip_pvt_lock(p); 23007 if (p->alreadygone) { 23008 /* If we're destroyed, don't bother */ 23009 sip_pvt_unlock(p); 23010 return 0; 23011 } 23012 23013 /* if this peer cannot handle reinvites of the media stream to devices 23014 that are known to be behind a NAT, then stop the process now 23015 */ 23016 if (nat_active && !ast_test_flag(&p->flags[0], SIP_CAN_REINVITE_NAT)) { 23017 sip_pvt_unlock(p); 23018 return 0; 23019 } 23020 23021 if (rtp) { 23022 changed |= ast_rtp_get_peer(rtp, &p->redirip); 23023 } else if (p->redirip.sin_addr.s_addr || ntohs(p->redirip.sin_port) != 0) { 23024 memset(&p->redirip, 0, sizeof(p->redirip)); 23025 changed = 1; 23026 } 23027 if (vrtp) { 23028 changed |= ast_rtp_get_peer(vrtp, &p->vredirip); 23029 } else if (p->vredirip.sin_addr.s_addr || ntohs(p->vredirip.sin_port) != 0) { 23030 memset(&p->vredirip, 0, sizeof(p->vredirip)); 23031 changed = 1; 23032 } 23033 if (trtp) { 23034 changed |= ast_rtp_get_peer(trtp, &p->tredirip); 23035 } else if (p->tredirip.sin_addr.s_addr || ntohs(p->tredirip.sin_port) != 0) { 23036 memset(&p->tredirip, 0, sizeof(p->tredirip)); 23037 changed = 1; 23038 } 23039 if (codecs && (p->redircodecs != codecs)) { 23040 p->redircodecs = codecs; 23041 changed = 1; 23042 } 23043 if (changed && !ast_test_flag(&p->flags[0], SIP_GOTREFER) && !ast_test_flag(&p->flags[0], SIP_DEFER_BYE_ON_TRANSFER)) { 23044 if (chan->_state != AST_STATE_UP) { /* We are in early state */ 23045 if (p->do_history) 23046 append_history(p, "ExtInv", "Initial invite sent with remote bridge proposal."); 23047 ast_debug(1, "Early remote bridge setting SIP '%s' - Sending media to %s\n", p->callid, ast_inet_ntoa(rtp ? p->redirip.sin_addr : p->ourip.sin_addr)); 23048 } else if (!p->pendinginvite) { /* We are up, and have no outstanding invite */ 23049 ast_debug(3, "Sending reinvite on SIP '%s' - It's audio soon redirected to IP %s\n", p->callid, ast_inet_ntoa(rtp ? p->redirip.sin_addr : p->ourip.sin_addr)); 23050 transmit_reinvite_with_sdp(p, FALSE, FALSE); 23051 } else if (!ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) { 23052 ast_debug(3, "Deferring reinvite on SIP '%s' - It's audio will be redirected to IP %s\n", p->callid, ast_inet_ntoa(rtp ? p->redirip.sin_addr : p->ourip.sin_addr)); 23053 /* We have a pending Invite. Send re-invite when we're done with the invite */ 23054 ast_set_flag(&p->flags[0], SIP_NEEDREINVITE); 23055 } 23056 } 23057 /* Reset lastrtprx timer */ 23058 p->lastrtprx = p->lastrtptx = time(NULL); 23059 sip_pvt_unlock(p); 23060 return 0; 23061 }
| static int sip_set_udptl_peer | ( | struct ast_channel * | chan, | |
| struct ast_udptl * | udptl | |||
| ) | [static] |
Definition at line 22886 of file chan_sip.c.
References ast_debug, ast_inet_ntoa(), ast_set_flag, ast_test_flag, ast_udptl_get_peer(), sip_pvt::callid, chan, FALSE, sip_pvt::flags, sip_pvt::lastrtprx, sip_pvt::lastrtptx, sip_pvt::ourip, sip_pvt::pendinginvite, SIP_GOTREFER, SIP_NEEDREINVITE, SIP_PENDINGBYE, sip_pvt_lock, sip_pvt_unlock, ast_channel::tech_pvt, transmit_reinvite_with_sdp(), TRUE, sip_pvt::udptl, and sip_pvt::udptlredirip.
22887 { 22888 struct sip_pvt *p; 22889 22890 p = chan->tech_pvt; 22891 if (!p) 22892 return -1; 22893 sip_pvt_lock(p); 22894 if (udptl) 22895 ast_udptl_get_peer(udptl, &p->udptlredirip); 22896 else 22897 memset(&p->udptlredirip, 0, sizeof(p->udptlredirip)); 22898 if (!ast_test_flag(&p->flags[0], SIP_GOTREFER)) { 22899 if (!p->pendinginvite) { 22900 ast_debug(3, "Sending reinvite on SIP '%s' - It's UDPTL soon redirected to IP %s:%d\n", p->callid, ast_inet_ntoa(udptl ? p->udptlredirip.sin_addr : p->ourip.sin_addr), udptl ? ntohs(p->udptlredirip.sin_port) : 0); 22901 transmit_reinvite_with_sdp(p, TRUE, FALSE); 22902 } else if (!ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) { 22903 ast_debug(3, "Deferring reinvite on SIP '%s' - It's UDPTL will be redirected to IP %s:%d\n", p->callid, ast_inet_ntoa(udptl ? p->udptlredirip.sin_addr : p->ourip.sin_addr), udptl ? ntohs(p->udptlredirip.sin_port) : 0); 22904 ast_set_flag(&p->flags[0], SIP_NEEDREINVITE); 22905 } 22906 } 22907 /* Reset lastrtprx timer */ 22908 p->lastrtprx = p->lastrtptx = time(NULL); 22909 sip_pvt_unlock(p); 22910 return 0; 22911 }
| static char * sip_show_channel | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Show details of one active dialog.
Definition at line 14635 of file chan_sip.c.
References sip_pvt::allowtransfer, ao2_iterator_init(), ao2_t_iterator_next, ao2_t_ref, ast_cli_args::argc, ast_cli_args::argv, ARRAY_LEN, ast_cli(), ast_getformatname_multiple(), ast_inet_ntoa(), ast_strlen_zero(), ast_test_flag, sip_pvt::callid, sip_pvt::capability, sip_pvt::cid_num, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, cli_yesno(), ast_cli_entry::command, complete_sipch(), dialogs, dtmfmode2str(), ast_cli_args::fd, sip_pvt::flags, sip_route::hop, cfsip_options::id, sip_pvt::jointcapability, sip_pvt::lastmsg, len(), ast_cli_args::line, sip_pvt::maxcallbitrate, ast_cli_args::n, ast_channel::name, nat2str(), ast_channel::nativeformats, sip_pvt::needdestroy, sip_pvt::noncodeccapability, NONE, sip_pvt::ourip, sip_pvt::owner, sip_pvt::peercapability, sip_pvt::peername, ast_cli_args::pos, sip_pvt::recv, sip_pvt::redirip, sip_pvt::route, sip_pvt::sa, SIP_DTMF, SIP_NAT, sip_options, SIP_OUTGOING, SIP_PROMISCREDIR, sip_pvt_lock, sip_pvt_unlock, SIPBUFSIZE, sip_pvt::sipoptions, sip_st_dlg::st_active, sip_st_dlg::st_active_peer_ua, sip_st_dlg::st_cached_max_se, sip_st_dlg::st_cached_min_se, sip_st_dlg::st_cached_mode, sip_st_dlg::st_cached_ref, sip_st_dlg::st_expirys, sip_st_dlg::st_interval, sip_st_dlg::st_ref, sip_st_dlg::st_schedid, sip_pvt::stimer, stmode2str(), strefresher2str(), sip_pvt::subscribed, subscription_type2str(), sip_pvt::tag, cfsip_options::text, sip_pvt::theirtag, transfermode2str(), TRUE, sip_pvt::udptl, sip_pvt::uri, ast_cli_entry::usage, sip_pvt::useragent, sip_pvt::username, sip_pvt::vrtp, and ast_cli_args::word.
14636 { 14637 struct sip_pvt *cur; 14638 size_t len; 14639 int found = 0; 14640 struct ao2_iterator i; 14641 14642 switch (cmd) { 14643 case CLI_INIT: 14644 e->command = "sip show channel"; 14645 e->usage = 14646 "Usage: sip show channel <call-id>\n" 14647 " Provides detailed status on a given SIP dialog (identified by SIP call-id).\n"; 14648 return NULL; 14649 case CLI_GENERATE: 14650 return complete_sipch(a->line, a->word, a->pos, a->n); 14651 } 14652 14653 if (a->argc != 4) 14654 return CLI_SHOWUSAGE; 14655 len = strlen(a->argv[3]); 14656 14657 i = ao2_iterator_init(dialogs, 0); 14658 14659 while ((cur = ao2_t_iterator_next(&i, "iterate thru dialogs"))) { 14660 sip_pvt_lock(cur); 14661 14662 if (!strncasecmp(cur->callid, a->argv[3], len)) { 14663 char formatbuf[SIPBUFSIZE/2]; 14664 ast_cli(a->fd, "\n"); 14665 if (cur->subscribed != NONE) 14666 ast_cli(a->fd, " * Subscription (type: %s)\n", subscription_type2str(cur->subscribed)); 14667 else 14668 ast_cli(a->fd, " * SIP Call\n"); 14669 ast_cli(a->fd, " Curr. trans. direction: %s\n", ast_test_flag(&cur->flags[0], SIP_OUTGOING) ? "Outgoing" : "Incoming"); 14670 ast_cli(a->fd, " Call-ID: %s\n", cur->callid); 14671 ast_cli(a->fd, " Owner channel ID: %s\n", cur->owner ? cur->owner->name : "<none>"); 14672 ast_cli(a->fd, " Our Codec Capability: %d\n", cur->capability); 14673 ast_cli(a->fd, " Non-Codec Capability (DTMF): %d\n", cur->noncodeccapability); 14674 ast_cli(a->fd, " Their Codec Capability: %d\n", cur->peercapability); 14675 ast_cli(a->fd, " Joint Codec Capability: %d\n", cur->jointcapability); 14676 ast_cli(a->fd, " Format: %s\n", ast_getformatname_multiple(formatbuf, sizeof(formatbuf), cur->owner ? cur->owner->nativeformats : 0) ); 14677 ast_cli(a->fd, " T.38 support %s\n", cli_yesno(cur->udptl != NULL)); 14678 ast_cli(a->fd, " Video support %s\n", cli_yesno(cur->vrtp != NULL)); 14679 ast_cli(a->fd, " MaxCallBR: %d kbps\n", cur->maxcallbitrate); 14680 ast_cli(a->fd, " Theoretical Address: %s:%d\n", ast_inet_ntoa(cur->sa.sin_addr), ntohs(cur->sa.sin_port)); 14681 ast_cli(a->fd, " Received Address: %s:%d\n", ast_inet_ntoa(cur->recv.sin_addr), ntohs(cur->recv.sin_port)); 14682 ast_cli(a->fd, " SIP Transfer mode: %s\n", transfermode2str(cur->allowtransfer)); 14683 ast_cli(a->fd, " NAT Support: %s\n", nat2str(ast_test_flag(&cur->flags[0], SIP_NAT))); 14684 ast_cli(a->fd, " Audio IP: %s %s\n", ast_inet_ntoa(cur->redirip.sin_addr.s_addr ? cur->redirip.sin_addr : cur->ourip.sin_addr), cur->redirip.sin_addr.s_addr ? "(Outside bridge)" : "(local)" ); 14685 ast_cli(a->fd, " Our Tag: %s\n", cur->tag); 14686 ast_cli(a->fd, " Their Tag: %s\n", cur->theirtag); 14687 ast_cli(a->fd, " SIP User agent: %s\n", cur->useragent); 14688 if (!ast_strlen_zero(cur->username)) 14689 ast_cli(a->fd, " Username: %s\n", cur->username); 14690 if (!ast_strlen_zero(cur->peername)) 14691 ast_cli(a->fd, " Peername: %s\n", cur->peername); 14692 if (!ast_strlen_zero(cur->uri)) 14693 ast_cli(a->fd, " Original uri: %s\n", cur->uri); 14694 if (!ast_strlen_zero(cur->cid_num)) 14695 ast_cli(a->fd, " Caller-ID: %s\n", cur->cid_num); 14696 ast_cli(a->fd, " Need Destroy: %s\n", cli_yesno(cur->needdestroy)); 14697 ast_cli(a->fd, " Last Message: %s\n", cur->lastmsg); 14698 ast_cli(a->fd, " Promiscuous Redir: %s\n", cli_yesno(ast_test_flag(&cur->flags[0], SIP_PROMISCREDIR))); 14699 ast_cli(a->fd, " Route: %s\n", cur->route ? cur->route->hop : "N/A"); 14700 ast_cli(a->fd, " DTMF Mode: %s\n", dtmfmode2str(ast_test_flag(&cur->flags[0], SIP_DTMF))); 14701 ast_cli(a->fd, " SIP Options: "); 14702 if (cur->sipoptions) { 14703 int x; 14704 for (x = 0 ; x < ARRAY_LEN(sip_options); x++) { 14705 if (cur->sipoptions & sip_options[x].id) 14706 ast_cli(a->fd, "%s ", sip_options[x].text); 14707 } 14708 ast_cli(a->fd, "\n"); 14709 } else 14710 ast_cli(a->fd, "(none)\n"); 14711 14712 if (!cur->stimer) 14713 ast_cli(a->fd, " Session-Timer: Uninitiallized\n"); 14714 else { 14715 ast_cli(a->fd, " Session-Timer: %s\n", cur->stimer->st_active ? "Active" : "Inactive"); 14716 if (cur->stimer->st_active == TRUE) { 14717 ast_cli(a->fd, " S-Timer Interval: %d\n", cur->stimer->st_interval); 14718 ast_cli(a->fd, " S-Timer Refresher: %s\n", strefresher2str(cur->stimer->st_ref)); 14719 ast_cli(a->fd, " S-Timer Expirys: %d\n", cur->stimer->st_expirys); 14720 ast_cli(a->fd, " S-Timer Sched Id: %d\n", cur->stimer->st_schedid); 14721 ast_cli(a->fd, " S-Timer Peer Sts: %s\n", cur->stimer->st_active_peer_ua ? "Active" : "Inactive"); 14722 ast_cli(a->fd, " S-Timer Cached Min-SE: %d\n", cur->stimer->st_cached_min_se); 14723 ast_cli(a->fd, " S-Timer Cached SE: %d\n", cur->stimer->st_cached_max_se); 14724 ast_cli(a->fd, " S-Timer Cached Ref: %s\n", strefresher2str(cur->stimer->st_cached_ref)); 14725 ast_cli(a->fd, " S-Timer Cached Mode: %s\n", stmode2str(cur->stimer->st_cached_mode)); 14726 } 14727 } 14728 14729 ast_cli(a->fd, "\n\n"); 14730 14731 found++; 14732 } 14733 14734 sip_pvt_unlock(cur); 14735 14736 ao2_t_ref(cur, -1, "toss dialog ptr set by iterator_next"); 14737 } 14738 14739 if (!found) 14740 ast_cli(a->fd, "No such SIP Call ID starting with '%s'\n", a->argv[3]); 14741 14742 return CLI_SUCCESS; 14743 }
| static char* sip_show_channels | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
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.
Definition at line 14458 of file chan_sip.c.
References ao2_t_callback, ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dialogs, ESS, ast_cli_args::fd, __show_chan_arg::fd, FORMAT2, FORMAT3, __show_chan_arg::numchans, OBJ_NODATA, show_channels_cb(), __show_chan_arg::subscriptions, and ast_cli_entry::usage.
14459 { 14460 struct __show_chan_arg arg = { .fd = a->fd, .numchans = 0 }; 14461 14462 14463 if (cmd == CLI_INIT) { 14464 e->command = "sip show {channels|subscriptions}"; 14465 e->usage = 14466 "Usage: sip show channels\n" 14467 " Lists all currently active SIP calls (dialogs).\n" 14468 "Usage: sip show subscriptions\n" 14469 " Lists active SIP subscriptions.\n"; 14470 return NULL; 14471 } else if (cmd == CLI_GENERATE) 14472 return NULL; 14473 14474 if (a->argc != e->args) 14475 return CLI_SHOWUSAGE; 14476 arg.subscriptions = !strcasecmp(a->argv[e->args - 1], "subscriptions"); 14477 if (!arg.subscriptions) 14478 ast_cli(arg.fd, FORMAT2, "Peer", "User/ANR", "Call ID", "Format", "Hold", "Last Message", "Expiry"); 14479 else 14480 ast_cli(arg.fd, FORMAT3, "Peer", "User", "Call ID", "Extension", "Last state", "Type", "Mailbox", "Expiry"); 14481 14482 /* iterate on the container and invoke the callback on each item */ 14483 ao2_t_callback(dialogs, OBJ_NODATA, show_channels_cb, &arg, "callback to show channels"); 14484 14485 /* print summary information */ 14486 ast_cli(arg.fd, "%d active SIP %s%s\n", arg.numchans, 14487 (arg.subscriptions ? "subscription" : "dialog"), 14488 ESS(arg.numchans)); /* ESS(n) returns an "s" if n>1 */ 14489 return CLI_SUCCESS; 14490 #undef FORMAT 14491 #undef FORMAT2 14492 #undef FORMAT3 14493 }
| static char * sip_show_channelstats | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
SIP show channelstats CLI (main function).
Definition at line 14150 of file chan_sip.c.
References ao2_t_callback, ast_cli_args::argc, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dialogs, ast_cli_args::fd, __show_chan_arg::fd, FORMAT2, __show_chan_arg::numchans, OBJ_NODATA, show_chanstats_cb(), and ast_cli_entry::usage.
14151 { 14152 struct __show_chan_arg arg = { .fd = a->fd, .numchans = 0 }; 14153 14154 switch (cmd) { 14155 case CLI_INIT: 14156 e->command = "sip show channelstats"; 14157 e->usage = 14158 "Usage: sip show channelstats\n" 14159 " Lists all currently active SIP channel's RTCP statistics.\n" 14160 " Note that calls in the much optimized RTP P2P bridge mode will not show any packets here."; 14161 return NULL; 14162 case CLI_GENERATE: 14163 return NULL; 14164 } 14165 14166 if (a->argc != 3) 14167 return CLI_SHOWUSAGE; 14168 14169 ast_cli(a->fd, FORMAT2, "Peer", "Call ID", "Duration", "Recv: Pack", "Lost", "%", "Jitter", "Send: Pack", "Lost", "Jitter"); 14170 /* iterate on the container and invoke the callback on each item */ 14171 ao2_t_callback(dialogs, OBJ_NODATA, show_chanstats_cb, &arg, "callback to sip show chanstats"); 14172 ast_cli(a->fd, "%d active SIP channel%s\n", arg.numchans, (arg.numchans != 1) ? "s" : ""); 14173 return CLI_SUCCESS; 14174 }
| static char * sip_show_domains | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
CLI command to list local domains.
Definition at line 13470 of file chan_sip.c.
References ast_cli(), AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, domain::context, domain::domain, domain_mode_to_text(), ast_cli_args::fd, FORMAT, domain::list, domain::mode, S_OR, and ast_cli_entry::usage.
13471 { 13472 struct domain *d; 13473 #define FORMAT "%-40.40s %-20.20s %-16.16s\n" 13474 13475 switch (cmd) { 13476 case CLI_INIT: 13477 e->command = "sip show domains"; 13478 e->usage = 13479 "Usage: sip show domains\n" 13480 " Lists all configured SIP local domains.\n" 13481 " Asterisk only responds to SIP messages to local domains.\n"; 13482 return NULL; 13483 case CLI_GENERATE: 13484 return NULL; 13485 } 13486 13487 if (AST_LIST_EMPTY(&domain_list)) { 13488 ast_cli(a->fd, "SIP Domain support not enabled.\n\n"); 13489 return CLI_SUCCESS; 13490 } else { 13491 ast_cli(a->fd, FORMAT, "Our local SIP domains:", "Context", "Set by"); 13492 AST_LIST_LOCK(&domain_list); 13493 AST_LIST_TRAVERSE(&domain_list, d, list) 13494 ast_cli(a->fd, FORMAT, d->domain, S_OR(d->context, "(default)"), 13495 domain_mode_to_text(d->mode)); 13496 AST_LIST_UNLOCK(&domain_list); 13497 ast_cli(a->fd, "\n"); 13498 return CLI_SUCCESS; 13499 } 13500 }
| static char * sip_show_history | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Show history details of one dialog.
Definition at line 14746 of file chan_sip.c.
References ao2_iterator_init(), ao2_t_iterator_next, ao2_t_ref, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_LIST_TRAVERSE, sip_pvt::callid, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_sip_show_history(), dialogs, sip_history::event, ast_cli_args::fd, sip_pvt::history, len(), ast_cli_args::line, sip_history::list, ast_cli_args::n, NONE, ast_cli_args::pos, sip_pvt_lock, sip_pvt_unlock, sip_pvt::subscribed, ast_cli_entry::usage, and ast_cli_args::word.
14747 { 14748 struct sip_pvt *cur; 14749 size_t len; 14750 int found = 0; 14751 struct ao2_iterator i; 14752 14753 switch (cmd) { 14754 case CLI_INIT: 14755 e->command = "sip show history"; 14756 e->usage = 14757 "Usage: sip show history <call-id>\n" 14758 " Provides detailed dialog history on a given SIP call (specified by call-id).\n"; 14759 return NULL; 14760 case CLI_GENERATE: 14761 return complete_sip_show_history(a->line, a->word, a->pos, a->n); 14762 } 14763 14764 if (a->argc != 4) 14765 return CLI_SHOWUSAGE; 14766 14767 if (!recordhistory) 14768 ast_cli(a->fd, "\n***Note: History recording is currently DISABLED. Use 'sip set history on' to ENABLE.\n"); 14769 14770 len = strlen(a->argv[3]); 14771 14772 i = ao2_iterator_init(dialogs, 0); 14773 while ((cur = ao2_t_iterator_next(&i, "iterate thru dialogs"))) { 14774 sip_pvt_lock(cur); 14775 if (!strncasecmp(cur->callid, a->argv[3], len)) { 14776 struct sip_history *hist; 14777 int x = 0; 14778 14779 ast_cli(a->fd, "\n"); 14780 if (cur->subscribed != NONE) 14781 ast_cli(a->fd, " * Subscription\n"); 14782 else 14783 ast_cli(a->fd, " * SIP Call\n"); 14784 if (cur->history) 14785 AST_LIST_TRAVERSE(cur->history, hist, list) 14786 ast_cli(a->fd, "%d. %s\n", ++x, hist->event); 14787 if (x == 0) 14788 ast_cli(a->fd, "Call '%s' has no history\n", cur->callid); 14789 found++; 14790 } 14791 sip_pvt_unlock(cur); 14792 ao2_t_ref(cur, -1, "toss dialog ptr from iterator_next"); 14793 } 14794 14795 if (!found) 14796 ast_cli(a->fd, "No such SIP Call ID starting with '%s'\n", a->argv[3]); 14797 14798 return CLI_SUCCESS; 14799 }
| static char * sip_show_inuse | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
CLI Command to show calls within limits set by call_limit.
Definition at line 12559 of file chan_sip.c.
References ao2_iterator_init(), ao2_lock(), ao2_t_iterator_next, ao2_unlock(), ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_copy_string(), sip_peer::call_limit, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, FALSE, ast_cli_args::fd, FORMAT, FORMAT2, sip_peer::inRinging, sip_peer::inUse, sip_peer::name, sip_peer::onHold, TRUE, unref_peer(), and ast_cli_entry::usage.
12560 { 12561 #define FORMAT "%-25.25s %-15.15s %-15.15s \n" 12562 #define FORMAT2 "%-25.25s %-15.15s %-15.15s \n" 12563 char ilimits[40]; 12564 char iused[40]; 12565 int showall = FALSE; 12566 struct ao2_iterator i; 12567 struct sip_peer *peer; 12568 12569 switch (cmd) { 12570 case CLI_INIT: 12571 e->command = "sip show inuse"; 12572 e->usage = 12573 "Usage: sip show inuse [all]\n" 12574 " List all SIP devices usage counters and limits.\n" 12575 " Add option \"all\" to show all devices, not only those with a limit.\n"; 12576 return NULL; 12577 case CLI_GENERATE: 12578 return NULL; 12579 } 12580 12581 if (a->argc < 3) 12582 return CLI_SHOWUSAGE; 12583 12584 if (a->argc == 4 && !strcmp(a->argv[3], "all")) 12585 showall = TRUE; 12586 12587 ast_cli(a->fd, FORMAT, "* Peer name", "In use", "Limit"); 12588 12589 i = ao2_iterator_init(peers, 0); 12590 12591 while ((peer = ao2_t_iterator_next(&i, "iterate thru peer table"))) { 12592 ao2_lock(peer); 12593 if (peer->call_limit) 12594 snprintf(ilimits, sizeof(ilimits), "%d", peer->call_limit); 12595 else 12596 ast_copy_string(ilimits, "N/A", sizeof(ilimits)); 12597 snprintf(iused, sizeof(iused), "%d/%d/%d", peer->inUse, peer->inRinging, peer->onHold); 12598 if (showall || peer->call_limit) 12599 ast_cli(a->fd, FORMAT2, peer->name, iused, ilimits); 12600 ao2_unlock(peer); 12601 unref_peer(peer, "toss iterator pointer"); 12602 } 12603 12604 return CLI_SUCCESS; 12605 #undef FORMAT 12606 #undef FORMAT2 12607 }
| static char * sip_show_objects | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
List all allocated SIP Objects (realtime or static).
Definition at line 13138 of file chan_sip.c.
References ao2_t_callback, ast_cli_args::argc, ast_cli(), ASTOBJ_CONTAINER_DUMP, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dialog_dump_func(), dialogs, ast_cli_args::fd, OBJ_NODATA, peer_dump_func(), regl, and ast_cli_entry::usage.
13139 { 13140 char tmp[256]; 13141 13142 switch (cmd) { 13143 case CLI_INIT: 13144 e->command = "sip show objects"; 13145 e->usage = 13146 "Usage: sip show objects\n" 13147 " Lists status of known SIP objects\n"; 13148 return NULL; 13149 case CLI_GENERATE: 13150 return NULL; 13151 } 13152 13153 if (a->argc != 3) 13154 return CLI_SHOWUSAGE; 13155 ast_cli(a->fd, "-= Peer objects: %d static, %d realtime, %d autocreate =-\n\n", speerobjs, rpeerobjs, apeerobjs); 13156 ao2_t_callback(peers, OBJ_NODATA, peer_dump_func, &a->fd, "initiate ao2_callback to dump peers"); 13157 ast_cli(a->fd, "-= Registry objects: %d =-\n\n", regobjs); 13158 ASTOBJ_CONTAINER_DUMP(a->fd, tmp, sizeof(tmp), ®l); 13159 ast_cli(a->fd, "-= Dialog objects:\n\n"); 13160 ao2_t_callback(dialogs, OBJ_NODATA, dialog_dump_func, &a->fd, "initiate ao2_callback to dump dialogs"); 13161 return CLI_SUCCESS; 13162 }
| static char * sip_show_peer | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Show one peer in detail.
Definition at line 13531 of file chan_sip.c.
References _sip_show_peer(), ast_cli_args::argc, ast_cli_args::argv, CLI_GENERATE, CLI_INIT, ast_cli_entry::command, complete_sip_show_peer(), ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.
13532 { 13533 switch (cmd) { 13534 case CLI_INIT: 13535 e->command = "sip show peer"; 13536 e->usage = 13537 "Usage: sip show peer <name> [load]\n" 13538 " Shows all details on one SIP peer and the current status.\n" 13539 " Option \"load\" forces lookup of peer in realtime storage.\n"; 13540 return NULL; 13541 case CLI_GENERATE: 13542 return complete_sip_show_peer(a->line, a->word, a->pos, a->n); 13543 } 13544 return _sip_show_peer(0, a->fd, NULL, NULL, a->argc, (const char **) a->argv); 13545 }
| static char * sip_show_peers | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
CLI Show Peers command.
Definition at line 12915 of file chan_sip.c.
References _sip_show_peers(), ast_cli_args::argc, ast_cli_args::argv, CLI_GENERATE, CLI_INIT, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.
12916 { 12917 switch (cmd) { 12918 case CLI_INIT: 12919 e->command = "sip show peers"; 12920 e->usage = 12921 "Usage: sip show peers [like <pattern>]\n" 12922 " Lists all known SIP peers.\n" 12923 " Optional regular expression pattern is used to filter the peer list.\n"; 12924 return NULL; 12925 case CLI_GENERATE: 12926 return NULL; 12927 } 12928 12929 return _sip_show_peers(a->fd, NULL, NULL, NULL, a->argc, (const char **) a->argv); 12930 }
| static char * sip_show_registry | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Show SIP Registry (registrations with other SIP proxies.
Definition at line 14011 of file chan_sip.c.
References ast_cli_args::argc, ast_cli(), ast_localtime(), ast_strftime(), ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_RDLOCK, ASTOBJ_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, FORMAT, FORMAT2, regl, regstate2str(), STANDARD_SIP_PORT, and ast_cli_entry::usage.
14012 { 14013 #define FORMAT2 "%-30.30s %-6.6s %-12.12s %8.8s %-20.20s %-25.25s\n" 14014 #define FORMAT "%-30.30s %-6.6s %-12.12s %8d %-20.20s %-25.25s\n" 14015 char host[80]; 14016 char tmpdat[256]; 14017 struct ast_tm tm; 14018 int counter = 0; 14019 14020 switch (cmd) { 14021 case CLI_INIT: 14022 e->command = "sip show registry"; 14023 e->usage = 14024 "Usage: sip show registry\n" 14025 " Lists all registration requests and status.\n"; 14026 return NULL; 14027 case CLI_GENERATE: 14028 return NULL; 14029 } 14030 14031 if (a->argc != 3) 14032 return CLI_SHOWUSAGE; 14033 ast_cli(a->fd, FORMAT2, "Host", "dnsmgr", "Username", "Refresh", "State", "Reg.Time"); 14034 14035 ASTOBJ_CONTAINER_TRAVERSE(®l, 1, do { 14036 ASTOBJ_RDLOCK(iterator); 14037 snprintf(host, sizeof(host), "%s:%d", iterator->hostname, iterator->portno ? iterator->portno : STANDARD_SIP_PORT); 14038 if (iterator->regtime.tv_sec) { 14039 ast_localtime(&iterator->regtime, &tm, NULL); 14040 ast_strftime(tmpdat, sizeof(tmpdat), "%a, %d %b %Y %T", &tm); 14041 } else 14042 tmpdat[0] = '\0'; 14043 ast_cli(a->fd, FORMAT, host, (iterator->dnsmgr) ? "Y" : "N", iterator->username, iterator->refresh, regstate2str(iterator->regstate), tmpdat); 14044 ASTOBJ_UNLOCK(iterator); 14045 counter++; 14046 } while(0)); 14047 ast_cli(a->fd, "%d SIP registrations.\n", counter); 14048 return CLI_SUCCESS; 14049 #undef FORMAT 14050 #undef FORMAT2 14051 }
| static char * sip_show_sched | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 13968 of file chan_sip.c.
References __sip_autodestruct(), ast_cli(), ast_sched_report(), ast_str_alloca, auto_congest(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, expire_register(), ast_cli_args::fd, retrans_pkt(), sched, sip_poke_noanswer(), sip_poke_peer_s(), sip_reg_timeout(), sip_reinvite_retry(), sip_reregister(), ast_str::str, and ast_cli_entry::usage.
13969 { 13970 struct ast_str *cbuf; 13971 struct ast_cb_names cbnames = {9, { "retrans_pkt", 13972 "__sip_autodestruct", 13973 "expire_register", 13974 "auto_congest", 13975 "sip_reg_timeout", 13976 "sip_poke_peer_s", 13977 "sip_poke_noanswer", 13978 "sip_reregister", 13979 "sip_reinvite_retry"}, 13980 { retrans_pkt, 13981 __sip_autodestruct, 13982 expire_register, 13983 auto_congest, 13984 sip_reg_timeout, 13985 sip_poke_peer_s, 13986 sip_poke_noanswer, 13987 sip_reregister, 13988 sip_reinvite_retry}}; 13989 13990 switch (cmd) { 13991 case CLI_INIT: 13992 e->command = "sip show sched"; 13993 e->usage = 13994 "Usage: sip show sched\n" 13995 " Shows stats on what's in the sched queue at the moment\n"; 13996 return NULL; 13997 case CLI_GENERATE: 13998 return NULL; 13999 } 14000 14001 cbuf = ast_str_alloca(2048); 14002 14003 ast_cli(a->fd, "\n"); 14004 ast_sched_report(sched, &cbuf, &cbnames); 14005 ast_cli(a->fd, "%s", cbuf->str); 14006 14007 return CLI_SUCCESS; 14008 }
| static char * sip_show_settings | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
List global settings for the SIP channel.
Definition at line 14179 of file chan_sip.c.
References ast_cli_args::argc, ast_check_realtime(), ast_cli(), ast_getformatname_multiple(), ast_inet_ntoa(), AST_JB_ENABLED, AST_JB_FORCED, AST_JB_LOG, AST_LIST_EMPTY, ast_strlen_zero(), ast_test_flag, ast_tos2str(), authl, buf, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, cli_yesno(), ast_cli_entry::command, default_prefs, default_tls_cfg, dtmfmode2str(), ast_tls_config::enabled, externhost, externrefresh, FALSE, ast_cli_args::fd, sip_proxy::force, global_flags, global_jbconf, global_outboundproxy, sip_settings::ignore_regexpire, ast_jb_conf::impl, ast_tcptls_session_args::local_address, localaddr, ast_jb_conf::max_size, msg, sip_proxy::name, nat2str(), ast_ha::netaddr, ast_ha::netmask, ast_ha::next, sip_settings::peer_rtupdate, prefix, print_codec_to_cli(), ast_jb_conf::resync_threshold, sip_settings::rtsave_sysname, S_OR, sip_cfg, SIP_DTMF, SIP_NAT, SIP_PAGE2_ALLOWOVERLAP, SIP_PAGE2_ALLOWSUBSCRIBE, SIP_PAGE2_RFC2833_COMPENSATE, SIP_PAGE2_RTCACHEFRIENDS, SIP_PAGE2_T38SUPPORT_RTP, SIP_PAGE2_T38SUPPORT_TCP, SIP_PAGE2_T38SUPPORT_UDPTL, SIP_PAGE2_TEXTSUPPORT, SIP_PAGE2_VIDEOSUPPORT, SIP_PROG_INBAND, SIP_PROG_INBAND_NEVER, SIP_PROG_INBAND_NO, SIP_PROMISCREDIR, sip_tcp_desc, sip_tls_desc, SIP_USECLIENTCODE, SIP_USEREQPHONE, SIPBUFSIZE, stmode2str(), strefresher2str(), transfermode2str(), and ast_cli_entry::usage.
14180 { 14181 int realtimepeers; 14182 int realtimeregs; 14183 char codec_buf[SIPBUFSIZE]; 14184 const char *msg; /* temporary msg pointer */ 14185 14186 switch (cmd) { 14187 case CLI_INIT: 14188 e->command = "sip show settings"; 14189 e->usage = 14190 "Usage: sip show settings\n" 14191 " Provides detailed list of the configuration of the SIP channel.\n"; 14192 return NULL; 14193 case CLI_GENERATE: 14194 return NULL; 14195 } 14196 14197 14198 realtimepeers = ast_check_realtime("sippeers"); 14199 realtimeregs = ast_check_realtime("sipregs"); 14200 14201 if (a->argc != 3) 14202 return CLI_SHOWUSAGE; 14203 ast_cli(a->fd, "\n\nGlobal Settings:\n"); 14204 ast_cli(a->fd, "----------------\n"); 14205 ast_cli(a->fd, " UDP SIP Port: %d\n", ntohs(bindaddr.sin_port)); 14206 ast_cli(a->fd, " UDP Bindaddress: %s\n", ast_inet_ntoa(bindaddr.sin_addr)); 14207 ast_cli(a->fd, " TCP SIP Port: "); 14208 if (sip_tcp_desc.local_address.sin_family == AF_INET) { 14209 ast_cli(a->fd, "%d\n", ntohs(sip_tcp_desc.local_address.sin_port)); 14210 ast_cli(a->fd, " TCP Bindaddress: %s\n", ast_inet_ntoa(sip_tcp_desc.local_address.sin_addr)); 14211 } else { 14212 ast_cli(a->fd, "Disabled\n"); 14213 } 14214 ast_cli(a->fd, " TLS SIP Port: "); 14215 if (default_tls_cfg.enabled != FALSE) { 14216 ast_cli(a->fd, "%d\n", ntohs(sip_tls_desc.local_address.sin_port)); 14217 ast_cli(a->fd, " TLS Bindaddress: %s\n", ast_inet_ntoa(sip_tls_desc.local_address.sin_addr)); 14218 } else { 14219 ast_cli(a->fd, "Disabled\n"); 14220 } 14221 ast_cli(a->fd, " Videosupport: %s\n", cli_yesno(ast_test_flag(&global_flags[1], SIP_PAGE2_VIDEOSUPPORT))); 14222 ast_cli(a->fd, " Textsupport: %s\n", cli_yesno(ast_test_flag(&global_flags[1], SIP_PAGE2_TEXTSUPPORT))); 14223 ast_cli(a->fd, " AutoCreate Peer: %s\n", cli_yesno(autocreatepeer)); 14224 ast_cli(a->fd, " Match Auth Username: %s\n", cli_yesno(global_match_auth_username)); 14225 ast_cli(a->fd, " Allow unknown access: %s\n", cli_yesno(global_allowguest)); 14226 ast_cli(a->fd, " Allow subscriptions: %s\n", cli_yesno(ast_test_flag(&global_flags[1], SIP_PAGE2_ALLOWSUBSCRIBE))); 14227 ast_cli(a->fd, " Allow overlap dialing: %s\n", cli_yesno(ast_test_flag(&global_flags[1], SIP_PAGE2_ALLOWOVERLAP))); 14228 ast_cli(a->fd, " Allow promsic. redir: %s\n", cli_yesno(ast_test_flag(&global_flags[0], SIP_PROMISCREDIR))); 14229 ast_cli(a->fd, " Enable call counters: %s\n", cli_yesno(global_callcounter)); 14230 ast_cli(a->fd, " SIP domain support: %s\n", cli_yesno(!AST_LIST_EMPTY(&domain_list))); 14231 ast_cli(a->fd, " Realm. auth: %s\n", cli_yesno(authl != NULL)); 14232 ast_cli(a->fd, " Our auth realm %s\n", global_realm); 14233 ast_cli(a->fd, " Call to non-local dom.: %s\n", cli_yesno(allow_external_domains)); 14234 ast_cli(a->fd, " URI user is phone no: %s\n", cli_yesno(ast_test_flag(&global_flags[0], SIP_USEREQPHONE))); 14235 ast_cli(a->fd, " Always auth rejects: %s\n", cli_yesno(global_alwaysauthreject)); 14236 ast_cli(a->fd, " Direct RTP setup: %s\n", cli_yesno(global_directrtpsetup)); 14237 ast_cli(a->fd, " User Agent: %s\n", global_useragent); 14238 ast_cli(a->fd, " SDP Session Name: %s\n", ast_strlen_zero(global_sdpsession) ? "-" : global_sdpsession); 14239 ast_cli(a->fd, " SDP Owner Name: %s\n", ast_strlen_zero(global_sdpowner) ? "-" : global_sdpowner); 14240 ast_cli(a->fd, " Reg. context: %s\n", S_OR(global_regcontext, "(not set)")); 14241 ast_cli(a->fd, " Regexten on Qualify: %s\n", cli_yesno(global_regextenonqualify)); 14242 ast_cli(a->fd, " Caller ID: %s\n", default_callerid); 14243 ast_cli(a->fd, " From: Domain: %s\n", default_fromdomain); 14244 ast_cli(a->fd, " Record SIP history: %s\n", recordhistory ? "On" : "Off"); 14245 ast_cli(a->fd, " Call Events: %s\n", global_callevents ? "On" : "Off"); 14246 ast_cli(a->fd, " Auth. Failure Events: %s\n", global_authfailureevents ? "On" : "Off"); 14247 14248 ast_cli(a->fd, " T38 fax pt UDPTL: %s\n", cli_yesno(ast_test_flag(&global_flags[1], SIP_PAGE2_T38SUPPORT_UDPTL))); 14249 #ifdef WHEN_WE_HAVE_T38_FOR_OTHER_TRANSPORTS 14250 ast_cli(a->fd, " T38 fax pt RTP: %s\n", cli_yesno(ast_test_flag(&global_flags[1], SIP_PAGE2_T38SUPPORT_RTP))); 14251 ast_cli(a->fd, " T38 fax pt TCP: %s\n", cli_yesno(ast_test_flag(&global_flags[1], SIP_PAGE2_T38SUPPORT_TCP))); 14252 #endif 14253 if (!realtimepeers && !realtimeregs) 14254 ast_cli(a->fd, " SIP realtime: Disabled\n" ); 14255 else 14256 ast_cli(a->fd, " SIP realtime: Enabled\n" ); 14257 ast_cli(a->fd, " Qualify Freq : %d ms\n", global_qualifyfreq); 14258 ast_cli(a->fd, "\nNetwork QoS Settings:\n"); 14259 ast_cli(a->fd, "---------------------------\n"); 14260 ast_cli(a->fd, " IP ToS SIP: %s\n", ast_tos2str(global_tos_sip)); 14261 ast_cli(a->fd, " IP ToS RTP audio: %s\n", ast_tos2str(global_tos_audio)); 14262 ast_cli(a->fd, " IP ToS RTP video: %s\n", ast_tos2str(global_tos_video)); 14263 ast_cli(a->fd, " IP ToS RTP text: %s\n", ast_tos2str(global_tos_text)); 14264 ast_cli(a->fd, " 802.1p CoS SIP: %d\n", global_cos_sip); 14265 ast_cli(a->fd, " 802.1p CoS RTP audio: %d\n", global_cos_audio); 14266 ast_cli(a->fd, " 802.1p CoS RTP video: %d\n", global_cos_video); 14267 ast_cli(a->fd, " 802.1p CoS RTP text: %d\n", global_cos_text); 14268 ast_cli(a->fd, " Jitterbuffer enabled: %s\n", cli_yesno(ast_test_flag(&global_jbconf, AST_JB_ENABLED))); 14269 ast_cli(a->fd, " Jitterbuffer forced: %s\n", cli_yesno(ast_test_flag(&global_jbconf, AST_JB_FORCED))); 14270 ast_cli(a->fd, " Jitterbuffer max size: %ld\n", global_jbconf.max_size); 14271 ast_cli(a->fd, " Jitterbuffer resync: %ld\n", global_jbconf.resync_threshold); 14272 ast_cli(a->fd, " Jitterbuffer impl: %s\n", global_jbconf.impl); 14273 ast_cli(a->fd, " Jitterbuffer log: %s\n", cli_yesno(ast_test_flag(&global_jbconf, AST_JB_LOG))); 14274 14275 ast_cli(a->fd, "\nNetwork Settings:\n"); 14276 ast_cli(a->fd, "---------------------------\n"); 14277 /* determine if/how SIP address can be remapped */ 14278 if (localaddr == NULL) 14279 msg = "Disabled, no localnet list"; 14280 else if (externip.sin_addr.s_addr == 0) 14281 msg = "Disabled, externip is 0.0.0.0"; 14282 else if (stunaddr.sin_addr.s_addr != 0) 14283 msg = "Enabled using STUN"; 14284 else if (!ast_strlen_zero(externhost)) 14285 msg = "Enabled using externhost"; 14286 else 14287 msg = "Enabled using externip"; 14288 ast_cli(a->fd, " SIP address remapping: %s\n", msg); 14289 ast_cli(a->fd, " Externhost: %s\n", S_OR(externhost, "<none>")); 14290 ast_cli(a->fd, " Externip: %s:%d\n", ast_inet_ntoa(externip.sin_addr), ntohs(externip.sin_port)); 14291 ast_cli(a->fd, " Externrefresh: %d\n", externrefresh); 14292 ast_cli(a->fd, " Internal IP: %s:%d\n", ast_inet_ntoa(internip.sin_addr), ntohs(internip.sin_port)); 14293 { 14294 struct ast_ha *d; 14295 const char *prefix = "Localnet:"; 14296 char buf[INET_ADDRSTRLEN]; /* need to print two addresses */ 14297 14298 for (d = localaddr; d ; prefix = "", d = d->next) { 14299 ast_cli(a->fd, " %-24s%s/%s\n", 14300 prefix, ast_inet_ntoa(d->netaddr), 14301 inet_ntop(AF_INET, &d->netmask, buf, sizeof(buf)) ); 14302 } 14303 } 14304 ast_cli(a->fd, " STUN server: %s:%d\n", ast_inet_ntoa(stunaddr.sin_addr), ntohs(stunaddr.sin_port)); 14305 14306 ast_cli(a->fd, "\nGlobal Signalling Settings:\n"); 14307 ast_cli(a->fd, "---------------------------\n"); 14308 ast_cli(a->fd, " Codecs: "); 14309 ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, global_capability); 14310 ast_cli(a->fd, "%s\n", codec_buf); 14311 ast_cli(a->fd, " Codec Order: "); 14312 print_codec_to_cli(a->fd, &default_prefs); 14313 ast_cli(a->fd, "\n"); 14314 ast_cli(a->fd, " Relax DTMF: %s\n", cli_yesno(global_relaxdtmf)); 14315 ast_cli(a->fd, " RFC2833 Compensation: %s\n", cli_yesno(ast_test_flag(&global_flags[1], SIP_PAGE2_RFC2833_COMPENSATE))); 14316 ast_cli(a->fd, " Compact SIP headers: %s\n", cli_yesno(compactheaders)); 14317 ast_cli(a->fd, " RTP Keepalive: %d %s\n", global_rtpkeepalive, global_rtpkeepalive ? "" : "(Disabled)" ); 14318 ast_cli(a->fd, " RTP Timeout: %d %s\n", global_rtptimeout, global_rtptimeout ? "" : "(Disabled)" ); 14319 ast_cli(a->fd, " RTP Hold Timeout: %d %s\n", global_rtpholdtimeout, global_rtpholdtimeout ? "" : "(Disabled)"); 14320 ast_cli(a->fd, " MWI NOTIFY mime type: %s\n", default_notifymime); 14321 ast_cli(a->fd, " DNS SRV lookup: %s\n", cli_yesno(global_srvlookup)); 14322 ast_cli(a->fd, " Pedantic SIP support: %s\n", cli_yesno(pedanticsipchecking)); 14323 ast_cli(a->fd, " Reg. min duration %d secs\n", min_expiry); 14324 ast_cli(a->fd, " Reg. max duration: %d secs\n", max_expiry); 14325 ast_cli(a->fd, " Reg. default duration: %d secs\n", default_expiry); 14326 ast_cli(a->fd, " Outbound reg. timeout: %d secs\n", global_reg_timeout); 14327 ast_cli(a->fd, " Outbound reg. attempts: %d\n", global_regattempts_max); 14328 ast_cli(a->fd, " Notify ringing state: %s\n", cli_yesno(global_notifyringing)); 14329 ast_cli(a->fd, " Notify hold state: %s\n", cli_yesno(global_notifyhold)); 14330 ast_cli(a->fd, " SIP Transfer mode: %s\n", transfermode2str(global_allowtransfer)); 14331 ast_cli(a->fd, " Max Call Bitrate: %d kbps\n", default_maxcallbitrate); 14332 ast_cli(a->fd, " Auto-Framing: %s\n", cli_yesno(global_autoframing)); 14333 ast_cli(a->fd, " Outb. proxy: %s %s\n", ast_strlen_zero(global_outboundproxy.name) ? "<not set>" : global_outboundproxy.name, 14334 global_outboundproxy.force ? "(forced)" : ""); 14335 ast_cli(a->fd, " Session Timers: %s\n", stmode2str(global_st_mode)); 14336 ast_cli(a->fd, " Session Refresher: %s\n", strefresher2str (global_st_refresher)); 14337 ast_cli(a->fd, " Session Expires: %d secs\n", global_max_se); 14338 ast_cli(a->fd, " Session Min-SE: %d secs\n", global_min_se); 14339 ast_cli(a->fd, " Timer T1: %d\n", global_t1); 14340 ast_cli(a->fd, " Timer T1 minimum: %d\n", global_t1min); 14341 ast_cli(a->fd, " Timer B: %d\n", global_timer_b); 14342 14343 ast_cli(a->fd, "\nDefault Settings:\n"); 14344 ast_cli(a->fd, "-----------------\n"); 14345 ast_cli(a->fd, " Context: %s\n", default_context); 14346 ast_cli(a->fd, " Nat: %s\n", nat2str(ast_test_flag(&global_flags[0], SIP_NAT))); 14347 ast_cli(a->fd, " DTMF: %s\n", dtmfmode2str(ast_test_flag(&global_flags[0], SIP_DTMF))); 14348 ast_cli(a->fd, " Qualify: %d\n", default_qualify); 14349 ast_cli(a->fd, " Use ClientCode: %s\n", cli_yesno(ast_test_flag(&global_flags[0], SIP_USECLIENTCODE))); 14350 ast_cli(a->fd, " Progress inband: %s\n", (ast_test_flag(&global_flags[0], SIP_PROG_INBAND) == SIP_PROG_INBAND_NEVER) ? "Never" : (ast_test_flag(&global_flags[0], SIP_PROG_INBAND) == SIP_PROG_INBAND_NO) ? "No" : "Yes" ); 14351 ast_cli(a->fd, " Language: %s\n", default_language); 14352 ast_cli(a->fd, " MOH Interpret: %s\n", default_mohinterpret); 14353 ast_cli(a->fd, " MOH Suggest: %s\n", default_mohsuggest); 14354 ast_cli(a->fd, " Voice Mail Extension: %s\n", default_vmexten); 14355 14356 14357 if (realtimepeers || realtimeregs) { 14358 ast_cli(a->fd, "\nRealtime SIP Settings:\n"); 14359 ast_cli(a->fd, "----------------------\n"); 14360 ast_cli(a->fd, " Realtime Peers: %s\n", cli_yesno(realtimepeers)); 14361 ast_cli(a->fd, " Realtime Regs: %s\n", cli_yesno(realtimeregs)); 14362 ast_cli(a->fd, " Cache Friends: %s\n", cli_yesno(ast_test_flag(&global_flags[1], SIP_PAGE2_RTCACHEFRIENDS))); 14363 ast_cli(a->fd, " Update: %s\n", cli_yesno(sip_cfg.peer_rtupdate)); 14364 ast_cli(a->fd, " Ignore Reg. Expire: %s\n", cli_yesno(sip_cfg.ignore_regexpire)); 14365 ast_cli(a->fd, " Save sys. name: %s\n", cli_yesno(sip_cfg.rtsave_sysname)); 14366 ast_cli(a->fd, " Auto Clear: %d\n", global_rtautoclear); 14367 } 14368 ast_cli(a->fd, "\n----\n"); 14369 return CLI_SUCCESS; 14370 }
| static char* sip_show_tcp | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Show active TCP connections.
Definition at line 12730 of file chan_sip.c.
References ast_cli_args::argc, ast_cli(), ast_inet_ntoa(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_tcptls_session_instance::client, ast_cli_entry::command, ast_cli_args::fd, FORMAT, FORMAT2, get_transport(), sip_threadinfo::list, ast_tcptls_session_instance::remote_address, sip_threadinfo::tcptls_session, sip_threadinfo::type, and ast_cli_entry::usage.
12731 { 12732 struct sip_threadinfo *th; 12733 12734 #define FORMAT2 "%-30.30s %3.6s %9.9s %6.6s\n" 12735 #define FORMAT "%-30.30s %-6d %-9.9s %-6.6s\n" 12736 12737 switch (cmd) { 12738 case CLI_INIT: 12739 e->command = "sip show tcp"; 12740 e->usage = 12741 "Usage: sip show tcp\n" 12742 " Lists all active TCP/TLS sessions.\n"; 12743 return NULL; 12744 case CLI_GENERATE: 12745 return NULL; 12746 } 12747 12748 if (a->argc != 3) 12749 return CLI_SHOWUSAGE; 12750 12751 ast_cli(a->fd, FORMAT2, "Host", "Port", "Transport", "Type"); 12752 AST_LIST_LOCK(&threadl); 12753 AST_LIST_TRAVERSE(&threadl, th, list) { 12754 ast_cli(a->fd, FORMAT, ast_inet_ntoa(th->tcptls_session->remote_address.sin_addr), 12755 ntohs(th->tcptls_session->remote_address.sin_port), 12756 get_transport(th->type), 12757 (th->tcptls_session->client ? "Client" : "Server")); 12758 12759 } 12760 AST_LIST_UNLOCK(&threadl); 12761 return CLI_SUCCESS; 12762 #undef FORMAT 12763 #undef FORMAT2 12764 }
| static char* sip_show_user | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Show one user in detail.
Definition at line 13893 of file chan_sip.c.
References ao2_lock(), ao2_unlock(), ast_cli_args::argc, ast_cli_args::argv, ast_callerid_merge(), ast_cdr_flags2str(), ast_cli(), ast_describe_caller_presentation(), ast_strlen_zero(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, cli_yesno(), ast_cli_entry::command, complete_sip_show_user(), FALSE, ast_cli_args::fd, find_peer(), FINDUSERS, ast_cli_args::line, ast_cli_args::n, ast_variable::name, ast_variable::next, ast_cli_args::pos, print_codec_to_cli(), print_group(), stmode2str(), strefresher2str(), transfermode2str(), TRUE, unref_peer(), ast_cli_entry::usage, user, ast_variable::value, and ast_cli_args::word.
13894 { 13895 char cbuf[256]; 13896 struct sip_peer *user; 13897 struct ast_variable *v; 13898 int load_realtime; 13899 13900 switch (cmd) { 13901 case CLI_INIT: 13902 e->command = "sip show user"; 13903 e->usage = 13904 "Usage: sip show user <name> [load]\n" 13905 " Shows all details on one SIP user and the current status.\n" 13906 " Option \"load\" forces lookup of peer in realtime storage.\n"; 13907 return NULL; 13908 case CLI_GENERATE: 13909 return complete_sip_show_user(a->line, a->word, a->pos, a->n); 13910 } 13911 13912 if (a->argc < 4) 13913 return CLI_SHOWUSAGE; 13914 13915 /* Load from realtime storage? */ 13916 load_realtime = (a->argc == 5 && !strcmp(a->argv[4], "load")) ? TRUE : FALSE; 13917 13918 if ((user = find_peer(a->argv[3], NULL, load_realtime, FINDUSERS, FALSE))) { 13919 ao2_lock(user); 13920 ast_cli(a->fd, "\n\n"); 13921 ast_cli(a->fd, " * Name : %s\n", user->name); 13922 ast_cli(a->fd, " Secret : %s\n", ast_strlen_zero(user->secret)?"<Not set>":"<Set>"); 13923 ast_cli(a->fd, " MD5Secret : %s\n", ast_strlen_zero(user->md5secret)?"<Not set>":"<Set>"); 13924 ast_cli(a->fd, " Context : %s\n", user->context); 13925 ast_cli(a->fd, " Language : %s\n", user->language); 13926 if (!ast_strlen_zero(user->accountcode)) 13927 ast_cli(a->fd, " Accountcode : %s\n", user->accountcode); 13928 ast_cli(a->fd, " AMA flags : %s\n", ast_cdr_flags2str(user->amaflags)); 13929 ast_cli(a->fd, " Transfer mode: %s\n", transfermode2str(user->allowtransfer)); 13930 ast_cli(a->fd, " MaxCallBR : %d kbps\n", user->maxcallbitrate); 13931 ast_cli(a->fd, " CallingPres : %s\n", ast_describe_caller_presentation(user->callingpres)); 13932 ast_cli(a->fd, " Call limit : %d\n", user->call_limit); 13933 ast_cli(a->fd, " Callgroup : "); 13934 print_group(a->fd, user->callgroup, 0); 13935 ast_cli(a->fd, " Pickupgroup : "); 13936 print_group(a->fd, user->pickupgroup, 0); 13937 ast_cli(a->fd, " Callerid : %s\n", ast_callerid_merge(cbuf, sizeof(cbuf), user->cid_name, user->cid_num, "<unspecified>")); 13938 ast_cli(a->fd, " ACL : %s\n", cli_yesno(user->ha != NULL)); 13939 ast_cli(a->fd, " Sess-Timers : %s\n", stmode2str(user->stimer.st_mode_oper)); 13940 ast_cli(a->fd, " Sess-Refresh : %s\n", strefresher2str(user->stimer.st_ref)); 13941 ast_cli(a->fd, " Sess-Expires : %d secs\n", user->stimer.st_max_se); 13942 ast_cli(a->fd, " Sess-Min-SE : %d secs\n", user->stimer.st_min_se); 13943 13944 ast_cli(a->fd, " Codec Order : ("); 13945 print_codec_to_cli(a->fd, &user->prefs); 13946 ast_cli(a->fd, ")\n"); 13947 13948 ast_cli(a->fd, " Auto-Framing: %s \n", cli_yesno(user->autoframing)); 13949 if (user->chanvars) { 13950 ast_cli(a->fd, " Variables :\n"); 13951 for (v = user->chanvars ; v ; v = v->next) 13952 ast_cli(a->fd, " %s = %s\n", v->name, v->value); 13953 } 13954 13955 ast_cli(a->fd, "\n"); 13956 13957 ao2_unlock(user); 13958 unref_peer(user, "sip show user"); 13959 } else { 13960 ast_cli(a->fd, "User %s not found.\n", a->argv[3]); 13961 ast_cli(a->fd, "\n"); 13962 } 13963 13964 return CLI_SUCCESS; 13965 }
| static char* sip_show_users | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
CLI Command 'SIP Show Users'.
Definition at line 12767 of file chan_sip.c.
References ao2_iterator_init(), ao2_iterator_next, ao2_lock(), ao2_unlock(), ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_test_flag, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, cli_yesno(), ast_cli_entry::command, FALSE, ast_cli_args::fd, FORMAT, nat2str(), SIP_NAT, SIP_TYPE_USER, TRUE, unref_peer(), ast_cli_entry::usage, and user.
12768 { 12769 regex_t regexbuf; 12770 int havepattern = FALSE; 12771 struct ao2_iterator user_iter; 12772 struct sip_peer *user; 12773 12774 #define FORMAT "%-25.25s %-15.15s %-15.15s %-15.15s %-5.5s%-10.10s\n" 12775 12776 switch (cmd) { 12777 case CLI_INIT: 12778 e->command = "sip show users"; 12779 e->usage = 12780 "Usage: sip show users [like <pattern>]\n" 12781 " Lists all known SIP users.\n" 12782 " Optional regular expression pattern is used to filter the user list.\n"; 12783 return NULL; 12784 case CLI_GENERATE: 12785 return NULL; 12786 } 12787 12788 switch (a->argc) { 12789 case 5: 12790 if (!strcasecmp(a->argv[3], "like")) { 12791 if (regcomp(®exbuf, a->argv[4], REG_EXTENDED | REG_NOSUB)) 12792 return CLI_SHOWUSAGE; 12793 havepattern = TRUE; 12794 } else 12795 return CLI_SHOWUSAGE; 12796 case 3: 12797 break; 12798 default: 12799 return CLI_SHOWUSAGE; 12800 } 12801 12802 ast_cli(a->fd, FORMAT, "Username", "Secret", "Accountcode", "Def.Context", "ACL", "NAT"); 12803 12804 user_iter = ao2_iterator_init(peers, 0); 12805 while ((user = ao2_iterator_next(&user_iter))) { 12806 ao2_lock(user); 12807 if (!(user->type & SIP_TYPE_USER)) { 12808 ao2_unlock(user); 12809 unref_peer(user, "sip show users"); 12810 continue; 12811 } 12812 12813 if (havepattern && regexec(®exbuf, user->name, 0, NULL, 0)) { 12814 ao2_unlock(user); 12815 unref_peer(user, "sip show users"); 12816 continue; 12817 } 12818 12819 ast_cli(a->fd, FORMAT, user->name, 12820 user->secret, 12821 user->accountcode, 12822 user->context, 12823 cli_yesno(user->ha != NULL), 12824 nat2str(ast_test_flag(&user->flags[0], SIP_NAT))); 12825 ao2_unlock(user); 12826 unref_peer(user, "sip show users"); 12827 } 12828 12829 if (havepattern) 12830 regfree(®exbuf); 12831 12832 return CLI_SUCCESS; 12833 #undef FORMAT 12834 }
| static int sip_sipredirect | ( | struct sip_pvt * | p, | |
| const char * | dest | |||
| ) | [static] |
Transfer call before connect with a 302 redirect.
Definition at line 23182 of file chan_sip.c.
References ast_copy_string(), ast_log(), ast_strdupa, ast_string_field_build, ast_strlen_zero(), get_header(), sip_pvt::initreq, LOG_ERROR, sip_pvt::our_contact, sip_alreadygone(), sip_scheddestroy(), SIP_TRANS_TIMEOUT, strcasestr(), strsep(), and transmit_response_reliable().
Referenced by sip_transfer().
23183 { 23184 char *cdest; 23185 char *extension, *host, *port; 23186 char tmp[80]; 23187 23188 cdest = ast_strdupa(dest); 23189 23190 extension = strsep(&cdest, "@"); 23191 host = strsep(&cdest, ":"); 23192 port = strsep(&cdest, ":"); 23193 if (ast_strlen_zero(extension)) { 23194 ast_log(LOG_ERROR, "Missing mandatory argument: extension\n"); 23195 return 0; 23196 } 23197 23198 /* we'll issue the redirect message here */ 23199 if (!host) { 23200 char *localtmp; 23201 23202 ast_copy_string(tmp, get_header(&p->initreq, "To"), sizeof(tmp)); 23203 if (ast_strlen_zero(tmp)) { 23204 ast_log(LOG_ERROR, "Cannot retrieve the 'To' header from the original SIP request!\n"); 23205 return 0; 23206 } 23207 if ( ( (localtmp = strcasestr(tmp, "sip:")) || (localtmp = strcasestr(tmp, "sips:")) ) 23208 && (localtmp = strchr(localtmp, '@'))) { 23209 char lhost[80], lport[80]; 23210 23211 memset(lhost, 0, sizeof(lhost)); 23212 memset(lport, 0, sizeof(lport)); 23213 localtmp++; 23214 /* This is okey because lhost and lport are as big as tmp */ 23215 sscanf(localtmp, "%[^<>:; ]:%[^<>:; ]", lhost, lport); 23216 if (ast_strlen_zero(lhost)) { 23217 ast_log(LOG_ERROR, "Can't find the host address\n"); 23218 return 0; 23219 } 23220 host = ast_strdupa(lhost); 23221 if (!ast_strlen_zero(lport)) { 23222 port = ast_strdupa(lport); 23223 } 23224 } 23225 } 23226 23227 ast_string_field_build(p, our_contact, "Transfer <sip:%s@%s%s%s>", extension, host, port ? ":" : "", port ? port : ""); 23228 transmit_response_reliable(p, "302 Moved Temporarily", &p->initreq); 23229 23230 sip_scheddestroy(p, SIP_TRANS_TIMEOUT); /* Make sure we stop send this reply. */ 23231 sip_alreadygone(p); 23232 /* hangup here */ 23233 return 0; 23234 }
| static struct sip_st_dlg * sip_st_alloc | ( | struct sip_pvt *const | p | ) | [static] |
Allocate Session-Timers struct w/in dialog.
Definition at line 6190 of file chan_sip.c.
References ast_calloc, ast_log(), LOG_ERROR, sip_st_dlg::st_schedid, and sip_pvt::stimer.
Referenced by handle_request_invite(), and st_get_mode().
06191 { 06192 struct sip_st_dlg *stp; 06193 06194 if (p->stimer) { 06195 ast_log(LOG_ERROR, "Session-Timer struct already allocated\n"); 06196 return p->stimer; 06197 } 06198 06199 if (!(stp = ast_calloc(1, sizeof(struct sip_st_dlg)))) 06200 return NULL; 06201 06202 p->stimer = stp; 06203 06204 stp->st_schedid = -1; /* Session-Timers ast_sched scheduler id */ 06205 06206 return p->stimer; 06207 }
| static int sip_standard_port | ( | enum sip_transport | type, | |
| int | port | |||
| ) | [static] |
Returns the port to use for this socket.
| type | The type of transport used | |
| port | Port we are checking to see if it's the standard port. |
Definition at line 20029 of file chan_sip.c.
References SIP_TRANSPORT_TLS, STANDARD_SIP_PORT, and STANDARD_TLS_PORT.
Referenced by build_contact(), and initreqprep().
20030 { 20031 if (type & SIP_TRANSPORT_TLS) 20032 return port == STANDARD_TLS_PORT; 20033 else 20034 return port == STANDARD_SIP_PORT; 20035 }
| static int sip_t38_abort | ( | const void * | data | ) | [static] |
Definition at line 17793 of file chan_sip.c.
References change_t38_state(), dialog_unref(), T38_DISABLED, and transmit_response_reliable().
Referenced by handle_request_invite().
17794 { 17795 struct sip_pvt *p = (struct sip_pvt *) data; 17796 17797 change_t38_state(p, T38_DISABLED); 17798 transmit_response_reliable(p, "488 Not acceptable here", &p->initreq); 17799 p->t38id = -1; 17800 dialog_unref(p, "unref the dialog ptr from sip_t38_abort, because it held a dialog ptr"); 17801 17802 return 0; 17803 }
| static struct ast_tcptls_session_instance* sip_tcp_locate | ( | struct sockaddr_in * | s | ) | [static] |
Find thread for TCP/TLS session (based on IP/Port.
Definition at line 20042 of file chan_sip.c.
References ao2_ref, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_tcptls_session_instance::remote_address, and sip_threadinfo::tcptls_session.
Referenced by sip_prepare_socket().
20043 { 20044 struct sip_threadinfo *th; 20045 struct ast_tcptls_session_instance *tcptls_instance = NULL; 20046 20047 AST_LIST_LOCK(&threadl); 20048 AST_LIST_TRAVERSE(&threadl, th, list) { 20049 if ((s->sin_family == th->tcptls_session->remote_address.sin_family) && 20050 (s->sin_addr.s_addr == th->tcptls_session->remote_address.sin_addr.s_addr) && 20051 (s->sin_port == th->tcptls_session->remote_address.sin_port)) { 20052 tcptls_instance = (ao2_ref(th->tcptls_session, +1), th->tcptls_session); 20053 break; 20054 } 20055 } 20056 AST_LIST_UNLOCK(&threadl); 20057 20058 return tcptls_instance; 20059 }
| static void * sip_tcp_worker_fn | ( | void * | ) | [static] |
SIP TCP connection handler.
Definition at line 2360 of file chan_sip.c.
References _sip_tcp_helper_thread().
Referenced by sip_prepare_socket().
02361 { 02362 struct ast_tcptls_session_instance *tcptls_session = data; 02363 02364 return _sip_tcp_helper_thread(NULL, tcptls_session); 02365 }
| static int sip_transfer | ( | struct ast_channel * | ast, | |
| const char * | dest | |||
| ) | [static] |
Transfer SIP call.
Definition at line 5560 of file chan_sip.c.
References ast_channel::_state, AST_STATE_RING, sip_pvt_lock, sip_pvt_unlock, sip_sipredirect(), ast_channel::tech_pvt, and transmit_refer().
05561 { 05562 struct sip_pvt *p = ast->tech_pvt; 05563 int res; 05564 05565 if (dest == NULL) /* functions below do not take a NULL */ 05566 dest = ""; 05567 sip_pvt_lock(p); 05568 if (ast->_state == AST_STATE_RING) 05569 res = sip_sipredirect(p, dest); 05570 else 05571 res = transmit_refer(p, dest); 05572 sip_pvt_unlock(p); 05573 return res; 05574 }
| static char * sip_unregister | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Unregister (force expiration) a SIP peer in the registry via CLI.
Definition at line 14057 of file chan_sip.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_sip_unregister(), sip_peer::expire, expire_register(), ast_cli_args::fd, find_peer(), FINDPEERS, ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, ref_peer(), TRUE, unref_peer(), ast_cli_entry::usage, and ast_cli_args::word.
14058 { 14059 struct sip_peer *peer; 14060 int load_realtime = 0; 14061 14062 switch (cmd) { 14063 case CLI_INIT: 14064 e->command = "sip unregister"; 14065 e->usage = 14066 "Usage: sip unregister <peer>\n" 14067 " Unregister (force expiration) a SIP peer from the registry\n"; 14068 return NULL; 14069 case CLI_GENERATE: 14070 return complete_sip_unregister(a->line, a->word, a->pos, a->n); 14071 } 14072 14073 if (a->argc != 3) 14074 return CLI_SHOWUSAGE; 14075 14076 if ((peer = find_peer(a->argv[2], NULL, load_realtime, FINDPEERS, TRUE))) { 14077 if (peer->expire > 0) { 14078 expire_register(ref_peer(peer, "ref for expire_register")); 14079 ast_cli(a->fd, "Unregistered peer \'%s\'\n\n", a->argv[2]); 14080 } else { 14081 ast_cli(a->fd, "Peer %s not registered\n", a->argv[2]); 14082 } 14083 unref_peer(peer, "sip_unregister: unref_peer via sip_unregister: done with peer from find_peer call"); 14084 } else { 14085 ast_cli(a->fd, "Peer unknown: \'%s\'. Not unregistered.\n", a->argv[2]); 14086 } 14087 14088 return CLI_SUCCESS; 14089 }
| static int sip_uri_cmp | ( | const char * | input1, | |
| const char * | input2 | |||
| ) | [static] |
Definition at line 17710 of file chan_sip.c.
References ast_strdupa, S_OR, sip_uri_headers_cmp(), sip_uri_params_cmp(), and strsep().
Referenced by handle_request_invite().
17711 { 17712 char *uri1 = ast_strdupa(input1); 17713 char *uri2 = ast_strdupa(input2); 17714 char *host1; 17715 char *host2; 17716 char *params1; 17717 char *params2; 17718 char *headers1; 17719 char *headers2; 17720 17721 /* Strip off "sip:" from the URI. We know this is present 17722 * because it was checked back in parse_request() 17723 */ 17724 strsep(&uri1, ":"); 17725 strsep(&uri2, ":"); 17726 17727 if ((host1 = strchr(uri1, '@'))) { 17728 *host1++ = '\0'; 17729 } 17730 if ((host2 = strchr(uri2, '@'))) { 17731 *host2++ = '\0'; 17732 } 17733 17734 /* Check for mismatched username and passwords. This is the 17735 * only case-sensitive comparison of a SIP URI 17736 */ 17737 if ((host1 && !host2) || 17738 (host2 && !host1) || 17739 (host1 && host2 && strcmp(uri1, uri2))) { 17740 return 1; 17741 } 17742 17743 if (!host1) 17744 host1 = uri1; 17745 if (!host2) 17746 host2 = uri2; 17747 17748 /* Strip off the parameters and headers so we can compare 17749 * host and port 17750 */ 17751 17752 if ((params1 = strchr(host1, ';'))) { 17753 *params1++ = '\0'; 17754 } 17755 if ((params2 = strchr(host2, ';'))) { 17756 *params2++ = '\0'; 17757 } 17758 17759 /* Headers come after parameters, but there may be headers without 17760 * parameters, thus the S_OR 17761 */ 17762 if ((headers1 = strchr(S_OR(params1, host1), '?'))) { 17763 *headers1++ = '\0'; 17764 } 17765 if ((headers2 = strchr(S_OR(params2, host2), '?'))) { 17766 *headers2++ = '\0'; 17767 } 17768 17769 /* Now the host/port are properly isolated. We can get by with a string comparison 17770 * because the SIP URI checking rules have some interesting exceptions that make 17771 * this possible. I will note 2 in particular 17772 * 1. hostnames which resolve to the same IP address as well as a hostname and its 17773 * IP address are not considered a match with SIP URI's. 17774 * 2. If one URI specifies a port and the other does not, then the URIs do not match. 17775 * This includes if one URI explicitly contains port 5060 and the other implies it 17776 * by not having a port specified. 17777 */ 17778 17779 if (strcasecmp(host1, host2)) { 17780 return 1; 17781 } 17782 17783 /* Headers have easier rules to follow, so do those first */ 17784 if (sip_uri_headers_cmp(headers1, headers2)) { 17785 return 1; 17786 } 17787 17788 /* And now the parameters. Ugh */ 17789 return sip_uri_params_cmp(params1, params2); 17790 }
| static int sip_uri_headers_cmp | ( | const char * | input1, | |
| const char * | input2 | |||
| ) | [static] |
helper routine for sip_uri_cmp
This takes the "headers" from two SIP URIs and determines if the URIs match. The rules for headers is simple. If a header appears in one URI, then it must also appear in the other URI. The order in which the headers appear does not matter.
| input1 | Headers from URI 1 | |
| input2 | Headers from URI 2 |
Definition at line 17664 of file chan_sip.c.
References ast_strdupa, ast_strlen_zero(), strcasestr(), and strsep().
Referenced by sip_uri_cmp().
17665 { 17666 char *headers1 = NULL; 17667 char *headers2 = NULL; 17668 int zerolength1 = 0; 17669 int zerolength2 = 0; 17670 int different = 0; 17671 char *header1; 17672 17673 if (ast_strlen_zero(input1)) { 17674 zerolength1 = 1; 17675 } else { 17676 headers1 = ast_strdupa(input1); 17677 } 17678 17679 if (ast_strlen_zero(input2)) { 17680 zerolength2 = 1; 17681 } else { 17682 headers2 = ast_strdupa(input2); 17683 } 17684 17685 if ((zerolength1 && !zerolength2) || 17686 (zerolength2 && !zerolength1)) 17687 return 1; 17688 17689 if (zerolength1 && zerolength2) 17690 return 0; 17691 17692 /* At this point, we can definitively state that both inputs are 17693 * not zero-length. First, one more optimization. If the length 17694 * of the headers is not equal, then we definitely have no match 17695 */ 17696 if (strlen(headers1) != strlen(headers2)) { 17697 return 1; 17698 } 17699 17700 for (header1 = strsep(&headers1, "&"); header1; header1 = strsep(&headers1, "&")) { 17701 if (!strcasestr(headers2, header1)) { 17702 different = 1; 17703 break; 17704 } 17705 } 17706 17707 return different; 17708 }
| static int sip_uri_params_cmp | ( | const char * | input1, | |
| const char * | input2 | |||
| ) | [static] |
helper routine for sip_uri_cmp
This takes the parameters from two SIP URIs and determines if the URIs match. The rules for parameters *suck*. Here's a breakdown 1. If a parameter appears in both URIs, then they must have the same value in order for the URIs to match 2. If one URI has a user, maddr, ttl, or method parameter, then the other URI must also have that parameter and must have the same value in order for the URIs to match 3. All other headers appearing in only one URI are not considered when determining if URIs match
| input1 | Parameters from URI 1 | |
| input2 | Parameters from URI 2 |
Definition at line 17524 of file chan_sip.c.
References ast_strdupa, and ast_strlen_zero().
Referenced by sip_uri_cmp().
17525 { 17526 char *params1 = NULL; 17527 char *params2 = NULL; 17528 char *pos1; 17529 char *pos2; 17530 int zerolength1 = 0; 17531 int zerolength2 = 0; 17532 int maddrmatch = 0; 17533 int ttlmatch = 0; 17534 int usermatch = 0; 17535 int methodmatch = 0; 17536 17537 if (ast_strlen_zero(input1)) { 17538 zerolength1 = 1; 17539 } else { 17540 params1 = ast_strdupa(input1); 17541 } 17542 if (ast_strlen_zero(input2)) { 17543 zerolength2 = 1; 17544 } else { 17545 params2 = ast_strdupa(input2); 17546 } 17547 17548 /*Quick optimization. If both params are zero-length, then 17549 * they match 17550 */ 17551 if (zerolength1 && zerolength2) { 17552 return 0; 17553 } 17554 17555 pos1 = params1; 17556 while (!ast_strlen_zero(pos1)) { 17557 char *name1 = pos1; 17558 char *value1 = strchr(pos1, '='); 17559 char *semicolon1 = strchr(pos1, ';'); 17560 int matched = 0; 17561 if (semicolon1) { 17562 *semicolon1++ = '\0'; 17563 } 17564 if (!value1) { 17565 goto fail; 17566 } 17567 *value1++ = '\0'; 17568 /* Checkpoint reached. We have the name and value parsed for param1 17569 * We have to duplicate params2 each time through the second loop 17570 * or else we can't search and replace the semicolons with \0 each 17571 * time 17572 */ 17573 pos2 = ast_strdupa(params2); 17574 while (!ast_strlen_zero(pos2)) { 17575 char *name2 = pos2; 17576 char *value2 = strchr(pos2, '='); 17577 char *semicolon2 = strchr(pos2, ';'); 17578 if (semicolon2) { 17579 *semicolon2++ = '\0'; 17580 } 17581 if (!value2) { 17582 goto fail; 17583 } 17584 *value2++ = '\0'; 17585 if (!strcasecmp(name1, name2)) { 17586 if (strcasecmp(value1, value2)) { 17587 goto fail; 17588 } else { 17589 matched = 1; 17590 break; 17591 } 17592 } 17593 pos2 = semicolon2; 17594 } 17595 /* Need to see if the parameter we're looking at is one of the 'must-match' parameters */ 17596 if (!strcasecmp(name1, "maddr")) { 17597 if (matched) { 17598 maddrmatch = 1; 17599 } else { 17600 goto fail; 17601 } 17602 } else if (!strcasecmp(name1, "ttl")) { 17603 if (matched) { 17604 ttlmatch = 1; 17605 } else { 17606 goto fail; 17607 } 17608 } else if (!strcasecmp(name1, "user")) { 17609 if (matched) { 17610 usermatch = 1; 17611 } else { 17612 goto fail; 17613 } 17614 } else if (!strcasecmp(name1, "method")) { 17615 if (matched) { 17616 methodmatch = 1; 17617 } else { 17618 goto fail; 17619 } 17620 } 17621 pos1 = semicolon1; 17622 } 17623 17624 /* We've made it out of that horrible O(m*n) construct and there are no 17625 * failures yet. We're not done yet, though, because params2 could have 17626 * an maddr, ttl, user, or method header and params1 did not. 17627 */ 17628 pos2 = params2; 17629 while (!ast_strlen_zero(pos2)) { 17630 char *name2 = pos2; 17631 char *value2 = strchr(pos2, '='); 17632 char *semicolon2 = strchr(pos2, ';'); 17633 if (semicolon2) { 17634 *semicolon2++ = '\0'; 17635 } 17636 if (!value2) { 17637 goto fail; 17638 } 17639 *value2++ = '\0'; 17640 if ((!strcasecmp(name2, "maddr") && !maddrmatch) || 17641 (!strcasecmp(name2, "ttl") && !ttlmatch) || 17642 (!strcasecmp(name2, "user") && !usermatch) || 17643 (!strcasecmp(name2, "method") && !methodmatch)) { 17644 goto fail; 17645 } 17646 } 17647 return 0; 17648 17649 fail: 17650 return 1; 17651 }
| static int sip_write | ( | struct ast_channel * | ast, | |
| struct ast_frame * | frame | |||
| ) | [static] |
Send frame to media channel (rtp).
Definition at line 5356 of file chan_sip.c.
References ast_channel::_state, AST_FORMAT_AUDIO_MASK, AST_FRAME_IMAGE, AST_FRAME_MODEM, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_getformatname_multiple(), ast_log(), ast_rtp_new_source(), ast_rtp_write(), ast_set_flag, AST_STATE_UP, ast_test_flag, ast_udptl_write(), change_t38_state(), FALSE, ast_frame::frametype, INV_EARLY_MEDIA, LOG_WARNING, ast_channel::nativeformats, ast_channel::readformat, red_buffer_t140(), SIP_OUTGOING, SIP_PAGE2_T38SUPPORT, SIP_PROGRESS_SENT, sip_pvt_lock, sip_pvt_unlock, ast_frame::subclass, T38_DISABLED, T38_ENABLED, T38_LOCAL_REINVITE, ast_channel::tech_pvt, transmit_reinvite_with_sdp(), transmit_response_with_sdp(), TRUE, ast_channel::writeformat, and XMIT_UNRELIABLE.
05357 { 05358 struct sip_pvt *p = ast->tech_pvt; 05359 int res = 0; 05360 05361 switch (frame->frametype) { 05362 case AST_FRAME_VOICE: 05363 if (!(frame->subclass & ast->nativeformats)) { 05364 char s1[512], s2[512], s3[512]; 05365 ast_log(LOG_WARNING, "Asked to transmit frame type %d, while native formats is %s(%d) read/write = %s(%d)/%s(%d)\n", 05366 frame->subclass, 05367 ast_getformatname_multiple(s1, sizeof(s1) - 1, ast->nativeformats & AST_FORMAT_AUDIO_MASK), 05368 ast->nativeformats & AST_FORMAT_AUDIO_MASK, 05369 ast_getformatname_multiple(s2, sizeof(s2) - 1, ast->readformat), 05370 ast->readformat, 05371 ast_getformatname_multiple(s3, sizeof(s3) - 1, ast->writeformat), 05372 ast->writeformat); 05373 return 0; 05374 } 05375 if (p) { 05376 sip_pvt_lock(p); 05377 if (p->rtp) { 05378 /* If channel is not up, activate early media session */ 05379 if ((ast->_state != AST_STATE_UP) && 05380 !ast_test_flag(&p->flags[0], SIP_PROGRESS_SENT) && 05381 !ast_test_flag(&p->flags[0], SIP_OUTGOING)) { 05382 ast_rtp_new_source(p->rtp); 05383 p->invitestate = INV_EARLY_MEDIA; 05384 transmit_response_with_sdp(p, "183 Session Progress", &p->initreq, XMIT_UNRELIABLE, FALSE); 05385 ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT); 05386 } else if (p->t38.state == T38_ENABLED && !p->t38.direct) { 05387 change_t38_state(p, T38_DISABLED); 05388 transmit_reinvite_with_sdp(p, FALSE, FALSE); 05389 } else { 05390 p->lastrtptx = time(NULL); 05391 res = ast_rtp_write(p->rtp, frame); 05392 } 05393 } 05394 sip_pvt_unlock(p); 05395 } 05396 break; 05397 case AST_FRAME_VIDEO: 05398 if (p) { 05399 sip_pvt_lock(p); 05400 if (p->vrtp) { 05401 /* Activate video early media */ 05402 if ((ast->_state != AST_STATE_UP) && 05403 !ast_test_flag(&p->flags[0], SIP_PROGRESS_SENT) && 05404 !ast_test_flag(&p->flags[0], SIP_OUTGOING)) { 05405 p->invitestate = INV_EARLY_MEDIA; 05406 transmit_response_with_sdp(p, "183 Session Progress", &p->initreq, XMIT_UNRELIABLE, FALSE); 05407 ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT); 05408 } 05409 p->lastrtptx = time(NULL); 05410 res = ast_rtp_write(p->vrtp, frame); 05411 } 05412 sip_pvt_unlock(p); 05413 } 05414 break; 05415 case AST_FRAME_TEXT: 05416 if (p) { 05417 sip_pvt_lock(p); 05418 if (p->red) { 05419 red_buffer_t140(p->trtp, frame); 05420 } else { 05421 if (p->trtp) { 05422 /* Activate text early media */ 05423 if ((ast->_state != AST_STATE_UP) && 05424 !ast_test_flag(&p->flags[0], SIP_PROGRESS_SENT) && 05425 !ast_test_flag(&p->flags[0], SIP_OUTGOING)) { 05426 p->invitestate = INV_EARLY_MEDIA; 05427 transmit_response_with_sdp(p, "183 Session Progress", &p->initreq, XMIT_UNRELIABLE, FALSE); 05428 ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT); 05429 } 05430 p->lastrtptx = time(NULL); 05431 res = ast_rtp_write(p->trtp, frame); 05432 } 05433 } 05434 sip_pvt_unlock(p); 05435 } 05436 break; 05437 case AST_FRAME_IMAGE: 05438 return 0; 05439 break; 05440 case AST_FRAME_MODEM: 05441 if (p) { 05442 sip_pvt_lock(p); 05443 /* UDPTL requires two-way communication, so early media is not needed here. 05444 we simply forget the frames if we get modem frames before the bridge is up. 05445 Fax will re-transmit. 05446 */ 05447 if (ast->_state == AST_STATE_UP) { 05448 if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT) && p->t38.state == T38_DISABLED) { 05449 if (!p->pendinginvite) { 05450 change_t38_state(p, T38_LOCAL_REINVITE); 05451 transmit_reinvite_with_sdp(p, TRUE, FALSE); 05452 } 05453 } else if (p->udptl && p->t38.state == T38_ENABLED) { 05454 res = ast_udptl_write(p->udptl, frame); 05455 } 05456 } 05457 sip_pvt_unlock(p); 05458 } 05459 break; 05460 default: 05461 ast_log(LOG_WARNING, "Can't send %d type frames with SIP write\n", frame->frametype); 05462 return 0; 05463 } 05464 05465 return res; 05466 }
| static int sipsock_read | ( | int * | id, | |
| int | fd, | |||
| short | events, | |||
| void * | ignore | |||
| ) | [static] |
Read data from SIP socket.
Definition at line 19868 of file chan_sip.c.
References AST_DYNSTR_BUILD_FAILED, ast_free, ast_log(), ast_str_create(), ast_str_set(), errno, handle_request_do(), len(), LOG_NOTICE, LOG_WARNING, SIP_MIN_PACKET, SIP_TRANSPORT_UDP, and sipsock.
Referenced by do_monitor().
19869 { 19870 struct sip_request req; 19871 struct sockaddr_in sin = { 0, }; 19872 int res; 19873 socklen_t len = sizeof(sin); 19874 static char readbuf[65535]; 19875 19876 memset(&req, 0, sizeof(req)); 19877 res = recvfrom(fd, readbuf, sizeof(readbuf) - 1, 0, (struct sockaddr *)&sin, &len); 19878 if (res < 0) { 19879 #if !defined(__FreeBSD__) 19880 if (errno == EAGAIN) 19881 ast_log(LOG_NOTICE, "SIP: Received packet with bad UDP checksum\n"); 19882 else 19883 #endif 19884 if (errno != ECONNREFUSED) 19885 ast_log(LOG_WARNING, "Recv error: %s\n", strerror(errno)); 19886 return 1; 19887 } 19888 19889 readbuf[res] = '\0'; 19890 19891 if (!(req.data = ast_str_create(SIP_MIN_PACKET))) { 19892 return 1; 19893 } 19894 19895 if (ast_str_set(&req.data, 0, "%s", readbuf) == AST_DYNSTR_BUILD_FAILED) { 19896 return -1; 19897 } 19898 19899 req.len = res; 19900 req.socket.fd = sipsock; 19901 req.socket.type = SIP_TRANSPORT_UDP; 19902 req.socket.tcptls_session = NULL; 19903 req.socket.port = bindaddr.sin_port; 19904 19905 handle_request_do(&req, &sin); 19906 if (req.data) { 19907 ast_free(req.data); 19908 req.data = NULL; 19909 } 19910 19911 return 1; 19912 }
Get the session-timer mode.
| p | pointer to the SIP dialog |
Definition at line 20731 of file chan_sip.c.
References FALSE, find_peer(), FINDPEERS, sip_pvt::peername, pp, SESSION_TIMER_MODE_INVALID, sip_st_alloc(), sip_st_dlg::st_cached_mode, sip_pvt::stimer, TRUE, and unref_peer().
Referenced by handle_request_invite(), handle_response_invite(), and transmit_invite().
20732 { 20733 if (!p->stimer) 20734 sip_st_alloc(p); 20735 20736 if (p->stimer->st_cached_mode != SESSION_TIMER_MODE_INVALID) 20737 return p->stimer->st_cached_mode; 20738 20739 if (p->peername) { 20740 struct sip_peer *pp = find_peer(p->peername, NULL, TRUE, FINDPEERS, FALSE); 20741 if (pp) { 20742 p->stimer->st_cached_mode = pp->stimer.st_mode_oper; 20743 unref_peer(pp, "unref peer pointer from find_peer call in st_get_mode"); 20744 return pp->stimer.st_mode_oper; 20745 } 20746 } 20747 20748 p->stimer->st_cached_mode = global_st_mode; 20749 return global_st_mode; 20750 }
| enum st_refresher st_get_refresher | ( | struct sip_pvt * | p | ) | [static] |
Get the entity (UAC or UAS) that's acting as the session-timer refresher.
| p | pointer to the SIP dialog |
Definition at line 20709 of file chan_sip.c.
References FALSE, find_peer(), FINDPEERS, sip_pvt::peername, pp, SESSION_TIMER_REFRESHER_AUTO, sip_st_dlg::st_cached_ref, sip_pvt::stimer, TRUE, and unref_peer().
Referenced by handle_request_invite().
20710 { 20711 if (p->stimer->st_cached_ref != SESSION_TIMER_REFRESHER_AUTO) 20712 return p->stimer->st_cached_ref; 20713 20714 if (p->peername) { 20715 struct sip_peer *pp = find_peer(p->peername, NULL, TRUE, FINDPEERS, FALSE); 20716 if (pp) { 20717 p->stimer->st_cached_ref = pp->stimer.st_ref; 20718 unref_peer(pp, "unref peer pointer from find_peer call in st_get_refresher"); 20719 return pp->stimer.st_ref; 20720 } 20721 } 20722 20723 p->stimer->st_cached_ref = global_st_refresher; 20724 return global_st_refresher; 20725 }
| int st_get_se | ( | struct sip_pvt * | p, | |
| int | max | |||
| ) | [static] |
Get Max or Min SE (session timer expiry).
| p | pointer to the SIP dialog | |
| max | if true, get max se, otherwise min se |
Definition at line 20674 of file chan_sip.c.
References FALSE, find_peer(), FINDPEERS, sip_pvt::peername, pp, sip_st_dlg::st_cached_max_se, sip_st_dlg::st_cached_min_se, sip_pvt::stimer, TRUE, and unref_peer().
Referenced by handle_request_invite(), reqprep(), and transmit_invite().
20675 { 20676 if (max == TRUE) { 20677 if (p->stimer->st_cached_max_se) { 20678 return p->stimer->st_cached_max_se; 20679 } else if (p->peername) { 20680 struct sip_peer *pp = find_peer(p->peername, NULL, TRUE, FINDPEERS, FALSE); 20681 if (pp) { 20682 p->stimer->st_cached_max_se = pp->stimer.st_max_se; 20683 unref_peer(pp, "unref peer pointer from find_peer call in st_get_se"); 20684 return (p->stimer->st_cached_max_se); 20685 } 20686 } 20687 p->stimer->st_cached_max_se = global_max_se; 20688 return (p->stimer->st_cached_max_se); 20689 } else { 20690 if (p->stimer->st_cached_min_se) { 20691 return p->stimer->st_cached_min_se; 20692 } else if (p->peername) { 20693 struct sip_peer *pp = find_peer(p->peername, NULL, TRUE, FINDPEERS, FALSE); 20694 if (pp) { 20695 p->stimer->st_cached_min_se = pp->stimer.st_min_se; 20696 unref_peer(pp, "unref peer pointer from find_peer call in st_get_se (2)"); 20697 return (p->stimer->st_cached_min_se); 20698 } 20699 } 20700 p->stimer->st_cached_min_se = global_min_se; 20701 return (p->stimer->st_cached_min_se); 20702 } 20703 }
| static void start_session_timer | ( | struct sip_pvt * | p | ) | [static] |
Session-Timers: Start session timer.
Definition at line 20481 of file chan_sip.c.
References ast_debug, ast_log(), ast_sched_add(), sip_pvt::callid, dialog_ref(), dialog_unref(), LOG_ERROR, LOG_WARNING, proc_session_timer(), sched, sip_st_dlg::st_interval, sip_st_dlg::st_schedid, and sip_pvt::stimer.
Referenced by handle_request_invite(), handle_response_invite(), and restart_session_timer().
20482 { 20483 if (!p->stimer) { 20484 ast_log(LOG_WARNING, "Null stimer in start_session_timer - %s\n", p->callid); 20485 return; 20486 } 20487 20488 p->stimer->st_schedid = ast_sched_add(sched, p->stimer->st_interval * 1000 / 2, proc_session_timer, 20489 dialog_ref(p, "adding session timer ref")); 20490 if (p->stimer->st_schedid < 0) { 20491 dialog_unref(p, "removing session timer ref"); 20492 ast_log(LOG_ERROR, "ast_sched_add failed.\n"); 20493 } 20494 ast_debug(2, "Session timer started: %d - %s\n", p->stimer->st_schedid, p->callid); 20495 }
| static const char* stmode2str | ( | enum st_mode | m | ) | [static] |
Definition at line 12667 of file chan_sip.c.
References map_x_s(), and stmodes.
Referenced by _sip_show_peer(), sip_show_channel(), sip_show_settings(), and sip_show_user().
| static void stop_media_flows | ( | struct sip_pvt * | p | ) | [static] |
Immediately stop RTP, VRTP and UDPTL as applicable.
Definition at line 16469 of file chan_sip.c.
References ast_rtp_stop(), ast_udptl_stop(), sip_pvt::rtp, sip_pvt::trtp, sip_pvt::udptl, and sip_pvt::vrtp.
Referenced by handle_request_bye(), handle_request_cancel(), handle_response(), and sip_hangup().
16470 { 16471 /* Immediately stop RTP, VRTP and UDPTL as applicable */ 16472 if (p->rtp) 16473 ast_rtp_stop(p->rtp); 16474 if (p->vrtp) 16475 ast_rtp_stop(p->vrtp); 16476 if (p->trtp) 16477 ast_rtp_stop(p->trtp); 16478 if (p->udptl) 16479 ast_udptl_stop(p->udptl); 16480 }
| static void stop_session_timer | ( | struct sip_pvt * | p | ) | [static] |
Session-Timers: Stop session timer.
Definition at line 20464 of file chan_sip.c.
References ast_debug, ast_log(), AST_SCHED_DEL_UNREF, sip_pvt::callid, dialog_unref(), FALSE, LOG_WARNING, sched, sip_st_dlg::st_active, sip_st_dlg::st_schedid, sip_pvt::stimer, and TRUE.
Referenced by handle_request_bye(), proc_session_timer(), sip_hangup(), and sip_scheddestroy().
20465 { 20466 if (!p->stimer) { 20467 ast_log(LOG_WARNING, "Null stimer in stop_session_timer - %s\n", p->callid); 20468 return; 20469 } 20470 20471 if (p->stimer->st_active == TRUE) { 20472 p->stimer->st_active = FALSE; 20473 AST_SCHED_DEL_UNREF(sched, p->stimer->st_schedid, 20474 dialog_unref(p, "removing session timer ref")); 20475 ast_debug(2, "Session timer stopped: %d - %s\n", p->stimer->st_schedid, p->callid); 20476 } 20477 }
| static int str2dtmfmode | ( | const char * | str | ) | [static] |
| static enum st_mode str2stmode | ( | const char * | s | ) | [static] |
Definition at line 12672 of file chan_sip.c.
References map_s_x(), and stmodes.
Referenced by build_peer().
| static enum st_refresher str2strefresher | ( | const char * | s | ) | [static] |
Definition at line 12690 of file chan_sip.c.
References map_s_x(), and strefreshers.
Referenced by build_peer().
12691 { 12692 return map_s_x(strefreshers, s, -1); 12693 }
| static const char * strefresher2str | ( | enum st_refresher | r | ) | [static] |
Definition at line 12685 of file chan_sip.c.
References map_x_s(), and strefreshers.
Referenced by _sip_show_peer(), reqprep(), respprep(), sip_show_channel(), sip_show_settings(), and sip_show_user().
12686 { 12687 return map_x_s(strefreshers, r, "Unknown"); 12688 }
| static const char * subscription_type2str | ( | enum subscriptiontype | subtype | ) | [static] |
Show subscription type in string format.
Definition at line 14373 of file chan_sip.c.
References ARRAY_LEN, subscription_types, and cfsubscription_types::text.
Referenced by show_channels_cb(), and sip_show_channel().
14374 { 14375 int i; 14376 14377 for (i = 1; i < ARRAY_LEN(subscription_types); i++) { 14378 if (subscription_types[i].type == subtype) { 14379 return subscription_types[i].text; 14380 } 14381 } 14382 return subscription_types[0].text; 14383 }
| static int t38_get_rate | ( | int | t38cap | ) | [static] |
Get Max T.38 Transmission rate from T38 capabilities.
Definition at line 8507 of file chan_sip.c.
References ast_debug, T38FAX_RATE_12000, T38FAX_RATE_14400, T38FAX_RATE_2400, T38FAX_RATE_4800, T38FAX_RATE_7200, and T38FAX_RATE_9600.
Referenced by add_sdp().
08508 { 08509 int maxrate = (t38cap & (T38FAX_RATE_14400 | T38FAX_RATE_12000 | T38FAX_RATE_9600 | T38FAX_RATE_7200 | T38FAX_RATE_4800 | T38FAX_RATE_2400)); 08510 08511 if (maxrate & T38FAX_RATE_14400) { 08512 ast_debug(2, "T38MaxBitRate 14400 found\n"); 08513 return 14400; 08514 } else if (maxrate & T38FAX_RATE_12000) { 08515 ast_debug(2, "T38MaxBitRate 12000 found\n"); 08516 return 12000; 08517 } else if (maxrate & T38FAX_RATE_9600) { 08518 ast_debug(2, "T38MaxBitRate 9600 found\n"); 08519 return 9600; 08520 } else if (maxrate & T38FAX_RATE_7200) { 08521 ast_debug(2, "T38MaxBitRate 7200 found\n"); 08522 return 7200; 08523 } else if (maxrate & T38FAX_RATE_4800) { 08524 ast_debug(2, "T38MaxBitRate 4800 found\n"); 08525 return 4800; 08526 } else if (maxrate & T38FAX_RATE_2400) { 08527 ast_debug(2, "T38MaxBitRate 2400 found\n"); 08528 return 2400; 08529 } else { 08530 ast_debug(2, "Strange, T38MaxBitRate NOT found in peers T38 SDP.\n"); 08531 return 0; 08532 } 08533 }
| static struct sip_peer * temp_peer | ( | const char * | name | ) | [static] |
Create temporary peer (used in autocreatepeer mode).
Definition at line 21526 of file chan_sip.c.
References ao2_t_alloc, ast_atomic_fetchadd_int(), ast_copy_string(), default_prefs, reg_source_db(), set_peer_defaults(), sip_destroy_peer_fn(), and TRUE.
Referenced by register_verify().
21527 { 21528 struct sip_peer *peer; 21529 21530 if (!(peer = ao2_t_alloc(sizeof(*peer), sip_destroy_peer_fn, "allocate a peer struct"))) 21531 return NULL; 21532 21533 ast_atomic_fetchadd_int(&apeerobjs, 1); 21534 set_peer_defaults(peer); 21535 21536 ast_copy_string(peer->name, name, sizeof(peer->name)); 21537 21538 peer->selfdestruct = TRUE; 21539 peer->host_dynamic = TRUE; 21540 peer->prefs = default_prefs; 21541 reg_source_db(peer); 21542 21543 return peer; 21544 }
| static void temp_pvt_cleanup | ( | void * | ) | [static] |
Definition at line 8191 of file chan_sip.c.
References ast_free, and ast_string_field_free_memory.
08192 { 08193 struct sip_pvt *p = data; 08194 08195 ast_string_field_free_memory(p); 08196 08197 ast_free(data); 08198 }
| static int temp_pvt_init | ( | void * | ) | [static] |
Definition at line 8183 of file chan_sip.c.
References ast_string_field_init, and sip_pvt::do_history.
08184 { 08185 struct sip_pvt *p = data; 08186 08187 p->do_history = 0; /* XXX do we need it ? isn't already all 0 ? */ 08188 return ast_string_field_init(p, 512); 08189 }
| static char* terminate_uri | ( | char * | uri | ) | [static] |
Terminate the uri at the first ';' or space. Technically we should ignore escaped space per RFC3261 (19.1.1 etc) but don't do it for the time being. Remember the uri format is:
* * sip:user:password@host:port;uri-parameters?headers * sips:user:password@host:port;uri-parameters?headers * *
Definition at line 11239 of file chan_sip.c.
Referenced by check_user_full(), and register_verify().
11240 { 11241 char *t = uri; 11242 while (*t && *t > ' ' && *t != ';') 11243 t++; 11244 *t = '\0'; 11245 return uri; 11246 }
| static char * transfermode2str | ( | enum transfermodes | mode | ) | const [static] |
Convert transfer mode to text string.
Definition at line 12611 of file chan_sip.c.
References TRANSFER_CLOSED, and TRANSFER_OPENFORALL.
Referenced by _sip_show_peer(), sip_show_channel(), sip_show_settings(), and sip_show_user().
12612 { 12613 if (mode == TRANSFER_OPENFORALL) 12614 return "open"; 12615 else if (mode == TRANSFER_CLOSED) 12616 return "closed"; 12617 return "strict"; 12618 }
| static void transmit_fake_auth_response | ( | struct sip_pvt * | p, | |
| int | sipmethod, | |||
| struct sip_request * | req, | |||
| enum xmittype | reliable | |||
| ) | [static] |
Send a fake 401 Unauthorized response when the administrator wants to hide the names of local devices from fishers.
Definition at line 11136 of file chan_sip.c.
References AST_DYNSTR_BUILD_FAILED, ast_random(), ast_skip_blanks(), ast_str_set(), ast_str_thread_get(), ast_string_field_build, ast_strlen_zero(), buf, check_auth_buf, CHECK_AUTH_BUF_INITLEN, DEFAULT_TRANS_TIMEOUT, get_header(), sip_request::ignore, sip_pvt::initreq, sip_pvt::randdata, s, SIP_REGISTER, sip_scheddestroy(), SIP_SUBSCRIBE, strsep(), transmit_response(), and transmit_response_with_auth().
Referenced by handle_request_invite(), handle_request_subscribe(), and register_verify().
11137 { 11138 /* We have to emulate EXACTLY what we'd get with a good peer 11139 * and a bad password, or else we leak information. */ 11140 const char *response = "407 Proxy Authentication Required"; 11141 const char *reqheader = "Proxy-Authorization"; 11142 const char *respheader = "Proxy-Authenticate"; 11143 const char *authtoken; 11144 struct ast_str *buf; 11145 char *c; 11146 11147 /* table of recognised keywords, and their value in the digest */ 11148 enum keys { K_NONCE, K_LAST }; 11149 struct x { 11150 const char *key; 11151 const char *s; 11152 } *i, keys[] = { 11153 [K_NONCE] = { "nonce=", "" }, 11154 [K_LAST] = { NULL, NULL} 11155 }; 11156 11157 if (sipmethod == SIP_REGISTER || sipmethod == SIP_SUBSCRIBE) { 11158 response = "401 Unauthorized"; 11159 reqheader = "Authorization"; 11160 respheader = "WWW-Authenticate"; 11161 } 11162 authtoken = get_header(req, reqheader); 11163 if (req->ignore && !ast_strlen_zero(p->randdata) && ast_strlen_zero(authtoken)) { 11164 /* This is a retransmitted invite/register/etc, don't reconstruct authentication 11165 * information */ 11166 transmit_response_with_auth(p, response, req, p->randdata, 0, respheader, 0); 11167 /* Schedule auto destroy in 32 seconds (according to RFC 3261) */ 11168 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 11169 return; 11170 } else if (ast_strlen_zero(p->randdata) || ast_strlen_zero(authtoken)) { 11171 /* We have no auth, so issue challenge and request authentication */ 11172 ast_string_field_build(p, randdata, "%08lx", ast_random()); /* Create nonce for challenge */ 11173 transmit_response_with_auth(p, response, req, p->randdata, 0, respheader, 0); 11174 /* Schedule auto destroy in 32 seconds */ 11175 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 11176 return; 11177 } 11178 11179 if (!(buf = ast_str_thread_get(&check_auth_buf, CHECK_AUTH_BUF_INITLEN))) { 11180 transmit_response(p, "403 Forbidden (Bad auth)", &p->initreq); 11181 return; 11182 } 11183 11184 /* Make a copy of the response and parse it */ 11185 if (ast_str_set(&buf, 0, "%s", authtoken) == AST_DYNSTR_BUILD_FAILED) { 11186 transmit_response(p, "403 Forbidden (Bad auth)", &p->initreq); 11187 return; 11188 } 11189 11190 c = buf->str; 11191 11192 while (c && *(c = ast_skip_blanks(c))) { /* lookup for keys */ 11193 for (i = keys; i->key != NULL; i++) { 11194 const char *separator = ","; /* default */ 11195 11196 if (strncasecmp(c, i->key, strlen(i->key)) != 0) { 11197 continue; 11198 } 11199 /* Found. Skip keyword, take text in quotes or up to the separator. */ 11200 c += strlen(i->key); 11201 if (*c == '"') { /* in quotes. Skip first and look for last */ 11202 c++; 11203 separator = "\""; 11204 } 11205 i->s = c; 11206 strsep(&c, separator); 11207 break; 11208 } 11209 if (i->key == NULL) { /* not found, jump after space or comma */ 11210 strsep(&c, " ,"); 11211 } 11212 } 11213 11214 /* Verify nonce from request matches our nonce. If not, send 401 with new nonce */ 11215 if (strcasecmp(p->randdata, keys[K_NONCE].s)) { 11216 if (!req->ignore) { 11217 ast_string_field_build(p, randdata, "%08lx", ast_random()); 11218 } 11219 transmit_response_with_auth(p, response, req, p->randdata, reliable, respheader, FALSE); 11220 11221 /* Schedule auto destroy in 32 seconds */ 11222 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 11223 } else { 11224 transmit_response(p, "403 Forbidden (Bad auth)", &p->initreq); 11225 } 11226 }
| static int transmit_info_with_digit | ( | struct sip_pvt * | p, | |
| const char | digit, | |||
| unsigned int | duration | |||
| ) | [static] |
Send SIP INFO dtmf message, see Cisco documentation on cisco.com.
Definition at line 10292 of file chan_sip.c.
References add_digit(), ast_test_flag, sip_pvt::flags, sip_pvt::ocseq, reqprep(), send_request(), SIP_DTMF, SIP_DTMF_SHORTINFO, SIP_INFO, and XMIT_RELIABLE.
Referenced by sip_senddigit_end().
10293 { 10294 struct sip_request req; 10295 10296 reqprep(&req, p, SIP_INFO, 0, 1); 10297 add_digit(&req, digit, duration, (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_SHORTINFO)); 10298 return send_request(p, &req, XMIT_RELIABLE, p->ocseq); 10299 }
| static int transmit_info_with_vidupdate | ( | struct sip_pvt * | p | ) | [static] |
Send SIP INFO with video update request.
Definition at line 10302 of file chan_sip.c.
References add_vidupdate(), sip_pvt::ocseq, reqprep(), send_request(), SIP_INFO, and XMIT_RELIABLE.
Referenced by sip_indicate().
10303 { 10304 struct sip_request req; 10305 10306 reqprep(&req, p, SIP_INFO, 0, 1); 10307 add_vidupdate(&req); 10308 return send_request(p, &req, XMIT_RELIABLE, p->ocseq); 10309 }
| static int transmit_invite | ( | struct sip_pvt * | p, | |
| int | sipmethod, | |||
| int | sdp, | |||
| int | init | |||
| ) | [static] |
Build REFER/INVITE/OPTIONS message and transmit it.
| init | 0 = Prepare request within dialog, 1= prepare request, new branch, 2= prepare new request and new dialog. do_proxy_auth calls this with init!=2 | |
| p | sip_pvt structure | |
| sdp | unknown | |
| sipmethod | unknown |
Definition at line 9390 of file chan_sip.c.
References add_header(), add_header_contentLength(), add_sdp(), sip_invite_param::addsipheaders, ALLOWED_METHODS, append_date(), ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_debug, AST_LIST_TRAVERSE, ast_log(), ast_random(), ast_skip_blanks(), ast_strdupa, ast_strlen_zero(), ast_udptl_offered_from_local(), ast_unescape_semicolon(), ast_var_name(), ast_var_value(), sip_invite_param::auth, sip_invite_param::authheader, sip_pvt::branch, buf, build_via(), chan, ast_var_t::entries, FALSE, sip_request::header, sip_request::headers, initialize_initreq(), sip_pvt::initreq, initreqprep(), sip_pvt::invite_branch, sip_pvt::lastinvite, LOG_WARNING, sip_request::method, ast_channel::name, sip_pvt::notify_headers, sip_pvt::ocseq, sip_pvt::options, sip_pvt::owner, sip_pvt::refer, sip_refer::refer_to, sip_refer::referred_by, sip_refer::referred_by_name, sip_invite_param::replaces, reqprep(), sip_pvt::rtp, send_request(), SESSION_TIMER_MODE_ORIGINATE, SIP_REFER, SIPBUFSIZE, sip_st_dlg::st_active, st_get_mode(), st_get_se(), sip_st_dlg::st_interval, t38properties::state, sip_pvt::stimer, SUPPORTED_EXTENSIONS, sip_pvt::t38, T38_LOCAL_REINVITE, TRUE, sip_pvt::udptl, var, ast_channel::varshead, XMIT_CRITICAL, and XMIT_RELIABLE.
Referenced by do_proxy_auth(), handle_request_invite(), proc_422_rsp(), sip_call(), and sip_poke_peer().
09391 { 09392 struct sip_request req; 09393 struct ast_variable *var; 09394 09395 req.method = sipmethod; 09396 if (init) {/* Bump branch even on initial requests */ 09397 p->branch ^= ast_random(); 09398 p->invite_branch = p->branch; 09399 build_via(p); 09400 } 09401 if (init > 1) 09402 initreqprep(&req, p, sipmethod); 09403 else 09404 /* If init=1, we should not generate a new branch. If it's 0, we need a new branch. */ 09405 reqprep(&req, p, sipmethod, 0, init ? 0 : 1); 09406 09407 if (p->options && p->options->auth) 09408 add_header(&req, p->options->authheader, p->options->auth); 09409 append_date(&req); 09410 if (sipmethod == SIP_REFER) { /* Call transfer */ 09411 if (p->refer) { 09412 char buf[SIPBUFSIZE]; 09413 if (!ast_strlen_zero(p->refer->refer_to)) 09414 add_header(&req, "Refer-To", p->refer->refer_to); 09415 if (!ast_strlen_zero(p->refer->referred_by)) { 09416 snprintf(buf, sizeof(buf), "%s <%s>", p->refer->referred_by_name, p->refer->referred_by); 09417 add_header(&req, "Referred-By", buf); 09418 } 09419 } 09420 } 09421 /* This new INVITE is part of an attended transfer. Make sure that the 09422 other end knows and replace the current call with this new call */ 09423 if (p->options && !ast_strlen_zero(p->options->replaces)) { 09424 add_header(&req, "Replaces", p->options->replaces); 09425 add_header(&req, "Require", "replaces"); 09426 } 09427 09428 /* Add Session-Timers related headers */ 09429 if (st_get_mode(p) == SESSION_TIMER_MODE_ORIGINATE) { 09430 char i2astr[10]; 09431 09432 if (!p->stimer->st_interval) 09433 p->stimer->st_interval = st_get_se(p, TRUE); 09434 09435 p->stimer->st_active = TRUE; 09436 09437 snprintf(i2astr, sizeof(i2astr), "%d", p->stimer->st_interval); 09438 add_header(&req, "Session-Expires", i2astr); 09439 snprintf(i2astr, sizeof(i2astr), "%d", st_get_se(p, FALSE)); 09440 add_header(&req, "Min-SE", i2astr); 09441 } 09442 09443 add_header(&req, "Allow", ALLOWED_METHODS); 09444 add_header(&req, "Supported", SUPPORTED_EXTENSIONS); 09445 09446 if(p->notify_headers) { 09447 char buf[512]; 09448 for (var = p->notify_headers; var; var = var->next) { 09449 ast_copy_string(buf, var->value, sizeof(buf)); 09450 add_header(&req, var->name, ast_unescape_semicolon(buf)); 09451 } 09452 } 09453 if (p->options && p->options->addsipheaders && p->owner) { 09454 struct ast_channel *chan = p->owner; /* The owner channel */ 09455 struct varshead *headp; 09456 09457 ast_channel_lock(chan); 09458 09459 headp = &chan->varshead; 09460 09461 if (!headp) 09462 ast_log(LOG_WARNING, "No Headp for the channel...ooops!\n"); 09463 else { 09464 const struct ast_var_t *current; 09465 AST_LIST_TRAVERSE(headp, current, entries) { 09466 /* SIPADDHEADER: Add SIP header to outgoing call */ 09467 if (!strncasecmp(ast_var_name(current), "SIPADDHEADER", strlen("SIPADDHEADER"))) { 09468 char *content, *end; 09469 const char *header = ast_var_value(current); 09470 char *headdup = ast_strdupa(header); 09471 09472 /* Strip of the starting " (if it's there) */ 09473 if (*headdup == '"') 09474 headdup++; 09475 if ((content = strchr(headdup, ':'))) { 09476 *content++ = '\0'; 09477 content = ast_skip_blanks(content); /* Skip white space */ 09478 /* Strip the ending " (if it's there) */ 09479 end = content + strlen(content) -1; 09480 if (*end == '"') 09481 *end = '\0'; 09482 09483 add_header(&req, headdup, content); 09484 if (sipdebug) 09485 ast_debug(1, "Adding SIP Header \"%s\" with content :%s: \n", headdup, content); 09486 } 09487 } 09488 } 09489 } 09490 09491 ast_channel_unlock(chan); 09492 } 09493 if (sdp) { 09494 if (p->udptl && p->t38.state == T38_LOCAL_REINVITE) { 09495 ast_udptl_offered_from_local(p->udptl, 1); 09496 ast_debug(1, "T38 is in state %d on channel %s\n", p->t38.state, p->owner ? p->owner->name : "<none>"); 09497 add_sdp(&req, p, FALSE, FALSE, TRUE); 09498 } else if (p->rtp) 09499 add_sdp(&req, p, FALSE, TRUE, FALSE); 09500 } else { 09501 if (!p->notify_headers) { 09502 add_header_contentLength(&req, 0); 09503 } 09504 } 09505 09506 if (!p->initreq.headers || init > 2) 09507 initialize_initreq(p, &req); 09508 p->lastinvite = p->ocseq; 09509 return send_request(p, &req, init ? XMIT_CRITICAL : XMIT_RELIABLE, p->ocseq); 09510 }
| static int transmit_message_with_text | ( | struct sip_pvt * | p, | |
| const char * | text | |||
| ) | [static] |
Transmit text with SIP MESSAGE method.
Definition at line 10198 of file chan_sip.c.
References add_text(), sip_pvt::ocseq, reqprep(), send_request(), SIP_MESSAGE, and XMIT_RELIABLE.
Referenced by sip_park_thread(), and sip_sendtext().
10199 { 10200 struct sip_request req; 10201 10202 reqprep(&req, p, SIP_MESSAGE, 0, 1); 10203 add_text(&req, text); 10204 return send_request(p, &req, XMIT_RELIABLE, p->ocseq); 10205 }
| static int transmit_notify_custom | ( | struct sip_pvt * | p, | |
| struct ast_variable * | vars | |||
| ) | [static] |
Notify device with custom headers from sip_notify.conf.
Definition at line 9761 of file chan_sip.c.
References add_header(), ast_copy_string(), ast_debug, ast_unescape_semicolon(), ast_variable_new(), buf, sip_request::headers, initialize_initreq(), sip_pvt::initreq, initreqprep(), ast_variable::name, ast_variable::next, sip_pvt::notify_headers, sip_pvt::ocseq, send_request(), SIP_NOTIFY, ast_variable::value, var, and XMIT_UNRELIABLE.
Referenced by manager_sipnotify(), and sip_cli_notify().
09761 { 09762 struct sip_request req; 09763 struct ast_variable *var, *newvar; 09764 09765 initreqprep(&req, p, SIP_NOTIFY); 09766 09767 /* Copy notify vars and add headers */ 09768 p->notify_headers = newvar = ast_variable_new("Subscription-State", "terminated", ""); 09769 add_header(&req, newvar->name, newvar->value); 09770 for (var = vars; var; var = var->next) { 09771 char buf[512]; 09772 ast_debug(2, " Adding pair %s=%s\n", var->name, var->value); 09773 ast_copy_string(buf, var->value, sizeof(buf)); 09774 add_header(&req, var->name, ast_unescape_semicolon(buf)); 09775 newvar->next = ast_variable_new(var->name, var->value, ""); 09776 newvar = newvar->next; 09777 } 09778 09779 if (!p->initreq.headers) { /* Initialize first request before sending */ 09780 initialize_initreq(p, &req); 09781 } 09782 09783 return send_request(p, &req, XMIT_UNRELIABLE, p->ocseq); 09784 }
| static int transmit_notify_with_mwi | ( | struct sip_pvt * | p, | |
| int | newmsgs, | |||
| int | oldmsgs, | |||
| char * | vmexten | |||
| ) | [static] |
Notify user of messages waiting in voicemail (RFC3842).
Definition at line 9701 of file chan_sip.c.
References add_header(), add_header_contentLength(), add_line(), ast_inet_ntoa(), ast_str_alloca, ast_str_append(), ast_test_flag, sip_pvt::expiry, sip_pvt::flags, sip_pvt::fromdomain, sip_request::headers, initialize_initreq(), sip_pvt::initreq, initreqprep(), sip_pvt::ocseq, sip_pvt::ourip, S_OR, send_request(), SIP_NOTIFY, SIP_PAGE2_BUGGY_MWI, ast_str::str, sip_pvt::subscribed, ast_str::used, and XMIT_RELIABLE.
Referenced by sip_send_mwi_to_peer().
09702 { 09703 struct sip_request req; 09704 struct ast_str *out = ast_str_alloca(500); 09705 09706 initreqprep(&req, p, SIP_NOTIFY); 09707 add_header(&req, "Event", "message-summary"); 09708 add_header(&req, "Content-Type", default_notifymime); 09709 09710 ast_str_append(&out, 0, "Messages-Waiting: %s\r\n", newmsgs ? "yes" : "no"); 09711 ast_str_append(&out, 0, "Message-Account: sip:%s@%s\r\n", 09712 S_OR(vmexten, default_vmexten), S_OR(p->fromdomain, ast_inet_ntoa(p->ourip.sin_addr))); 09713 /* Cisco has a bug in the SIP stack where it can't accept the 09714 (0/0) notification. This can temporarily be disabled in 09715 sip.conf with the "buggymwi" option */ 09716 ast_str_append(&out, 0, "Voice-Message: %d/%d%s\r\n", 09717 newmsgs, oldmsgs, (ast_test_flag(&p->flags[1], SIP_PAGE2_BUGGY_MWI) ? "" : " (0/0)")); 09718 09719 if (p->subscribed) { 09720 if (p->expiry) 09721 add_header(&req, "Subscription-State", "active"); 09722 else /* Expired */ 09723 add_header(&req, "Subscription-State", "terminated;reason=timeout"); 09724 } 09725 09726 add_header_contentLength(&req, out->used); 09727 add_line(&req, out->str); 09728 09729 if (!p->initreq.headers) 09730 initialize_initreq(p, &req); 09731 return send_request(p, &req, XMIT_RELIABLE, p->ocseq); 09732 }
| static int transmit_notify_with_sipfrag | ( | struct sip_pvt * | p, | |
| int | cseq, | |||
| char * | message, | |||
| int | terminate | |||
| ) | [static] |
Notify a transferring party of the status of transfer (RFC3515).
Definition at line 9735 of file chan_sip.c.
References add_header(), add_header_contentLength(), add_line(), ALLOWED_METHODS, sip_request::headers, initialize_initreq(), sip_pvt::initreq, sip_pvt::lastnoninvite, sip_pvt::ocseq, reqprep(), send_request(), SIP_NOTIFY, SIPBUFSIZE, SUPPORTED_EXTENSIONS, and XMIT_RELIABLE.
Referenced by handle_request_refer(), local_attended_transfer(), and sip_park_thread().
09736 { 09737 struct sip_request req; 09738 char tmp[SIPBUFSIZE/2]; 09739 09740 reqprep(&req, p, SIP_NOTIFY, 0, 1); 09741 snprintf(tmp, sizeof(tmp), "refer;id=%d", cseq); 09742 add_header(&req, "Event", tmp); 09743 add_header(&req, "Subscription-state", terminate ? "terminated;reason=noresource" : "active"); 09744 add_header(&req, "Content-Type", "message/sipfrag;version=2.0"); 09745 add_header(&req, "Allow", ALLOWED_METHODS); 09746 add_header(&req, "Supported", SUPPORTED_EXTENSIONS); 09747 09748 snprintf(tmp, sizeof(tmp), "SIP/2.0 %s\r\n", message); 09749 add_header_contentLength(&req, strlen(tmp)); 09750 add_line(&req, tmp); 09751 09752 if (!p->initreq.headers) 09753 initialize_initreq(p, &req); 09754 09755 p->lastnoninvite = p->ocseq; 09756 09757 return send_request(p, &req, XMIT_RELIABLE, p->ocseq); 09758 }
| static int transmit_refer | ( | struct sip_pvt * | p, | |
| const char * | dest | |||
| ) | [static] |
Transmit SIP REFER message (initiated by the transfer() dialplan application.
Definition at line 10219 of file chan_sip.c.
References add_header(), ALLOWED_METHODS, ast_copy_string(), ast_debug, ast_log(), ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, sip_pvt::callid, sip_pvt::flags, get_header(), get_in_brackets(), sip_request::headers, sip_pvt::initreq, LOG_NOTICE, sip_pvt::ocseq, sip_pvt::our_contact, sip_pvt::refer, REFER_SENT, sip_refer::refer_to, sip_refer::referred_by, reqprep(), send_request(), SIP_OUTGOING, SIP_REFER, sip_refer_allocate(), sip_refer::status, SUPPORTED_EXTENSIONS, sip_pvt::tag, sip_pvt::theirtag, and XMIT_RELIABLE.
Referenced by sip_transfer().
10220 { 10221 struct sip_request req = { 10222 .headers = 0, 10223 }; 10224 char from[256]; 10225 const char *of; 10226 char *c; 10227 char referto[256]; 10228 char *ttag, *ftag; 10229 char *theirtag = ast_strdupa(p->theirtag); 10230 10231 if (sipdebug) 10232 ast_debug(1, "SIP transfer of %s to %s\n", p->callid, dest); 10233 10234 /* Are we transfering an inbound or outbound call ? */ 10235 if (ast_test_flag(&p->flags[0], SIP_OUTGOING)) { 10236 of = get_header(&p->initreq, "To"); 10237 ttag = theirtag; 10238 ftag = p->tag; 10239 } else { 10240 of = get_header(&p->initreq, "From"); 10241 ftag = theirtag; 10242 ttag = p->tag; 10243 } 10244 10245 ast_copy_string(from, of, sizeof(from)); 10246 of = get_in_brackets(from); 10247 ast_string_field_set(p, from, of); 10248 if (!strncasecmp(of, "sip:", 4)) 10249 of += 4; 10250 else if (!strncasecmp(of, "sips:", 5)) 10251 of += 5; 10252 else 10253 ast_log(LOG_NOTICE, "From address missing 'sip(s):', using it anyway\n"); 10254 /* Get just the username part */ 10255 if ((c = strchr(dest, '@'))) 10256 c = NULL; 10257 else if ((c = strchr(of, '@'))) 10258 *c++ = '\0'; 10259 if (c) 10260 snprintf(referto, sizeof(referto), "<sip:%s@%s>", dest, c); 10261 else 10262 snprintf(referto, sizeof(referto), "<sip:%s>", dest); 10263 10264 /* save in case we get 407 challenge */ 10265 sip_refer_allocate(p); 10266 ast_copy_string(p->refer->refer_to, referto, sizeof(p->refer->refer_to)); 10267 ast_copy_string(p->refer->referred_by, p->our_contact, sizeof(p->refer->referred_by)); 10268 p->refer->status = REFER_SENT; /* Set refer status */ 10269 10270 reqprep(&req, p, SIP_REFER, 0, 1); 10271 10272 add_header(&req, "Refer-To", referto); 10273 add_header(&req, "Allow", ALLOWED_METHODS); 10274 add_header(&req, "Supported", SUPPORTED_EXTENSIONS); 10275 if (!ast_strlen_zero(p->our_contact)) 10276 add_header(&req, "Referred-By", p->our_contact); 10277 10278 return send_request(p, &req, XMIT_RELIABLE, p->ocseq); 10279 10280 /* We should propably wait for a NOTIFY here until we ack the transfer */ 10281 /* Maybe fork a new thread and wait for a STATUS of REFER_200OK on the refer status before returning to app_transfer */ 10282 10283 /*! \todo In theory, we should hang around and wait for a reply, before 10284 returning to the dial plan here. Don't know really how that would 10285 affect the transfer() app or the pbx, but, well, to make this 10286 useful we should have a STATUS code on transfer(). 10287 */ 10288 }
| static int transmit_register | ( | struct sip_registry * | r, | |
| int | sipmethod, | |||
| const char * | auth, | |||
| const char * | authheader | |||
| ) | [static] |
Transmit register to SIP proxy or UA auth = NULL on the initial registration (from sip_reregister()).
Definition at line 9964 of file chan_sip.c.
References add_header(), add_header_contentLength(), append_history, ast_debug, ast_dnsmgr_lookup(), ast_log(), ast_random(), ast_sched_add(), AST_SCHED_REPLACE_UNREF, ast_set_flag, ast_sip_ouraddrfor(), ast_string_field_set, ast_strlen_zero(), ast_verbose, sip_pvt::authname, sip_registry::authuser, sip_pvt::branch, build_callid_registry(), build_contact(), build_reply_digest(), build_via(), sip_registry::call, sip_registry::callback, sip_pvt::callid, sip_registry::callid, sip_registry::callid_valid, create_addr(), DEFAULT_MAX_FORWARDS, dialog_ref(), dialog_unlink_all(), dialog_unref(), sip_registry::dnsmgr, sip_pvt::do_history, sip_registry::domain, sip_registry::expiry, exten, sip_pvt::flags, sip_pvt::fromdomain, sip_pvt::fromuser, get_transport(), sip_request::headers, sip_registry::hostname, init_req(), initialize_initreq(), sip_pvt::initreq, sip_request::lines, ast_tcptls_session_args::local_address, LOG_NOTICE, LOG_WARNING, make_our_tag(), MAXHOSTNAMELEN, sip_registry::md5secret, sip_pvt::nonce, sip_registry::nonce, sip_registry::noncecount, sip_pvt::noncecount, obproxy_get(), sip_pvt::ocseq, sip_registry::ocseq, sip_registry::opaque, sip_pvt::opaque, sip_pvt::our_contact, sip_pvt::ourip, sip_pvt::peermd5secret, sip_pvt::peername, sip_pvt::peersecret, sip_socket::port, sip_registry::portno, sip_registry::qop, sip_pvt::qop, sip_registry::realm, sip_pvt::realm, sip_pvt::recv, ref_proxy(), REG_STATE_AUTHSENT, REG_STATE_REGSENT, sip_registry::regattempts, sip_pvt::registry, registry_addref(), registry_unref(), sip_registry::regstate, sip_pvt::sa, sched, sip_registry::secret, send_request(), sip_alloc(), sip_debug_test_pvt(), sip_methods, SIP_OUTGOING, sip_reg_timeout(), SIP_REGISTER, sip_tcp_desc, SIP_TRANSPORT_TCP, SIP_TRANSPORT_TLS, sip_pvt::socket, STANDARD_SIP_PORT, sip_pvt::tag, cfsip_methods::text, sip_pvt::theirtag, sip_registry::timeout, sip_pvt::tohost, sip_registry::transport, TRUE, sip_socket::type, sip_pvt::uri, sip_registry::us, sip_pvt::username, sip_registry::username, sip_pvt::via, and XMIT_CRITICAL.
Referenced by __sip_do_register(), do_register_auth(), handle_response_register(), and sip_reg_timeout().
09965 { 09966 struct sip_request req; 09967 char from[256]; 09968 char to[256]; 09969 char tmp[80]; 09970 char addr[80]; 09971 struct sip_pvt *p; 09972 int res; 09973 char *fromdomain; 09974 09975 /* exit if we are already in process with this registrar ?*/ 09976 if (r == NULL || ((auth == NULL) && (r->regstate == REG_STATE_REGSENT || r->regstate == REG_STATE_AUTHSENT))) { 09977 if (r) { 09978 ast_log(LOG_NOTICE, "Strange, trying to register %s@%s when registration already pending\n", r->username, r->hostname); 09979 } 09980 return 0; 09981 } 09982 09983 if (r->dnsmgr == NULL) { 09984 char transport[MAXHOSTNAMELEN]; 09985 snprintf(transport, sizeof(transport), "_sip._%s", get_transport(r->transport)); /* have to use static get_transport function */ 09986 ast_dnsmgr_lookup(r->hostname, &r->us, &r->dnsmgr, global_srvlookup ? transport : NULL); 09987 } 09988 09989 if (r->call) { /* We have a registration */ 09990 if (!auth) { 09991 ast_log(LOG_WARNING, "Already have a REGISTER going on to %s@%s?? \n", r->username, r->hostname); 09992 return 0; 09993 } else { 09994 p = dialog_ref(r->call, "getting a copy of the r->call dialog in transmit_register"); 09995 make_our_tag(p->tag, sizeof(p->tag)); /* create a new local tag for every register attempt */ 09996 ast_string_field_set(p, theirtag, NULL); /* forget their old tag, so we don't match tags when getting response */ 09997 } 09998 } else { 09999 /* Build callid for registration if we haven't registered before */ 10000 if (!r->callid_valid) { 10001 build_callid_registry(r, internip.sin_addr, default_fromdomain); 10002 r->callid_valid = TRUE; 10003 } 10004 /* Allocate SIP dialog for registration */ 10005 if (!(p = sip_alloc( r->callid, NULL, 0, SIP_REGISTER))) { 10006 ast_log(LOG_WARNING, "Unable to allocate registration transaction (memory or socket error)\n"); 10007 return 0; 10008 } 10009 10010 if (p->do_history) 10011 append_history(p, "RegistryInit", "Account: %s@%s", r->username, r->hostname); 10012 10013 ref_proxy(p, obproxy_get(p, NULL)); 10014 10015 /* Use port number specified if no SRV record was found */ 10016 if (!r->us.sin_port && r->portno) 10017 r->us.sin_port = htons(r->portno); 10018 10019 /* Find address to hostname */ 10020 if (create_addr(p, r->hostname, &r->us, 0)) { 10021 /* we have what we hope is a temporary network error, 10022 * probably DNS. We need to reschedule a registration try */ 10023 dialog_unlink_all(p, TRUE, TRUE); 10024 p = dialog_unref(p, "unref dialog after unlink_all"); 10025 if (r->timeout > -1) { 10026 AST_SCHED_REPLACE_UNREF(r->timeout, sched, global_reg_timeout * 1000, sip_reg_timeout, r, 10027 registry_unref(_data, "del for REPLACE of registry ptr"), 10028 registry_unref(r, "object ptr dec when SCHED_REPLACE add failed"), 10029 registry_addref(r,"add for REPLACE registry ptr")); 10030 ast_log(LOG_WARNING, "Still have a registration timeout for %s@%s (create_addr() error), %d\n", r->username, r->hostname, r->timeout); 10031 } else { 10032 r->timeout = ast_sched_add(sched, global_reg_timeout * 1000, sip_reg_timeout, registry_addref(r, "add for REPLACE registry ptr")); 10033 ast_log(LOG_WARNING, "Probably a DNS error for registration to %s@%s, trying REGISTER again (after %d seconds)\n", r->username, r->hostname, global_reg_timeout); 10034 } 10035 r->regattempts++; 10036 return 0; 10037 } 10038 10039 /* Copy back Call-ID in case create_addr changed it */ 10040 ast_string_field_set(r, callid, p->callid); 10041 if (!r->dnsmgr && r->portno) { 10042 p->sa.sin_port = htons(r->portno); 10043 p->recv.sin_port = htons(r->portno); 10044 } else { /* Set registry port to the port set from the peer definition/srv or default */ 10045 r->portno = ntohs(p->sa.sin_port); 10046 } 10047 ast_set_flag(&p->flags[0], SIP_OUTGOING); /* Registration is outgoing call */ 10048 r->call = dialog_ref(p, "copying dialog into registry r->call"); /* Save pointer to SIP dialog */ 10049 p->registry = registry_addref(r, "transmit_register: addref to p->registry in transmit_register"); /* Add pointer to registry in packet */ 10050 if (!ast_strlen_zero(r->secret)) /* Secret (password) */ 10051 ast_string_field_set(p, peersecret, r->secret); 10052 if (!ast_strlen_zero(r->md5secret)) 10053 ast_string_field_set(p, peermd5secret, r->md5secret); 10054 /* User name in this realm 10055 - if authuser is set, use that, otherwise use username */ 10056 if (!ast_strlen_zero(r->authuser)) { 10057 ast_string_field_set(p, peername, r->authuser); 10058 ast_string_field_set(p, authname, r->authuser); 10059 } else if (!ast_strlen_zero(r->username)) { 10060 ast_string_field_set(p, peername, r->username); 10061 ast_string_field_set(p, authname, r->username); 10062 ast_string_field_set(p, fromuser, r->username); 10063 } 10064 if (!ast_strlen_zero(r->username)) 10065 ast_string_field_set(p, username, r->username); 10066 /* Save extension in packet */ 10067 if (!ast_strlen_zero(r->callback)) 10068 ast_string_field_set(p, exten, r->callback); 10069 10070 /* Set transport and port so the correct contact is built */ 10071 p->socket.type = r->transport; 10072 if (r->transport == SIP_TRANSPORT_TLS || r->transport == SIP_TRANSPORT_TCP) { 10073 p->socket.port = sip_tcp_desc.local_address.sin_port; 10074 } 10075 10076 /* 10077 check which address we should use in our contact header 10078 based on whether the remote host is on the external or 10079 internal network so we can register through nat 10080 */ 10081 ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip); 10082 build_contact(p); 10083 } 10084 10085 /* set up a timeout */ 10086 if (auth == NULL) { 10087 if (r->timeout > -1) 10088 ast_log(LOG_WARNING, "Still have a registration timeout, #%d - deleting it\n", r->timeout); 10089 AST_SCHED_REPLACE_UNREF(r->timeout, sched, global_reg_timeout * 1000, sip_reg_timeout, r, 10090 registry_unref(_data,"reg ptr unrefed from del in SCHED_REPLACE"), 10091 registry_unref(r,"reg ptr unrefed from add failure in SCHED_REPLACE"), 10092 registry_addref(r,"reg ptr reffed from add in SCHED_REPLACE")); 10093 ast_debug(1, "Scheduled a registration timeout for %s id #%d \n", r->hostname, r->timeout); 10094 } 10095 10096 if ((fromdomain = strchr(r->username, '@'))) { 10097 /* the domain name is just behind '@' */ 10098 fromdomain++ ; 10099 /* We have a domain in the username for registration */ 10100 snprintf(from, sizeof(from), "<sip:%s>;tag=%s", r->username, p->tag); 10101 if (!ast_strlen_zero(p->theirtag)) 10102 snprintf(to, sizeof(to), "<sip:%s>;tag=%s", r->username, p->theirtag); 10103 else 10104 snprintf(to, sizeof(to), "<sip:%s>", r->username); 10105 10106 /* If the registration username contains '@', then the domain should be used as 10107 the equivalent of "fromdomain" for the registration */ 10108 if (ast_strlen_zero(p->fromdomain)) { 10109 ast_string_field_set(p, fromdomain, fromdomain); 10110 } 10111 } else { 10112 snprintf(from, sizeof(from), "<sip:%s@%s>;tag=%s", r->username, p->tohost, p->tag); 10113 if (!ast_strlen_zero(p->theirtag)) 10114 snprintf(to, sizeof(to), "<sip:%s@%s>;tag=%s", r->username, p->tohost, p->theirtag); 10115 else 10116 snprintf(to, sizeof(to), "<sip:%s@%s>", r->username, p->tohost); 10117 } 10118 10119 /* Fromdomain is what we are registering to, regardless of actual 10120 host name from SRV */ 10121 if (!ast_strlen_zero(p->fromdomain)) { 10122 if (r->portno && r->portno != STANDARD_SIP_PORT) 10123 snprintf(addr, sizeof(addr), "sip:%s:%d", p->fromdomain, r->portno); 10124 else 10125 snprintf(addr, sizeof(addr), "sip:%s", p->fromdomain); 10126 } else { 10127 if (r->portno && r->portno != STANDARD_SIP_PORT) 10128 snprintf(addr, sizeof(addr), "sip:%s:%d", r->hostname, r->portno); 10129 else 10130 snprintf(addr, sizeof(addr), "sip:%s", r->hostname); 10131 } 10132 ast_string_field_set(p, uri, addr); 10133 10134 p->branch ^= ast_random(); 10135 10136 init_req(&req, sipmethod, addr); 10137 10138 /* Add to CSEQ */ 10139 snprintf(tmp, sizeof(tmp), "%u %s", ++r->ocseq, sip_methods[sipmethod].text); 10140 p->ocseq = r->ocseq; 10141 10142 build_via(p); 10143 add_header(&req, "Via", p->via); 10144 add_header(&req, "Max-Forwards", DEFAULT_MAX_FORWARDS); 10145 add_header(&req, "From", from); 10146 add_header(&req, "To", to); 10147 add_header(&req, "Call-ID", p->callid); 10148 add_header(&req, "CSeq", tmp); 10149 if (!ast_strlen_zero(global_useragent)) 10150 add_header(&req, "User-Agent", global_useragent); 10151 10152 10153 if (auth) /* Add auth header */ 10154 add_header(&req, authheader, auth); 10155 else if (!ast_strlen_zero(r->nonce)) { 10156 char digest[1024]; 10157 10158 /* We have auth data to reuse, build a digest header. 10159 * Note, this is not always useful because some parties do not 10160 * like nonces to be reused (for good reasons!) so they will 10161 * challenge us anyways. 10162 */ 10163 if (sipdebug) 10164 ast_debug(1, " >>> Re-using Auth data for %s@%s\n", r->username, r->hostname); 10165 ast_string_field_set(p, realm, r->realm); 10166 ast_string_field_set(p, nonce, r->nonce); 10167 ast_string_field_set(p, domain, r->domain); 10168 ast_string_field_set(p, opaque, r->opaque); 10169 ast_string_field_set(p, qop, r->qop); 10170 p->noncecount = ++r->noncecount; 10171 10172 memset(digest, 0, sizeof(digest)); 10173 if(!build_reply_digest(p, sipmethod, digest, sizeof(digest))) 10174 add_header(&req, "Authorization", digest); 10175 else 10176 ast_log(LOG_NOTICE, "No authorization available for authentication of registration to %s@%s\n", r->username, r->hostname); 10177 10178 } 10179 10180 snprintf(tmp, sizeof(tmp), "%d", r->expiry); 10181 add_header(&req, "Expires", tmp); 10182 add_header(&req, "Contact", p->our_contact); 10183 add_header_contentLength(&req, 0); 10184 10185 initialize_initreq(p, &req); 10186 if (sip_debug_test_pvt(p)) { 10187 ast_verbose("REGISTER %d headers, %d lines\n", p->initreq.headers, p->initreq.lines); 10188 } 10189 r->regstate = auth ? REG_STATE_AUTHSENT : REG_STATE_REGSENT; 10190 r->regattempts++; /* Another attempt */ 10191 ast_debug(4, "REGISTER attempt %d to %s@%s\n", r->regattempts, r->username, r->hostname); 10192 res = send_request(p, &req, XMIT_CRITICAL, p->ocseq); 10193 dialog_unref(p, "p is finished here at the end of transmit_register"); 10194 return res; 10195 }
| static int transmit_reinvite_with_sdp | ( | struct sip_pvt * | p, | |
| int | t38version, | |||
| int | oldsdp | |||
| ) | [static] |
Transmit reinvite with SDP.
If oldsdp is TRUE then the SDP version number is not incremented. This is needed for Session-Timers so we can send a re-invite to refresh the SIP session without modifying the media session.
Definition at line 9081 of file chan_sip.c.
References add_header(), add_sdp(), ALLOWED_METHODS, append_history, ast_set_flag, ast_test_flag, sip_pvt::do_history, FALSE, sip_pvt::flags, initialize_initreq(), sip_pvt::lastinvite, sip_pvt::ocseq, reqprep(), send_request(), SIP_INVITE, SIP_OUTGOING, SIP_REINVITE_UPDATE, SIP_UPDATE, SUPPORTED_EXTENSIONS, TRUE, and XMIT_CRITICAL.
Referenced by check_pendings(), handle_response_invite(), proc_session_timer(), sip_indicate(), sip_read(), sip_sendhtml(), sip_set_rtp_peer(), sip_set_udptl_peer(), and sip_write().
09082 { 09083 struct sip_request req; 09084 09085 reqprep(&req, p, ast_test_flag(&p->flags[0], SIP_REINVITE_UPDATE) ? SIP_UPDATE : SIP_INVITE, 0, 1); 09086 09087 add_header(&req, "Allow", ALLOWED_METHODS); 09088 add_header(&req, "Supported", SUPPORTED_EXTENSIONS); 09089 if (sipdebug) { 09090 if (oldsdp == TRUE) 09091 add_header(&req, "X-asterisk-Info", "SIP re-invite (Session-Timers)"); 09092 else 09093 add_header(&req, "X-asterisk-Info", "SIP re-invite (External RTP bridge)"); 09094 } 09095 09096 if (p->do_history) 09097 append_history(p, "ReInv", "Re-invite sent"); 09098 if (t38version) 09099 add_sdp(&req, p, oldsdp, FALSE, TRUE); 09100 else 09101 add_sdp(&req, p, oldsdp, TRUE, FALSE); 09102 09103 /* Use this as the basis */ 09104 initialize_initreq(p, &req); 09105 p->lastinvite = p->ocseq; 09106 ast_set_flag(&p->flags[0], SIP_OUTGOING); /* Change direction of this dialog */ 09107 09108 return send_request(p, &req, XMIT_CRITICAL, p->ocseq); 09109 }
| static int transmit_request | ( | struct sip_pvt * | p, | |
| int | sipmethod, | |||
| int | inc, | |||
| enum xmittype | reliable, | |||
| int | newbranch | |||
| ) | [static] |
Transmit generic SIP request returns XMIT_ERROR if transmit failed with a critical error (don't retry).
Definition at line 10314 of file chan_sip.c.
References add_header(), add_header_contentLength(), sip_pvt::answered_elsewhere, INV_CONFIRMED, sip_pvt::invitestate, sip_pvt::ocseq, reqprep(), send_request(), SIP_ACK, and SIP_CANCEL.
Referenced by check_pendings(), handle_response(), handle_response_invite(), and sip_hangup().
10315 { 10316 struct sip_request resp; 10317 10318 if (sipmethod == SIP_ACK) 10319 p->invitestate = INV_CONFIRMED; 10320 10321 reqprep(&resp, p, sipmethod, seqno, newbranch); 10322 if (sipmethod == SIP_CANCEL && p->answered_elsewhere) 10323 add_header(&resp, "Reason", "SIP;cause=200;text=\"Call completed elsewhere\""); 10324 10325 add_header_contentLength(&resp, 0); 10326 return send_request(p, &resp, reliable, seqno ? seqno : p->ocseq); 10327 }
| static int transmit_request_with_auth | ( | struct sip_pvt * | p, | |
| int | sipmethod, | |||
| int | seqno, | |||
| enum xmittype | reliable, | |||
| int | newbranch | |||
| ) | [static] |
Transmit SIP request, auth added.
Definition at line 10345 of file chan_sip.c.
References add_header(), add_header_contentLength(), ast_cause2str(), ast_log(), ast_strlen_zero(), auth_headers(), sip_invite_param::auth_type, buf, build_reply_digest(), sip_pvt::callid, dummy(), sip_pvt::hangupcause, LOG_WARNING, sip_pvt::ocseq, sip_pvt::options, PROXY_AUTH, sip_pvt::realm, reqprep(), send_request(), and SIP_BYE.
Referenced by __sip_autodestruct(), check_pendings(), and sip_hangup().
10346 { 10347 struct sip_request resp; 10348 10349 reqprep(&resp, p, sipmethod, seqno, newbranch); 10350 if (!ast_strlen_zero(p->realm)) { 10351 char digest[1024]; 10352 10353 memset(digest, 0, sizeof(digest)); 10354 if(!build_reply_digest(p, sipmethod, digest, sizeof(digest))) { 10355 char *dummy, *response; 10356 enum sip_auth_type code = p->options ? p->options->auth_type : PROXY_AUTH; /* XXX force 407 if unknown */ 10357 auth_headers(code, &dummy, &response); 10358 add_header(&resp, response, digest); 10359 } else 10360 ast_log(LOG_WARNING, "No authentication available for call %s\n", p->callid); 10361 } 10362 /* If we are hanging up and know a cause for that, send it in clear text to make 10363 debugging easier. */ 10364 if (sipmethod == SIP_BYE) { 10365 char buf[10]; 10366 10367 add_header(&resp, "X-Asterisk-HangupCause", ast_cause2str(p->hangupcause)); 10368 snprintf(buf, sizeof(buf), "%d", p->hangupcause); 10369 add_header(&resp, "X-Asterisk-HangupCauseCode", buf); 10370 } 10371 10372 add_header_contentLength(&resp, 0); 10373 return send_request(p, &resp, reliable, seqno ? seqno : p->ocseq); 10374 }
| static int transmit_response | ( | struct sip_pvt * | p, | |
| const char * | msg, | |||
| const struct sip_request * | req | |||
| ) | [static] |
Transmit response, no retransmits.
Definition at line 8253 of file chan_sip.c.
References __transmit_response(), and XMIT_UNRELIABLE.
08254 { 08255 return __transmit_response(p, msg, req, XMIT_UNRELIABLE); 08256 }
| static int transmit_response_reliable | ( | struct sip_pvt * | p, | |
| const char * | msg, | |||
| const struct sip_request * | req | |||
| ) | [static] |
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.
Definition at line 8289 of file chan_sip.c.
References __transmit_response(), sip_request::ignore, XMIT_CRITICAL, and XMIT_UNRELIABLE.
Referenced by handle_incoming(), handle_invite_replaces(), handle_request_bye(), handle_request_cancel(), handle_request_invite(), handle_request_subscribe(), sip_hangup(), sip_indicate(), sip_sipredirect(), and sip_t38_abort().
08290 { 08291 return __transmit_response(p, msg, req, req->ignore ? XMIT_UNRELIABLE : XMIT_CRITICAL); 08292 }
| static int transmit_response_using_temp | ( | ast_string_field | callid, | |
| struct sockaddr_in * | sin, | |||
| int | useglobal_nat, | |||
| const int | intended_method, | |||
| const struct sip_request * | req, | |||
| const char * | msg | |||
| ) | [static] |
Transmit response, no retransmits, using a temporary pvt structure.
Definition at line 8201 of file chan_sip.c.
References __transmit_response(), ast_copy_flags, ast_log(), ast_random(), ast_sip_ouraddrfor(), ast_string_field_init, ast_string_field_set, ast_test_flag, ast_threadstorage_get(), build_via(), copy_socket_data(), do_setnat(), sip_pvt::fromdomain, global_flags, INITIAL_CSEQ, LOG_ERROR, make_our_tag(), SIP_NAT, SIP_NAT_ROUTE, sip_request::socket, ts_temp_pvt, and XMIT_UNRELIABLE.
Referenced by find_call().
08202 { 08203 struct sip_pvt *p = NULL; 08204 08205 if (!(p = ast_threadstorage_get(&ts_temp_pvt, sizeof(*p)))) { 08206 ast_log(LOG_ERROR, "Failed to get temporary pvt\n"); 08207 return -1; 08208 } 08209 08210 /* XXX the structure may be dirty from previous usage. 08211 * Here we should state clearly how we should reinitialize it 08212 * before using it. 08213 * E.g. certainly the threadstorage should be left alone, 08214 * but other thihngs such as flags etc. maybe need cleanup ? 08215 */ 08216 08217 /* Initialize the bare minimum */ 08218 p->method = intended_method; 08219 08220 if (!sin) 08221 p->ourip = internip; 08222 else { 08223 p->sa = *sin; 08224 ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip); 08225 } 08226 08227 p->branch = ast_random(); 08228 make_our_tag(p->tag, sizeof(p->tag)); 08229 p->ocseq = INITIAL_CSEQ; 08230 08231 if (useglobal_nat && sin) { 08232 ast_copy_flags(&p->flags[0], &global_flags[0], SIP_NAT); 08233 p->recv = *sin; 08234 do_setnat(p, ast_test_flag(&p->flags[0], SIP_NAT) & SIP_NAT_ROUTE); 08235 } 08236 08237 ast_string_field_set(p, fromdomain, default_fromdomain); 08238 build_via(p); 08239 ast_string_field_set(p, callid, callid); 08240 08241 copy_socket_data(&p->socket, &req->socket); 08242 08243 /* Use this temporary pvt structure to send the message */ 08244 __transmit_response(p, msg, req, XMIT_UNRELIABLE); 08245 08246 /* Free the string fields, but not the pool space */ 08247 ast_string_field_init(p, 0); 08248 08249 return 0; 08250 }
| static int transmit_response_with_allow | ( | struct sip_pvt * | p, | |
| const char * | msg, | |||
| const struct sip_request * | req, | |||
| enum xmittype | reliable | |||
| ) | [static] |
Append Accept header, content length before transmitting response.
Definition at line 8317 of file chan_sip.c.
References add_header(), add_header_contentLength(), respprep(), and send_response().
Referenced by handle_incoming(), and handle_request_options().
08318 { 08319 struct sip_request resp; 08320 respprep(&resp, p, msg, req); 08321 add_header(&resp, "Accept", "application/sdp"); 08322 add_header_contentLength(&resp, 0); 08323 return send_response(p, &resp, reliable, 0); 08324 }
| static int transmit_response_with_auth | ( | struct sip_pvt * | p, | |
| const char * | msg, | |||
| const struct sip_request * | req, | |||
| const char * | rand, | |||
| enum xmittype | reliable, | |||
| const char * | header, | |||
| int | stale | |||
| ) | [static] |
Respond with authorization request.
Definition at line 8327 of file chan_sip.c.
References add_header(), add_header_contentLength(), append_history, ast_log(), get_header(), LOG_WARNING, sip_pvt::noncecount, respprep(), send_response(), and sip_pvt::username.
Referenced by check_auth(), and transmit_fake_auth_response().
08328 { 08329 struct sip_request resp; 08330 char tmp[512]; 08331 int seqno = 0; 08332 08333 if (reliable && (sscanf(get_header(req, "CSeq"), "%d ", &seqno) != 1)) { 08334 ast_log(LOG_WARNING, "Unable to determine sequence number from '%s'\n", get_header(req, "CSeq")); 08335 return -1; 08336 } 08337 /* Stale means that they sent us correct authentication, but 08338 based it on an old challenge (nonce) */ 08339 snprintf(tmp, sizeof(tmp), "Digest algorithm=MD5, realm=\"%s\", nonce=\"%s\"%s", global_realm, randdata, stale ? ", stale=true" : ""); 08340 respprep(&resp, p, msg, req); 08341 add_header(&resp, header, tmp); 08342 add_header_contentLength(&resp, 0); 08343 append_history(p, "AuthChal", "Auth challenge sent for %s - nc %d", p->username, p->noncecount); 08344 return send_response(p, &resp, reliable, seqno); 08345 }
| static int transmit_response_with_date | ( | struct sip_pvt * | p, | |
| const char * | msg, | |||
| const struct sip_request * | req | |||
| ) | [static] |
Append date and content length before transmitting response.
Definition at line 8307 of file chan_sip.c.
References add_header_contentLength(), append_date(), respprep(), send_response(), and XMIT_UNRELIABLE.
Referenced by register_verify().
08308 { 08309 struct sip_request resp; 08310 respprep(&resp, p, msg, req); 08311 append_date(&resp); 08312 add_header_contentLength(&resp, 0); 08313 return send_response(p, &resp, XMIT_UNRELIABLE, 0); 08314 }
| static int transmit_response_with_minse | ( | struct sip_pvt * | p, | |
| const char * | msg, | |||
| const struct sip_request * | req, | |||
| int | minse_int | |||
| ) | [static] |
Transmit 422 response with Min-SE header (Session-Timers).
Definition at line 8270 of file chan_sip.c.
References add_header(), add_header_contentLength(), append_date(), respprep(), send_response(), and XMIT_UNRELIABLE.
Referenced by handle_request_invite().
08271 { 08272 struct sip_request resp; 08273 char minse_str[20]; 08274 08275 respprep(&resp, p, msg, req); 08276 append_date(&resp); 08277 08278 snprintf(minse_str, sizeof(minse_str), "%d", minse_int); 08279 add_header(&resp, "Min-SE", minse_str); 08280 08281 add_header_contentLength(&resp, 0); 08282 return send_response(p, &resp, XMIT_UNRELIABLE, 0); 08283 }
| static int transmit_response_with_sdp | ( | struct sip_pvt * | p, | |
| const char * | msg, | |||
| const struct sip_request * | req, | |||
| enum xmittype | reliable, | |||
| int | oldsdp | |||
| ) | [static] |
Used for 200 OK and 183 early media.
Definition at line 8998 of file chan_sip.c.
References add_sdp(), ast_debug, ast_log(), ast_rtp_codec_setpref(), ast_test_flag, sip_pvt::autoframing, sip_pvt::callid, FALSE, sip_pvt::flags, get_header(), LOG_ERROR, LOG_WARNING, sip_pvt::pendinginvite, sip_pvt::prefs, respprep(), sip_pvt::rtp, send_response(), SIP_OUTGOING, t38properties::state, sip_pvt::t38, T38_ENABLED, T38_PEER_DIRECT, TRUE, and try_suggested_sip_codec().
Referenced by handle_invite_replaces(), handle_request_invite(), sip_answer(), sip_indicate(), and sip_write().
08999 { 09000 struct sip_request resp; 09001 int seqno; 09002 if (sscanf(get_header(req, "CSeq"), "%d ", &seqno) != 1) { 09003 ast_log(LOG_WARNING, "Unable to get seqno from '%s'\n", get_header(req, "CSeq")); 09004 return -1; 09005 } 09006 respprep(&resp, p, msg, req); 09007 if (p->rtp) { 09008 if (!p->autoframing && !ast_test_flag(&p->flags[0], SIP_OUTGOING)) { 09009 ast_debug(1, "Setting framing from config on incoming call\n"); 09010 ast_rtp_codec_setpref(p->rtp, &p->prefs); 09011 } 09012 try_suggested_sip_codec(p); 09013 if (p->t38.state == T38_PEER_DIRECT || p->t38.state == T38_ENABLED) { 09014 add_sdp(&resp, p, oldsdp, TRUE, TRUE); 09015 } else { 09016 add_sdp(&resp, p, oldsdp, TRUE, FALSE); 09017 } 09018 } else 09019 ast_log(LOG_ERROR, "Can't add SDP to response, since we have no RTP session allocated. Call-ID %s\n", p->callid); 09020 if (reliable && !p->pendinginvite) 09021 p->pendinginvite = seqno; /* Buggy clients sends ACK on RINGING too */ 09022 return send_response(p, &resp, reliable, seqno); 09023 }
| static int transmit_response_with_t38_sdp | ( | struct sip_pvt * | p, | |
| char * | msg, | |||
| struct sip_request * | req, | |||
| int | retrans | |||
| ) | [static] |
Used for 200 OK and 183 early media.
Definition at line 8951 of file chan_sip.c.
References add_sdp(), ast_log(), ast_udptl_offered_from_local(), sip_pvt::callid, get_header(), LOG_ERROR, LOG_WARNING, sip_pvt::pendinginvite, respprep(), send_response(), and sip_pvt::udptl.
Referenced by handle_request_invite(), and sip_indicate().
08952 { 08953 struct sip_request resp; 08954 int seqno; 08955 08956 if (sscanf(get_header(req, "CSeq"), "%d ", &seqno) != 1) { 08957 ast_log(LOG_WARNING, "Unable to get seqno from '%s'\n", get_header(req, "CSeq")); 08958 return -1; 08959 } 08960 respprep(&resp, p, msg, req); 08961 if (p->udptl) { 08962 ast_udptl_offered_from_local(p->udptl, 0); 08963 add_sdp(&resp, p, 0, 0, 1); 08964 } else 08965 ast_log(LOG_ERROR, "Can't add SDP to response, since we have no UDPTL session allocated. Call-ID %s\n", p->callid); 08966 if (retrans && !p->pendinginvite) 08967 p->pendinginvite = seqno; /* Buggy clients sends ACK on RINGING too */ 08968 return send_response(p, &resp, retrans, seqno); 08969 }
| static int transmit_response_with_unsupported | ( | struct sip_pvt * | p, | |
| const char * | msg, | |||
| const struct sip_request * | req, | |||
| const char * | unsupported | |||
| ) | [static] |
Transmit response, no retransmits.
Definition at line 8259 of file chan_sip.c.
References add_header(), add_header_contentLength(), append_date(), respprep(), send_response(), and XMIT_UNRELIABLE.
Referenced by handle_request_invite().
08260 { 08261 struct sip_request resp; 08262 respprep(&resp, p, msg, req); 08263 append_date(&resp); 08264 add_header(&resp, "Unsupported", unsupported); 08265 add_header_contentLength(&resp, 0); 08266 return send_response(p, &resp, XMIT_UNRELIABLE, 0); 08267 }
| static int transmit_state_notify | ( | struct sip_pvt * | p, | |
| int | state, | |||
| int | full, | |||
| int | timeout | |||
| ) | [static] |
Used in the SUBSCRIBE notification subsystem (RFC3265).
Definition at line 9513 of file chan_sip.c.
References add_header(), add_header_contentLength(), add_line(), ast_copy_string(), ast_device_state(), AST_DEVICE_UNAVAILABLE, AST_EXTENSION_BUSY, AST_EXTENSION_DEACTIVATED, AST_EXTENSION_INUSE, AST_EXTENSION_NOT_INUSE, AST_EXTENSION_ONHOLD, AST_EXTENSION_REMOVED, AST_EXTENSION_RINGING, AST_EXTENSION_UNAVAILABLE, ast_get_hint(), ast_log(), AST_MAX_EXTENSION, ast_str_alloca, ast_str_append(), sip_pvt::context, CPIM_PIDF_XML, DIALOG_INFO_XML, sip_pvt::dialogver, sip_pvt::expiry, sip_pvt::exten, find_subscription_type(), get_header(), get_in_brackets(), sip_pvt::initreq, LOG_WARNING, NONE, sip_pvt::ocseq, sip_pvt::pendinginvite, PIDF_XML, remove_uri_parameters(), reqprep(), send_request(), SIP_NOTIFY, ast_str::str, strsep(), sip_pvt::subscribed, ast_str::used, XMIT_RELIABLE, and XPIDF_XML.
Referenced by __sip_autodestruct(), cb_extensionstate(), and handle_request_subscribe().
09514 { 09515 struct ast_str *tmp = ast_str_alloca(4000); 09516 char from[256], to[256]; 09517 char *c, *mfrom, *mto; 09518 struct sip_request req; 09519 char hint[AST_MAX_EXTENSION]; 09520 char *statestring = "terminated"; 09521 const struct cfsubscription_types *subscriptiontype; 09522 enum state { NOTIFY_OPEN, NOTIFY_INUSE, NOTIFY_CLOSED } local_state = NOTIFY_OPEN; 09523 char *pidfstate = "--"; 09524 char *pidfnote= "Ready"; 09525 09526 memset(from, 0, sizeof(from)); 09527 memset(to, 0, sizeof(to)); 09528 09529 switch (state) { 09530 case (AST_EXTENSION_RINGING | AST_EXTENSION_INUSE): 09531 statestring = (global_notifyringing) ? "early" : "confirmed"; 09532 local_state = NOTIFY_INUSE; 09533 pidfstate = "busy"; 09534 pidfnote = "Ringing"; 09535 break; 09536 case AST_EXTENSION_RINGING: 09537 statestring = "early"; 09538 local_state = NOTIFY_INUSE; 09539 pidfstate = "busy"; 09540 pidfnote = "Ringing"; 09541 break; 09542 case AST_EXTENSION_INUSE: 09543 statestring = "confirmed"; 09544 local_state = NOTIFY_INUSE; 09545 pidfstate = "busy"; 09546 pidfnote = "On the phone"; 09547 break; 09548 case AST_EXTENSION_BUSY: 09549 statestring = "confirmed"; 09550 local_state = NOTIFY_CLOSED; 09551 pidfstate = "busy"; 09552 pidfnote = "On the phone"; 09553 break; 09554 case AST_EXTENSION_UNAVAILABLE: 09555 statestring = "terminated"; 09556 local_state = NOTIFY_CLOSED; 09557 pidfstate = "away"; 09558 pidfnote = "Unavailable"; 09559 break; 09560 case AST_EXTENSION_ONHOLD: 09561 statestring = "confirmed"; 09562 local_state = NOTIFY_CLOSED; 09563 pidfstate = "busy"; 09564 pidfnote = "On hold"; 09565 break; 09566 case AST_EXTENSION_NOT_INUSE: 09567 default: 09568 /* Default setting */ 09569 break; 09570 } 09571 09572 subscriptiontype = find_subscription_type(p->subscribed); 09573 09574 /* Check which device/devices we are watching and if they are registered */ 09575 if (ast_get_hint(hint, sizeof(hint), NULL, 0, NULL, p->context, p->exten)) { 09576 char *hint2 = hint, *individual_hint = NULL; 09577 int hint_count = 0, unavailable_count = 0; 09578 09579 while ((individual_hint = strsep(&hint2, "&"))) { 09580 hint_count++; 09581 09582 if (ast_device_state(individual_hint) == AST_DEVICE_UNAVAILABLE) 09583 unavailable_count++; 09584 } 09585 09586 /* If none of the hinted devices are registered, we will 09587 * override notification and show no availability. 09588 */ 09589 if (hint_count > 0 && hint_count == unavailable_count) { 09590 local_state = NOTIFY_CLOSED; 09591 pidfstate = "away"; 09592 pidfnote = "Not online"; 09593 } 09594 } 09595 09596 ast_copy_string(from, get_header(&p->initreq, "From"), sizeof(from)); 09597 c = get_in_brackets(from); 09598 if (strncasecmp(c, "sip:", 4) && strncasecmp(c, "sips:", 5)) { 09599 ast_log(LOG_WARNING, "Huh? Not a SIP header (%s)?\n", c); 09600 return -1; 09601 } 09602 09603 mfrom = remove_uri_parameters(c); 09604 09605 ast_copy_string(to, get_header(&p->initreq, "To"), sizeof(to)); 09606 c = get_in_brackets(to); 09607 if (strncasecmp(c, "sip:", 4) && strncasecmp(c, "sips:", 5)) { 09608 ast_log(LOG_WARNING, "Huh? Not a SIP header (%s)?\n", c); 09609 return -1; 09610 } 09611 mto = remove_uri_parameters(c); 09612 09613 reqprep(&req, p, SIP_NOTIFY, 0, 1); 09614 09615 09616 add_header(&req, "Event", subscriptiontype->event); 09617 add_header(&req, "Content-Type", subscriptiontype->mediatype); 09618 switch(state) { 09619 case AST_EXTENSION_DEACTIVATED: 09620 if (timeout) 09621 add_header(&req, "Subscription-State", "terminated;reason=timeout"); 09622 else { 09623 add_header(&req, "Subscription-State", "terminated;reason=probation"); 09624 add_header(&req, "Retry-After", "60"); 09625 } 09626 break; 09627 case AST_EXTENSION_REMOVED: 09628 add_header(&req, "Subscription-State", "terminated;reason=noresource"); 09629 break; 09630 default: 09631 if (p->expiry) 09632 add_header(&req, "Subscription-State", "active"); 09633 else /* Expired */ 09634 add_header(&req, "Subscription-State", "terminated;reason=timeout"); 09635 } 09636 switch (p->subscribed) { 09637 case XPIDF_XML: 09638 case CPIM_PIDF_XML: 09639 ast_str_append(&tmp, 0, 09640 "<?xml version=\"1.0\"?>\n" 09641 "<!DOCTYPE presence PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n" 09642 "<presence>\n"); 09643 ast_str_append(&tmp, 0, "<presentity uri=\"%s;method=SUBSCRIBE\" />\n", mfrom); 09644 ast_str_append(&tmp, 0, "<atom id=\"%s\">\n", p->exten); 09645 ast_str_append(&tmp, 0, "<address uri=\"%s;user=ip\" priority=\"0.800000\">\n", mto); 09646 ast_str_append(&tmp, 0, "<status status=\"%s\" />\n", (local_state == NOTIFY_OPEN) ? "open" : (local_state == NOTIFY_INUSE) ? "inuse" : "closed"); 09647 ast_str_append(&tmp, 0, "<msnsubstatus substatus=\"%s\" />\n", (local_state == NOTIFY_OPEN) ? "online" : (local_state == NOTIFY_INUSE) ? "onthephone" : "offline"); 09648 ast_str_append(&tmp, 0, "</address>\n</atom>\n</presence>\n"); 09649 break; 09650 case PIDF_XML: /* Eyebeam supports this format */ 09651 ast_str_append(&tmp, 0, 09652 "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n" 09653 "<presence xmlns=\"urn:ietf:params:xml:ns:pidf\" \nxmlns:pp=\"urn:ietf:params:xml:ns:pidf:person\"\nxmlns:es=\"urn:ietf:params:xml:ns:pidf:rpid:status:rpid-status\"\nxmlns:ep=\"urn:ietf:params:xml:ns:pidf:rpid:rpid-person\"\nentity=\"%s\">\n", mfrom); 09654 ast_str_append(&tmp, 0, "<pp:person><status>\n"); 09655 if (pidfstate[0] != '-') 09656 ast_str_append(&tmp, 0, "<ep:activities><ep:%s/></ep:activities>\n", pidfstate); 09657 ast_str_append(&tmp, 0, "</status></pp:person>\n"); 09658 ast_str_append(&tmp, 0, "<note>%s</note>\n", pidfnote); /* Note */ 09659 ast_str_append(&tmp, 0, "<tuple id=\"%s\">\n", p->exten); /* Tuple start */ 09660 ast_str_append(&tmp, 0, "<contact priority=\"1\">%s</contact>\n", mto); 09661 if (pidfstate[0] == 'b') /* Busy? Still open ... */ 09662 ast_str_append(&tmp, 0, "<status><basic>open</basic></status>\n"); 09663 else 09664 ast_str_append(&tmp, 0, "<status><basic>%s</basic></status>\n", (local_state != NOTIFY_CLOSED) ? "open" : "closed"); 09665 ast_str_append(&tmp, 0, "</tuple>\n</presence>\n"); 09666 break; 09667 case DIALOG_INFO_XML: /* SNOM subscribes in this format */ 09668 ast_str_append(&tmp, 0, "<?xml version=\"1.0\"?>\n"); 09669 ast_str_append(&tmp, 0, "<dialog-info xmlns=\"urn:ietf:params:xml:ns:dialog-info\" version=\"%d\" state=\"%s\" entity=\"%s\">\n", p->dialogver++, full ? "full":"partial", mto); 09670 if ((state & AST_EXTENSION_RINGING) && global_notifyringing) 09671 ast_str_append(&tmp, 0, "<dialog id=\"%s\" direction=\"recipient\">\n", p->exten); 09672 else 09673 ast_str_append(&tmp, 0, "<dialog id=\"%s\">\n", p->exten); 09674 ast_str_append(&tmp, 0, "<state>%s</state>\n", statestring); 09675 if (state == AST_EXTENSION_ONHOLD) { 09676 ast_str_append(&tmp, 0, "<local>\n<target uri=\"%s\">\n" 09677 "<param pname=\"+sip.rendering\" pvalue=\"no\"/>\n" 09678 "</target>\n</local>\n", mto); 09679 } 09680 ast_str_append(&tmp, 0, "</dialog>\n</dialog-info>\n"); 09681 break; 09682 case NONE: 09683 default: 09684 break; 09685 } 09686 09687 add_header_contentLength(&req, tmp->used); 09688 add_line(&req, tmp->str); 09689 09690 p->pendinginvite = p->ocseq; /* Remember that we have a pending NOTIFY in order not to confuse the NOTIFY subsystem */ 09691 09692 return send_request(p, &req, XMIT_RELIABLE, p->ocseq); 09693 }
| static void try_suggested_sip_codec | ( | struct sip_pvt * | p | ) | [static] |
Try setting codec suggested by the SIP_CODEC channel variable.
Definition at line 5309 of file chan_sip.c.
References ast_getformatbyname(), ast_log(), sip_pvt::capability, sip_pvt::jointcapability, LOG_NOTICE, sip_pvt::owner, and pbx_builtin_getvar_helper().
Referenced by sip_answer(), and transmit_response_with_sdp().
05310 { 05311 int fmt; 05312 const char *codec; 05313 05314 codec = pbx_builtin_getvar_helper(p->owner, "SIP_CODEC"); 05315 if (!codec) 05316 return; 05317 05318 fmt = ast_getformatbyname(codec); 05319 if (fmt) { 05320 ast_log(LOG_NOTICE, "Changing codec to '%s' for this call because of ${SIP_CODEC} variable\n", codec); 05321 if (p->jointcapability & fmt) { 05322 p->jointcapability &= fmt; 05323 p->capability &= fmt; 05324 } else 05325 ast_log(LOG_NOTICE, "Ignoring ${SIP_CODEC} variable because it is not shared by both ends.\n"); 05326 } else 05327 ast_log(LOG_NOTICE, "Ignoring ${SIP_CODEC} variable because of unrecognized/not configured codec (check allow/disallow in sip.conf): %s\n", codec); 05328 return; 05329 }
| static int unload_module | ( | void | ) | [static] |
PBX unload module API.
Definition at line 23480 of file chan_sip.c.
References ao2_iterator_init(), ao2_t_iterator_next, ao2_t_ref, ast_channel_unregister(), ast_cli_unregister_multiple(), ast_context_destroy(), ast_context_find(), ast_custom_function_unregister(), ast_free, ast_free_ha(), AST_LIST_LOCK, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_manager_unregister(), ast_mutex_lock(), ast_mutex_unlock(), AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_rtp_proto_unregister(), ast_sched_dump(), ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, ast_tcptls_server_stop(), ast_udptl_proto_unregister(), ast_unload_realtime(), ast_unregister_application(), ASTOBJ_CONTAINER_DESTROY, ASTOBJ_CONTAINER_DESTROYALL, authl, ast_tls_config::cafile, ast_tls_config::capath, ast_tls_config::certfile, checksipdomain_function, ast_tls_config::cipher, clear_realm_authentication(), clear_sip_domains(), cli_sip, default_tls_cfg, dialog_unlink_all(), dialogs, localaddr, ast_tcptls_session_args::master, monlock, sip_pvt::owner, peers_by_ip, regl, sched, sched_context_destroy(), sip_header_function, sip_registry_destroy(), sip_rtp, sip_tcp_desc, sip_tech, sip_tls_desc, sip_udptl, sipchaninfo_function, sippeer_function, sipsock, sip_threadinfo::stop, thread, sip_threadinfo::threadid, and TRUE.
23481 { 23482 struct sip_pvt *p; 23483 struct sip_threadinfo *th; 23484 struct ast_context *con; 23485 struct ao2_iterator i; 23486 23487 ast_sched_dump(sched); 23488 23489 /* First, take us out of the channel type list */ 23490 ast_channel_unregister(&sip_tech); 23491 23492 /* Unregister dial plan functions */ 23493 ast_custom_function_unregister(&sipchaninfo_function); 23494 ast_custom_function_unregister(&sippeer_function); 23495 ast_custom_function_unregister(&sip_header_function); 23496 ast_custom_function_unregister(&checksipdomain_function); 23497 23498 /* Unregister dial plan applications */ 23499 ast_unregister_application(app_dtmfmode); 23500 ast_unregister_application(app_sipaddheader); 23501 23502 /* Unregister CLI commands */ 23503 ast_cli_unregister_multiple(cli_sip, sizeof(cli_sip) / sizeof(struct ast_cli_entry)); 23504 23505 /* Disconnect from the RTP subsystem */ 23506 ast_rtp_proto_unregister(&sip_rtp); 23507 23508 /* Disconnect from UDPTL */ 23509 ast_udptl_proto_unregister(&sip_udptl); 23510 23511 /* Unregister AMI actions */ 23512 ast_manager_unregister("SIPpeers"); 23513 ast_manager_unregister("SIPshowpeer"); 23514 ast_manager_unregister("SIPqualifypeer"); 23515 ast_manager_unregister("SIPshowregistry"); 23516 ast_manager_unregister("SIPnotify"); 23517 23518 /* Kill TCP/TLS server threads */ 23519 if (sip_tcp_desc.master) 23520 ast_tcptls_server_stop(&sip_tcp_desc); 23521 if (sip_tls_desc.master) 23522 ast_tcptls_server_stop(&sip_tls_desc); 23523 23524 /* Kill all existing TCP/TLS threads */ 23525 AST_LIST_LOCK(&threadl); 23526 AST_LIST_TRAVERSE_SAFE_BEGIN(&threadl, th, list) { 23527 pthread_t thread = th->threadid; 23528 th->stop = 1; 23529 AST_LIST_UNLOCK(&threadl); 23530 pthread_kill(thread, SIGURG); 23531 pthread_join(thread, NULL); 23532 AST_LIST_LOCK(&threadl); 23533 } 23534 AST_LIST_TRAVERSE_SAFE_END; 23535 AST_LIST_UNLOCK(&threadl); 23536 23537 /* Hangup all dialogs if they have an owner */ 23538 i = ao2_iterator_init(dialogs, 0); 23539 while ((p = ao2_t_iterator_next(&i, "iterate thru dialogs"))) { 23540 if (p->owner) 23541 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD); 23542 ao2_t_ref(p, -1, "toss dialog ptr from iterator_next"); 23543 } 23544 23545 ast_mutex_lock(&monlock); 23546 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) { 23547 pthread_cancel(monitor_thread); 23548 pthread_kill(monitor_thread, SIGURG); 23549 pthread_join(monitor_thread, NULL); 23550 } 23551 monitor_thread = AST_PTHREADT_STOP; 23552 ast_mutex_unlock(&monlock); 23553 23554 /* Destroy all the dialogs and free their memory */ 23555 i = ao2_iterator_init(dialogs, 0); 23556 while ((p = ao2_t_iterator_next(&i, "iterate thru dialogs"))) { 23557 dialog_unlink_all(p, TRUE, TRUE); 23558 ao2_t_ref(p, -1, "throw away iterator result"); 23559 } 23560 23561 /* Free memory for local network address mask */ 23562 ast_free_ha(localaddr); 23563 23564 clear_realm_authentication(authl); 23565 23566 23567 if (default_tls_cfg.certfile) 23568 ast_free(default_tls_cfg.certfile); 23569 if (default_tls_cfg.cipher) 23570 ast_free(default_tls_cfg.cipher); 23571 if (default_tls_cfg.cafile) 23572 ast_free(default_tls_cfg.cafile); 23573 if (default_tls_cfg.capath) 23574 ast_free(default_tls_cfg.capath); 23575 23576 ASTOBJ_CONTAINER_DESTROYALL(®l, sip_registry_destroy); 23577 ASTOBJ_CONTAINER_DESTROY(®l); 23578 23579 ao2_t_ref(peers, -1, "unref the peers table"); 23580 ao2_t_ref(peers_by_ip, -1, "unref the peers_by_ip table"); 23581 ao2_t_ref(dialogs, -1, "unref the dialogs table"); 23582 23583 clear_sip_domains(); 23584 close(sipsock); 23585 sched_context_destroy(sched); 23586 con = ast_context_find(used_context); 23587 if (con) 23588 ast_context_destroy(con, "SIP"); 23589 ast_unload_realtime("sipregs"); 23590 ast_unload_realtime("sippeers"); 23591 23592 return 0; 23593 }
| static void* unref_peer | ( | struct sip_peer * | peer, | |
| char * | tag | |||
| ) | [static] |
helper functions to unreference various types of objects. By handling them this way, we don't have to declare the destructor on each call, which removes the chance of errors.
Definition at line 2491 of file chan_sip.c.
References ao2_t_ref.
Referenced by __sip_autodestruct(), __sip_destroy(), _sip_qualify_peer(), _sip_show_peer(), _sip_show_peers(), build_peer(), check_peer_ok(), complete_sip_peer(), complete_sip_registered_peer(), complete_sip_user(), create_addr(), expire_register(), function_sippeer(), handle_request_subscribe(), handle_response_peerpoke(), parse_register_contact(), reg_source_db(), register_verify(), sip_devicestate(), sip_do_debug_peer(), sip_peer_hold(), sip_poke_all_peers(), sip_poke_noanswer(), sip_poke_peer(), sip_poke_peer_s(), sip_prune_realtime(), sip_show_inuse(), sip_show_user(), sip_show_users(), sip_unregister(), st_get_mode(), st_get_refresher(), st_get_se(), and update_call_counter().
02492 { 02493 ao2_t_ref(peer, -1, tag); 02494 return NULL; 02495 }
| static int update_call_counter | ( | struct sip_pvt * | fup, | |
| int | event | |||
| ) | [static] |
update_call_counter: Handle call_limit for SIP devices Setting a call-limit will cause calls above the limit not to be accepted.
Remember that for a type=friend, there's one limit for the user and another for the peer, not a combined call limit. This will cause unexpected behaviour in subscriptions, since a "friend" is *two* devices in Asterisk, not one.
Thought: For realtime, we should probably update storage with inuse counter...
Definition at line 4804 of file chan_sip.c.
References ao2_lock(), ao2_unlock(), ast_clear_flag, ast_copy_string(), ast_debug, AST_DEVICE_UNKNOWN, ast_devstate_changed(), ast_log(), ast_set_flag, ast_strlen_zero(), ast_test_flag, sip_peer::call_limit, DEC_CALL_LIMIT, DEC_CALL_RINGING, FALSE, find_peer(), FINDALLDEVICES, sip_pvt::flags, INC_CALL_LIMIT, INC_CALL_RINGING, sip_peer::inRinging, sip_peer::inUse, inuse, LOG_ERROR, sip_peer::name, name, sip_pvt::outgoing_call, sip_pvt::peername, SIP_CALL_LIMIT, SIP_INC_COUNT, SIP_INC_RINGING, SIP_PAGE2_CALL_ONHOLD, sip_peer_hold(), sip_pvt_lock, sip_pvt_unlock, TRUE, unref_peer(), and sip_pvt::username.
Referenced by __sip_destroy(), handle_request_cancel(), handle_request_invite(), handle_response_invite(), sip_call(), and sip_hangup().
04805 { 04806 char name[256]; 04807 int *inuse = NULL, *call_limit = NULL, *inringing = NULL; 04808 int outgoing = fup->outgoing_call; 04809 struct sip_peer *p = NULL; 04810 04811 ast_debug(3, "Updating call counter for %s call\n", outgoing ? "outgoing" : "incoming"); 04812 04813 04814 /* Test if we need to check call limits, in order to avoid 04815 realtime lookups if we do not need it */ 04816 if (!ast_test_flag(&fup->flags[0], SIP_CALL_LIMIT) && !ast_test_flag(&fup->flags[1], SIP_PAGE2_CALL_ONHOLD)) 04817 return 0; 04818 04819 ast_copy_string(name, fup->username, sizeof(name)); 04820 04821 /* Check the list of devices */ 04822 if ( (p = find_peer(ast_strlen_zero(fup->peername) ? name : fup->peername, NULL, TRUE, FINDALLDEVICES, FALSE) ) ) { /* Try to find peer */ 04823 inuse = &p->inUse; 04824 call_limit = &p->call_limit; 04825 inringing = &p->inRinging; 04826 ast_copy_string(name, fup->peername, sizeof(name)); 04827 } 04828 if (!p) { 04829 ast_debug(2, "%s is not a local device, no call limit\n", name); 04830 return 0; 04831 } 04832 04833 switch(event) { 04834 /* incoming and outgoing affects the inUse counter */ 04835 case DEC_CALL_LIMIT: 04836 /* Decrement inuse count if applicable */ 04837 if (inuse) { 04838 sip_pvt_lock(fup); 04839 ao2_lock(p); 04840 if (*inuse > 0) { 04841 if (ast_test_flag(&fup->flags[0], SIP_INC_COUNT)) { 04842 (*inuse)--; 04843 ast_clear_flag(&fup->flags[0], SIP_INC_COUNT); 04844 } 04845 } else { 04846 *inuse = 0; 04847 } 04848 ao2_unlock(p); 04849 sip_pvt_unlock(fup); 04850 } 04851 04852 /* Decrement ringing count if applicable */ 04853 if (inringing) { 04854 sip_pvt_lock(fup); 04855 ao2_lock(p); 04856 if (*inringing > 0) { 04857 if (ast_test_flag(&fup->flags[0], SIP_INC_RINGING)) { 04858 (*inringing)--; 04859 ast_clear_flag(&fup->flags[0], SIP_INC_RINGING); 04860 } 04861 } else { 04862 *inringing = 0; 04863 } 04864 ao2_unlock(p); 04865 sip_pvt_unlock(fup); 04866 } 04867 04868 /* Decrement onhold count if applicable */ 04869 sip_pvt_lock(fup); 04870 ao2_lock(p); 04871 if (ast_test_flag(&fup->flags[1], SIP_PAGE2_CALL_ONHOLD) && global_notifyhold) { 04872 ast_clear_flag(&fup->flags[1], SIP_PAGE2_CALL_ONHOLD); 04873 ao2_unlock(p); 04874 sip_pvt_unlock(fup); 04875 sip_peer_hold(fup, FALSE); 04876 } else { 04877 ao2_unlock(p); 04878 sip_pvt_unlock(fup); 04879 } 04880 if (sipdebug) 04881 ast_debug(2, "Call %s %s '%s' removed from call limit %d\n", outgoing ? "to" : "from", "peer", name, *call_limit); 04882 break; 04883 04884 case INC_CALL_RINGING: 04885 case INC_CALL_LIMIT: 04886 /* If call limit is active and we have reached the limit, reject the call */ 04887 if (*call_limit > 0 ) { 04888 if (*inuse >= *call_limit) { 04889 ast_log(LOG_ERROR, "Call %s %s '%s' rejected due to usage limit of %d\n", outgoing ? "to" : "from", "peer", name, *call_limit); 04890 unref_peer(p, "update_call_counter: unref peer p, call limit exceeded"); 04891 return -1; 04892 } 04893 } 04894 if (inringing && (event == INC_CALL_RINGING)) { 04895 sip_pvt_lock(fup); 04896 ao2_lock(p); 04897 if (!ast_test_flag(&fup->flags[0], SIP_INC_RINGING)) { 04898 (*inringing)++; 04899 ast_set_flag(&fup->flags[0], SIP_INC_RINGING); 04900 } 04901 ao2_unlock(p); 04902 sip_pvt_unlock(fup); 04903 } 04904 if (inuse) { 04905 sip_pvt_lock(fup); 04906 ao2_lock(p); 04907 if (!ast_test_flag(&fup->flags[0], SIP_INC_COUNT)) { 04908 (*inuse)++; 04909 ast_set_flag(&fup->flags[0], SIP_INC_COUNT); 04910 } 04911 ao2_unlock(p); 04912 sip_pvt_unlock(fup); 04913 } 04914 if (sipdebug) { 04915 ast_debug(2, "Call %s %s '%s' is %d out of %d\n", outgoing ? "to" : "from", "peer", name, *inuse, *call_limit); 04916 } 04917 break; 04918 04919 case DEC_CALL_RINGING: 04920 if (inringing) { 04921 sip_pvt_lock(fup); 04922 ao2_lock(p); 04923 if (ast_test_flag(&fup->flags[0], SIP_INC_RINGING)) { 04924 if (*inringing > 0) { 04925 (*inringing)--; 04926 } 04927 ast_clear_flag(&fup->flags[0], SIP_INC_RINGING); 04928 } 04929 ao2_unlock(p); 04930 sip_pvt_unlock(fup); 04931 } 04932 break; 04933 04934 default: 04935 ast_log(LOG_ERROR, "update_call_counter(%s, %d) called with no event!\n", name, event); 04936 } 04937 04938 if (p) { 04939 ast_devstate_changed(AST_DEVICE_UNKNOWN, "SIP/%s", p->name); 04940 unref_peer(p, "update_call_counter: unref_peer from call counter"); 04941 } 04942 return 0; 04943 }
| static void update_peer | ( | struct sip_peer * | p, | |
| int | expire | |||
| ) | [static] |
Update peer data in database (if used).
Definition at line 3903 of file chan_sip.c.
References sip_peer::addr, ast_test_flag, sip_peer::deprecated_username, sip_peer::flags, sip_peer::fullcontact, sip_peer::is_realtime, sip_peer::lastms, sip_peer::name, sip_settings::peer_rtupdate, realtime_update_peer(), sip_cfg, SIP_PAGE2_RTCACHEFRIENDS, sip_peer::useragent, and sip_peer::username.
Referenced by register_verify().
03904 { 03905 int rtcachefriends = ast_test_flag(&p->flags[1], SIP_PAGE2_RTCACHEFRIENDS); 03906 if (sip_cfg.peer_rtupdate && 03907 (p->is_realtime || rtcachefriends)) { 03908 realtime_update_peer(p->name, &p->addr, p->username, rtcachefriends ? p->fullcontact : NULL, p->useragent, expire, p->deprecated_username, p->lastms); 03909 } 03910 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, } [static] |
Definition at line 23599 of file chan_sip.c.
int allow_external_domains [static] |
Accept calls to external SIP domains?
Definition at line 790 of file chan_sip.c.
int apeerobjs = 0 [static] |
Autocreated peer objects
Definition at line 823 of file chan_sip.c.
char* app_dtmfmode = "SIPDtmfMode" [static] |
Definition at line 23065 of file chan_sip.c.
char* app_sipaddheader = "SIPAddHeader" [static] |
Definition at line 23067 of file chan_sip.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 23599 of file chan_sip.c.
Authentication list for realm authentication.
Definition at line 1772 of file chan_sip.c.
Referenced by build_reply_digest(), reload_config(), sip_show_settings(), and unload_module().
int autocreatepeer [static] |
Auto creation of peers at registration? Default off.
Definition at line 760 of file chan_sip.c.
struct sockaddr_in bindaddr [static] |
UDP: The address we bind to
Definition at line 1793 of file chan_sip.c.
struct ast_threadstorage check_auth_buf = { .once = PTHREAD_ONCE_INIT, .key_init = __init_check_auth_buf , .custom_init = NULL , } [static] |
Definition at line 10882 of file chan_sip.c.
Referenced by check_auth(), and transmit_fake_auth_response().
struct ast_custom_function checksipdomain_function [static] |
struct ast_cli_entry cli_sip[] [static] |
SIP Cli commands definition.
Definition at line 23360 of file chan_sip.c.
Referenced by load_module(), and unload_module().
struct ast_cli_entry cli_sip_do_history_deprecated = { .handler = sip_do_history_deprecated , .summary = "Enable/Disable SIP history" ,__VA_ARGS__ } [static] |
Definition at line 23358 of file chan_sip.c.
int compactheaders [static] |
send compact sip headers
Definition at line 782 of file chan_sip.c.
const char config[] = "sip.conf" [static] |
Main configuration file
Definition at line 287 of file chan_sip.c.
struct sockaddr_in debugaddr [static] |
Definition at line 1838 of file chan_sip.c.
char default_callerid[AST_MAX_EXTENSION] [static] |
Definition at line 726 of file chan_sip.c.
char default_context[AST_MAX_CONTEXT] [static] |
Definition at line 723 of file chan_sip.c.
int default_expiry = DEFAULT_DEFAULT_EXPIRY [static] |
Definition at line 244 of file chan_sip.c.
char default_fromdomain[AST_MAX_EXTENSION] [static] |
Definition at line 727 of file chan_sip.c.
struct ast_jb_conf default_jbconf [static] |
Global jitterbuffer configuration - by default, jb is disabled.
Definition at line 278 of file chan_sip.c.
char default_language[MAX_LANGUAGE] [static] |
Definition at line 725 of file chan_sip.c.
int default_maxcallbitrate [static] |
Maximum bitrate for call
Definition at line 735 of file chan_sip.c.
char default_mohinterpret[MAX_MUSICCLASS] [static] |
Global setting for moh class to use when put on hold
Definition at line 731 of file chan_sip.c.
char default_mohsuggest[MAX_MUSICCLASS] [static] |
Global setting for moh class to suggest when putting a bridged channel on hold
Definition at line 732 of file chan_sip.c.
char default_notifymime[AST_MAX_EXTENSION] [static] |
Definition at line 728 of file chan_sip.c.
char default_parkinglot[AST_MAX_CONTEXT] [static] |
Parkinglot
Definition at line 734 of file chan_sip.c.
struct ast_codec_pref default_prefs [static] |
Default codec prefs
Definition at line 736 of file chan_sip.c.
Referenced by build_device(), reload_config(), set_peer_defaults(), sip_alloc(), sip_show_settings(), and temp_peer().
int default_qualify [static] |
Default Qualify= setting
Definition at line 729 of file chan_sip.c.
char default_subscribecontext[AST_MAX_CONTEXT] [static] |
Definition at line 724 of file chan_sip.c.
struct ast_tls_config default_tls_cfg [static] |
Default TLS connection configuration.
Definition at line 2294 of file chan_sip.c.
Referenced by reload_config(), sip_prepare_socket(), sip_show_settings(), and unload_module().
char default_vmexten[AST_MAX_EXTENSION] [static] |
Definition at line 730 of file chan_sip.c.
char* descrip_dtmfmode = " SIPDtmfMode(inband|info|rfc2833): Changes the dtmfmode for a SIP call\n" [static] |
Definition at line 23064 of file chan_sip.c.
char* descrip_sipaddheader [static] |
Definition at line 23070 of file chan_sip.c.
| 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.
Definition at line 1419 of file chan_sip.c.
Referenced by complete_sipch(), create_addr_from_peer(), dialog_needdestroy(), dialog_unlink_all(), do_monitor(), find_call(), get_sip_pvt_byid_locked(), handle_request_subscribe(), load_module(), manager_sipnotify(), sip_alloc(), sip_cli_notify(), sip_poke_peer(), sip_request_call(), sip_send_mwi_to_peer(), sip_show_channel(), sip_show_channels(), sip_show_channelstats(), sip_show_history(), sip_show_objects(), and unload_module().
mapping between dtmf flags and strings
Definition at line 13171 of file chan_sip.c.
Referenced by conf_run(), dtmfmode2str(), handle_link_data(), handle_remote_data(), send_dtmf(), and str2dtmfmode().
int dumphistory [static] |
Dump history to verbose before destroying SIP dialog
Definition at line 784 of file chan_sip.c.
time_t externexpire [static] |
Expiration counter for re-resolving external host name in dynamic DNS
Definition at line 1824 of file chan_sip.c.
Referenced by ast_sip_ouraddrfor().
char externhost[MAXHOSTNAMELEN] [static] |
External host name
Definition at line 1823 of file chan_sip.c.
Referenced by ast_sip_ouraddrfor(), and sip_show_settings().
struct sockaddr_in externip [static] |
our external IP address/port for SIP sessions. externip.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:
+ with "externip = host[:port]" we specify the address/port explicitly. The address is looked up only once when (re)loading the config file;
+ with "externhost = host[:port]" we do a similar thing, but the hostname is stored in externhost, and the hostname->IP mapping is refreshed every 'externrefresh' seconds;
+ with "stunaddr = host[:port]" we run queries every externrefresh seconds to the specified server, and store the result in externip.
Other variables (externhost, externexpire, externrefresh) are used to support the above functions. External IP address if we are behind NAT
Definition at line 1821 of file chan_sip.c.
int externrefresh = 10 [static] |
Definition at line 1825 of file chan_sip.c.
Referenced by ast_sip_ouraddrfor(), and sip_show_settings().
int global_allowguest [static] |
allow unauthenticated peers to connect?
Definition at line 768 of file chan_sip.c.
int global_allowsubscribe [static] |
Flag for disabling ALL subscriptions, this is FALSE only if all peers are FALSE the global setting is in globals_flags[1]
Definition at line 772 of file chan_sip.c.
enum transfermodes global_allowtransfer [static] |
SIP Refer restriction scheme
Definition at line 798 of file chan_sip.c.
int global_alwaysauthreject [static] |
Send 401 Unauthorized for all failing requests
Definition at line 757 of file chan_sip.c.
int global_authfailureevents [static] |
Whether we send authentication failure manager events or not. Default no.
Definition at line 792 of file chan_sip.c.
int global_autoframing [static] |
Turn autoframing on or off.
Definition at line 797 of file chan_sip.c.
int global_callcounter [static] |
Enable call counters for all devices. This is currently enabled by setting the peer call-limit to 999. When we remove the call-limit from the code, we can make it with just a boolean flag in the device structure
Definition at line 769 of file chan_sip.c.
int global_callevents [static] |
Whether we send manager events or not
Definition at line 791 of file chan_sip.c.
int global_capability = AST_FORMAT_ULAW | AST_FORMAT_ALAW | AST_FORMAT_GSM | AST_FORMAT_H263 [static] |
struct ast_ha* global_contact_ha = NULL [static] |
Global list of addresses dynamic peers are not allowed to use.
Definition at line 815 of file chan_sip.c.
Referenced by build_peer(), parse_register_contact(), and reload_config().
unsigned int global_cos_audio [static] |
802.1p class of service for audio RTP packets
Definition at line 779 of file chan_sip.c.
unsigned int global_cos_sip [static] |
802.1p class of service for SIP packets
Definition at line 778 of file chan_sip.c.
unsigned int global_cos_text [static] |
802.1p class of service for text RTP packets
Definition at line 781 of file chan_sip.c.
unsigned int global_cos_video [static] |
802.1p class of service for video RTP packets
Definition at line 780 of file chan_sip.c.
int global_directrtpsetup [static] |
Enable support for Direct RTP setup (no re-invites)
Definition at line 753 of file chan_sip.c.
int global_dynamic_exclude_static = 0 [static] |
Definition at line 816 of file chan_sip.c.
struct ast_flags global_flags[2] = {{0}} [static] |
global SIP_ flags
Definition at line 827 of file chan_sip.c.
Referenced by build_peer(), build_radius_record(), get_destination(), load_module(), load_moh_classes(), local_ast_moh_start(), set_peer_defaults(), sip_alloc(), sip_show_settings(), and transmit_response_using_temp().
struct ast_jb_conf global_jbconf [static] |
Global jitterbuffer configuration
Definition at line 285 of file chan_sip.c.
int global_match_auth_username [static] |
Match auth username if available instead of From: Default off.
Definition at line 761 of file chan_sip.c.
int global_matchexterniplocally [static] |
Match externip/externhost setting against localnet setting
Definition at line 800 of file chan_sip.c.
int global_max_se [static] |
Highest threshold for session refresh interval
Definition at line 810 of file chan_sip.c.
int global_min_se [static] |
Lowest threshold for session refresh interval
Definition at line 809 of file chan_sip.c.
int global_notifyhold [static] |
Send notifications on hold
Definition at line 756 of file chan_sip.c.
int global_notifyringing [static] |
Send notifications on ringing
Definition at line 755 of file chan_sip.c.
struct sip_proxy global_outboundproxy [static] |
Outbound proxy
Definition at line 799 of file chan_sip.c.
Referenced by obproxy_get(), ref_proxy(), and sip_show_settings().
int global_qualifyfreq [static] |
Qualify frequency
Definition at line 801 of file chan_sip.c.
char global_realm[MAXHOSTNAMELEN] [static] |
Default realm
Definition at line 785 of file chan_sip.c.
int global_reg_timeout [static] |
Definition at line 766 of file chan_sip.c.
int global_regattempts_max [static] |
Registration attempts before giving up
Definition at line 767 of file chan_sip.c.
char global_regcontext[AST_MAX_CONTEXT] [static] |
Context for auto-extensions
Definition at line 786 of file chan_sip.c.
int global_regextenonqualify [static] |
Whether to add/remove regexten when qualifying peers
Definition at line 796 of file chan_sip.c.
int global_relaxdtmf [static] |
Relax DTMF
Definition at line 762 of file chan_sip.c.
int global_rtautoclear [static] |
Realtime ??
Definition at line 754 of file chan_sip.c.
int global_rtpholdtimeout [static] |
Time out call if no RTP during hold
Definition at line 764 of file chan_sip.c.
int global_rtpkeepalive [static] |
Send RTP keepalives
Definition at line 765 of file chan_sip.c.
int global_rtptimeout [static] |
Time out call if no RTP
Definition at line 763 of file chan_sip.c.
char global_sdpowner[AST_MAX_EXTENSION] [static] |
SDP owner name for the SIP channel
Definition at line 789 of file chan_sip.c.
char global_sdpsession[AST_MAX_EXTENSION] [static] |
SDP session name for the SIP channel
Definition at line 788 of file chan_sip.c.
int global_srvlookup [static] |
SRV Lookup on or off. Default is on
Definition at line 758 of file chan_sip.c.
enum st_mode global_st_mode [static] |
Mode of operation for Session-Timers
Definition at line 807 of file chan_sip.c.
enum st_refresher global_st_refresher [static] |
Session-Timer refresher
Definition at line 808 of file chan_sip.c.
int global_t1 [static] |
T1 time
Definition at line 793 of file chan_sip.c.
int global_t1min [static] |
T1 roundtrip time minimum
Definition at line 794 of file chan_sip.c.
int global_t38_capability = T38FAX_VERSION_0 | T38FAX_RATE_2400 | T38FAX_RATE_4800 | T38FAX_RATE_7200 | T38FAX_RATE_9600 [static] |
Definition at line 1120 of file chan_sip.c.
int global_timer_b [static] |
Timer B - RFC 3261 Section 17.1.1.2
Definition at line 795 of file chan_sip.c.
unsigned int global_tos_audio [static] |
IP type of service for audio RTP packets
Definition at line 775 of file chan_sip.c.
unsigned int global_tos_sip [static] |
IP type of service for SIP packets
Definition at line 774 of file chan_sip.c.
unsigned int global_tos_text [static] |
IP type of service for text RTP packets
Definition at line 777 of file chan_sip.c.
unsigned int global_tos_video [static] |
IP type of service for video RTP packets
Definition at line 776 of file chan_sip.c.
char global_useragent[AST_MAX_EXTENSION] [static] |
Useragent for the SIP channel
Definition at line 787 of file chan_sip.c.
int hash_dialog_size = 563 [static] |
int hash_peer_size = 563 [static] |
Size of peer hash table, prime number preferred!
Definition at line 1659 of file chan_sip.c.
Referenced by load_module().
int hash_user_size = 563 [static] |
Definition at line 1661 of file chan_sip.c.
struct _map_x_s insecurestr[] [static] |
struct sockaddr_in internip [static] |
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.
Definition at line 1801 of file chan_sip.c.
struct invstate2stringtable invitestate2string[] [static] |
Readable descriptions of device states.
Referenced by show_chanstats_cb().
struct io_context* io [static] |
The IO context
Definition at line 847 of file chan_sip.c.
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.
List of local networks, on the same side of NAT as this Asterisk
Definition at line 1834 of file chan_sip.c.
Referenced by ast_sip_ouraddrfor(), sip_show_settings(), and unload_module().
char mandescr_show_peer[] [static] |
Initial value:
"Description: Show one SIP peer with details on current status.\n" "Variables: \n" " Peer: <name> The peer name you want to check.\n" " ActionID: <id> Optional action ID for this AMI transaction.\n"
Definition at line 13503 of file chan_sip.c.
Referenced by load_module().
char mandescr_show_peers[] [static] |
char mandescr_show_registry[] [static] |
Manager Action SIPShowRegistry description.
Definition at line 12837 of file chan_sip.c.
Referenced by load_module().
char mandescr_sipnotify[] [static] |
int max_expiry = DEFAULT_MAX_EXPIRY [static] |
Maximum accepted registration time
Definition at line 243 of file chan_sip.c.
int min_expiry = DEFAULT_MIN_EXPIRY [static] |
Minimum accepted registration time
Definition at line 242 of file chan_sip.c.
pthread_t monitor_thread = AST_PTHREADT_NULL [static] |
This is the thread for the monitor which checks for input on the channels which are not currently in use.
Definition at line 841 of file chan_sip.c.
ast_mutex_t monlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
Protect the monitoring thread, so only one process can kill or start it, and not when it's doing something critical.
Definition at line 835 of file chan_sip.c.
ast_mutex_t netlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
Definition at line 831 of file chan_sip.c.
const char notify_config[] = "sip_notify.conf" [static] |
Configuration file for sending Notify with CLI commands to reconfigure or reboot phones
Definition at line 288 of file chan_sip.c.
struct ast_config* notify_types [static] |
The list of manual NOTIFY types we know how to send
Definition at line 1840 of file chan_sip.c.
Referenced by complete_sipnotify(), and sip_cli_notify().
int ourport_tcp [static] |
The port used for TCP connections
Definition at line 1836 of file chan_sip.c.
Referenced by _sip_tcp_helper_thread().
int ourport_tls [static] |
The port used for TCP/TLS connections
Definition at line 1837 of file chan_sip.c.
Referenced by _sip_tcp_helper_thread().
int pedanticsipchecking [static] |
Extra checking ? Default off
Definition at line 759 of file chan_sip.c.
| struct ao2_container* peers |
| struct ao2_container* peers_by_ip |
Definition at line 1669 of file chan_sip.c.
Referenced by expire_register(), find_peer(), load_module(), parse_register_contact(), register_verify(), sip_prune_realtime(), and unload_module().
int recordhistory [static] |
Record SIP history. Off by default
Definition at line 783 of file chan_sip.c.
struct _map_x_s referstatusstrings[] [static] |
struct ast_register_list regl [static] |
The register list: Other SIP proxies we register with and place calls to.
Referenced by load_module(), manager_show_registry(), reload_config(), sip_register(), sip_send_all_registers(), sip_show_objects(), sip_show_registry(), and unload_module().
int regobjs = 0 [static] |
Registry objects
Definition at line 824 of file chan_sip.c.
struct _map_x_s regstatestrings[] [static] |
int rpeerobjs = 0 [static] |
Realtime peers
Definition at line 822 of file chan_sip.c.
struct sched_context* sched [static] |
The scheduling context
Definition at line 846 of file chan_sip.c.
struct sip_settings sip_cfg [static] |
Definition at line 745 of file chan_sip.c.
Referenced by build_peer(), destroy_association(), handle_response_peerpoke(), realtime_update_peer(), sip_poke_noanswer(), sip_show_settings(), and update_peer().
struct ast_custom_function sip_header_function [static] |
struct cfsip_methods sip_methods[] [static] |
The core structure to setup dialogs. We parse incoming messages by using structure and then route the messages according to the type.
Referenced by __sip_autodestruct(), __sip_destroy(), __sip_pretend_ack(), __sip_semi_ack(), build_reply_digest(), check_auth(), dialog_needdestroy(), do_proxy_auth(), find_call(), find_call_cb(), find_sip_method(), get_destination(), handle_incoming(), handle_request_bye(), handle_request_invite(), handle_request_register(), handle_request_subscribe(), handle_response(), init_req(), initialize_initreq(), initreqprep(), method_match(), reqprep(), retrans_pkt(), send_request(), send_response(), sip_alloc(), sip_scheddestroy(), and transmit_register().
struct cfsip_options sip_options[] [static] |
List of well-known SIP options. If we get this in a require, we should check the list and answer accordingly.
Referenced by _sip_show_peer(), parse_sip_options(), and sip_show_channel().
ast_mutex_t sip_reload_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
int sip_reloading = FALSE [static] |
Flag for avoiding multiple reloads at the same time
Definition at line 843 of file chan_sip.c.
enum channelreloadreason sip_reloadreason [static] |
Reason for last reload/load of configuration
Definition at line 844 of file chan_sip.c.
struct ast_rtp_protocol sip_rtp [static] |
Interface structure with callbacks used to connect to RTP module.
Definition at line 2349 of file chan_sip.c.
Referenced by load_module(), and unload_module().
struct ast_tcptls_session_args sip_tcp_desc [static] |
The TCP server definition.
Definition at line 2297 of file chan_sip.c.
Referenced by reload_config(), sip_show_settings(), transmit_register(), and unload_module().
struct ast_channel_tech sip_tech [static] |
Definition of this channel for PBX channel registration.
Definition at line 2253 of file chan_sip.c.
Referenced by load_module(), sip_new(), and unload_module().
struct ast_channel_tech sip_tech_info [static] |
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.
Definition at line 2287 of file chan_sip.c.
Referenced by load_module(), and sip_new().
struct ast_tls_config sip_tls_cfg [static] |
struct ast_tcptls_session_args sip_tls_desc [static] |
The TCP/TLS server definition.
Definition at line 2308 of file chan_sip.c.
Referenced by reload_config(), sip_show_settings(), and unload_module().
struct ast_udptl_protocol sip_udptl [static] |
Initial value:
{
type: "SIP",
get_udptl_info: sip_get_udptl_peer,
set_udptl_peer: sip_set_udptl_peer,
}
Definition at line 2610 of file chan_sip.c.
Referenced by load_module(), and unload_module().
struct ast_custom_function sipchaninfo_function [static] |
Structure to declare a dialplan function: SIPCHANINFO.
Definition at line 15707 of file chan_sip.c.
Referenced by load_module(), and unload_module().
enum sip_debug_e sipdebug [static] |
Definition at line 1135 of file chan_sip.c.
int sipdebug_text [static] |
extra debugging for 'text' related events. At the moment this is set together with sip_debug_console.
Definition at line 1141 of file chan_sip.c.
Structure to declare a dialplan function: SIPPEER.
Definition at line 15616 of file chan_sip.c.
Referenced by load_module(), and unload_module().
int sipsock = -1 [static] |
Main socket for SIP communication.
sipsock is shared between the SIP manager thread (which handles reload requests), the io handler (sipsock_read()) and the user routines that issue writes (using __sip_xmit()). The socket is -1 only when opening fails (this is a permanent condition), or when we are handling a reload() that changes its address (this is a transient situation during which we might have a harmless race, see below). Because the conditions for the race to be possible are extremely rare, we don't want to pay the cost of locking on every I/O. Rather, we remember that when the race may occur, communication is bound to fail anyways, so we just live with this event and let the protocol handle this above us.
Definition at line 1791 of file chan_sip.c.
Referenced by ast_sip_ouraddrfor(), do_monitor(), reg_source_db(), sip_prepare_socket(), sipsock_read(), and unload_module().
int* sipsock_read_id [static] |
ID of IO entry for sipsock FD
Definition at line 848 of file chan_sip.c.
int speerobjs = 0 [static] |
Static peers
Definition at line 821 of file chan_sip.c.
Report Peer status in character string.
Definition at line 12660 of file chan_sip.c.
Referenced by stmode2str(), and str2stmode().
struct _map_x_s strefreshers[] [static] |
Definition at line 12678 of file chan_sip.c.
Referenced by str2strefresher(), and strefresher2str().
struct sockaddr_in stunaddr [static] |
stun server address
Definition at line 1826 of file chan_sip.c.
struct cfsubscription_types subscription_types[] [static] |
Subscription types that we support. We support
Referenced by find_subscription_type(), and subscription_type2str().
char* synopsis_dtmfmode = "Change the dtmfmode for a SIP call" [static] |
Definition at line 23063 of file chan_sip.c.
char* synopsis_sipaddheader = "Add a SIP header to the outbound call" [static] |
Definition at line 23068 of file chan_sip.c.
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] |
name of automatically created context for unloading
Definition at line 828 of file chan_sip.c.
1.4.7