#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 | offered_media |
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 | tcptls_packet |
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 int | global_t38_maxdatagram |
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_FAX_DETECT (1 << 28) |
#define | SIP_PAGE2_FLAGS_TO_COPY |
#define | SIP_PAGE2_HAVEPEERCONTEXT (1 << 3) |
#define | SIP_PAGE2_IGNORESDPVERSION (1 << 19) |
#define | SIP_PAGE2_REGISTERTRYING (1 << 29) |
#define | SIP_PAGE2_RFC2833_COMPENSATE (1 << 25) |
#define | SIP_PAGE2_RPORT_PRESENT (1 << 10) |
#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 (3 << 20) |
#define | SIP_PAGE2_T38SUPPORT_UDPTL (1 << 20) |
#define | SIP_PAGE2_T38SUPPORT_UDPTL_FEC (2 << 20) |
#define | SIP_PAGE2_T38SUPPORT_UDPTL_REDUNDANCY (3 << 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) |
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_dynamic_exclude_static = 0 |
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_prematuremediafilter |
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_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_shrinkcallerid |
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, INFO" |
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 "Anonymous" |
#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 %-15.15s %-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 (%5.2f%%) %-6.6u %-10.10u%-1.1s %-10.10u (%5.2f%%) %-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 %-15.15s %-15.15s %-15.15s %-7.7s %-15.15s %-6.6s\n" |
#define | FORMAT2 "%-15.15s %-11.11s %-8.8s %-10.10s %-10.10s ( %%) %-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 %-15.15s %-15.15s %-15.15s %-13.13s %-15.15s %-10.10s %-6.6s\n" |
#define | FORMAT4 "%-15.15s %-15.15s %-15.15s %-15.15s %-13.13s %-15.15s %-10.10s %-6.6d\n" |
#define | FROMDOMAIN_INVALID "anonymous.invalid" |
#define | INITIAL_CSEQ 101 |
#define | IS_SIP_TECH(t) ((t) == &sip_tech || (t) == &sip_tech_info) |
#define | MAX_AUTHTRIES 3 |
#define | MAX_HISTORY_ENTRIES 50 |
#define | MAX_RETRANS 6 |
#define | NO_RTP 0 |
#define | NOT_SUPPORTED 0 |
#define | PROVIS_KEEPALIVE_TIMEOUT 60000 |
#define | RTP 1 |
#define | SDP_MAX_RTPMAP_CODECS 32 |
#define | SDP_SAMPLE_RATE(x) 8000 |
#define | SIP_MAX_HEADERS 64 |
#define | SIP_MAX_LINES 256 |
#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 | media_type { SDP_AUDIO, SDP_VIDEO, SDP_IMAGE, SDP_TEXT } |
enum | parse_register_result { PARSE_REGISTER_DENIED, 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_tcptls_alert { TCPTLS_ALERT_DATA, TCPTLS_ALERT_STOP } |
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_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 int | __sip_ack (struct sip_pvt *p, int seqno, int resp, int sipmethod) |
Acknowledges receipt of a packet and stops retransmission called with p locked. | |
static int | __sip_autodestruct (const void *data) |
Kill a SIP dialog (called only by the scheduler) The scheduler has a reference to this dialog when p->autokillid != -1, and we are called using that reference. So if the event is not rescheduled, we need to call dialog_unref(). | |
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, struct sip_pvt *p) |
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, int devstate_only) |
Build peer from configuration (file or realtime static/dynamic). | |
static int | build_reply_digest (struct sip_pvt *p, int method, char *digest, int digest_len) |
Build reply digest. | |
static void | build_route (struct sip_pvt *p, struct sip_request *req, int backwards) |
Build route list from Record-Route header. | |
static void | build_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 * | faxec2str (int faxec) |
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, int transport) |
Locate device by name or ip address. | |
static struct sip_auth * | find_realm_authentication (struct sip_auth *authlist, const char *realm) |
Find authentication for a specific realm. | |
static int | find_sdp (struct sip_request *req) |
Determine whether a SIP message contains an SDP in its body. | |
static 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_ip_and_port_from_sdp (struct sip_request *req, const enum media_type media, struct sockaddr_in *sin) |
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_iterate (int *start, struct sip_request *req, const char *name) |
Lookup 'name' in the SDP starting at the 'start' line. Returns the matching line, and 'start' is updated with the next line number. | |
static char | get_sdp_line (int *start, int stop, struct sip_request *req, const char **value) |
Fetches the next valid SDP line between the 'start' line (inclusive) and the 'stop' line (exclusive). Returns the type ('a', 'c', ...) and matching line in reference 'start' is updated with the next line number. | |
static struct sip_pvt * | get_sip_pvt_byid_locked (const char *callid, const char *totag, const char *fromtag) |
Lock dialog lock and find matching pvt lock. | |
static const char * | get_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 int | get_transport_str2enum (const char *transport) |
Return int representing a bit field of transport types found in const char *transport. | |
static const char * | gettag (const struct sip_request *req, const char *header, char *tagbuf, int tagbufsize) |
Get tag from packet. | |
static int | handle_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, int *nounlock) |
Handle the transfer part of INVITE with a replaces: header, meaning a target pickup or an attended transfer. Used only once. XXX 'ignore' is unused. | |
static int | handle_request_bye (struct sip_pvt *p, struct sip_request *req) |
Handle incoming BYE request. | |
static int | handle_request_cancel (struct sip_pvt *p, struct sip_request *req) |
Handle incoming CANCEL request. | |
static int | handle_request_do (struct sip_request *req, struct 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 int | handle_t38_options (struct ast_flags *flags, struct ast_flags *mask, struct ast_variable *v, int *maxdatagram) |
Handle T.38 configuration options common to users and peers. | |
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 | interpret_t38_parameters (struct sip_pvt *p, const struct ast_control_t38_parameters *parameters) |
Helper function which updates T.38 capability information and triggers a reinvite. | |
static 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, const char *scheme, char **ret_name, char **pass, char **domain, char **port, char **options, char **transport) |
* 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 int | port_str2int (const char *pt, unsigned int standard) |
converts ascii port to int representation. If no pt buffer is provided or the pt has errors when being converted to an int value, the port provided as the standard is used. | |
static void | print_codec_to_cli (int fd, struct ast_codec_pref *pref) |
Print codec list from preference to CLI/manager. | |
static void | print_group (int fd, ast_group_t group, int crlf) |
Print call group and pickup group. | |
static void | proc_422_rsp (struct sip_pvt *p, struct sip_request *rsp) |
Handle 422 response to INVITE with session-timer requested. | |
static int | proc_session_timer (const void *vp) |
Session-Timers: Process session refresh timeout event. | |
static void | process_request_queue (struct sip_pvt *p, int *recount, int *nounlock) |
static int | process_sdp (struct sip_pvt *p, struct sip_request *req, int t38action) |
Process SIP SDP offer, select formats and activate RTP channels If offer is rejected, we will not change any properties of the call Return 0 on success, a negative value on errors. Must be called after find_sdp(). | |
static int | process_sdp_a_audio (const char *a, struct sip_pvt *p, struct ast_rtp *newaudiortp, int *last_rtpmap_codec) |
static int | process_sdp_a_image (const char *a, struct sip_pvt *p) |
static int | process_sdp_a_sendonly (const char *a, int *sendonly) |
static int | process_sdp_a_text (const char *a, struct sip_pvt *p, struct ast_rtp *newtextrtp, char *red_fmtp, int *red_num_gen, int *red_data_pt, int *last_rtpmap_codec) |
static int | process_sdp_a_video (const char *a, struct sip_pvt *p, struct ast_rtp *newvideortp, int *last_rtpmap_codec) |
static int | process_sdp_c (const char *c, struct ast_hostent *hp) |
static int | process_sdp_o (const char *o, struct sip_pvt *p) |
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_provisional_keepalive (const void *data) |
static int | send_provisional_keepalive_full (struct sip_pvt *pvt, int with_sdp) |
static int | send_provisional_keepalive_with_sdp (const void *data) |
static int | send_request (struct sip_pvt *p, struct sip_request *req, enum xmittype reliable, int seqno) |
Send SIP Request to the other part of the dialogue. | |
static int | send_response (struct sip_pvt *p, struct sip_request *req, enum xmittype reliable, int seqno) |
Transmit response on SIP request. | |
static int | set_address_from_contact (struct sip_pvt *pvt) |
Change the other partys IP address based on given contact. | |
static void | set_destination (struct sip_pvt *p, char *uri) |
Set destination from SIP URI. | |
static void | set_insecure_flags (struct ast_flags *flags, const char *value, int lineno) |
Parse insecure= setting in sip.conf and set flags according to setting. | |
static void | set_nonce_randdata (struct sip_pvt *p, int forceupdate) |
builds the sip_pvt's randdata field which is used for the nonce challenge. When forceupdate is not set, the nonce is only updated if the current one is stale. In this case, a stalenonce is one which has already received a response, if a nonce has not received a response it is not always necessary or beneficial to create a new one. | |
static void | set_peer_defaults (struct sip_peer *peer) |
Set peer defaults before configuring specific configurations. | |
static void | set_socket_transport (struct sip_socket *socket, int transport) |
static void | set_t38_capabilities (struct sip_pvt *p) |
Set the global T38 capabilities on a SIP dialog structure. | |
static int | 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, struct sip_request *req) |
Allocate sip_pvt structure, set defaults and link in the container. Returns a reference to the object so whoever uses it later must remember to release the reference. | |
static void | sip_alreadygone (struct sip_pvt *dialog) |
Encapsulate setting of SIP_ALREADYGONE to be able to trace it with debugging. | |
static int | sip_answer (struct ast_channel *ast) |
sip_answer: Answer SIP call , send 200 OK on Invite Part of PBX interface | |
static int | sip_call (struct ast_channel *ast, char *dest, int timeout) |
Initiate SIP call from PBX used from the dial() application. | |
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 void | sip_tcptls_client_args_destructor (void *obj) |
static int | sip_tcptls_write (struct ast_tcptls_session_instance *tcptls_session, const void *buf, size_t len) |
used to indicate to a tcptls thread that data is ready to be written | |
static struct sip_threadinfo * | sip_threadinfo_create (struct ast_tcptls_session_instance *tcptls_session, int transport) |
creates a sip_threadinfo object and links it into the threadt table. | |
static void | sip_threadinfo_destructor (void *obj) |
static int | sip_transfer (struct ast_channel *ast, const char *dest) |
Transfer SIP call. | |
static char * | sip_unregister (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
Unregister (force expiration) a SIP peer in the registry via CLI. | |
static 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 unsigned int | t38_get_rate (enum ast_control_t38_rate rate) |
Get Max T.38 Transmission rate from T38 capabilities. | |
static void | tcptls_packet_destructor (void *obj) |
static struct sip_peer * | temp_peer (const char *name) |
Create temporary peer (used in autocreatepeer mode). | |
static void | temp_pvt_cleanup (void *) |
static int | temp_pvt_init (void *) |
static char * | terminate_uri (char *uri) |
static int | threadinfo_locate_cb (void *obj, void *arg, int flags) |
static int | threadt_cmp_cb (void *obj, void *arg, int flags) |
static int | threadt_hash_cb (const void *obj, const int flags) |
static char * | transfermode2str (enum transfermodes mode) |
Convert transfer mode to text string. | |
static 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_provisional_response (struct sip_pvt *p, const char *msg, const struct sip_request *req, int with_sdp) |
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). | |
static void | update_provisional_keepalive (struct sip_pvt *pvt, int with_sdp) |
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 unsigned int | chan_idx |
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 _map_x_s | faxecmodes [] |
static struct ast_ha * | global_contact_ha = NULL |
Global list of addresses dynamic peers are not allowed to use. | |
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 = NULL |
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 ao2_container * | threadt |
The table of TCP threads. | |
static struct ast_threadstorage | ts_temp_pvt = { .once = PTHREAD_ONCE_INIT , .key_init = __init_ts_temp_pvt , .custom_init = temp_pvt_init , } |
********** 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, INFO" |
SIP Methods we support.
Definition at line 656 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 2148 of file chan_sip.c.
Referenced by __sip_autodestruct(), __sip_reliable_xmit(), auto_congest(), build_reply_digest(), cb_extensionstate(), check_auth(), do_register_auth(), handle_invite_replaces(), handle_request_bye(), handle_request_do(), handle_request_invite(), handle_request_refer(), handle_request_register(), handle_request_subscribe(), handle_response(), handle_response_invite(), local_attended_transfer(), obproxy_get(), process_sdp(), 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 "Anonymous" |
#define CHECK_AUTH_BUF_INITLEN 256 |
Definition at line 11767 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 2055 of file chan_sip.c.
Referenced by create_addr_from_peer(), and register_verify().
#define DEC_CALL_LIMIT 0 |
Definition at line 857 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 859 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 704 of file chan_sip.c.
#define DEFAULT_ALLOWGUEST TRUE |
Definition at line 692 of file chan_sip.c.
#define DEFAULT_AUTOCREATEPEER FALSE |
Definition at line 708 of file chan_sip.c.
#define DEFAULT_CALLCOUNTER FALSE |
Definition at line 693 of file chan_sip.c.
#define DEFAULT_CALLERID "asterisk" |
Definition at line 690 of file chan_sip.c.
#define DEFAULT_COMPACTHEADERS FALSE |
Definition at line 695 of file chan_sip.c.
#define DEFAULT_CONTEXT "default" |
Definition at line 686 of file chan_sip.c.
#define DEFAULT_COS_AUDIO 5 |
Level 2 class of service for audio media
Definition at line 701 of file chan_sip.c.
#define DEFAULT_COS_SIP 4 |
Level 2 class of service for SIP signalling
Definition at line 700 of file chan_sip.c.
#define DEFAULT_COS_TEXT 5 |
Level 2 class of service for text media (T.140)
Definition at line 703 of file chan_sip.c.
#define DEFAULT_COS_VIDEO 6 |
Level 2 class of service for video media
Definition at line 702 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 251 of file chan_sip.c.
#define DEFAULT_MAX_CALL_BITRATE (384) |
Max bitrate for video
Definition at line 712 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 270 of file chan_sip.c.
#define DEFAULT_MAXMS 2000 |
Qualification: Must be faster than 2 seconds by default
Definition at line 249 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 271 of file chan_sip.c.
#define DEFAULT_MOHINTERPRET "default" |
Definition at line 687 of file chan_sip.c.
#define DEFAULT_MOHSUGGEST "" |
Definition at line 688 of file chan_sip.c.
#define DEFAULT_NOTIFYMIME "application/simple-message-summary" |
Definition at line 691 of file chan_sip.c.
#define DEFAULT_NOTIFYRINGING TRUE |
Definition at line 706 of file chan_sip.c.
#define DEFAULT_PEDANTIC FALSE |
Definition at line 707 of file chan_sip.c.
#define DEFAULT_QUALIFY FALSE |
Definition at line 709 of file chan_sip.c.
#define DEFAULT_QUALIFYFREQ 60 * 1000 |
Qualification: How often to check for the host to be up
Definition at line 250 of file chan_sip.c.
#define DEFAULT_REALM "asterisk" |
Realm for HTTP digest authentication
Definition at line 705 of file chan_sip.c.
#define DEFAULT_REGEXTENONQUALIFY FALSE |
Definition at line 710 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 253 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 716 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 715 of file chan_sip.c.
#define DEFAULT_SRVLOOKUP TRUE |
Recommended setting is ON
Definition at line 694 of file chan_sip.c.
#define DEFAULT_T1MIN 100 |
100 MS for minimal roundtrip time
Definition at line 711 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 697 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 696 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 699 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 698 of file chan_sip.c.
#define DEFAULT_TRANS_TIMEOUT -1 |
Definition at line 259 of file chan_sip.c.
Referenced by __sip_autodestruct(), auto_congest(), 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 714 of file chan_sip.c.
#define DEFAULT_VMEXTEN "asterisk" |
Definition at line 689 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(), st_get_se(), and transmit_register().
#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 %-15.15s %-15.15s %-15.15s %-3.3s %-3.3s %-15.15s %-10.10s\n" |
Definition at line 15378 of file chan_sip.c.
#define FORMAT "%-15.15s %-11.11s %-8.8s %-10.10u%-1.1s %-10.10u (%5.2f%%) %-6.6u %-10.10u%-1.1s %-10.10u (%5.2f%%) %-6.6u\n" |
Definition at line 15378 of file chan_sip.c.
#define FORMAT "%-30.30s %-6.6s %-12.12s %8d %-20.20s %-25.25s\n" |
Definition at line 15378 of file chan_sip.c.
#define FORMAT "%-40.40s %-20.20s %-16.16s\n" |
Definition at line 15378 of file chan_sip.c.
#define FORMAT "%-25.25s %-15.15s %-3.3s %-3.3s %-3.3s %-8d %-10s %s\n" |
Definition at line 15378 of file chan_sip.c.
#define FORMAT "%-25.25s %-15.15s %-15.15s %-15.15s %-5.5s%-10.10s\n" |
Definition at line 15378 of file chan_sip.c.
#define FORMAT "%-30.30s %-6d %-9.9s %-6.6s\n" |
Definition at line 15378 of file chan_sip.c.
#define FORMAT "%-25.25s %-15.15s %-15.15s \n" |
Definition at line 15378 of file chan_sip.c.
#define FORMAT2 "%-15.15s %-15.15s %-15.15s %-15.15s %-7.7s %-15.15s %-6.6s\n" |
Definition at line 15377 of file chan_sip.c.
#define FORMAT2 "%-15.15s %-11.11s %-8.8s %-10.10s %-10.10s ( %%) %-6.6s %-10.10s %-10.10s ( %%) %-6.6s\n" |
Definition at line 15377 of file chan_sip.c.
#define FORMAT2 "%-30.30s %-6.6s %-12.12s %8.8s %-20.20s %-25.25s\n" |
Definition at line 15377 of file chan_sip.c.
#define FORMAT2 "%-25.25s %-15.15s %-3.3s %-3.3s %-3.3s %-8s %-10s %s\n" |
Definition at line 15377 of file chan_sip.c.
#define FORMAT2 "%-30.30s %3.6s %9.9s %6.6s\n" |
Definition at line 15377 of file chan_sip.c.
#define FORMAT2 "%-25.25s %-15.15s %-15.15s \n" |
Definition at line 15377 of file chan_sip.c.
#define FORMAT3 "%-15.15s %-15.15s %-15.15s %-15.15s %-13.13s %-15.15s %-10.10s %-6.6s\n" |
#define FORMAT4 "%-15.15s %-15.15s %-15.15s %-15.15s %-13.13s %-15.15s %-10.10s %-6.6d\n" |
#define FROMDOMAIN_INVALID "anonymous.invalid" |
#define INC_CALL_LIMIT 1 |
Definition at line 858 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 268 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 2372 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_AUTHTRIES 3 |
Try authentication three times, then fail
Definition at line 261 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 254 of file chan_sip.c.
#define NO_RTP 0 |
Definition at line 290 of file chan_sip.c.
#define NOT_SUPPORTED 0 |
Definition at line 574 of file chan_sip.c.
#define PROVIS_KEEPALIVE_TIMEOUT 60000 |
How long to wait before retransmitting a provisional response (rfc 3261 13.3.1.1)
Definition at line 260 of file chan_sip.c.
Referenced by send_provisional_keepalive_full(), and update_provisional_keepalive().
#define REQ_OFFSET_TO_STR | ( | req, | |||
offset | ) | ((req)->data->str + ((req)->offset)) |
Definition at line 923 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(), get_sdp_line(), handle_incoming(), handle_request_do(), handle_request_invite(), reqprep(), and send_response().
#define RTP 1 |
Definition at line 289 of file chan_sip.c.
#define SDP_MAX_RTPMAP_CODECS 32 |
Maximum number of codecs allowed in received SDP
Definition at line 273 of file chan_sip.c.
Referenced by process_sdp_a_audio(), process_sdp_a_text(), and process_sdp_a_video().
#define SDP_SAMPLE_RATE | ( | x | ) | 8000 |
Definition at line 9368 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 1006 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 1034 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 1035 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 1009 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 1017 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 1021 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 1019 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 1020 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 1018 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 1022 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 1054 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 1051 of file chan_sip.c.
Referenced by add_codec_to_sdp(), handle_common_options(), and process_sdp_a_audio().
#define SIP_GOTREFER (1 << 6) |
D: Got a refer?
Definition at line 1005 of file chan_sip.c.
Referenced by handle_request_refer(), local_attended_transfer(), 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 1007 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 1008 of file chan_sip.c.
Referenced by update_call_counter().
#define SIP_INSECURE (3 << 23) |
DP: three settings, uses two bits
Definition at line 1039 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 1042 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 1040 of file chan_sip.c.
#define SIP_INSECURE_PORT (1 << 23) |
DP: don't require matching port for incoming requests
Definition at line 1041 of file chan_sip.c.
Referenced by find_peer(), get_insecure_variable_from_config(), peer_ipcmp_cb(), and set_insecure_flags().
#define SIP_MAX_HEADERS 64 |
Max amount of SIP headers to read
Definition at line 263 of file chan_sip.c.
Referenced by add_header(), and parse_request().
#define SIP_MAX_LINES 256 |
Max amount of lines in SIP attachment (like SDP)
Definition at line 264 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 265 of file chan_sip.c.
#define SIP_MIN_PACKET 1024 |
Initialize size of memory to allocate for packets
Definition at line 266 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 1025 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 1029 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 1026 of file chan_sip.c.
Referenced by handle_common_options().
#define SIP_NAT_RFC3581 (1 << 18) |
DP: NAT RFC3581
Definition at line 1027 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 1028 of file chan_sip.c.
Referenced by _sip_show_peers(), build_peer(), check_peer_ok(), check_user_full(), 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 1003 of file chan_sip.c.
Referenced by check_pendings(), interpret_t38_parameters(), sip_hangup(), sip_reinvite_retry(), sip_sendhtml(), sip_set_rtp_peer(), and sip_set_udptl_peer().
#define SIP_OPT_100REL (1 << 1) |
Definition at line 578 of file chan_sip.c.
#define SIP_OPT_EARLY_SESSION (1 << 3) |
Definition at line 580 of file chan_sip.c.
#define SIP_OPT_EVENTLIST (1 << 11) |
Definition at line 588 of file chan_sip.c.
#define SIP_OPT_FROMCHANGE (1 << 17) |
Definition at line 594 of file chan_sip.c.
#define SIP_OPT_GRUU (1 << 12) |
Definition at line 589 of file chan_sip.c.
#define SIP_OPT_HISTINFO (1 << 15) |
Definition at line 592 of file chan_sip.c.
#define SIP_OPT_JOIN (1 << 4) |
Definition at line 581 of file chan_sip.c.
#define SIP_OPT_NOREFERSUB (1 << 14) |
Definition at line 591 of file chan_sip.c.
#define SIP_OPT_PATH (1 << 5) |
Definition at line 582 of file chan_sip.c.
#define SIP_OPT_PRECONDITION (1 << 7) |
Definition at line 584 of file chan_sip.c.
#define SIP_OPT_PREF (1 << 6) |
Definition at line 583 of file chan_sip.c.
#define SIP_OPT_PRIVACY (1 << 8) |
Definition at line 585 of file chan_sip.c.
#define SIP_OPT_RECLISTINV (1 << 18) |
Definition at line 595 of file chan_sip.c.
#define SIP_OPT_RECLISTSUB (1 << 19) |
Definition at line 596 of file chan_sip.c.
#define SIP_OPT_REPLACES (1 << 0) |
#define SIP_OPT_RESPRIORITY (1 << 16) |
Definition at line 593 of file chan_sip.c.
#define SIP_OPT_SDP_ANAT (1 << 9) |
Definition at line 586 of file chan_sip.c.
#define SIP_OPT_SEC_AGREE (1 << 10) |
Definition at line 587 of file chan_sip.c.
#define SIP_OPT_TARGET_DIALOG (1 << 13) |
Definition at line 590 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 1000 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 1074 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 1073 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 1089 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 1083 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 1086 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 1085 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 1090 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_FAX_DETECT (1 << 28) |
DP: Fax Detection support
Definition at line 1091 of file chan_sip.c.
Referenced by handle_common_options(), sip_new(), sip_read(), and sip_rtp_read().
#define SIP_PAGE2_FLAGS_TO_COPY |
Value:
(SIP_PAGE2_ALLOWSUBSCRIBE | SIP_PAGE2_ALLOWOVERLAP | SIP_PAGE2_IGNORESDPVERSION | \ 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 | SIP_PAGE2_FAX_DETECT | \ SIP_PAGE2_HAVEPEERCONTEXT)
Definition at line 1096 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_HAVEPEERCONTEXT (1 << 3) |
#define SIP_PAGE2_IGNORESDPVERSION (1 << 19) |
GDP: Ignore the SDP session version number we receive and treat all sessions as new
Definition at line 1076 of file chan_sip.c.
Referenced by _sip_show_peer(), handle_common_options(), process_sdp_o(), sip_show_settings(), and sip_show_user().
#define SIP_PAGE2_REGISTERTRYING (1 << 29) |
DP: Send 100 Trying on REGISTER attempts
Definition at line 1092 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 1088 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_RPORT_PRESENT (1 << 10) |
Was rport received in the Via header?
Definition at line 1070 of file chan_sip.c.
Referenced by check_user_full(), and check_via().
#define SIP_PAGE2_RTAUTOCLEAR (1 << 2) |
GP: Should we clean memory from peers after expiry?
Definition at line 1065 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 1064 of file chan_sip.c.
Referenced by build_peer(), parse_register_contact(), reload_config(), sip_prune_realtime(), sip_show_settings(), and update_peer().
#define SIP_PAGE2_STATECHANGEQUEUE (1 << 9) |
D: Unsent state pending change exists
Definition at line 1068 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 1075 of file chan_sip.c.
Referenced by build_peer(), handle_request_subscribe(), register_verify(), and sip_send_mwi_to_peer().
#define SIP_PAGE2_T38SUPPORT (3 << 20) |
GDP: T.38 Fax Support
Definition at line 1078 of file chan_sip.c.
Referenced by _sip_show_peer(), check_peer_ok(), create_addr_from_peer(), handle_request_invite(), handle_t38_options(), interpret_t38_parameters(), set_t38_capabilities(), sip_alloc(), sip_queryoption(), and sip_show_settings().
#define SIP_PAGE2_T38SUPPORT_UDPTL (1 << 20) |
GDP: T.38 Fax Support (no error correction)
Definition at line 1079 of file chan_sip.c.
Referenced by handle_t38_options(), and set_t38_capabilities().
#define SIP_PAGE2_T38SUPPORT_UDPTL_FEC (2 << 20) |
GDP: T.38 Fax Support (FEC error correction)
Definition at line 1080 of file chan_sip.c.
Referenced by handle_t38_options(), and set_t38_capabilities().
#define SIP_PAGE2_T38SUPPORT_UDPTL_REDUNDANCY (3 << 20) |
GDP: T.38 Fax Support (redundancy error correction)
Definition at line 1081 of file chan_sip.c.
Referenced by handle_t38_options(), and set_t38_capabilities().
#define SIP_PAGE2_TEXTSUPPORT (1 << 15) |
GDP: Global text enable
Definition at line 1072 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 1093 of file chan_sip.c.
Referenced by handle_t38_options(), and process_sdp().
#define SIP_PAGE2_VIDEOSUPPORT (1 << 14) |
DP: Video supported if offered?
Definition at line 1071 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 1094 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 1004 of file chan_sip.c.
Referenced by check_pendings(), handle_response_invite(), interpret_t38_parameters(), register_verify(), sip_hangup(), 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 1045 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 1047 of file chan_sip.c.
Referenced by handle_common_options(), and sip_show_settings().
#define SIP_PROG_INBAND_YES (2 << 25) |
Definition at line 1048 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 1002 of file chan_sip.c.
Referenced by sip_indicate(), and sip_write().
#define SIP_PROMISCREDIR (1 << 11) |
DP: Promiscuous redirection
Definition at line 1011 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_invite_replaces(), handle_request_bye(), 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) |
Definition at line 1422 of file chan_sip.c.
Referenced by dialog_needdestroy(), find_call(), and sip_hangup().
#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_bye(), 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 1032 of file chan_sip.c.
Referenced by handle_common_options().
#define SIP_REINVITE_NONE (0 << 20) |
DP: no reinvite allowed
Definition at line 1033 of file chan_sip.c.
#define SIP_REINVITE_UPDATE (4 << 20) |
DP: use UPDATE (RFC3311) when reinviting this peer
Definition at line 1036 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 1050 of file chan_sip.c.
Referenced by _sip_show_peer(), handle_common_options(), and initreqprep().
#define SIP_TIMER_T1 500 |
Definition at line 255 of file chan_sip.c.
#define SIP_TRANS_TIMEOUT 64 * SIP_TIMER_T1 |
SIP request timeout (rfc 3261) 64*T1
Definition at line 256 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 1012 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 1014 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 1013 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 666 of file chan_sip.c.
Referenced by __set_address_from_contact(), build_peer(), check_via(), create_addr(), 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 668 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 573 of file chan_sip.c.
#define SUPPORTED_EXTENSIONS "replaces, timer" |
SIP Extensions we support.
Definition at line 663 of file chan_sip.c.
Referenced by respprep(), transmit_invite(), transmit_notify_with_sipfrag(), transmit_refer(), and transmit_reinvite_with_sdp().
#define TRUE 1 |
Definition at line 207 of file chan_sip.c.
#define UNLINK | ( | element, | |||
head, | |||||
prev | ) |
some list management macros.
Definition at line 1888 of file chan_sip.c.
Referenced by __sip_ack(), handle_request_cancel(), 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(), sip_poke_peer(), and sip_tcptls_write().
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 954 of file chan_sip.c.
00954 { 00955 SIP_DOMAIN_AUTO, /*!< This domain is auto-configured */ 00956 SIP_DOMAIN_CONFIG, /*!< This domain is from configuration */ 00957 };
enum invitestates |
States for the INVITE transaction, not the dialog.
Definition at line 310 of file chan_sip.c.
00310 { 00311 INV_NONE = 0, /*!< No state at all, maybe not an INVITE dialog */ 00312 INV_CALLING = 1, /*!< Invite sent, no answer */ 00313 INV_PROCEEDING = 2, /*!< We got/sent 1xx message */ 00314 INV_EARLY_MEDIA = 3, /*!< We got 18x message with to-tag back */ 00315 INV_COMPLETED = 4, /*!< Got final response with error. Wait for ACK, then CONFIRMED */ 00316 INV_CONFIRMED = 5, /*!< Confirmed response - we've got an ack (Incoming calls only) */ 00317 INV_TERMINATED = 6, /*!< Transaction done - either successful (AST_STATE_UP) or failed, but done 00318 The only way out of this is a BYE from one side */ 00319 INV_CANCELLED = 7, /*!< Transaction cancelled by client or server in non-terminated state */ 00320 };
enum media_type |
Definition at line 348 of file chan_sip.c.
00348 { 00349 PARSE_REGISTER_DENIED, 00350 PARSE_REGISTER_FAILED, 00351 PARSE_REGISTER_UPDATE, 00352 PARSE_REGISTER_QUERY, 00353 };
enum referstatus |
Parameters to know status of transfer.
Definition at line 1141 of file chan_sip.c.
01141 { 01142 REFER_IDLE, /*!< No REFER is in progress */ 01143 REFER_SENT, /*!< Sent REFER to transferee */ 01144 REFER_RECEIVED, /*!< Received REFER from transferrer */ 01145 REFER_CONFIRMED, /*!< Refer confirmed with a 100 TRYING (unused) */ 01146 REFER_ACCEPTED, /*!< Accepted by transferee */ 01147 REFER_RINGING, /*!< Target Ringing */ 01148 REFER_200OK, /*!< Answered by transfer target */ 01149 REFER_FAILED, /*!< REFER declined - go on */ 01150 REFER_NOAUTH /*!< We had no auth for REFER */ 01151 };
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 1111 of file chan_sip.c.
01111 { 01112 sip_debug_none = 0, 01113 sip_debug_config = 1, 01114 sip_debug_console = 2, 01115 };
enum sip_peer_type |
Definition at line 1503 of file chan_sip.c.
01503 { 01504 SIP_TYPE_PEER = (1 << 0), 01505 SIP_TYPE_USER = (1 << 1), 01506 };
enum sip_result |
The result of a lot of functions.
Definition at line 302 of file chan_sip.c.
00302 { 00303 AST_SUCCESS = 0, /*! FALSE means success, funny enough */ 00304 AST_FAILURE = -1, 00305 };
enum sip_tcptls_alert |
TCPTLS_ALERT_DATA | There is new data to be sent out. |
TCPTLS_ALERT_STOP | A request to stop the tcp_handler thread. |
Definition at line 1643 of file chan_sip.c.
01643 { 01644 /*! \brief There is new data to be sent out */ 01645 TCPTLS_ALERT_DATA, 01646 /*! \brief A request to stop the tcp_handler thread */ 01647 TCPTLS_ALERT_STOP, 01648 };
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 1895 of file chan_sip.c.
01895 { 01896 SDP_T38_NONE = 0, /*!< Do not modify T38 information at all */ 01897 SDP_T38_INITIATE, /*!< Remote side has requested T38 with us */ 01898 SDP_T38_ACCEPT, /*!< Remote side accepted our T38 request */ 01899 };
enum t38state |
T38 States for a call.
T38_DISABLED | Not enabled |
T38_LOCAL_REINVITE | Offered from local - REINVITE |
T38_PEER_REINVITE | Offered from peer - REINVITE |
T38_ENABLED | Negotiated (enabled) |
Definition at line 1126 of file chan_sip.c.
01126 { 01127 T38_DISABLED = 0, /*!< Not enabled */ 01128 T38_LOCAL_REINVITE, /*!< Offered from local - REINVITE */ 01129 T38_PEER_REINVITE, /*!< Offered from peer - REINVITE */ 01130 T38_ENABLED /*!< Negotiated (enabled) */ 01131 };
enum transfermodes |
Authorization scheme for call transfers.
Definition at line 295 of file chan_sip.c.
00295 { 00296 TRANSFER_OPENFORALL, /*!< Allow all SIP transfers */ 00297 TRANSFER_CLOSED, /*!< Allow no SIP transfers */ 00298 };
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 341 of file chan_sip.c.
00341 { 00342 XMIT_CRITICAL = 2, /*!< Transmit critical SIP message reliably, with re-transmits. 00343 If it fails, it's critical and will cause a teardown of the session */ 00344 XMIT_RELIABLE = 1, /*!< Transmit SIP message reliably, with re-transmits */ 00345 XMIT_UNRELIABLE = 0, /*!< Transmit SIP message without bothering with re-transmits */ 00346 };
static const char * __get_header | ( | const struct sip_request * | req, | |
const char * | name, | |||
int * | start | |||
) | [static] |
Definition at line 6495 of file chan_sip.c.
References ast_skip_blanks(), find_alias(), sip_request::header, sip_request::headers, pass, and REQ_OFFSET_TO_STR.
06496 { 06497 int pass; 06498 06499 /* 06500 * Technically you can place arbitrary whitespace both before and after the ':' in 06501 * a header, although RFC3261 clearly says you shouldn't before, and place just 06502 * one afterwards. If you shouldn't do it, what absolute idiot decided it was 06503 * a good idea to say you can do it, and if you can do it, why in the hell would. 06504 * you say you shouldn't. 06505 * Anyways, pedanticsipchecking controls whether we allow spaces before ':', 06506 * and we always allow spaces after that for compatibility. 06507 */ 06508 for (pass = 0; name && pass < 2;pass++) { 06509 int x, len = strlen(name); 06510 for (x = *start; x < req->headers; x++) { 06511 char *header = REQ_OFFSET_TO_STR(req, header[x]); 06512 if (!strncasecmp(header, name, len)) { 06513 char *r = header + len; /* skip name */ 06514 if (pedanticsipchecking) 06515 r = ast_skip_blanks(r); 06516 06517 if (*r == ':') { 06518 *start = x+1; 06519 return ast_skip_blanks(r+1); 06520 } 06521 } 06522 } 06523 if (pass == 0) /* Try aliases */ 06524 name = find_alias(name, NULL); 06525 } 06526 06527 /* Don't return NULL, so get_header is always a valid pointer */ 06528 return ""; 06529 }
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 24898 of file chan_sip.c.
static int __set_address_from_contact | ( | const char * | fullcontact, | |
struct sockaddr_in * | sin, | |||
int | tcp | |||
) | [static] |
Definition at line 11367 of file chan_sip.c.
References ahp, ast_copy_string(), ast_gethostbyname(), ast_log(), get_transport_str2enum(), hp, LOG_WARNING, parse_uri(), port_str2int(), SIP_TRANSPORT_TLS, STANDARD_SIP_PORT, and STANDARD_TLS_PORT.
Referenced by build_peer(), and set_address_from_contact().
11368 { 11369 struct hostent *hp; 11370 struct ast_hostent ahp; 11371 int port = STANDARD_SIP_PORT; 11372 char *host, *pt, *transport; 11373 char contact_buf[256]; 11374 char *contact; 11375 11376 /* Work on a copy */ 11377 ast_copy_string(contact_buf, fullcontact, sizeof(contact_buf)); 11378 contact = contact_buf; 11379 11380 /* 11381 * We have only the part in <brackets> here so we just need to parse a SIP URI. 11382 * 11383 * Note: The outbound proxy could be using UDP between the proxy and Asterisk. 11384 * We still need to be able to send to the remote agent through the proxy. 11385 */ 11386 11387 if (parse_uri(contact, "sip:,sips:", &contact, NULL, &host, &pt, NULL, &transport)) { 11388 ast_log(LOG_WARNING, "Invalid contact uri %s (missing sip: or sips:), attempting to use anyway\n", fullcontact); 11389 } 11390 11391 /* set port */ 11392 if (((get_transport_str2enum(transport) == SIP_TRANSPORT_TLS)) || !(strncasecmp(fullcontact, "sips", 4))) { 11393 port = port_str2int(pt, STANDARD_TLS_PORT); 11394 } else { 11395 port = port_str2int(pt, STANDARD_SIP_PORT); 11396 } 11397 11398 /* XXX This could block for a long time XXX */ 11399 /* We should only do this if it's a name, not an IP */ 11400 hp = ast_gethostbyname(host, &ahp); 11401 if (!hp) { 11402 ast_log(LOG_WARNING, "Invalid host name in Contact: (can't resolve in DNS) : '%s'\n", host); 11403 return -1; 11404 } 11405 sin->sin_family = AF_INET; 11406 memcpy(&sin->sin_addr, hp->h_addr, sizeof(sin->sin_addr)); 11407 sin->sin_port = htons(port); 11408 11409 return 0; 11410 }
static int __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 3650 of file chan_sip.c.
References ast_debug, ast_free, ast_sched_del(), sip_pvt::callid, sip_pkt::data, dialog_unref(), FALSE, 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, TRUE, and UNLINK.
Referenced by __sip_pretend_ack(), handle_incoming(), handle_request_invite(), and handle_response().
03651 { 03652 struct sip_pkt *cur, *prev = NULL; 03653 const char *msg = "Not Found"; /* used only for debugging */ 03654 int res = FALSE; 03655 03656 /* If we have an outbound proxy for this dialog, then delete it now since 03657 the rest of the requests in this dialog needs to follow the routing. 03658 If obforcing is set, we will keep the outbound proxy during the whole 03659 dialog, regardless of what the SIP rfc says 03660 */ 03661 if (p->outboundproxy && !p->outboundproxy->force){ 03662 ref_proxy(p, NULL); 03663 } 03664 03665 for (cur = p->packets; cur; prev = cur, cur = cur->next) { 03666 if (cur->seqno != seqno || cur->is_resp != resp) 03667 continue; 03668 if (cur->is_resp || cur->method == sipmethod) { 03669 res = TRUE; 03670 msg = "Found"; 03671 if (!resp && (seqno == p->pendinginvite)) { 03672 ast_debug(1, "Acked pending invite %d\n", p->pendinginvite); 03673 p->pendinginvite = 0; 03674 } 03675 if (cur->retransid > -1) { 03676 if (sipdebug) 03677 ast_debug(4, "** SIP TIMER: Cancelling retransmit of packet (reply received) Retransid #%d\n", cur->retransid); 03678 } 03679 /* This odd section is designed to thwart a 03680 * race condition in the packet scheduler. There are 03681 * two conditions under which deleting the packet from the 03682 * scheduler can fail. 03683 * 03684 * 1. The packet has been removed from the scheduler because retransmission 03685 * is being attempted. The problem is that if the packet is currently attempting 03686 * retransmission and we are at this point in the code, then that MUST mean 03687 * that retrans_pkt is waiting on p's lock. Therefore we will relinquish the 03688 * lock temporarily to allow retransmission. 03689 * 03690 * 2. The packet has reached its maximum number of retransmissions and has 03691 * been permanently removed from the packet scheduler. If this is the case, then 03692 * the packet's retransid will be set to -1. The atomicity of the setting and checking 03693 * of the retransid to -1 is ensured since in both cases p's lock is held. 03694 */ 03695 while (cur->retransid > -1 && ast_sched_del(sched, cur->retransid)) { 03696 sip_pvt_unlock(p); 03697 usleep(1); 03698 sip_pvt_lock(p); 03699 } 03700 UNLINK(cur, p->packets, prev); 03701 dialog_unref(cur->owner, "unref pkt cur->owner dialog from sip ack before freeing pkt"); 03702 if (cur->data) 03703 ast_free(cur->data); 03704 ast_free(cur); 03705 break; 03706 } 03707 } 03708 ast_debug(1, "Stopping retransmission on '%s' of %s %d: Match %s\n", 03709 p->callid, resp ? "Response" : "Request", seqno, msg); 03710 return res; 03711 }
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 3548 of file chan_sip.c.
References __sip_pretend_ack(), 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(), sip_pvt::lastmsg, LOG_WARNING, sip_pvt::method, method_match(), sip_pvt::needdestroy, NONE, sip_pvt::owner, sip_pvt::packets, sip_pvt::refer, sip_pvt::relatedpeer, SIP_BYE, SIP_CANCEL, 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().
03549 { 03550 struct sip_pvt *p = (struct sip_pvt *)data; 03551 03552 /* If this is a subscription, tell the phone that we got a timeout */ 03553 if (p->subscribed) { 03554 transmit_state_notify(p, AST_EXTENSION_DEACTIVATED, 1, TRUE); /* Send last notification */ 03555 p->subscribed = NONE; 03556 append_history(p, "Subscribestatus", "timeout"); 03557 ast_debug(3, "Re-scheduled destruction of SIP subscription %s\n", p->callid ? p->callid : "<unknown>"); 03558 return 10000; /* Reschedule this destruction so that we know that it's gone */ 03559 } 03560 03561 /* If there are packets still waiting for delivery, delay the destruction */ 03562 if (p->packets) { 03563 if (!p->needdestroy) { 03564 char method_str[31]; 03565 ast_debug(3, "Re-scheduled destruction of SIP call %s\n", p->callid ? p->callid : "<unknown>"); 03566 append_history(p, "ReliableXmit", "timeout"); 03567 if (sscanf(p->lastmsg, "Tx: %30s", method_str) == 1 || sscanf(p->lastmsg, "Rx: %30s", method_str) == 1) { 03568 if (method_match(SIP_CANCEL, method_str) || method_match(SIP_BYE, method_str)) { 03569 p->needdestroy = 1; 03570 } 03571 } 03572 return 10000; 03573 } else { 03574 /* They've had their chance to respond. Time to bail */ 03575 __sip_pretend_ack(p); 03576 } 03577 } 03578 03579 if (p->subscribed == MWI_NOTIFICATION) 03580 if (p->relatedpeer) 03581 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) */ 03582 03583 /* Reset schedule ID */ 03584 p->autokillid = -1; 03585 03586 if (p->owner) { 03587 ast_log(LOG_WARNING, "Autodestruct on dialog '%s' with owner in place (Method: %s)\n", p->callid, sip_methods[p->method].text); 03588 ast_queue_hangup_with_cause(p->owner, AST_CAUSE_PROTOCOL_ERROR); 03589 } else if (p->refer && !p->alreadygone) { 03590 ast_debug(3, "Finally hanging up channel after transfer: %s\n", p->callid); 03591 transmit_request_with_auth(p, SIP_BYE, 0, XMIT_RELIABLE, 1); 03592 append_history(p, "ReferBYE", "Sending BYE on transferer call leg %s", p->callid); 03593 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 03594 } else { 03595 append_history(p, "AutoDestroy", "%s", p->callid); 03596 ast_debug(3, "Auto destroying SIP dialog '%s'\n", p->callid); 03597 dialog_unlink_all(p, TRUE, TRUE); /* once it's unlinked and unrefd everywhere, it'll be freed automagically */ 03598 /* dialog_unref(p, "unref dialog-- no other matching conditions"); -- unlink all now should finish off the dialog's references and free it. */ 03599 /* sip_destroy(p); */ /* Go ahead and destroy dialog. All attempts to recover is done */ 03600 /* sip_destroy also absorbs the reference */ 03601 } 03602 dialog_unref(p, "The ref to a dialog passed to this sched callback is going out of scope; unref it."); 03603 return 0; 03604 }
static void __sip_destroy | ( | struct sip_pvt * | p, | |
int | lockowner, | |||
int | lockdialoglist | |||
) | [static] |
Execute destruction of SIP dialog structure, release memory.
Definition at line 5098 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, sip_pvt::stimer, ast_channel::tech_pvt, TRUE, unref_peer(), and update_call_counter().
Referenced by sip_destroy().
05099 { 05100 struct sip_request *req; 05101 05102 if (p->stimer) { 05103 ast_free(p->stimer); 05104 p->stimer = NULL; 05105 } 05106 05107 if (sip_debug_test_pvt(p)) 05108 ast_verbose("Really destroying SIP dialog '%s' Method: %s\n", p->callid, sip_methods[p->method].text); 05109 05110 if (ast_test_flag(&p->flags[0], SIP_INC_COUNT) || ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD)) { 05111 update_call_counter(p, DEC_CALL_LIMIT); 05112 ast_debug(2, "This call did not properly clean up call limits. Call ID %s\n", p->callid); 05113 } 05114 05115 /* Unlink us from the owner if we have one */ 05116 if (p->owner) { 05117 if (lockowner) 05118 ast_channel_lock(p->owner); 05119 if (option_debug) 05120 ast_log(LOG_DEBUG, "Detaching from %s\n", p->owner->name); 05121 p->owner->tech_pvt = NULL; 05122 /* Make sure that the channel knows its backend is going away */ 05123 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 05124 if (lockowner) 05125 ast_channel_unlock(p->owner); 05126 /* Give the channel a chance to react before deallocation */ 05127 usleep(1); 05128 } 05129 05130 /* Remove link from peer to subscription of MWI */ 05131 if (p->relatedpeer && p->relatedpeer->mwipvt) 05132 p->relatedpeer->mwipvt = dialog_unref(p->relatedpeer->mwipvt, "delete ->relatedpeer->mwipvt"); 05133 if (p->relatedpeer && p->relatedpeer->call == p) 05134 p->relatedpeer->call = dialog_unref(p->relatedpeer->call, "unset the relatedpeer->call field in tandem with relatedpeer field itself"); 05135 05136 if (p->relatedpeer) 05137 p->relatedpeer = unref_peer(p->relatedpeer,"unsetting a dialog relatedpeer field in sip_destroy"); 05138 05139 if (p->registry) { 05140 if (p->registry->call == p) 05141 p->registry->call = dialog_unref(p->registry->call, "nulling out the registry's call dialog field in unlink_all"); 05142 p->registry = registry_unref(p->registry, "delete p->registry"); 05143 } 05144 05145 if (dumphistory) 05146 sip_dump_history(p); 05147 05148 if (p->options) 05149 ast_free(p->options); 05150 05151 if (p->notify_headers) { 05152 ast_variables_destroy(p->notify_headers); 05153 p->notify_headers = NULL; 05154 } 05155 if (p->rtp) { 05156 ast_rtp_destroy(p->rtp); 05157 } 05158 if (p->vrtp) { 05159 ast_rtp_destroy(p->vrtp); 05160 } 05161 if (p->trtp) { 05162 while (ast_rtp_get_bridged(p->trtp)) 05163 usleep(1); 05164 ast_rtp_destroy(p->trtp); 05165 } 05166 if (p->udptl) 05167 ast_udptl_destroy(p->udptl); 05168 if (p->refer) 05169 ast_free(p->refer); 05170 if (p->route) { 05171 free_old_route(p->route); 05172 p->route = NULL; 05173 } 05174 if (p->initreq.data) 05175 ast_free(p->initreq.data); 05176 05177 /* Destroy Session-Timers if allocated */ 05178 if (p->stimer) { 05179 p->stimer->quit_flag = 1; 05180 if (p->stimer->st_active == TRUE && p->stimer->st_schedid > -1) { 05181 AST_SCHED_DEL_UNREF(sched, p->stimer->st_schedid, 05182 dialog_unref(p, "removing session timer ref")); 05183 } 05184 ast_free(p->stimer); 05185 p->stimer = NULL; 05186 } 05187 05188 /* Clear history */ 05189 if (p->history) { 05190 struct sip_history *hist; 05191 while ( (hist = AST_LIST_REMOVE_HEAD(p->history, list)) ) { 05192 ast_free(hist); 05193 p->history_entries--; 05194 } 05195 ast_free(p->history); 05196 p->history = NULL; 05197 } 05198 05199 while ((req = AST_LIST_REMOVE_HEAD(&p->request_queue, next))) { 05200 ast_free(req); 05201 } 05202 05203 if (p->chanvars) { 05204 ast_variables_destroy(p->chanvars); 05205 p->chanvars = NULL; 05206 } 05207 05208 ast_string_field_free_memory(p); 05209 05210 if (p->socket.tcptls_session) { 05211 ao2_ref(p->socket.tcptls_session, -1); 05212 p->socket.tcptls_session = NULL; 05213 } 05214 }
static int __sip_do_register | ( | struct sip_registry * | r | ) | [static] |
Register with SIP proxy.
Definition at line 10701 of file chan_sip.c.
References SIP_REGISTER, and transmit_register().
Referenced by sip_reregister().
10702 { 10703 int res; 10704 10705 res = transmit_register(r, SIP_REGISTER, NULL, NULL); 10706 return res; 10707 }
static void __sip_pretend_ack | ( | struct sip_pvt * | p | ) | [static] |
Pretend to ack all packets called with p locked.
Definition at line 3715 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 __sip_autodestruct(), handle_request_bye(), handle_request_cancel(), sip_hangup(), and sip_reg_timeout().
03716 { 03717 struct sip_pkt *cur = NULL; 03718 03719 while (p->packets) { 03720 int method; 03721 if (cur == p->packets) { 03722 ast_log(LOG_WARNING, "Have a packet that doesn't want to give up! %s\n", sip_methods[cur->method].text); 03723 return; 03724 } 03725 cur = p->packets; 03726 method = (cur->method) ? cur->method : find_sip_method(cur->data->str); 03727 __sip_ack(p, cur->seqno, cur->is_resp, method); 03728 } 03729 }
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 3470 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_buffer, 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, sip_pkt::response_code, retrans_pkt(), sched, SIP_INVITE, SIP_TRANSPORT_UDP, sip_pvt::socket, ast_str::str, sip_pvt::timer_t1, sip_socket::type, and XMIT_ERROR.
Referenced by send_request(), and send_response().
03471 { 03472 struct sip_pkt *pkt = NULL; 03473 int siptimer_a = DEFAULT_RETRANS; 03474 int xmitres = 0; 03475 int respid; 03476 03477 if (sipmethod == SIP_INVITE) { 03478 /* Note this is a pending invite */ 03479 p->pendinginvite = seqno; 03480 } 03481 03482 /* If the transport is something reliable (TCP or TLS) then don't really send this reliably */ 03483 /* I removed the code from retrans_pkt that does the same thing so it doesn't get loaded into the scheduler */ 03484 /* According to the RFC some packets need to be retransmitted even if its TCP, so this needs to get revisited */ 03485 if (!(p->socket.type & SIP_TRANSPORT_UDP)) { 03486 xmitres = __sip_xmit(p, data, len); /* Send packet */ 03487 if (xmitres == XMIT_ERROR) { /* Serious network trouble, no need to try again */ 03488 append_history(p, "XmitErr", "%s", fatal ? "(Critical)" : "(Non-critical)"); 03489 return AST_FAILURE; 03490 } else 03491 return AST_SUCCESS; 03492 } 03493 03494 if (!(pkt = ast_calloc(1, sizeof(*pkt) + len + 1))) 03495 return AST_FAILURE; 03496 /* copy data, add a terminator and save length */ 03497 if (!(pkt->data = ast_str_create(len))) { 03498 ast_free(pkt); 03499 return AST_FAILURE; 03500 } 03501 ast_str_set(&pkt->data, 0, "%s%s", data->str, "\0"); 03502 pkt->packetlen = len; 03503 /* copy other parameters from the caller */ 03504 pkt->method = sipmethod; 03505 pkt->seqno = seqno; 03506 pkt->is_resp = resp; 03507 pkt->is_fatal = fatal; 03508 pkt->owner = dialog_ref(p, "__sip_reliable_xmit: setting pkt->owner"); 03509 pkt->next = p->packets; 03510 p->packets = pkt; /* Add it to the queue */ 03511 if (resp) { 03512 /* Parse out the response code */ 03513 if (sscanf(ast_str_buffer(pkt->data), "SIP/2.0 %30u", &respid) == 1) { 03514 pkt->response_code = respid; 03515 } 03516 } 03517 pkt->timer_t1 = p->timer_t1; /* Set SIP timer T1 */ 03518 pkt->retransid = -1; 03519 if (pkt->timer_t1) 03520 siptimer_a = pkt->timer_t1 * 2; 03521 03522 /* Schedule retransmission */ 03523 AST_SCHED_REPLACE_VARIABLE(pkt->retransid, sched, siptimer_a, retrans_pkt, pkt, 1); 03524 if (sipdebug) 03525 ast_debug(4, "*** SIP TIMER: Initializing retransmit timer on packet: Id #%d\n", pkt->retransid); 03526 03527 xmitres = __sip_xmit(pkt->owner, pkt->data, pkt->packetlen); /* Send packet */ 03528 03529 if (xmitres == XMIT_ERROR) { /* Serious network trouble, no need to try again */ 03530 append_history(pkt->owner, "XmitErr", "%s", pkt->is_fatal ? "(Critical)" : "(Non-critical)"); 03531 ast_log(LOG_ERROR, "Serious Network Trouble; __sip_xmit returns error for pkt data\n"); 03532 AST_SCHED_DEL(sched, pkt->retransid); 03533 p->packets = pkt->next; 03534 pkt->owner = dialog_unref(pkt->owner,"pkt is being freed, its dialog ref is dead now"); 03535 ast_free(pkt->data); 03536 ast_free(pkt); 03537 return AST_FAILURE; 03538 } else { 03539 return AST_SUCCESS; 03540 } 03541 }
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 3732 of file chan_sip.c.
References ast_debug, AST_SCHED_DEL, sip_pvt::callid, sip_pkt::data, FALSE, sip_pkt::is_resp, method_match(), sip_pkt::next, sip_pvt::packets, sip_pkt::retransid, sched, sip_pkt::seqno, sip_methods, ast_str::str, cfsip_methods::text, and TRUE.
Referenced by handle_response(), and sip_hangup().
03733 { 03734 struct sip_pkt *cur; 03735 int res = FALSE; 03736 03737 for (cur = p->packets; cur; cur = cur->next) { 03738 if (cur->seqno == seqno && cur->is_resp == resp && 03739 (cur->is_resp || method_match(sipmethod, cur->data->str))) { 03740 /* this is our baby */ 03741 if (cur->retransid > -1) { 03742 if (sipdebug) 03743 ast_debug(4, "*** SIP TIMER: Cancelling retransmission #%d - %s (got response)\n", cur->retransid, sip_methods[sipmethod].text); 03744 } 03745 AST_SCHED_DEL(sched, cur->retransid); 03746 res = TRUE; 03747 break; 03748 } 03749 } 03750 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"); 03751 return res; 03752 }
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 3169 of file chan_sip.c.
References ast_debug, ast_inet_ntoa(), ast_log(), sip_request::data, errno, sip_socket::fd, get_transport_pvt(), LOG_WARNING, sip_prepare_socket(), sip_real_dst(), sip_tcptls_write(), 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().
03170 { 03171 int res = 0; 03172 const struct sockaddr_in *dst = sip_real_dst(p); 03173 03174 ast_debug(1, "Trying to put '%.11s' onto %s socket destined for %s:%d\n", data->str, get_transport_pvt(p), ast_inet_ntoa(dst->sin_addr), htons(dst->sin_port)); 03175 03176 if (sip_prepare_socket(p) < 0) 03177 return XMIT_ERROR; 03178 03179 if (p->socket.type == SIP_TRANSPORT_UDP) { 03180 res = sendto(p->socket.fd, data->str, len, 0, (const struct sockaddr *)dst, sizeof(struct sockaddr_in)); 03181 } else if (p->socket.tcptls_session) { 03182 res = sip_tcptls_write(p->socket.tcptls_session, data->str, len); 03183 } else { 03184 ast_debug(2, "Socket type is TCP but no tcptls_session is present to write to\n"); 03185 return XMIT_ERROR; 03186 } 03187 03188 if (res == -1) { 03189 switch (errno) { 03190 case EBADF: /* Bad file descriptor - seems like this is generated when the host exist, but doesn't accept the UDP packet */ 03191 case EHOSTUNREACH: /* Host can't be reached */ 03192 case ENETDOWN: /* Inteface down */ 03193 case ENETUNREACH: /* Network failure */ 03194 case ECONNREFUSED: /* ICMP port unreachable */ 03195 res = XMIT_ERROR; /* Don't bother with trying to transmit again */ 03196 } 03197 } 03198 if (res != len) 03199 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)); 03200 03201 return res; 03202 }
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 8927 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().
08928 { 08929 struct sip_request resp; 08930 int seqno = 0; 08931 08932 if (reliable && (sscanf(get_header(req, "CSeq"), "%30d ", &seqno) != 1)) { 08933 ast_log(LOG_WARNING, "Unable to determine sequence number from '%s'\n", get_header(req, "CSeq")); 08934 return -1; 08935 } 08936 respprep(&resp, p, msg, req); 08937 add_header_contentLength(&resp, 0); 08938 /* If we are cancelling an incoming invite for some reason, add information 08939 about the reason why we are doing this in clear text */ 08940 if (p->method == SIP_INVITE && msg[0] != '1' && p->owner && p->owner->hangupcause) { 08941 char buf[10]; 08942 08943 add_header(&resp, "X-Asterisk-HangupCause", ast_cause2str(p->owner->hangupcause)); 08944 snprintf(buf, sizeof(buf), "%d", p->owner->hangupcause); 08945 add_header(&resp, "X-Asterisk-HangupCauseCode", buf); 08946 } 08947 return send_response(p, &resp, reliable, seqno); 08948 }
static void __unreg_module | ( | void | ) | [static] |
Definition at line 24898 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 14496 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().
14497 { 14498 struct sip_peer *peer; 14499 int load_realtime; 14500 14501 if (argc < 4) 14502 return CLI_SHOWUSAGE; 14503 14504 load_realtime = (argc == 5 && !strcmp(argv[4], "load")) ? TRUE : FALSE; 14505 if ((peer = find_peer(argv[3], NULL, load_realtime, FINDPEERS, FALSE, 0))) { 14506 sip_poke_peer(peer, 1); 14507 unref_peer(peer, "qualify: done with peer"); 14508 } else if (type == 0) { 14509 ast_cli(fd, "Peer '%s' not found\n", argv[3]); 14510 } else { 14511 astman_send_error(s, m, "Peer not found"); 14512 } 14513 return CLI_SUCCESS; 14514 }
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 14581 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, faxec2str(), 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, sip_peer::parkinglot, 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_IGNORESDPVERSION, SIP_PAGE2_REGISTERTRYING, SIP_PAGE2_T38SUPPORT, 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, sip_peer::t38_maxdatagram, 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().
14582 { 14583 char status[30] = ""; 14584 char cbuf[256]; 14585 struct sip_peer *peer; 14586 char codec_buf[512]; 14587 struct ast_codec_pref *pref; 14588 struct ast_variable *v; 14589 struct sip_auth *auth; 14590 int x = 0, codec = 0, load_realtime; 14591 int realtimepeers; 14592 14593 realtimepeers = ast_check_realtime("sippeers"); 14594 14595 if (argc < 4) 14596 return CLI_SHOWUSAGE; 14597 14598 load_realtime = (argc == 5 && !strcmp(argv[4], "load")) ? TRUE : FALSE; 14599 peer = find_peer(argv[3], NULL, load_realtime, FINDPEERS, FALSE, 0); 14600 14601 if (s) { /* Manager */ 14602 if (peer) { 14603 const char *id = astman_get_header(m, "ActionID"); 14604 14605 astman_append(s, "Response: Success\r\n"); 14606 if (!ast_strlen_zero(id)) 14607 astman_append(s, "ActionID: %s\r\n", id); 14608 } else { 14609 snprintf (cbuf, sizeof(cbuf), "Peer %s not found.", argv[3]); 14610 astman_send_error(s, m, cbuf); 14611 return CLI_SUCCESS; 14612 } 14613 } 14614 if (peer && type==0 ) { /* Normal listing */ 14615 struct ast_str *mailbox_str = ast_str_alloca(512); 14616 ast_cli(fd, "\n\n"); 14617 ast_cli(fd, " * Name : %s\n", peer->name); 14618 if (realtimepeers) { /* Realtime is enabled */ 14619 ast_cli(fd, " Realtime peer: %s\n", peer->is_realtime ? "Yes, cached" : "No"); 14620 } 14621 ast_cli(fd, " Secret : %s\n", ast_strlen_zero(peer->secret)?"<Not set>":"<Set>"); 14622 ast_cli(fd, " MD5Secret : %s\n", ast_strlen_zero(peer->md5secret)?"<Not set>":"<Set>"); 14623 for (auth = peer->auth; auth; auth = auth->next) { 14624 ast_cli(fd, " Realm-auth : Realm %-15.15s User %-10.20s ", auth->realm, auth->username); 14625 ast_cli(fd, "%s\n", !ast_strlen_zero(auth->secret)?"<Secret set>":(!ast_strlen_zero(auth->md5secret)?"<MD5secret set>" : "<Not set>")); 14626 } 14627 ast_cli(fd, " Context : %s\n", peer->context); 14628 ast_cli(fd, " Subscr.Cont. : %s\n", S_OR(peer->subscribecontext, "<Not set>") ); 14629 ast_cli(fd, " Language : %s\n", peer->language); 14630 if (!ast_strlen_zero(peer->accountcode)) 14631 ast_cli(fd, " Accountcode : %s\n", peer->accountcode); 14632 ast_cli(fd, " AMA flags : %s\n", ast_cdr_flags2str(peer->amaflags)); 14633 ast_cli(fd, " Transfer mode: %s\n", transfermode2str(peer->allowtransfer)); 14634 ast_cli(fd, " CallingPres : %s\n", ast_describe_caller_presentation(peer->callingpres)); 14635 if (!ast_strlen_zero(peer->fromuser)) 14636 ast_cli(fd, " FromUser : %s\n", peer->fromuser); 14637 if (!ast_strlen_zero(peer->fromdomain)) 14638 ast_cli(fd, " FromDomain : %s\n", peer->fromdomain); 14639 ast_cli(fd, " Callgroup : "); 14640 print_group(fd, peer->callgroup, 0); 14641 ast_cli(fd, " Pickupgroup : "); 14642 print_group(fd, peer->pickupgroup, 0); 14643 peer_mailboxes_to_str(&mailbox_str, peer); 14644 ast_cli(fd, " Mailbox : %s\n", mailbox_str->str); 14645 ast_cli(fd, " VM Extension : %s\n", peer->vmexten); 14646 ast_cli(fd, " LastMsgsSent : %d/%d\n", (peer->lastmsgssent & 0x7fff0000) >> 16, peer->lastmsgssent & 0xffff); 14647 ast_cli(fd, " Call limit : %d\n", peer->call_limit); 14648 if (peer->busy_level) 14649 ast_cli(fd, " Busy level : %d\n", peer->busy_level); 14650 ast_cli(fd, " Dynamic : %s\n", cli_yesno(peer->host_dynamic)); 14651 ast_cli(fd, " Callerid : %s\n", ast_callerid_merge(cbuf, sizeof(cbuf), peer->cid_name, peer->cid_num, "<unspecified>")); 14652 ast_cli(fd, " MaxCallBR : %d kbps\n", peer->maxcallbitrate); 14653 ast_cli(fd, " Expire : %ld\n", ast_sched_when(sched, peer->expire)); 14654 ast_cli(fd, " Insecure : %s\n", insecure2str(ast_test_flag(&peer->flags[0], SIP_INSECURE))); 14655 ast_cli(fd, " Nat : %s\n", nat2str(ast_test_flag(&peer->flags[0], SIP_NAT))); 14656 ast_cli(fd, " ACL : %s\n", cli_yesno(peer->ha != NULL)); 14657 ast_cli(fd, " T.38 support : %s\n", cli_yesno(ast_test_flag(&peer->flags[1], SIP_PAGE2_T38SUPPORT))); 14658 ast_cli(fd, " T.38 EC mode : %s\n", faxec2str(ast_test_flag(&peer->flags[1], SIP_PAGE2_T38SUPPORT))); 14659 ast_cli(fd, " T.38 MaxDtgrm: %d\n", peer->t38_maxdatagram); 14660 ast_cli(fd, " CanReinvite : %s\n", cli_yesno(ast_test_flag(&peer->flags[0], SIP_CAN_REINVITE))); 14661 ast_cli(fd, " PromiscRedir : %s\n", cli_yesno(ast_test_flag(&peer->flags[0], SIP_PROMISCREDIR))); 14662 ast_cli(fd, " User=Phone : %s\n", cli_yesno(ast_test_flag(&peer->flags[0], SIP_USEREQPHONE))); 14663 ast_cli(fd, " Video Support: %s\n", cli_yesno(ast_test_flag(&peer->flags[1], SIP_PAGE2_VIDEOSUPPORT))); 14664 ast_cli(fd, " Text Support : %s\n", cli_yesno(ast_test_flag(&peer->flags[1], SIP_PAGE2_TEXTSUPPORT))); 14665 ast_cli(fd, " Ign SDP ver : %s\n", cli_yesno(ast_test_flag(&peer->flags[1], SIP_PAGE2_IGNORESDPVERSION))); 14666 ast_cli(fd, " Trust RPID : %s\n", cli_yesno(ast_test_flag(&peer->flags[0], SIP_TRUSTRPID))); 14667 ast_cli(fd, " Send RPID : %s\n", cli_yesno(ast_test_flag(&peer->flags[0], SIP_SENDRPID))); 14668 ast_cli(fd, " Subscriptions: %s\n", cli_yesno(ast_test_flag(&peer->flags[1], SIP_PAGE2_ALLOWSUBSCRIBE))); 14669 ast_cli(fd, " Overlap dial : %s\n", cli_yesno(ast_test_flag(&peer->flags[1], SIP_PAGE2_ALLOWOVERLAP))); 14670 if (peer->outboundproxy) 14671 ast_cli(fd, " Outb. proxy : %s %s\n", ast_strlen_zero(peer->outboundproxy->name) ? "<not set>" : peer->outboundproxy->name, 14672 peer->outboundproxy->force ? "(forced)" : ""); 14673 14674 /* - is enumerated */ 14675 ast_cli(fd, " DTMFmode : %s\n", dtmfmode2str(ast_test_flag(&peer->flags[0], SIP_DTMF))); 14676 ast_cli(fd, " Timer T1 : %d\n", peer->timer_t1); 14677 ast_cli(fd, " Timer B : %d\n", peer->timer_b); 14678 ast_cli(fd, " ToHost : %s\n", peer->tohost); 14679 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)); 14680 ast_cli(fd, " Defaddr->IP : %s Port %d\n", ast_inet_ntoa(peer->defaddr.sin_addr), ntohs(peer->defaddr.sin_port)); 14681 ast_cli(fd, " Transport : %s\n", get_transport(peer->socket.type)); 14682 if (!ast_strlen_zero(global_regcontext)) 14683 ast_cli(fd, " Reg. exten : %s\n", peer->regexten); 14684 ast_cli(fd, " Def. Username: %s\n", peer->username); 14685 ast_cli(fd, " SIP Options : "); 14686 if (peer->sipoptions) { 14687 int lastoption = -1; 14688 for (x = 0 ; x < ARRAY_LEN(sip_options); x++) { 14689 if (sip_options[x].id != lastoption) { 14690 if (peer->sipoptions & sip_options[x].id) 14691 ast_cli(fd, "%s ", sip_options[x].text); 14692 lastoption = x; 14693 } 14694 } 14695 } else 14696 ast_cli(fd, "(none)"); 14697 14698 ast_cli(fd, "\n"); 14699 ast_cli(fd, " Codecs : "); 14700 ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, peer->capability); 14701 ast_cli(fd, "%s\n", codec_buf); 14702 ast_cli(fd, " Codec Order : ("); 14703 print_codec_to_cli(fd, &peer->prefs); 14704 ast_cli(fd, ")\n"); 14705 14706 ast_cli(fd, " Auto-Framing : %s \n", cli_yesno(peer->autoframing)); 14707 ast_cli(fd, " 100 on REG : %s\n", ast_test_flag(&peer->flags[1], SIP_PAGE2_REGISTERTRYING) ? "Yes" : "No"); 14708 ast_cli(fd, " Status : "); 14709 peer_status(peer, status, sizeof(status)); 14710 ast_cli(fd, "%s\n", status); 14711 ast_cli(fd, " Useragent : %s\n", peer->useragent); 14712 ast_cli(fd, " Reg. Contact : %s\n", peer->fullcontact); 14713 ast_cli(fd, " Qualify Freq : %d ms\n", peer->qualifyfreq); 14714 if (peer->chanvars) { 14715 ast_cli(fd, " Variables :\n"); 14716 for (v = peer->chanvars ; v ; v = v->next) 14717 ast_cli(fd, " %s = %s\n", v->name, v->value); 14718 } 14719 14720 ast_cli(fd, " Sess-Timers : %s\n", stmode2str(peer->stimer.st_mode_oper)); 14721 ast_cli(fd, " Sess-Refresh : %s\n", strefresher2str(peer->stimer.st_ref)); 14722 ast_cli(fd, " Sess-Expires : %d secs\n", peer->stimer.st_max_se); 14723 ast_cli(fd, " Min-Sess : %d secs\n", peer->stimer.st_min_se); 14724 ast_cli(fd, " Parkinglot : %s\n", peer->parkinglot); 14725 ast_cli(fd, "\n"); 14726 peer = unref_peer(peer, "sip_show_peer: unref_peer: done with peer ptr"); 14727 } else if (peer && type == 1) { /* manager listing */ 14728 char buffer[256]; 14729 struct ast_str *mailbox_str = ast_str_alloca(512); 14730 astman_append(s, "Channeltype: SIP\r\n"); 14731 astman_append(s, "ObjectName: %s\r\n", peer->name); 14732 astman_append(s, "ChanObjectType: peer\r\n"); 14733 astman_append(s, "SecretExist: %s\r\n", ast_strlen_zero(peer->secret)?"N":"Y"); 14734 astman_append(s, "MD5SecretExist: %s\r\n", ast_strlen_zero(peer->md5secret)?"N":"Y"); 14735 astman_append(s, "Context: %s\r\n", peer->context); 14736 astman_append(s, "Language: %s\r\n", peer->language); 14737 if (!ast_strlen_zero(peer->accountcode)) 14738 astman_append(s, "Accountcode: %s\r\n", peer->accountcode); 14739 astman_append(s, "AMAflags: %s\r\n", ast_cdr_flags2str(peer->amaflags)); 14740 astman_append(s, "CID-CallingPres: %s\r\n", ast_describe_caller_presentation(peer->callingpres)); 14741 if (!ast_strlen_zero(peer->fromuser)) 14742 astman_append(s, "SIP-FromUser: %s\r\n", peer->fromuser); 14743 if (!ast_strlen_zero(peer->fromdomain)) 14744 astman_append(s, "SIP-FromDomain: %s\r\n", peer->fromdomain); 14745 astman_append(s, "Callgroup: "); 14746 astman_append(s, "%s\r\n", ast_print_group(buffer, sizeof(buffer), peer->callgroup)); 14747 astman_append(s, "Pickupgroup: "); 14748 astman_append(s, "%s\r\n", ast_print_group(buffer, sizeof(buffer), peer->pickupgroup)); 14749 peer_mailboxes_to_str(&mailbox_str, peer); 14750 astman_append(s, "VoiceMailbox: %s\r\n", mailbox_str->str); 14751 astman_append(s, "TransferMode: %s\r\n", transfermode2str(peer->allowtransfer)); 14752 astman_append(s, "LastMsgsSent: %d\r\n", peer->lastmsgssent); 14753 astman_append(s, "Call-limit: %d\r\n", peer->call_limit); 14754 astman_append(s, "Busy-level: %d\r\n", peer->busy_level); 14755 astman_append(s, "MaxCallBR: %d kbps\r\n", peer->maxcallbitrate); 14756 astman_append(s, "Dynamic: %s\r\n", peer->host_dynamic?"Y":"N"); 14757 astman_append(s, "Callerid: %s\r\n", ast_callerid_merge(cbuf, sizeof(cbuf), peer->cid_name, peer->cid_num, "")); 14758 astman_append(s, "RegExpire: %ld seconds\r\n", ast_sched_when(sched, peer->expire)); 14759 astman_append(s, "SIP-AuthInsecure: %s\r\n", insecure2str(ast_test_flag(&peer->flags[0], SIP_INSECURE))); 14760 astman_append(s, "SIP-NatSupport: %s\r\n", nat2str(ast_test_flag(&peer->flags[0], SIP_NAT))); 14761 astman_append(s, "ACL: %s\r\n", (peer->ha?"Y":"N")); 14762 astman_append(s, "SIP-CanReinvite: %s\r\n", (ast_test_flag(&peer->flags[0], SIP_CAN_REINVITE)?"Y":"N")); 14763 astman_append(s, "SIP-PromiscRedir: %s\r\n", (ast_test_flag(&peer->flags[0], SIP_PROMISCREDIR)?"Y":"N")); 14764 astman_append(s, "SIP-UserPhone: %s\r\n", (ast_test_flag(&peer->flags[0], SIP_USEREQPHONE)?"Y":"N")); 14765 astman_append(s, "SIP-VideoSupport: %s\r\n", (ast_test_flag(&peer->flags[1], SIP_PAGE2_VIDEOSUPPORT)?"Y":"N")); 14766 astman_append(s, "SIP-TextSupport: %s\r\n", (ast_test_flag(&peer->flags[1], SIP_PAGE2_TEXTSUPPORT)?"Y":"N")); 14767 astman_append(s, "SIP-T.38Support: %s\r\n", (ast_test_flag(&peer->flags[1], SIP_PAGE2_T38SUPPORT)?"Y":"N")); 14768 astman_append(s, "SIP-T.38EC: %s\r\n", faxec2str(ast_test_flag(&peer->flags[1], SIP_PAGE2_T38SUPPORT))); 14769 astman_append(s, "SIP-T.38MaxDtgrm: %d\r\n", peer->t38_maxdatagram); 14770 astman_append(s, "SIP-Sess-Timers: %s\r\n", stmode2str(peer->stimer.st_mode_oper)); 14771 astman_append(s, "SIP-Sess-Refresh: %s\r\n", strefresher2str(peer->stimer.st_ref)); 14772 astman_append(s, "SIP-Sess-Expires: %d\r\n", peer->stimer.st_max_se); 14773 astman_append(s, "SIP-Sess-Min: %d\r\n", peer->stimer.st_min_se); 14774 14775 /* - is enumerated */ 14776 astman_append(s, "SIP-DTMFmode: %s\r\n", dtmfmode2str(ast_test_flag(&peer->flags[0], SIP_DTMF))); 14777 astman_append(s, "ToHost: %s\r\n", peer->tohost); 14778 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)); 14779 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)); 14780 astman_append(s, "Default-Username: %s\r\n", peer->username); 14781 if (!ast_strlen_zero(global_regcontext)) 14782 astman_append(s, "RegExtension: %s\r\n", peer->regexten); 14783 astman_append(s, "Codecs: "); 14784 ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, peer->capability); 14785 astman_append(s, "%s\r\n", codec_buf); 14786 astman_append(s, "CodecOrder: "); 14787 pref = &peer->prefs; 14788 for(x = 0; x < 32 ; x++) { 14789 codec = ast_codec_pref_index(pref, x); 14790 if (!codec) 14791 break; 14792 astman_append(s, "%s", ast_getformatname(codec)); 14793 if (x < 31 && ast_codec_pref_index(pref, x+1)) 14794 astman_append(s, ","); 14795 } 14796 14797 astman_append(s, "\r\n"); 14798 astman_append(s, "Status: "); 14799 peer_status(peer, status, sizeof(status)); 14800 astman_append(s, "%s\r\n", status); 14801 astman_append(s, "SIP-Useragent: %s\r\n", peer->useragent); 14802 astman_append(s, "Reg-Contact: %s\r\n", peer->fullcontact); 14803 astman_append(s, "QualifyFreq: %d ms\r\n", peer->qualifyfreq); 14804 astman_append(s, "Parkinglot: %s\r\n", peer->parkinglot); 14805 if (peer->chanvars) { 14806 for (v = peer->chanvars ; v ; v = v->next) { 14807 astman_append(s, "ChanVariable: %s=%s\r\n", v->name, v->value); 14808 } 14809 } 14810 14811 peer = unref_peer(peer, "sip_show_peer: unref_peer: done with peer"); 14812 14813 } else { 14814 ast_cli(fd, "Peer %s not found.\n", argv[3]); 14815 ast_cli(fd, "\n"); 14816 } 14817 14818 return CLI_SUCCESS; 14819 }
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 13889 of file chan_sip.c.
References sip_peer::addr, ao2_container_count(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_lock(), ao2_t_iterator_next, ao2_unlock(), ast_calloc, ast_check_realtime(), ast_cli(), ast_copy_string(), ast_free, ast_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(), peers, 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().
13890 { 13891 regex_t regexbuf; 13892 int havepattern = FALSE; 13893 struct sip_peer *peer; 13894 struct ao2_iterator i; 13895 13896 /* the last argument is left-aligned, so we don't need a size anyways */ 13897 #define FORMAT2 "%-25.25s %-15.15s %-3.3s %-3.3s %-3.3s %-8s %-10s %s\n" 13898 #define FORMAT "%-25.25s %-15.15s %-3.3s %-3.3s %-3.3s %-8d %-10s %s\n" 13899 13900 char name[256]; 13901 int total_peers = 0; 13902 int peers_mon_online = 0; 13903 int peers_mon_offline = 0; 13904 int peers_unmon_offline = 0; 13905 int peers_unmon_online = 0; 13906 const char *id; 13907 char idtext[256] = ""; 13908 int realtimepeers; 13909 int objcount = ao2_container_count(peers); 13910 struct sip_peer **peerarray; 13911 int k; 13912 13913 13914 realtimepeers = ast_check_realtime("sippeers"); 13915 peerarray = ast_calloc(sizeof(struct sip_peer *), objcount); 13916 13917 if (s) { /* Manager - get ActionID */ 13918 id = astman_get_header(m, "ActionID"); 13919 if (!ast_strlen_zero(id)) 13920 snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id); 13921 } 13922 13923 switch (argc) { 13924 case 5: 13925 if (!strcasecmp(argv[3], "like")) { 13926 if (regcomp(®exbuf, argv[4], REG_EXTENDED | REG_NOSUB)) 13927 return CLI_SHOWUSAGE; 13928 havepattern = TRUE; 13929 } else 13930 return CLI_SHOWUSAGE; 13931 case 3: 13932 break; 13933 default: 13934 return CLI_SHOWUSAGE; 13935 } 13936 13937 if (!s) /* Normal list */ 13938 ast_cli(fd, FORMAT2, "Name/username", "Host", "Dyn", "Nat", "ACL", "Port", "Status", (realtimepeers ? "Realtime" : "")); 13939 13940 13941 i = ao2_iterator_init(peers, 0); 13942 while ((peer = ao2_t_iterator_next(&i, "iterate thru peers table"))) { 13943 ao2_lock(peer); 13944 13945 if (!(peer->type & SIP_TYPE_PEER)) { 13946 ao2_unlock(peer); 13947 unref_peer(peer, "unref peer because it's actually a user"); 13948 continue; 13949 } 13950 13951 if (havepattern && regexec(®exbuf, peer->name, 0, NULL, 0)) { 13952 objcount--; 13953 ao2_unlock(peer); 13954 unref_peer(peer, "toss iterator peer ptr before continue"); 13955 continue; 13956 } 13957 13958 peerarray[total_peers++] = peer; 13959 ao2_unlock(peer); 13960 } 13961 ao2_iterator_destroy(&i); 13962 13963 qsort(peerarray, total_peers, sizeof(struct sip_peer *), peercomparefunc); 13964 13965 for(k=0; k < total_peers; k++) { 13966 char status[20] = ""; 13967 char srch[2000]; 13968 char pstatus; 13969 peer = peerarray[k]; 13970 13971 ao2_lock(peer); 13972 if (havepattern && regexec(®exbuf, peer->name, 0, NULL, 0)) { 13973 ao2_unlock(peer); 13974 unref_peer(peer, "toss iterator peer ptr before continue"); 13975 continue; 13976 } 13977 13978 if (!ast_strlen_zero(peer->username) && !s) 13979 snprintf(name, sizeof(name), "%s/%s", peer->name, peer->username); 13980 else 13981 ast_copy_string(name, peer->name, sizeof(name)); 13982 13983 pstatus = peer_status(peer, status, sizeof(status)); 13984 if (pstatus == 1) 13985 peers_mon_online++; 13986 else if (pstatus == 0) 13987 peers_mon_offline++; 13988 else { 13989 if (peer->addr.sin_port == 0) 13990 peers_unmon_offline++; 13991 else 13992 peers_unmon_online++; 13993 } 13994 13995 snprintf(srch, sizeof(srch), FORMAT, name, 13996 peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)", 13997 peer->host_dynamic ? " D " : " ", /* Dynamic or not? */ 13998 ast_test_flag(&peer->flags[0], SIP_NAT_ROUTE) ? " N " : " ", /* NAT=yes? */ 13999 peer->ha ? " A " : " ", /* permit/deny */ 14000 ntohs(peer->addr.sin_port), status, 14001 realtimepeers ? (peer->is_realtime ? "Cached RT":"") : ""); 14002 14003 if (!s) {/* Normal CLI list */ 14004 ast_cli(fd, FORMAT, name, 14005 peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)", 14006 peer->host_dynamic ? " D " : " ", /* Dynamic or not? */ 14007 ast_test_flag(&peer->flags[0], SIP_NAT_ROUTE) ? " N " : " ", /* NAT=yes? */ 14008 peer->ha ? " A " : " ", /* permit/deny */ 14009 14010 ntohs(peer->addr.sin_port), status, 14011 realtimepeers ? (peer->is_realtime ? "Cached RT":"") : ""); 14012 } else { /* Manager format */ 14013 /* The names here need to be the same as other channels */ 14014 astman_append(s, 14015 "Event: PeerEntry\r\n%s" 14016 "Channeltype: SIP\r\n" 14017 "ObjectName: %s\r\n" 14018 "ChanObjectType: peer\r\n" /* "peer" or "user" */ 14019 "IPaddress: %s\r\n" 14020 "IPport: %d\r\n" 14021 "Dynamic: %s\r\n" 14022 "Natsupport: %s\r\n" 14023 "VideoSupport: %s\r\n" 14024 "TextSupport: %s\r\n" 14025 "ACL: %s\r\n" 14026 "Status: %s\r\n" 14027 "RealtimeDevice: %s\r\n\r\n", 14028 idtext, 14029 peer->name, 14030 peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "-none-", 14031 ntohs(peer->addr.sin_port), 14032 peer->host_dynamic ? "yes" : "no", /* Dynamic or not? */ 14033 ast_test_flag(&peer->flags[0], SIP_NAT_ROUTE) ? "yes" : "no", /* NAT=yes? */ 14034 ast_test_flag(&peer->flags[1], SIP_PAGE2_VIDEOSUPPORT) ? "yes" : "no", /* VIDEOSUPPORT=yes? */ 14035 ast_test_flag(&peer->flags[1], SIP_PAGE2_TEXTSUPPORT) ? "yes" : "no", /* TEXTSUPPORT=yes? */ 14036 peer->ha ? "yes" : "no", /* permit/deny */ 14037 status, 14038 realtimepeers ? (peer->is_realtime ? "yes":"no") : "no"); 14039 } 14040 ao2_unlock(peer); 14041 unref_peer(peer, "toss iterator peer ptr"); 14042 } 14043 14044 if (!s) 14045 ast_cli(fd, "%d sip peers [Monitored: %d online, %d offline Unmonitored: %d online, %d offline]\n", 14046 total_peers, peers_mon_online, peers_mon_offline, peers_unmon_online, peers_unmon_offline); 14047 14048 if (havepattern) 14049 regfree(®exbuf); 14050 14051 if (total) 14052 *total = total_peers; 14053 14054 ast_free(peerarray); 14055 14056 return CLI_SUCCESS; 14057 #undef FORMAT 14058 #undef FORMAT2 14059 }
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 2544 of file chan_sip.c.
References ao2_lock(), ao2_ref, ao2_t_find, ao2_t_ref, ao2_t_unlink, ao2_unlock(), ast_debug, ast_free, AST_LIST_REMOVE_HEAD, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_poll, ast_str_append(), ast_str_buffer, ast_str_create(), ast_str_reset(), ast_tcptls_client_start(), ast_tcptls_server_write(), buf, cleanup(), ast_tcptls_session_instance::client, copy_request(), tcptls_packet::data, sip_request::data, tcptls_packet::entry, errno, ast_tcptls_session_instance::f, ast_tcptls_session_instance::fd, get_header(), handle_request_do(), tcptls_packet::len, ast_tcptls_session_instance::lock, LOG_ERROR, LOG_WARNING, me, MIN, OBJ_POINTER, ast_tcptls_session_instance::parent, parse_request(), ast_tcptls_session_instance::remote_address, REQ_OFFSET_TO_STR, set_socket_transport(), SIP_MIN_PACKET, sip_threadinfo_create(), SIP_TRANSPORT_TCP, SIP_TRANSPORT_TLS, ast_tcptls_session_instance::ssl, TCPTLS_ALERT_DATA, TCPTLS_ALERT_STOP, sip_threadinfo::tcptls_session, and threadt.
Referenced by sip_tcp_worker_fn().
02545 { 02546 int res, cl; 02547 struct sip_request req = { 0, } , reqcpy = { 0, }; 02548 struct sip_threadinfo *me = NULL; 02549 char buf[1024] = ""; 02550 struct pollfd fds[2] = { { 0 }, { 0 }, }; 02551 struct ast_tcptls_session_args *ca = NULL; 02552 02553 /* If this is a server session, then the connection has already been setup, 02554 * simply create the threadinfo object so we can access this thread for writing. 02555 * 02556 * if this is a client connection more work must be done. 02557 * 1. We own the parent session args for a client connection. This pointer needs 02558 * to be held on to so we can decrement it's ref count on thread destruction. 02559 * 2. The threadinfo object was created before this thread was launched, however 02560 * it must be found within the threadt table. 02561 * 3. Last, the tcptls_session must be started. 02562 */ 02563 if (!tcptls_session->client) { 02564 if (!(me = sip_threadinfo_create(tcptls_session, tcptls_session->ssl ? SIP_TRANSPORT_TLS : SIP_TRANSPORT_TCP))) { 02565 goto cleanup; 02566 } 02567 ao2_t_ref(me, +1, "Adding threadinfo ref for tcp_helper_thread"); 02568 } else { 02569 struct sip_threadinfo tmp = { 02570 .tcptls_session = tcptls_session, 02571 }; 02572 02573 if ((!(ca = tcptls_session->parent)) || 02574 (!(me = ao2_t_find(threadt, &tmp, OBJ_POINTER, "ao2_find, getting sip_threadinfo in tcp helper thread"))) || 02575 (!(tcptls_session = ast_tcptls_client_start(tcptls_session)))) { 02576 goto cleanup; 02577 } 02578 } 02579 02580 me->threadid = pthread_self(); 02581 ast_debug(2, "Starting thread for %s server\n", tcptls_session->ssl ? "SSL" : "TCP"); 02582 02583 /* set up pollfd to watch for reads on both the socket and the alert_pipe */ 02584 fds[0].fd = tcptls_session->fd; 02585 fds[1].fd = me->alert_pipe[0]; 02586 fds[0].events = fds[1].events = POLLIN | POLLPRI; 02587 02588 if (!(req.data = ast_str_create(SIP_MIN_PACKET))) 02589 goto cleanup; 02590 if (!(reqcpy.data = ast_str_create(SIP_MIN_PACKET))) 02591 goto cleanup; 02592 02593 for (;;) { 02594 struct ast_str *str_save; 02595 02596 res = ast_poll(fds, 2, -1); /* polls for both socket and alert_pipe */ 02597 if (res < 0) { 02598 ast_debug(2, "SIP %s server :: ast_wait_for_input returned %d\n", tcptls_session->ssl ? "SSL": "TCP", res); 02599 goto cleanup; 02600 } 02601 02602 /* handle the socket event, check for both reads from the socket fd, 02603 * and writes from alert_pipe fd */ 02604 if (fds[0].revents) { /* there is data on the socket to be read */ 02605 02606 fds[0].revents = 0; 02607 02608 /* clear request structure */ 02609 str_save = req.data; 02610 memset(&req, 0, sizeof(req)); 02611 req.data = str_save; 02612 ast_str_reset(req.data); 02613 02614 str_save = reqcpy.data; 02615 memset(&reqcpy, 0, sizeof(reqcpy)); 02616 reqcpy.data = str_save; 02617 ast_str_reset(reqcpy.data); 02618 02619 memset(buf, 0, sizeof(buf)); 02620 02621 if (tcptls_session->ssl) { 02622 set_socket_transport(&req.socket, SIP_TRANSPORT_TLS); 02623 req.socket.port = htons(ourport_tls); 02624 } else { 02625 set_socket_transport(&req.socket, SIP_TRANSPORT_TCP); 02626 req.socket.port = htons(ourport_tcp); 02627 } 02628 req.socket.fd = tcptls_session->fd; 02629 02630 /* Read in headers one line at a time */ 02631 while (req.len < 4 || strncmp(REQ_OFFSET_TO_STR(&req, len - 4), "\r\n\r\n", 4)) { 02632 ast_mutex_lock(&tcptls_session->lock); 02633 if (!fgets(buf, sizeof(buf), tcptls_session->f)) { 02634 ast_mutex_unlock(&tcptls_session->lock); 02635 goto cleanup; 02636 } 02637 ast_mutex_unlock(&tcptls_session->lock); 02638 if (me->stop) 02639 goto cleanup; 02640 ast_str_append(&req.data, 0, "%s", buf); 02641 req.len = req.data->used; 02642 } 02643 copy_request(&reqcpy, &req); 02644 parse_request(&reqcpy); 02645 /* In order to know how much to read, we need the content-length header */ 02646 if (sscanf(get_header(&reqcpy, "Content-Length"), "%30d", &cl)) { 02647 while (cl > 0) { 02648 size_t bytes_read; 02649 ast_mutex_lock(&tcptls_session->lock); 02650 if (!(bytes_read = fread(buf, 1, MIN(sizeof(buf) - 1, cl), tcptls_session->f))) { 02651 ast_mutex_unlock(&tcptls_session->lock); 02652 goto cleanup; 02653 } 02654 buf[bytes_read] = '\0'; 02655 ast_mutex_unlock(&tcptls_session->lock); 02656 if (me->stop) 02657 goto cleanup; 02658 cl -= strlen(buf); 02659 ast_str_append(&req.data, 0, "%s", buf); 02660 req.len = req.data->used; 02661 } 02662 } 02663 /*! \todo XXX If there's no Content-Length or if the content-length and what 02664 we receive is not the same - we should generate an error */ 02665 02666 req.socket.tcptls_session = tcptls_session; 02667 handle_request_do(&req, &tcptls_session->remote_address); 02668 } 02669 if (fds[1].revents) { /* alert_pipe indicates there is data in the send queue to be sent */ 02670 enum sip_tcptls_alert alert; 02671 struct tcptls_packet *packet; 02672 02673 fds[1].revents = 0; 02674 02675 if (read(me->alert_pipe[0], &alert, sizeof(alert)) == -1) { 02676 ast_log(LOG_ERROR, "read() failed: %s\n", strerror(errno)); 02677 continue; 02678 } 02679 02680 switch (alert) { 02681 case TCPTLS_ALERT_STOP: 02682 goto cleanup; 02683 case TCPTLS_ALERT_DATA: 02684 ao2_lock(me); 02685 if (!(packet = AST_LIST_REMOVE_HEAD(&me->packet_q, entry))) { 02686 ast_log(LOG_WARNING, "TCPTLS thread alert_pipe indicated packet should be sent, but frame_q is empty"); 02687 } else if (ast_tcptls_server_write(tcptls_session, ast_str_buffer(packet->data), packet->len) == -1) { 02688 ast_log(LOG_WARNING, "Failure to write to tcp/tls socket\n"); 02689 } 02690 02691 if (packet) { 02692 ao2_t_ref(packet, -1, "tcptls packet sent, this is no longer needed"); 02693 } 02694 ao2_unlock(me); 02695 break; 02696 default: 02697 ast_log(LOG_ERROR, "Unknown tcptls thread alert '%d'\n", alert); 02698 } 02699 } 02700 } 02701 02702 ast_debug(2, "Shutting down thread for %s server\n", tcptls_session->ssl ? "SSL" : "TCP"); 02703 02704 cleanup: 02705 if (me) { 02706 ao2_t_unlink(threadt, me, "Removing tcptls helper thread, thread is closing"); 02707 ao2_t_ref(me, -1, "Removing tcp_helper_threads threadinfo ref"); 02708 } 02709 if (reqcpy.data) { 02710 ast_free(reqcpy.data); 02711 } 02712 02713 if (req.data) { 02714 ast_free(req.data); 02715 req.data = NULL; 02716 } 02717 02718 /* if client, we own the parent session arguments and must decrement ref */ 02719 if (ca) { 02720 ao2_t_ref(ca, -1, "closing tcptls thread, getting rid of client tcptls_session arguments"); 02721 } 02722 02723 if (tcptls_session) { 02724 ast_mutex_lock(&tcptls_session->lock); 02725 if (tcptls_session->f) { 02726 fclose(tcptls_session->f); 02727 tcptls_session->f = NULL; 02728 } 02729 if (tcptls_session->fd != -1) { 02730 close(tcptls_session->fd); 02731 tcptls_session->fd = -1; 02732 } 02733 tcptls_session->parent = NULL; 02734 ast_mutex_unlock(&tcptls_session->lock); 02735 02736 ao2_ref(tcptls_session, -1); 02737 tcptls_session = NULL; 02738 } 02739 02740 return NULL; 02741 }
static int acf_channel_read | ( | struct ast_channel * | chan, | |
const char * | funcname, | |||
char * | preparse, | |||
char * | buf, | |||
size_t | buflen | |||
) | [static] |
Definition at line 20004 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.
20005 { 20006 struct sip_pvt *p = chan->tech_pvt; 20007 char *all = "", *parse = ast_strdupa(preparse); 20008 int res = 0; 20009 AST_DECLARE_APP_ARGS(args, 20010 AST_APP_ARG(param); 20011 AST_APP_ARG(type); 20012 AST_APP_ARG(field); 20013 ); 20014 AST_STANDARD_APP_ARGS(args, parse); 20015 20016 /* Sanity check */ 20017 if (!IS_SIP_TECH(chan->tech)) { 20018 ast_log(LOG_ERROR, "Cannot call %s on a non-SIP channel\n", funcname); 20019 return 0; 20020 } 20021 20022 memset(buf, 0, buflen); 20023 20024 if (p == NULL) { 20025 return -1; 20026 } 20027 20028 if (!strcasecmp(args.param, "peerip")) { 20029 ast_copy_string(buf, p->sa.sin_addr.s_addr ? ast_inet_ntoa(p->sa.sin_addr) : "", buflen); 20030 } else if (!strcasecmp(args.param, "recvip")) { 20031 ast_copy_string(buf, p->recv.sin_addr.s_addr ? ast_inet_ntoa(p->recv.sin_addr) : "", buflen); 20032 } else if (!strcasecmp(args.param, "from")) { 20033 ast_copy_string(buf, p->from, buflen); 20034 } else if (!strcasecmp(args.param, "uri")) { 20035 ast_copy_string(buf, p->uri, buflen); 20036 } else if (!strcasecmp(args.param, "useragent")) { 20037 ast_copy_string(buf, p->useragent, buflen); 20038 } else if (!strcasecmp(args.param, "peername")) { 20039 ast_copy_string(buf, p->peername, buflen); 20040 } else if (!strcasecmp(args.param, "t38passthrough")) { 20041 ast_copy_string(buf, (p->t38.state == T38_DISABLED) ? "0" : "1", buflen); 20042 } else if (!strcasecmp(args.param, "rtpdest")) { 20043 struct sockaddr_in sin; 20044 struct ast_rtp *stream = NULL; 20045 20046 if (ast_strlen_zero(args.type)) 20047 args.type = "audio"; 20048 20049 if (!strcasecmp(args.type, "audio")) { 20050 stream = p->rtp; 20051 } else if (!strcasecmp(args.type, "video")) { 20052 stream = p->vrtp; 20053 } else if (!strcasecmp(args.type, "text")) { 20054 stream = p->trtp; 20055 } else { 20056 return -1; 20057 } 20058 20059 if (!stream) { 20060 return -1; 20061 } 20062 20063 ast_rtp_get_peer(stream, &sin); 20064 snprintf(buf, buflen, "%s:%d", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 20065 } else if (!strcasecmp(args.param, "rtpqos")) { 20066 struct ast_rtp_quality qos; 20067 struct ast_rtp *rtp = p->rtp; 20068 20069 memset(&qos, 0, sizeof(qos)); 20070 20071 if (ast_strlen_zero(args.type)) 20072 args.type = "audio"; 20073 if (ast_strlen_zero(args.field)) 20074 args.field = "all"; 20075 20076 if (!strcasecmp(args.type, "AUDIO")) { 20077 all = ast_rtp_get_quality(rtp = p->rtp, &qos, RTPQOS_SUMMARY); 20078 } else if (!strcasecmp(args.type, "VIDEO")) { 20079 all = ast_rtp_get_quality(rtp = p->vrtp, &qos, RTPQOS_SUMMARY); 20080 } else if (!strcasecmp(args.type, "TEXT")) { 20081 all = ast_rtp_get_quality(rtp = p->trtp, &qos, RTPQOS_SUMMARY); 20082 } else { 20083 return -1; 20084 } 20085 20086 if (!strcasecmp(args.field, "local_ssrc")) 20087 snprintf(buf, buflen, "%u", qos.local_ssrc); 20088 else if (!strcasecmp(args.field, "local_lostpackets")) 20089 snprintf(buf, buflen, "%u", qos.local_lostpackets); 20090 else if (!strcasecmp(args.field, "local_jitter")) 20091 snprintf(buf, buflen, "%.0f", qos.local_jitter * 1000.0); 20092 else if (!strcasecmp(args.field, "local_count")) 20093 snprintf(buf, buflen, "%u", qos.local_count); 20094 else if (!strcasecmp(args.field, "remote_ssrc")) 20095 snprintf(buf, buflen, "%u", qos.remote_ssrc); 20096 else if (!strcasecmp(args.field, "remote_lostpackets")) 20097 snprintf(buf, buflen, "%u", qos.remote_lostpackets); 20098 else if (!strcasecmp(args.field, "remote_jitter")) 20099 snprintf(buf, buflen, "%.0f", qos.remote_jitter * 1000.0); 20100 else if (!strcasecmp(args.field, "remote_count")) 20101 snprintf(buf, buflen, "%u", qos.remote_count); 20102 else if (!strcasecmp(args.field, "rtt")) 20103 snprintf(buf, buflen, "%.0f", qos.rtt * 1000.0); 20104 else if (!strcasecmp(args.field, "all")) 20105 ast_copy_string(buf, all, buflen); 20106 else if (!ast_rtp_get_qos(rtp, args.field, buf, buflen)) 20107 ; 20108 else { 20109 ast_log(LOG_WARNING, "Unrecognized argument '%s' to %s\n", preparse, funcname); 20110 return -1; 20111 } 20112 } else { 20113 res = -1; 20114 } 20115 return res; 20116 }
static void add_blank | ( | struct sip_request * | req | ) | [static] |
add a blank line if no body
Definition at line 3763 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().
03764 { 03765 if (!req->lines) { 03766 /* Add extra empty return. add_header() reserves 4 bytes so cannot be truncated */ 03767 ast_str_append(&req->data, 0, "\r\n"); 03768 req->len = req->data->used; 03769 } 03770 }
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 9190 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().
09193 { 09194 int rtp_code; 09195 struct ast_format_list fmt; 09196 09197 09198 if (debug) 09199 ast_verbose("Adding codec 0x%x (%s) to SDP\n", codec, ast_getformatname(codec)); 09200 if ((rtp_code = ast_rtp_lookup_code(p->rtp, 1, codec)) == -1) 09201 return; 09202 09203 if (p->rtp) { 09204 struct ast_codec_pref *pref = ast_rtp_codec_getpref(p->rtp); 09205 fmt = ast_codec_pref_getsize(pref, codec); 09206 } 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 */ 09207 return; 09208 ast_str_append(m_buf, 0, " %d", rtp_code); 09209 ast_str_append(a_buf, 0, "a=rtpmap:%d %s/%d\r\n", rtp_code, 09210 ast_rtp_lookup_mime_subtype(1, codec, 09211 ast_test_flag(&p->flags[0], SIP_G726_NONSTANDARD) ? AST_RTP_OPT_G726_NONSTANDARD : 0), 09212 sample_rate); 09213 if (codec == AST_FORMAT_G729A) { 09214 /* Indicate that we don't support VAD (G.729 annex B) */ 09215 ast_str_append(a_buf, 0, "a=fmtp:%d annexb=no\r\n", rtp_code); 09216 } else if (codec == AST_FORMAT_G723_1) { 09217 /* Indicate that we don't support VAD (G.723.1 annex A) */ 09218 ast_str_append(a_buf, 0, "a=fmtp:%d annexa=no\r\n", rtp_code); 09219 } else if (codec == AST_FORMAT_ILBC) { 09220 /* Add information about us using only 20/30 ms packetization */ 09221 ast_str_append(a_buf, 0, "a=fmtp:%d mode=%d\r\n", rtp_code, fmt.cur_ms); 09222 } 09223 09224 if (fmt.cur_ms && (fmt.cur_ms < *min_packet_size)) 09225 *min_packet_size = fmt.cur_ms; 09226 09227 /* Our first codec packetization processed cannot be zero */ 09228 if ((*min_packet_size)==0 && fmt.cur_ms) 09229 *min_packet_size = fmt.cur_ms; 09230 }
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 9141 of file chan_sip.c.
References add_header(), add_header_contentLength(), and add_line().
Referenced by transmit_info_with_digit().
09142 { 09143 char tmp[256]; 09144 int event; 09145 if (mode) { 09146 /* Application/dtmf short version used by some implementations */ 09147 if (digit == '*') 09148 event = 10; 09149 else if (digit == '#') 09150 event = 11; 09151 else if ((digit >= 'A') && (digit <= 'D')) 09152 event = 12 + digit - 'A'; 09153 else 09154 event = atoi(&digit); 09155 snprintf(tmp, sizeof(tmp), "%d\r\n", event); 09156 add_header(req, "Content-Type", "application/dtmf"); 09157 add_header_contentLength(req, strlen(tmp)); 09158 add_line(req, tmp); 09159 } else { 09160 /* Application/dtmf-relay as documented by Cisco */ 09161 snprintf(tmp, sizeof(tmp), "Signal=%c\r\nDuration=%u\r\n", digit, duration); 09162 add_header(req, "Content-Type", "application/dtmf-relay"); 09163 add_header_contentLength(req, strlen(tmp)); 09164 add_line(req, tmp); 09165 } 09166 return 0; 09167 }
static int add_header | ( | struct sip_request * | req, | |
const char * | var, | |||
const char * | value | |||
) | [static] |
Add header to SIP message.
Definition at line 8392 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.
08393 { 08394 if (req->headers == SIP_MAX_HEADERS) { 08395 ast_log(LOG_WARNING, "Out of SIP header space\n"); 08396 return -1; 08397 } 08398 08399 if (req->lines) { 08400 ast_log(LOG_WARNING, "Can't add more headers when lines have been added\n"); 08401 return -1; 08402 } 08403 08404 if (compactheaders) 08405 var = find_alias(var, var); 08406 08407 ast_str_append(&req->data, 0, "%s: %s\r\n", var, value); 08408 req->header[req->headers] = req->len; 08409 08410 req->len = req->data->used; 08411 req->headers++; 08412 08413 return 0; 08414 }
static int add_header_contentLength | ( | struct sip_request * | req, | |
int | len | |||
) | [static] |
Add 'Content-Length' header to SIP message.
Definition at line 8417 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().
08418 { 08419 char clen[10]; 08420 08421 snprintf(clen, sizeof(clen), "%d", len); 08422 return add_header(req, "Content-Length", clen); 08423 }
static int add_line | ( | struct sip_request * | req, | |
const char * | line | |||
) | [static] |
Add content (not header) to SIP message.
Definition at line 8426 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.
08427 { 08428 if (req->lines == SIP_MAX_LINES) { 08429 ast_log(LOG_WARNING, "Out of SIP line space\n"); 08430 return -1; 08431 } 08432 if (!req->lines) 08433 /* Add extra empty return */ 08434 req->len += ast_str_append(&req->data, 0, "\r\n"); 08435 req->line[req->lines] = req->len; 08436 ast_str_append(&req->data, 0, "%s", line); 08437 req->len = req->data->used; 08438 req->lines++; 08439 return 0; 08440 }
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 9308 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().
09311 { 09312 int rtp_code; 09313 09314 if (debug) 09315 ast_verbose("Adding non-codec 0x%x (%s) to SDP\n", format, ast_rtp_lookup_mime_subtype(0, format, 0)); 09316 if ((rtp_code = ast_rtp_lookup_code(p->rtp, 0, format)) == -1) 09317 return; 09318 09319 ast_str_append(m_buf, 0, " %d", rtp_code); 09320 ast_str_append(a_buf, 0, "a=rtpmap:%d %s/%d\r\n", rtp_code, 09321 ast_rtp_lookup_mime_subtype(0, format, 0), 09322 sample_rate); 09323 if (format == AST_RTP_DTMF) /* Indicate we support DTMF and FLASH... */ 09324 ast_str_append(a_buf, 0, "a=fmtp:%d 0-16\r\n", rtp_code); 09325 }
static void add_peer_mailboxes | ( | struct sip_peer * | peer, | |
const char * | value | |||
) | [static] |
Definition at line 22740 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().
22741 { 22742 char *next, *mbox, *context; 22743 22744 next = ast_strdupa(value); 22745 22746 while ((mbox = context = strsep(&next, ","))) { 22747 struct sip_mailbox *mailbox; 22748 22749 if (!(mailbox = ast_calloc(1, sizeof(*mailbox)))) 22750 continue; 22751 22752 strsep(&context, "@"); 22753 if (ast_strlen_zero(mbox)) { 22754 ast_free(mailbox); 22755 continue; 22756 } 22757 mailbox->mailbox = ast_strdup(mbox); 22758 mailbox->context = ast_strdup(context); 22759 22760 AST_LIST_INSERT_TAIL(&peer->mailboxes, mailbox, entry); 22761 } 22762 }
static void add_peer_mwi_subs | ( | struct sip_peer * | peer | ) | [static] |
Definition at line 20257 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().
20258 { 20259 struct sip_mailbox *mailbox; 20260 20261 AST_LIST_TRAVERSE(&peer->mailboxes, mailbox, entry) { 20262 mailbox->event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, peer, 20263 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox->mailbox, 20264 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, S_OR(mailbox->context, "default"), 20265 AST_EVENT_IE_END); 20266 } 20267 }
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 22564 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, and sip_auth::username.
Referenced by build_peer().
22565 { 22566 char authcopy[256]; 22567 char *username=NULL, *realm=NULL, *secret=NULL, *md5secret=NULL; 22568 struct sip_auth *a, *b, *auth; 22569 22570 if (ast_strlen_zero(configuration)) 22571 return authlist; 22572 22573 ast_debug(1, "Auth config :: %s\n", configuration); 22574 22575 ast_copy_string(authcopy, configuration, sizeof(authcopy)); 22576 username = authcopy; 22577 22578 /* split user[:secret] and relm */ 22579 realm = strrchr(username, '@'); 22580 if (realm) 22581 *realm++ = '\0'; 22582 if (ast_strlen_zero(username) || ast_strlen_zero(realm)) { 22583 ast_log(LOG_WARNING, "Format for authentication entry is user[:secret]@realm at line %d\n", lineno); 22584 return authlist; 22585 } 22586 22587 /* parse username at ':' for secret, or '#" for md5secret */ 22588 if ((secret = strchr(username, ':'))) { 22589 *secret++ = '\0'; 22590 } else if ((md5secret = strchr(username, '#'))) { 22591 *md5secret++ = '\0'; 22592 } 22593 22594 if (!(auth = ast_calloc(1, sizeof(*auth)))) 22595 return authlist; 22596 22597 ast_copy_string(auth->realm, realm, sizeof(auth->realm)); 22598 ast_copy_string(auth->username, username, sizeof(auth->username)); 22599 if (secret) 22600 ast_copy_string(auth->secret, secret, sizeof(auth->secret)); 22601 if (md5secret) 22602 ast_copy_string(auth->md5secret, md5secret, sizeof(auth->md5secret)); 22603 22604 /* find the end of the list */ 22605 for (b = NULL, a = authlist; a ; b = a, a = a->next) 22606 ; 22607 if (b) 22608 b->next = auth; /* Add structure add end of list */ 22609 else 22610 authlist = auth; 22611 22612 ast_verb(3, "Added authentication for realm %s\n", realm); 22613 22614 return authlist; 22615 22616 }
static void add_route | ( | struct sip_request * | req, | |
struct sip_route * | route | |||
) | [static] |
Add route header into request per learned route.
Definition at line 8543 of file chan_sip.c.
References add_header(), ast_copy_string(), sip_route::hop, sip_route::next, and SIPBUFSIZE.
Referenced by initreqprep(), and reqprep().
08544 { 08545 char r[SIPBUFSIZE*2], *p; 08546 int n, rem = sizeof(r); 08547 08548 if (!route) 08549 return; 08550 08551 p = r; 08552 for (;route ; route = route->next) { 08553 n = strlen(route->hop); 08554 if (rem < n+3) /* we need room for ",<route>" */ 08555 break; 08556 if (p != r) { /* add a separator after fist route */ 08557 *p++ = ','; 08558 --rem; 08559 } 08560 *p++ = '<'; 08561 ast_copy_string(p, route->hop, rem); /* cannot fail */ 08562 p += n; 08563 *p++ = '>'; 08564 rem -= (n+2); 08565 } 08566 *p = '\0'; 08567 add_header(req, "Route", r); 08568 }
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 9376 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_T38_RATE_MANAGEMENT_LOCAL_TCF, AST_T38_RATE_MANAGEMENT_TRANSFERRED_TCF, ast_test_flag, ast_udptl_get_error_correction_scheme(), ast_udptl_get_local_max_datagram(), ast_udptl_get_us(), ast_verbose, buf, sip_request::debug, FALSE, ast_control_t38_parameters::fill_bit_removal, sip_pvt::flags, get_our_media_address(), sip_pvt::jointcapability, sip_pvt::jointnoncodeccapability, sip_pvt::lastrtprx, sip_pvt::lastrtptx, ast_str::len, LOG_WARNING, sip_pvt::maxcallbitrate, sip_pvt::notext, sip_pvt::novideo, sip_pvt::offered_media, t38properties::our_parms, sip_pvt::ourip, sip_pvt::owner, sip_pvt::prefcodec, sip_pvt::prefs, ast_control_t38_parameters::rate, ast_control_t38_parameters::rate_management, sip_pvt::rtp, SDP_AUDIO, SDP_IMAGE, SDP_SAMPLE_RATE, SDP_TEXT, SDP_VIDEO, sip_pvt::sessionid, sip_pvt::sessionversion, sip_debug_test_pvt(), SIP_PAGE2_CALL_ONHOLD, SIP_PAGE2_CALL_ONHOLD_INACTIVE, SIP_PAGE2_CALL_ONHOLD_ONEDIR, SIPBUFSIZE, ast_str::str, sip_pvt::t38, t38_get_rate(), ast_control_t38_parameters::transcoding_jbig, ast_control_t38_parameters::transcoding_mmr, sip_pvt::tredirip, sip_pvt::trtp, TRUE, sip_pvt::udptl, UDPTL_ERROR_CORRECTION_FEC, UDPTL_ERROR_CORRECTION_NONE, UDPTL_ERROR_CORRECTION_REDUNDANCY, sip_pvt::udptlredirip, ast_str::used, ast_control_t38_parameters::version, version, and sip_pvt::vrtp.
09377 { 09378 int len = 0; 09379 int alreadysent = 0; 09380 09381 struct sockaddr_in sin; 09382 struct sockaddr_in vsin; 09383 struct sockaddr_in tsin; 09384 struct sockaddr_in dest; 09385 struct sockaddr_in udptlsin; 09386 struct sockaddr_in vdest = { 0, }; 09387 struct sockaddr_in tdest = { 0, }; 09388 struct sockaddr_in udptldest = { 0, }; 09389 09390 /* SDP fields */ 09391 char *version = "v=0\r\n"; /* Protocol version */ 09392 char subject[256]; /* Subject of the session */ 09393 char owner[256]; /* Session owner/creator */ 09394 char connection[256]; /* Connection data */ 09395 char *session_time = "t=0 0\r\n"; /* Time the session is active */ 09396 char bandwidth[256] = ""; /* Max bitrate */ 09397 char *hold = ""; 09398 struct ast_str *m_audio = ast_str_alloca(256); /* Media declaration line for audio */ 09399 struct ast_str *m_video = ast_str_alloca(256); /* Media declaration line for video */ 09400 struct ast_str *m_text = ast_str_alloca(256); /* Media declaration line for text */ 09401 struct ast_str *m_modem = ast_str_alloca(256); /* Media declaration line for modem */ 09402 struct ast_str *a_audio = ast_str_alloca(1024); /* Attributes for audio */ 09403 struct ast_str *a_video = ast_str_alloca(1024); /* Attributes for video */ 09404 struct ast_str *a_text = ast_str_alloca(1024); /* Attributes for text */ 09405 struct ast_str *a_modem = ast_str_alloca(1024); /* Attributes for modem */ 09406 09407 int x; 09408 int capability = 0; 09409 int needaudio = FALSE; 09410 int needvideo = FALSE; 09411 int needtext = FALSE; 09412 int debug = sip_debug_test_pvt(p); 09413 int min_audio_packet_size = 0; 09414 int min_video_packet_size = 0; 09415 int min_text_packet_size = 0; 09416 09417 char codecbuf[SIPBUFSIZE]; 09418 char buf[SIPBUFSIZE]; 09419 char dummy_answer[256]; 09420 09421 /* Set the SDP session name */ 09422 snprintf(subject, sizeof(subject), "s=%s\r\n", ast_strlen_zero(global_sdpsession) ? "-" : global_sdpsession); 09423 09424 if (!p->rtp) { 09425 ast_log(LOG_WARNING, "No way to add SDP without an RTP structure\n"); 09426 return AST_FAILURE; 09427 } 09428 /* XXX We should not change properties in the SIP dialog until 09429 we have acceptance of the offer if this is a re-invite */ 09430 09431 /* Set RTP Session ID and version */ 09432 if (!p->sessionid) { 09433 p->sessionid = (int)ast_random(); 09434 p->sessionversion = p->sessionid; 09435 } else { 09436 if (oldsdp == FALSE) 09437 p->sessionversion++; 09438 } 09439 09440 if (add_audio) { 09441 /* Check if we need video in this call */ 09442 if ((p->jointcapability & AST_FORMAT_VIDEO_MASK) && !p->novideo) { 09443 if (p->vrtp) { 09444 needvideo = TRUE; 09445 ast_debug(2, "This call needs video offers!\n"); 09446 } else 09447 ast_debug(2, "This call needs video offers, but there's no video support enabled!\n"); 09448 } 09449 /* Check if we need text in this call */ 09450 if ((p->jointcapability & AST_FORMAT_TEXT_MASK) && !p->notext) { 09451 if (sipdebug_text) 09452 ast_verbose("We think we can do text\n"); 09453 if (p->trtp) { 09454 if (sipdebug_text) { 09455 ast_verbose("And we have a text rtp object\n"); 09456 } 09457 needtext = TRUE; 09458 ast_debug(2, "This call needs text offers! \n"); 09459 } else { 09460 ast_debug(2, "This call needs text offers, but there's no text support enabled ! \n"); 09461 } 09462 } 09463 } 09464 09465 get_our_media_address(p, needvideo, &sin, &vsin, &tsin, &dest, &vdest); 09466 09467 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)); 09468 snprintf(connection, sizeof(connection), "c=IN IP4 %s\r\n", ast_inet_ntoa(dest.sin_addr)); 09469 09470 if (add_audio) { 09471 capability = p->jointcapability; 09472 09473 /* XXX note, Video and Text are negated - 'true' means 'no' */ 09474 ast_debug(1, "** Our capability: %s Video flag: %s Text flag: %s\n", ast_getformatname_multiple(codecbuf, sizeof(codecbuf), capability), 09475 p->novideo ? "True" : "False", p->notext ? "True" : "False"); 09476 ast_debug(1, "** Our prefcodec: %s \n", ast_getformatname_multiple(codecbuf, sizeof(codecbuf), p->prefcodec)); 09477 09478 /* Check if we need audio */ 09479 if (capability & AST_FORMAT_AUDIO_MASK) 09480 needaudio = TRUE; 09481 09482 if (debug) 09483 ast_verbose("Audio is at %s port %d\n", ast_inet_ntoa(p->ourip.sin_addr), ntohs(sin.sin_port)); 09484 09485 /* Ok, we need video. Let's add what we need for video and set codecs. 09486 Video is handled differently than audio since we can not transcode. */ 09487 if (needvideo) { 09488 ast_str_append(&m_video, 0, "m=video %d RTP/AVP", ntohs(vsin.sin_port)); 09489 09490 /* Build max bitrate string */ 09491 if (p->maxcallbitrate) 09492 snprintf(bandwidth, sizeof(bandwidth), "b=CT:%d\r\n", p->maxcallbitrate); 09493 if (debug) 09494 ast_verbose("Video is at %s port %d\n", ast_inet_ntoa(p->ourip.sin_addr), ntohs(vdest.sin_port)); 09495 } 09496 09497 /* Ok, we need text. Let's add what we need for text and set codecs. 09498 Text is handled differently than audio since we can not transcode. */ 09499 if (needtext) { 09500 if (sipdebug_text) 09501 ast_verbose("Lets set up the text sdp\n"); 09502 /* Determine text destination */ 09503 if (p->tredirip.sin_addr.s_addr) { 09504 tdest.sin_addr = p->tredirip.sin_addr; 09505 tdest.sin_port = p->tredirip.sin_port; 09506 } else { 09507 tdest.sin_addr = p->ourip.sin_addr; 09508 tdest.sin_port = tsin.sin_port; 09509 } 09510 ast_str_append(&m_text, 0, "m=text %d RTP/AVP", ntohs(tdest.sin_port)); 09511 09512 if (debug) /* XXX should I use tdest below ? */ 09513 ast_verbose("Text is at %s port %d\n", ast_inet_ntoa(p->ourip.sin_addr), ntohs(tsin.sin_port)); 09514 09515 } 09516 09517 /* Start building generic SDP headers */ 09518 09519 /* We break with the "recommendation" and send our IP, in order that our 09520 peer doesn't have to ast_gethostbyname() us */ 09521 09522 ast_str_append(&m_audio, 0, "m=audio %d RTP/AVP", ntohs(dest.sin_port)); 09523 09524 if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD) == SIP_PAGE2_CALL_ONHOLD_ONEDIR) 09525 hold = "a=recvonly\r\n"; 09526 else if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD) == SIP_PAGE2_CALL_ONHOLD_INACTIVE) 09527 hold = "a=inactive\r\n"; 09528 else 09529 hold = "a=sendrecv\r\n"; 09530 09531 /* Now, start adding audio codecs. These are added in this order: 09532 - First what was requested by the calling channel 09533 - Then preferences in order from sip.conf device config for this peer/user 09534 - Then other codecs in capabilities, including video 09535 */ 09536 09537 /* Prefer the audio codec we were requested to use, first, no matter what 09538 Note that p->prefcodec can include video codecs, so mask them out 09539 */ 09540 if (capability & p->prefcodec) { 09541 int codec = p->prefcodec & AST_FORMAT_AUDIO_MASK; 09542 09543 add_codec_to_sdp(p, codec, SDP_SAMPLE_RATE(codec), 09544 &m_audio, &a_audio, 09545 debug, &min_audio_packet_size); 09546 alreadysent |= codec; 09547 } 09548 09549 /* Start by sending our preferred audio/video codecs */ 09550 for (x = 0; x < 32; x++) { 09551 int codec; 09552 09553 if (!(codec = ast_codec_pref_index(&p->prefs, x))) 09554 break; 09555 09556 if (!(capability & codec)) 09557 continue; 09558 09559 if (alreadysent & codec) 09560 continue; 09561 09562 add_codec_to_sdp(p, codec, SDP_SAMPLE_RATE(codec), 09563 &m_audio, &a_audio, 09564 debug, &min_audio_packet_size); 09565 alreadysent |= codec; 09566 } 09567 09568 /* Now send any other common audio and video codecs, and non-codec formats: */ 09569 for (x = 1; x <= (needtext ? AST_FORMAT_TEXT_MASK : (needvideo ? AST_FORMAT_VIDEO_MASK : AST_FORMAT_AUDIO_MASK)); x <<= 1) { 09570 if (!(capability & x)) /* Codec not requested */ 09571 continue; 09572 09573 if (alreadysent & x) /* Already added to SDP */ 09574 continue; 09575 09576 if (x & AST_FORMAT_AUDIO_MASK) 09577 add_codec_to_sdp(p, x, SDP_SAMPLE_RATE(x), 09578 &m_audio, &a_audio, debug, &min_audio_packet_size); 09579 else if (x & AST_FORMAT_VIDEO_MASK) 09580 add_vcodec_to_sdp(p, x, 90000, 09581 &m_video, &a_video, debug, &min_video_packet_size); 09582 else if (x & AST_FORMAT_TEXT_MASK) 09583 add_tcodec_to_sdp(p, x, 1000, 09584 &m_text, &a_text, debug, &min_text_packet_size); 09585 } 09586 09587 /* Now add DTMF RFC2833 telephony-event as a codec */ 09588 for (x = 1; x <= AST_RTP_MAX; x <<= 1) { 09589 if (!(p->jointnoncodeccapability & x)) 09590 continue; 09591 09592 add_noncodec_to_sdp(p, x, 8000, &m_audio, &a_audio, debug); 09593 } 09594 09595 ast_debug(3, "-- Done with adding codecs to SDP\n"); 09596 09597 if (!p->owner || !ast_internal_timing_enabled(p->owner)) 09598 ast_str_append(&a_audio, 0, "a=silenceSupp:off - - - -\r\n"); 09599 09600 if (min_audio_packet_size) 09601 ast_str_append(&a_audio, 0, "a=ptime:%d\r\n", min_audio_packet_size); 09602 09603 /* XXX don't think you can have ptime for video */ 09604 if (min_video_packet_size) 09605 ast_str_append(&a_video, 0, "a=ptime:%d\r\n", min_video_packet_size); 09606 09607 /* XXX don't think you can have ptime for text */ 09608 if (min_text_packet_size) 09609 ast_str_append(&a_text, 0, "a=ptime:%d\r\n", min_text_packet_size); 09610 } 09611 09612 if (add_t38) { 09613 ast_udptl_get_us(p->udptl, &udptlsin); 09614 09615 /* Determine T.38 UDPTL destination */ 09616 if (p->udptlredirip.sin_addr.s_addr) { 09617 udptldest.sin_port = p->udptlredirip.sin_port; 09618 udptldest.sin_addr = p->udptlredirip.sin_addr; 09619 } else { 09620 udptldest.sin_addr = p->ourip.sin_addr; 09621 udptldest.sin_port = udptlsin.sin_port; 09622 } 09623 09624 if (debug) 09625 ast_debug(1, "T.38 UDPTL is at %s port %d\n", ast_inet_ntoa(p->ourip.sin_addr), ntohs(udptlsin.sin_port)); 09626 09627 /* We break with the "recommendation" and send our IP, in order that our 09628 peer doesn't have to ast_gethostbyname() us */ 09629 09630 ast_str_append(&m_modem, 0, "m=image %d udptl t38\r\n", ntohs(udptldest.sin_port)); 09631 09632 ast_str_append(&a_modem, 0, "a=T38FaxVersion:%d\r\n", p->t38.our_parms.version); 09633 ast_str_append(&a_modem, 0, "a=T38MaxBitRate:%d\r\n", t38_get_rate(p->t38.our_parms.rate)); 09634 if (p->t38.our_parms.fill_bit_removal) { 09635 ast_str_append(&a_modem, 0, "a=T38FaxFillBitRemoval\r\n"); 09636 } 09637 if (p->t38.our_parms.transcoding_mmr) { 09638 ast_str_append(&a_modem, 0, "a=T38FaxTranscodingMMR\r\n"); 09639 } 09640 if (p->t38.our_parms.transcoding_jbig) { 09641 ast_str_append(&a_modem, 0, "a=T38FaxTranscodingJBIG\r\n"); 09642 } 09643 switch (p->t38.our_parms.rate_management) { 09644 case AST_T38_RATE_MANAGEMENT_TRANSFERRED_TCF: 09645 ast_str_append(&a_modem, 0, "a=T38FaxRateManagement:transferredTCF\r\n"); 09646 break; 09647 case AST_T38_RATE_MANAGEMENT_LOCAL_TCF: 09648 ast_str_append(&a_modem, 0, "a=T38FaxRateManagement:localTCF\r\n"); 09649 break; 09650 } 09651 ast_str_append(&a_modem, 0, "a=T38FaxMaxDatagram:%u\r\n", ast_udptl_get_local_max_datagram(p->udptl)); 09652 switch (ast_udptl_get_error_correction_scheme(p->udptl)) { 09653 case UDPTL_ERROR_CORRECTION_NONE: 09654 break; 09655 case UDPTL_ERROR_CORRECTION_FEC: 09656 ast_str_append(&a_modem, 0, "a=T38FaxUdpEC:t38UDPFEC\r\n"); 09657 break; 09658 case UDPTL_ERROR_CORRECTION_REDUNDANCY: 09659 ast_str_append(&a_modem, 0, "a=T38FaxUdpEC:t38UDPRedundancy\r\n"); 09660 break; 09661 } 09662 } 09663 09664 if (m_audio->len - m_audio->used < 2 || m_video->len - m_video->used < 2 || 09665 m_text->len - m_text->used < 2 || a_text->len - a_text->used < 2 || 09666 a_audio->len - a_audio->used < 2 || a_video->len - a_video->used < 2) 09667 ast_log(LOG_WARNING, "SIP SDP may be truncated due to undersized buffer!!\n"); 09668 09669 if (needaudio) 09670 ast_str_append(&m_audio, 0, "\r\n"); 09671 if (needvideo) 09672 ast_str_append(&m_video, 0, "\r\n"); 09673 if (needtext) 09674 ast_str_append(&m_text, 0, "\r\n"); 09675 09676 len = strlen(version) + strlen(subject) + strlen(owner) + 09677 strlen(connection) + strlen(session_time); 09678 if (needaudio) 09679 len += m_audio->used + a_audio->used + strlen(hold); 09680 if (needvideo) /* only if video response is appropriate */ 09681 len += m_video->used + a_video->used + strlen(bandwidth) + strlen(hold); 09682 if (needtext) /* only if text response is appropriate */ 09683 len += m_text->used + a_text->used + strlen(hold); 09684 if (add_t38) 09685 len += m_modem->used + a_modem->used; 09686 09687 add_header(resp, "Content-Type", "application/sdp"); 09688 add_header_contentLength(resp, len); 09689 add_line(resp, version); 09690 add_line(resp, owner); 09691 add_line(resp, subject); 09692 add_line(resp, connection); 09693 if (needvideo) /* only if video response is appropriate */ 09694 add_line(resp, bandwidth); 09695 add_line(resp, session_time); 09696 if (needaudio) { 09697 add_line(resp, m_audio->str); 09698 add_line(resp, a_audio->str); 09699 add_line(resp, hold); 09700 } else if (p->offered_media[SDP_AUDIO].offered) { 09701 snprintf(dummy_answer, sizeof(dummy_answer), "m=audio 0 RTP/AVP %s\r\n", p->offered_media[SDP_AUDIO].text); 09702 add_line(resp, dummy_answer); 09703 } 09704 if (needvideo) { /* only if video response is appropriate */ 09705 add_line(resp, m_video->str); 09706 add_line(resp, a_video->str); 09707 add_line(resp, hold); /* Repeat hold for the video stream */ 09708 } else if (p->offered_media[SDP_VIDEO].offered) { 09709 snprintf(dummy_answer, sizeof(dummy_answer), "m=video 0 RTP/AVP %s\r\n", p->offered_media[SDP_VIDEO].text); 09710 add_line(resp, dummy_answer); 09711 } 09712 if (needtext) { /* only if text response is appropriate */ 09713 add_line(resp, m_text->str); 09714 add_line(resp, a_text->str); 09715 add_line(resp, hold); /* Repeat hold for the text stream */ 09716 } else if (p->offered_media[SDP_TEXT].offered) { 09717 snprintf(dummy_answer, sizeof(dummy_answer), "m=text 0 RTP/AVP %s\r\n", p->offered_media[SDP_TEXT].text); 09718 add_line(resp, dummy_answer); 09719 } 09720 if (add_t38) { 09721 add_line(resp, m_modem->str); 09722 add_line(resp, a_modem->str); 09723 } else if (p->offered_media[SDP_IMAGE].offered) { 09724 add_line(resp, "m=image 0 udptl t38\r\n"); 09725 } 09726 09727 /* Update lastrtprx when we send our SDP */ 09728 p->lastrtprx = p->lastrtptx = time(NULL); /* XXX why both ? */ 09729 09730 ast_debug(3, "Done building SDP. Settling with this capability: %s\n", ast_getformatname_multiple(buf, SIPBUFSIZE, capability)); 09731 09732 return AST_SUCCESS; 09733 }
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 22500 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.
22501 { 22502 struct domain *d; 22503 22504 if (ast_strlen_zero(domain)) { 22505 ast_log(LOG_WARNING, "Zero length domain.\n"); 22506 return 1; 22507 } 22508 22509 if (!(d = ast_calloc(1, sizeof(*d)))) 22510 return 0; 22511 22512 ast_copy_string(d->domain, domain, sizeof(d->domain)); 22513 22514 if (!ast_strlen_zero(context)) 22515 ast_copy_string(d->context, context, sizeof(d->context)); 22516 22517 d->mode = mode; 22518 22519 AST_LIST_LOCK(&domain_list); 22520 AST_LIST_INSERT_TAIL(&domain_list, d, list); 22521 AST_LIST_UNLOCK(&domain_list); 22522 22523 if (sipdebug) 22524 ast_debug(1, "Added local SIP domain '%s'\n", domain); 22525 22526 return 1; 22527 }
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 9256 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().
09259 { 09260 int rtp_code; 09261 09262 if (!p->trtp) 09263 return; 09264 09265 if (debug) 09266 ast_verbose("Adding text codec 0x%x (%s) to SDP\n", codec, ast_getformatname(codec)); 09267 09268 if ((rtp_code = ast_rtp_lookup_code(p->trtp, 1, codec)) == -1) 09269 return; 09270 09271 ast_str_append(m_buf, 0, " %d", rtp_code); 09272 ast_str_append(a_buf, 0, "a=rtpmap:%d %s/%d\r\n", rtp_code, 09273 ast_rtp_lookup_mime_subtype(1, codec, 0), sample_rate); 09274 /* Add fmtp code here */ 09275 09276 if (codec == AST_FORMAT_T140RED) { 09277 ast_str_append(a_buf, 0, "a=fmtp:%d %d/%d/%d\r\n", rtp_code, 09278 ast_rtp_lookup_code(p->trtp, 1, AST_FORMAT_T140), 09279 ast_rtp_lookup_code(p->trtp, 1, AST_FORMAT_T140), 09280 ast_rtp_lookup_code(p->trtp, 1, AST_FORMAT_T140)); 09281 09282 } 09283 }
static int add_text | ( | struct sip_request * | req, | |
const char * | text | |||
) | [static] |
Add text body to SIP message.
Definition at line 9128 of file chan_sip.c.
References add_header(), add_header_contentLength(), and add_line().
Referenced by transmit_message_with_text().
09129 { 09130 /* XXX Convert \n's to \r\n's XXX */ 09131 add_header(req, "Content-Type", "text/plain;charset=UTF-8"); 09132 add_header_contentLength(req, strlen(text)); 09133 add_line(req, text); 09134 return 0; 09135 }
static struct ast_variable* add_var | ( | const char * | buf, | |
struct ast_variable * | list | |||
) | [static] |
implement the setvar config line
Definition at line 22649 of file chan_sip.c.
References ast_strdupa, ast_variable_new(), and ast_variable::next.
Referenced by build_device(), and build_peer().
22650 { 22651 struct ast_variable *tmpvar = NULL; 22652 char *varname = ast_strdupa(buf), *varval = NULL; 22653 22654 if ((varval = strchr(varname, '='))) { 22655 *varval++ = '\0'; 22656 if ((tmpvar = ast_variable_new(varname, varval, ""))) { 22657 tmpvar->next = list; 22658 list = tmpvar; 22659 } 22660 } 22661 return list; 22662 }
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 9234 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().
09237 { 09238 int rtp_code; 09239 09240 if (!p->vrtp) 09241 return; 09242 09243 if (debug) 09244 ast_verbose("Adding video codec 0x%x (%s) to SDP\n", codec, ast_getformatname(codec)); 09245 09246 if ((rtp_code = ast_rtp_lookup_code(p->vrtp, 1, codec)) == -1) 09247 return; 09248 09249 ast_str_append(m_buf, 0, " %d", rtp_code); 09250 ast_str_append(a_buf, 0, "a=rtpmap:%d %s/%d\r\n", rtp_code, 09251 ast_rtp_lookup_mime_subtype(1, codec, 0), sample_rate); 09252 /* Add fmtp code here */ 09253 }
static int add_vidupdate | ( | struct sip_request * | req | ) | [static] |
add XML encoded media control with update
Definition at line 9171 of file chan_sip.c.
References add_header(), add_header_contentLength(), and add_line().
Referenced by transmit_info_with_vidupdate().
09172 { 09173 const char *xml_is_a_huge_waste_of_space = 09174 "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\r\n" 09175 " <media_control>\r\n" 09176 " <vc_primitive>\r\n" 09177 " <to_encoder>\r\n" 09178 " <picture_fast_update>\r\n" 09179 " </picture_fast_update>\r\n" 09180 " </to_encoder>\r\n" 09181 " </vc_primitive>\r\n" 09182 " </media_control>\r\n"; 09183 add_header(req, "Content-Type", "application/media_control+xml"); 09184 add_header_contentLength(req, strlen(xml_is_a_huge_waste_of_space)); 09185 add_line(req, xml_is_a_huge_waste_of_space); 09186 return 0; 09187 }
static void append_date | ( | struct sip_request * | req | ) | [static] |
Append date to SIP message.
Definition at line 9062 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().
09063 { 09064 char tmpdat[256]; 09065 struct tm tm; 09066 time_t t = time(NULL); 09067 09068 gmtime_r(&t, &tm); 09069 strftime(tmpdat, sizeof(tmpdat), "%a, %d %b %Y %T GMT", &tm); 09070 add_header(req, "Date", tmpdat); 09071 }
static void append_history_full | ( | struct sip_pvt * | p, | |
const char * | fmt, | |||
... | ||||
) | [static] |
Append to SIP dialog history with arg list.
Definition at line 3326 of file chan_sip.c.
References append_history_va(), and sip_pvt::do_history.
03327 { 03328 va_list ap; 03329 03330 if (!p) 03331 return; 03332 03333 if (!p->do_history && !recordhistory && !dumphistory) 03334 return; 03335 03336 va_start(ap, fmt); 03337 append_history_va(p, fmt, ap); 03338 va_end(ap); 03339 03340 return; 03341 }
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 3299 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().
03300 { 03301 char buf[80], *c = buf; /* max history length */ 03302 struct sip_history *hist; 03303 int l; 03304 03305 vsnprintf(buf, sizeof(buf), fmt, ap); 03306 strsep(&c, "\r\n"); /* Trim up everything after \r or \n */ 03307 l = strlen(buf) + 1; 03308 if (!(hist = ast_calloc(1, sizeof(*hist) + l))) 03309 return; 03310 if (!p->history && !(p->history = ast_calloc(1, sizeof(*p->history)))) { 03311 ast_free(hist); 03312 return; 03313 } 03314 memcpy(hist->event, buf, l); 03315 if (p->history_entries == MAX_HISTORY_ENTRIES) { 03316 struct sip_history *oldest; 03317 oldest = AST_LIST_REMOVE_HEAD(p->history, list); 03318 p->history_entries--; 03319 ast_free(oldest); 03320 } 03321 AST_LIST_INSERT_TAIL(p->history, hist, list); 03322 p->history_entries++; 03323 }
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 18066 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().
18067 { 18068 if (chan && chan->_state == AST_STATE_UP) { 18069 if (ast_test_flag(chan, AST_FLAG_MOH)) 18070 ast_moh_stop(chan); 18071 else if (chan->generatordata) 18072 ast_deactivate_generator(chan); 18073 } 18074 }
static void ast_sip_ouraddrfor | ( | struct in_addr * | them, | |
struct sockaddr_in * | us, | |||
struct sip_pvt * | p | |||
) | [static] |
NAT fix - decide which IP address to use for Asterisk server?
Using the localaddr structure built up with localnet statements in sip.conf apply it to their address to see if we need to substitute our externip or can get away with our internal bindaddr 'us' is always overwritten.
Definition at line 3224 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(), get_transport(), ast_tcptls_session_args::local_address, localaddr, LOG_NOTICE, LOG_WARNING, PARSE_INADDR, sip_tcp_desc, sip_tls_desc, SIP_TRANSPORT_TCP, SIP_TRANSPORT_TLS, SIP_TRANSPORT_UDP, sip_pvt::socket, and sip_socket::type.
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().
03225 { 03226 struct sockaddr_in theirs; 03227 /* Set want_remap to non-zero if we want to remap 'us' to an externally 03228 * reachable IP address and port. This is done if: 03229 * 1. we have a localaddr list (containing 'internal' addresses marked 03230 * as 'deny', so ast_apply_ha() will return AST_SENSE_DENY on them, 03231 * and AST_SENSE_ALLOW on 'external' ones); 03232 * 2. either stunaddr or externip is set, so we know what to use as the 03233 * externally visible address; 03234 * 3. the remote address, 'them', is external; 03235 * 4. the address returned by ast_ouraddrfor() is 'internal' (AST_SENSE_DENY 03236 * when passed to ast_apply_ha() so it does need to be remapped. 03237 * This fourth condition is checked later. 03238 */ 03239 int want_remap; 03240 03241 *us = internip; /* starting guess for the internal address */ 03242 /* now ask the system what would it use to talk to 'them' */ 03243 ast_ouraddrfor(them, &us->sin_addr); 03244 theirs.sin_addr = *them; 03245 03246 want_remap = localaddr && 03247 (externip.sin_addr.s_addr || stunaddr.sin_addr.s_addr) && 03248 ast_apply_ha(localaddr, &theirs) == AST_SENSE_ALLOW ; 03249 03250 if (want_remap && 03251 (!global_matchexterniplocally || !ast_apply_ha(localaddr, us)) ) { 03252 /* if we used externhost or stun, see if it is time to refresh the info */ 03253 if (externexpire && time(NULL) >= externexpire) { 03254 if (stunaddr.sin_addr.s_addr) { 03255 ast_stun_request(sipsock, &stunaddr, NULL, &externip); 03256 } else { 03257 if (ast_parse_arg(externhost, PARSE_INADDR, &externip)) 03258 ast_log(LOG_NOTICE, "Warning: Re-lookup of '%s' failed!\n", externhost); 03259 } 03260 externexpire = time(NULL) + externrefresh; 03261 } 03262 if (externip.sin_addr.s_addr) 03263 *us = externip; 03264 else 03265 ast_log(LOG_WARNING, "stun failed\n"); 03266 ast_debug(1, "Target address %s is not local, substituting externip\n", 03267 ast_inet_ntoa(*(struct in_addr *)&them->s_addr)); 03268 } else if (p) { 03269 /* no remapping, but we bind to a specific address, so use it. */ 03270 switch (p->socket.type) { 03271 case SIP_TRANSPORT_TCP: 03272 if (sip_tcp_desc.local_address.sin_addr.s_addr) { 03273 *us = sip_tcp_desc.local_address; 03274 } else { 03275 us->sin_port = sip_tcp_desc.local_address.sin_port; 03276 } 03277 break; 03278 case SIP_TRANSPORT_TLS: 03279 if (sip_tls_desc.local_address.sin_addr.s_addr) { 03280 *us = sip_tls_desc.local_address; 03281 } else { 03282 us->sin_port = sip_tls_desc.local_address.sin_port; 03283 } 03284 break; 03285 case SIP_TRANSPORT_UDP: 03286 /* fall through on purpose */ 03287 default: 03288 if (bindaddr.sin_addr.s_addr) { 03289 *us = bindaddr; 03290 } 03291 } 03292 } else if (bindaddr.sin_addr.s_addr) { 03293 *us = bindaddr; 03294 } 03295 ast_debug(3, "Setting SIP_TRANSPORT_%s with address %s:%d\n", get_transport(p->socket.type), ast_inet_ntoa(us->sin_addr), ntohs(us->sin_port)); 03296 }
Attempt transfer of SIP call This fix for attended transfers on a local PBX.
Definition at line 18078 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.
18079 { 18080 int res = 0; 18081 struct ast_channel *peera = NULL, 18082 *peerb = NULL, 18083 *peerc = NULL, 18084 *peerd = NULL; 18085 18086 18087 /* We will try to connect the transferee with the target and hangup 18088 all channels to the transferer */ 18089 ast_debug(4, "Sip transfer:--------------------\n"); 18090 if (transferer->chan1) 18091 ast_debug(4, "-- Transferer to PBX channel: %s State %s\n", transferer->chan1->name, ast_state2str(transferer->chan1->_state)); 18092 else 18093 ast_debug(4, "-- No transferer first channel - odd??? \n"); 18094 if (target->chan1) 18095 ast_debug(4, "-- Transferer to PBX second channel (target): %s State %s\n", target->chan1->name, ast_state2str(target->chan1->_state)); 18096 else 18097 ast_debug(4, "-- No target first channel ---\n"); 18098 if (transferer->chan2) 18099 ast_debug(4, "-- Bridged call to transferee: %s State %s\n", transferer->chan2->name, ast_state2str(transferer->chan2->_state)); 18100 else 18101 ast_debug(4, "-- No bridged call to transferee\n"); 18102 if (target->chan2) 18103 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)"); 18104 else 18105 ast_debug(4, "-- No target second channel ---\n"); 18106 ast_debug(4, "-- END Sip transfer:--------------------\n"); 18107 if (transferer->chan2) { /* We have a bridge on the transferer's channel */ 18108 peera = transferer->chan1; /* Transferer - PBX -> transferee channel * the one we hangup */ 18109 peerb = target->chan1; /* Transferer - PBX -> target channel - This will get lost in masq */ 18110 peerc = transferer->chan2; /* Asterisk to Transferee */ 18111 peerd = target->chan2; /* Asterisk to Target */ 18112 ast_debug(3, "SIP transfer: Four channels to handle\n"); 18113 } else if (target->chan2) { /* Transferer has no bridge (IVR), but transferee */ 18114 peera = target->chan1; /* Transferer to PBX -> target channel */ 18115 peerb = transferer->chan1; /* Transferer to IVR*/ 18116 peerc = target->chan2; /* Asterisk to Target */ 18117 peerd = transferer->chan2; /* Nothing */ 18118 ast_debug(3, "SIP transfer: Three channels to handle\n"); 18119 } 18120 18121 if (peera && peerb && peerc && (peerb != peerc)) { 18122 ast_quiet_chan(peera); /* Stop generators */ 18123 ast_quiet_chan(peerb); 18124 ast_quiet_chan(peerc); 18125 if (peerd) 18126 ast_quiet_chan(peerd); 18127 18128 ast_debug(4, "SIP transfer: trying to masquerade %s into %s\n", peerc->name, peerb->name); 18129 if (ast_channel_masquerade(peerb, peerc)) { 18130 ast_log(LOG_WARNING, "Failed to masquerade %s into %s\n", peerb->name, peerc->name); 18131 res = -1; 18132 } else 18133 ast_debug(4, "SIP transfer: Succeeded to masquerade channels.\n"); 18134 return res; 18135 } else { 18136 ast_log(LOG_NOTICE, "SIP Transfer attempted with no appropriate bridged calls to transfer\n"); 18137 if (transferer->chan1) 18138 ast_softhangup_nolock(transferer->chan1, AST_SOFTHANGUP_DEV); 18139 if (target->chan1) 18140 ast_softhangup_nolock(target->chan1, AST_SOFTHANGUP_DEV); 18141 return -1; 18142 } 18143 return 0; 18144 }
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 11153 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().
11154 { 11155 if (code == WWW_AUTH) { /* 401 */ 11156 *header = "WWW-Authenticate"; 11157 *respheader = "Authorization"; 11158 } else if (code == PROXY_AUTH) { /* 407 */ 11159 *header = "Proxy-Authenticate"; 11160 *respheader = "Proxy-Authorization"; 11161 } else { 11162 ast_verbose("-- wrong response code %d\n", code); 11163 *header = *respheader = "Invalid"; 11164 } 11165 }
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 4964 of file chan_sip.c.
References append_history, ast_channel_trylock, ast_channel_unlock, AST_CONTROL_CONGESTION, ast_queue_control(), DEFAULT_TRANS_TIMEOUT, dialog_unref(), sip_pvt_lock, sip_pvt_unlock, and sip_scheddestroy().
04965 { 04966 struct sip_pvt *p = (struct sip_pvt *)arg; 04967 04968 sip_pvt_lock(p); 04969 p->initid = -1; /* event gone, will not be rescheduled */ 04970 if (p->owner) { 04971 /* XXX fails on possible deadlock */ 04972 if (!ast_channel_trylock(p->owner)) { 04973 append_history(p, "Cong", "Auto-congesting (timer)"); 04974 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 04975 ast_channel_unlock(p->owner); 04976 } 04977 04978 /* Give the channel a chance to act before we proceed with destruction */ 04979 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 04980 } 04981 sip_pvt_unlock(p); 04982 dialog_unref(p, "unreffing arg passed into auto_congest callback (p->initid)"); 04983 return 0; 04984 }
static void build_callid_pvt | ( | struct sip_pvt * | pvt | ) | [static] |
Build SIP Call-ID value for a non-REGISTER transaction.
Definition at line 6687 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().
06688 { 06689 char buf[33]; 06690 06691 const char *host = S_OR(pvt->fromdomain, ast_inet_ntoa(pvt->ourip.sin_addr)); 06692 06693 ast_string_field_build(pvt, callid, "%s@%s", generate_random_string(buf, sizeof(buf)), host); 06694 06695 }
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 6698 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().
06699 { 06700 char buf[33]; 06701 06702 const char *host = S_OR(fromdomain, ast_inet_ntoa(ourip)); 06703 06704 ast_string_field_build(reg, callid, "%s@%s", generate_random_string(buf, sizeof(buf)), host); 06705 }
static void build_contact | ( | struct sip_pvt * | p | ) | [static] |
Build contact header - the contact header we send out.
Definition at line 9926 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().
09927 { 09928 int ourport = ntohs(p->ourip.sin_port); 09929 /* only add port if it's non-standard for the transport type */ 09930 if (!sip_standard_port(p->socket.type, ourport)) { 09931 if (p->socket.type == SIP_TRANSPORT_UDP) 09932 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); 09933 else 09934 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)); 09935 } else { 09936 if (p->socket.type == SIP_TRANSPORT_UDP) 09937 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)); 09938 else 09939 ast_string_field_build(p, our_contact, "<sip:%s%s%s;transport=%s>", p->exten, ast_strlen_zero(p->exten) ? "" : "@", ast_inet_ntoa(p->ourip.sin_addr), get_transport(p->socket.type)); 09940 } 09941 }
static struct sip_peer * build_peer | ( | const char * | name, | |
struct ast_variable * | v, | |||
struct ast_variable * | alt, | |||
int | realtime, | |||
int | devstate_only | |||
) | [static] |
Build peer from configuration (file or realtime static/dynamic).
< The first transport listed should be default outbound
Definition at line 22765 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_set_flag, ast_skip_blanks(), ast_str_alloca, ast_str_append(), ast_str_reset(), ast_str_set(), ast_str_strlen, 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::default_outbound_transport, 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(), handle_t38_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, peers, sip_peer::pickupgroup, sip_socket::port, port_str2int(), sip_peer::portinuri, 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(), set_socket_transport(), sip_cfg, sip_destroy_peer_fn(), SIP_NAT_ROUTE, SIP_PAGE2_ALLOWSUBSCRIBE, SIP_PAGE2_HAVEPEERCONTEXT, 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::t38_maxdatagram, 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.
22766 { 22767 struct sip_peer *peer = NULL; 22768 struct ast_ha *oldha = NULL; 22769 int found = 0; 22770 int firstpass = 1; 22771 uint16_t port = 0; 22772 int format = 0; /* Ama flags */ 22773 time_t regseconds = 0; 22774 struct ast_flags peerflags[2] = {{(0)}}; 22775 struct ast_flags mask[2] = {{(0)}}; 22776 char callback[256] = ""; 22777 struct sip_peer tmp_peer; 22778 const char *srvlookup = NULL; 22779 static int deprecation_warning = 1; 22780 int alt_fullcontact = alt ? 1 : 0; 22781 struct ast_str *fullcontact = ast_str_alloca(512); 22782 22783 if (!realtime || ast_test_flag(&global_flags[1], SIP_PAGE2_RTCACHEFRIENDS)) { 22784 /* Note we do NOT use find_peer here, to avoid realtime recursion */ 22785 /* We also use a case-sensitive comparison (unlike find_peer) so 22786 that case changes made to the peer name will be properly handled 22787 during reload 22788 */ 22789 ast_copy_string(tmp_peer.name, name, sizeof(tmp_peer.name)); 22790 peer = ao2_t_find(peers, &tmp_peer, OBJ_POINTER | OBJ_UNLINK, "find and unlink peer from peers table"); 22791 } 22792 22793 if (peer) { 22794 /* Already in the list, remove it and it will be added back (or FREE'd) */ 22795 found++; 22796 if (!(peer->the_mark)) 22797 firstpass = 0; 22798 } else { 22799 if (!(peer = ao2_t_alloc(sizeof(*peer), sip_destroy_peer_fn, "allocate a peer struct"))) 22800 return NULL; 22801 22802 if (realtime && !ast_test_flag(&global_flags[1], SIP_PAGE2_RTCACHEFRIENDS)) { 22803 ast_atomic_fetchadd_int(&rpeerobjs, 1); 22804 ast_debug(3, "-REALTIME- peer built. Name: %s. Peer objects: %d\n", name, rpeerobjs); 22805 } else 22806 ast_atomic_fetchadd_int(&speerobjs, 1); 22807 } 22808 22809 /* Note that our peer HAS had its reference count increased */ 22810 if (firstpass) { 22811 peer->lastmsgssent = -1; 22812 oldha = peer->ha; 22813 peer->ha = NULL; 22814 set_peer_defaults(peer); /* Set peer defaults */ 22815 peer->type = 0; 22816 } 22817 if (!found && name) 22818 ast_copy_string(peer->name, name, sizeof(peer->name)); 22819 22820 /* If we have channel variables, remove them (reload) */ 22821 if (peer->chanvars) { 22822 ast_variables_destroy(peer->chanvars); 22823 peer->chanvars = NULL; 22824 /* XXX should unregister ? */ 22825 } 22826 22827 if (found) 22828 peer->portinuri = 0; 22829 22830 /* If we have realm authentication information, remove them (reload) */ 22831 clear_realm_authentication(peer->auth); 22832 peer->auth = NULL; 22833 peer->default_outbound_transport = 0; 22834 peer->transports = 0; 22835 22836 for (; v || ((v = alt) && !(alt=NULL)); v = v->next) { 22837 if (!devstate_only) { 22838 if (handle_common_options(&peerflags[0], &mask[0], v)) { 22839 continue; 22840 } 22841 if (handle_t38_options(&peerflags[0], &mask[0], v, &peer->t38_maxdatagram)) { 22842 continue; 22843 } 22844 if (!strcasecmp(v->name, "transport") && !ast_strlen_zero(v->value)) { 22845 char *val = ast_strdupa(v->value); 22846 char *trans; 22847 22848 while ((trans = strsep(&val, ","))) { 22849 trans = ast_skip_blanks(trans); 22850 22851 if (!strncasecmp(trans, "udp", 3)) { 22852 peer->transports |= SIP_TRANSPORT_UDP; 22853 } else if (!strncasecmp(trans, "tcp", 3)) { 22854 peer->transports |= SIP_TRANSPORT_TCP; 22855 } else if (!strncasecmp(trans, "tls", 3)) { 22856 peer->transports |= SIP_TRANSPORT_TLS; 22857 } else { 22858 ast_log(LOG_NOTICE, "'%s' is not a valid transport type. if no other is specified, udp will be used.\n", trans); 22859 } 22860 22861 if (!peer->default_outbound_transport) { /*!< The first transport listed should be default outbound */ 22862 peer->default_outbound_transport = peer->transports; 22863 } 22864 } 22865 } else if (realtime && !strcasecmp(v->name, "regseconds")) { 22866 ast_get_time_t(v->value, ®seconds, 0, NULL); 22867 } else if (realtime && !strcasecmp(v->name, "name")) { 22868 ast_copy_string(peer->name, v->value, sizeof(peer->name)); 22869 } else if (!strcasecmp(v->name, "type")) { 22870 if (!strcasecmp(v->value, "peer")) { 22871 peer->type |= SIP_TYPE_PEER; 22872 } else if (!strcasecmp(v->value, "user")) { 22873 peer->type |= SIP_TYPE_USER; 22874 } else if (!strcasecmp(v->value, "friend")) { 22875 peer->type = SIP_TYPE_USER | SIP_TYPE_PEER; 22876 } 22877 } else if (!strcasecmp(v->name, "secret")) { 22878 ast_copy_string(peer->secret, v->value, sizeof(peer->secret)); 22879 } else if (!strcasecmp(v->name, "md5secret")) { 22880 ast_copy_string(peer->md5secret, v->value, sizeof(peer->md5secret)); 22881 } else if (!strcasecmp(v->name, "auth")) { 22882 peer->auth = add_realm_authentication(peer->auth, v->value, v->lineno); 22883 } else if (!strcasecmp(v->name, "callerid")) { 22884 ast_callerid_split(v->value, peer->cid_name, sizeof(peer->cid_name), peer->cid_num, sizeof(peer->cid_num)); 22885 } else if (!strcasecmp(v->name, "fullname")) { 22886 ast_copy_string(peer->cid_name, v->value, sizeof(peer->cid_name)); 22887 } else if (!strcasecmp(v->name, "trunkname")) { 22888 /* This is actually for a trunk, so we don't want to override callerid */ 22889 ast_copy_string(peer->cid_name, "", sizeof(peer->cid_name)); 22890 } else if (!strcasecmp(v->name, "cid_number")) { 22891 ast_copy_string(peer->cid_num, v->value, sizeof(peer->cid_num)); 22892 } else if (!strcasecmp(v->name, "context")) { 22893 ast_copy_string(peer->context, v->value, sizeof(peer->context)); 22894 ast_set_flag(&peer->flags[1], SIP_PAGE2_HAVEPEERCONTEXT); 22895 } else if (!strcasecmp(v->name, "subscribecontext")) { 22896 ast_copy_string(peer->subscribecontext, v->value, sizeof(peer->subscribecontext)); 22897 } else if (!strcasecmp(v->name, "fromdomain")) { 22898 ast_copy_string(peer->fromdomain, v->value, sizeof(peer->fromdomain)); 22899 } else if (!strcasecmp(v->name, "usereqphone")) { 22900 ast_set2_flag(&peer->flags[0], ast_true(v->value), SIP_USEREQPHONE); 22901 } else if (!strcasecmp(v->name, "fromuser")) { 22902 ast_copy_string(peer->fromuser, v->value, sizeof(peer->fromuser)); 22903 } else if (!strcasecmp(v->name, "outboundproxy")) { 22904 char *port, *next, *force, *proxyname; 22905 int forceopt = FALSE; 22906 /* Set peer channel variable */ 22907 next = proxyname = ast_strdupa(v->value); 22908 if ((port = strchr(proxyname, ':'))) { 22909 *port++ = '\0'; 22910 next = port; 22911 } 22912 if ((force = strchr(next, ','))) { 22913 *force++ = '\0'; 22914 forceopt = strcmp(force, "force"); 22915 } 22916 /* Allocate proxy object */ 22917 peer->outboundproxy = proxy_allocate(proxyname, port, forceopt); 22918 } else if (!strcasecmp(v->name, "host")) { 22919 if (!strcasecmp(v->value, "dynamic")) { 22920 /* They'll register with us */ 22921 if (!found || !peer->host_dynamic) { 22922 /* Initialize stuff if this is a new peer, or if it used to 22923 * not be dynamic before the reload. */ 22924 memset(&peer->addr.sin_addr, 0, 4); 22925 peer->addr.sin_port = 0; 22926 } 22927 peer->host_dynamic = TRUE; 22928 } else { 22929 /* Non-dynamic. Make sure we become that way if we're not */ 22930 AST_SCHED_DEL_UNREF(sched, peer->expire, 22931 unref_peer(peer, "removing register expire ref")); 22932 /* the port will either be set to a default value or a config specified value once all option parsing is complete */ 22933 peer->addr.sin_port = 0; 22934 peer->host_dynamic = FALSE; 22935 srvlookup = v->value; 22936 if (global_dynamic_exclude_static) { 22937 int err = 0; 22938 global_contact_ha = ast_append_ha("deny", (char *)ast_inet_ntoa(peer->addr.sin_addr), global_contact_ha, &err); 22939 if (err) { 22940 ast_log(LOG_ERROR, "Bad ACL entry in configuration line %d : %s\n", v->lineno, v->value); 22941 } 22942 } 22943 } 22944 } else if (!strcasecmp(v->name, "defaultip")) { 22945 if (!ast_strlen_zero(v->value) && ast_get_ip(&peer->defaddr, v->value)) { 22946 unref_peer(peer, "unref_peer: from build_peer defaultip"); 22947 return NULL; 22948 } 22949 } else if (!strcasecmp(v->name, "permit") || !strcasecmp(v->name, "deny")) { 22950 int ha_error = 0; 22951 if (!ast_strlen_zero(v->value)) { 22952 peer->ha = ast_append_ha(v->name, v->value, peer->ha, &ha_error); 22953 } 22954 if (ha_error) { 22955 ast_log(LOG_ERROR, "Bad ACL entry in configuration line %d : %s\n", v->lineno, v->value); 22956 } 22957 } else if (!strcasecmp(v->name, "contactpermit") || !strcasecmp(v->name, "contactdeny")) { 22958 int ha_error = 0; 22959 if (!ast_strlen_zero(v->value)) { 22960 peer->contactha = ast_append_ha(v->name + 7, v->value, peer->contactha, &ha_error); 22961 } 22962 if (ha_error) { 22963 ast_log(LOG_ERROR, "Bad ACL entry in configuration line %d : %s\n", v->lineno, v->value); 22964 } 22965 } else if (!strcasecmp(v->name, "port")) { 22966 peer->portinuri = 1; 22967 if (!(port = port_str2int(v->value, 0))) { 22968 if (realtime) { 22969 /* If stored as integer, could be 0 for some DBs (notably MySQL) */ 22970 peer->portinuri = 0; 22971 } else { 22972 ast_log(LOG_WARNING, "Invalid peer port configuration at line %d : %s\n", v->lineno, v->value); 22973 } 22974 } 22975 } else if (!strcasecmp(v->name, "callingpres")) { 22976 peer->callingpres = ast_parse_caller_presentation(v->value); 22977 if (peer->callingpres == -1) { 22978 peer->callingpres = atoi(v->value); 22979 } 22980 } else if (!strcasecmp(v->name, "username") || !strcmp(v->name, "defaultuser")) { /* "username" is deprecated */ 22981 ast_copy_string(peer->username, v->value, sizeof(peer->username)); 22982 if (!strcasecmp(v->name, "username")) { 22983 if (deprecation_warning) { 22984 ast_log(LOG_NOTICE, "The 'username' field for sip peers has been deprecated in favor of the term 'defaultuser'\n"); 22985 deprecation_warning = 0; 22986 } 22987 peer->deprecated_username = 1; 22988 } 22989 } else if (!strcasecmp(v->name, "language")) { 22990 ast_copy_string(peer->language, v->value, sizeof(peer->language)); 22991 } else if (!strcasecmp(v->name, "regexten")) { 22992 ast_copy_string(peer->regexten, v->value, sizeof(peer->regexten)); 22993 } else if (!strcasecmp(v->name, "callbackextension")) { 22994 ast_copy_string(callback, v->value, sizeof(callback)); 22995 } else if (!strcasecmp(v->name, "amaflags")) { 22996 format = ast_cdr_amaflags2int(v->value); 22997 if (format < 0) { 22998 ast_log(LOG_WARNING, "Invalid AMA Flags for peer: %s at line %d\n", v->value, v->lineno); 22999 } else { 23000 peer->amaflags = format; 23001 } 23002 } else if (!strcasecmp(v->name, "accountcode")) { 23003 ast_copy_string(peer->accountcode, v->value, sizeof(peer->accountcode)); 23004 } else if (!strcasecmp(v->name, "mohinterpret")) { 23005 ast_copy_string(peer->mohinterpret, v->value, sizeof(peer->mohinterpret)); 23006 } else if (!strcasecmp(v->name, "mohsuggest")) { 23007 ast_copy_string(peer->mohsuggest, v->value, sizeof(peer->mohsuggest)); 23008 } else if (!strcasecmp(v->name, "parkinglot")) { 23009 ast_copy_string(peer->parkinglot, v->value, sizeof(peer->parkinglot)); 23010 } else if (!strcasecmp(v->name, "mailbox")) { 23011 add_peer_mailboxes(peer, v->value); 23012 } else if (!strcasecmp(v->name, "hasvoicemail")) { 23013 /* People expect that if 'hasvoicemail' is set, that the mailbox will 23014 * be also set, even if not explicitly specified. */ 23015 if (ast_true(v->value) && AST_LIST_EMPTY(&peer->mailboxes)) { 23016 add_peer_mailboxes(peer, name); 23017 } 23018 } else if (!strcasecmp(v->name, "subscribemwi")) { 23019 ast_set2_flag(&peer->flags[1], ast_true(v->value), SIP_PAGE2_SUBSCRIBEMWIONLY); 23020 } else if (!strcasecmp(v->name, "vmexten")) { 23021 ast_copy_string(peer->vmexten, v->value, sizeof(peer->vmexten)); 23022 } else if (!strcasecmp(v->name, "callgroup")) { 23023 peer->callgroup = ast_get_group(v->value); 23024 } else if (!strcasecmp(v->name, "allowtransfer")) { 23025 peer->allowtransfer = ast_true(v->value) ? TRANSFER_OPENFORALL : TRANSFER_CLOSED; 23026 } else if (!strcasecmp(v->name, "pickupgroup")) { 23027 peer->pickupgroup = ast_get_group(v->value); 23028 } else if (!strcasecmp(v->name, "allow")) { 23029 int error = ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, TRUE); 23030 if (error) { 23031 ast_log(LOG_WARNING, "Codec configuration errors found in line %d : %s = %s\n", v->lineno, v->name, v->value); 23032 } 23033 } else if (!strcasecmp(v->name, "disallow")) { 23034 int error = ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, FALSE); 23035 if (error) { 23036 ast_log(LOG_WARNING, "Codec configuration errors found in line %d : %s = %s\n", v->lineno, v->name, v->value); 23037 } 23038 } else if (!strcasecmp(v->name, "registertrying")) { 23039 ast_set2_flag(&peer->flags[1], ast_true(v->value), SIP_PAGE2_REGISTERTRYING); 23040 } else if (!strcasecmp(v->name, "autoframing")) { 23041 peer->autoframing = ast_true(v->value); 23042 } else if (!strcasecmp(v->name, "rtptimeout")) { 23043 if ((sscanf(v->value, "%30d", &peer->rtptimeout) != 1) || (peer->rtptimeout < 0)) { 23044 ast_log(LOG_WARNING, "'%s' is not a valid RTP hold time at line %d. Using default.\n", v->value, v->lineno); 23045 peer->rtptimeout = global_rtptimeout; 23046 } 23047 } else if (!strcasecmp(v->name, "rtpholdtimeout")) { 23048 if ((sscanf(v->value, "%30d", &peer->rtpholdtimeout) != 1) || (peer->rtpholdtimeout < 0)) { 23049 ast_log(LOG_WARNING, "'%s' is not a valid RTP hold time at line %d. Using default.\n", v->value, v->lineno); 23050 peer->rtpholdtimeout = global_rtpholdtimeout; 23051 } 23052 } else if (!strcasecmp(v->name, "rtpkeepalive")) { 23053 if ((sscanf(v->value, "%30d", &peer->rtpkeepalive) != 1) || (peer->rtpkeepalive < 0)) { 23054 ast_log(LOG_WARNING, "'%s' is not a valid RTP keepalive time at line %d. Using default.\n", v->value, v->lineno); 23055 peer->rtpkeepalive = global_rtpkeepalive; 23056 } 23057 } else if (!strcasecmp(v->name, "timert1")) { 23058 if ((sscanf(v->value, "%30d", &peer->timer_t1) != 1) || (peer->timer_t1 < 0)) { 23059 ast_log(LOG_WARNING, "'%s' is not a valid T1 time at line %d. Using default.\n", v->value, v->lineno); 23060 peer->timer_t1 = global_t1; 23061 } 23062 /* Note that Timer B is dependent upon T1 and MUST NOT be lower 23063 * than T1 * 64, according to RFC 3261, Section 17.1.1.2 */ 23064 if (peer->timer_b < peer->timer_t1 * 64) { 23065 peer->timer_b = peer->timer_t1 * 64; 23066 } 23067 } else if (!strcasecmp(v->name, "timerb")) { 23068 if ((sscanf(v->value, "%30d", &peer->timer_b) != 1) || (peer->timer_b < 0)) { 23069 ast_log(LOG_WARNING, "'%s' is not a valid Timer B time at line %d. Using default.\n", v->value, v->lineno); 23070 peer->timer_b = global_timer_b; 23071 } 23072 if (peer->timer_b < peer->timer_t1 * 64) { 23073 static int warning = 0; 23074 if (warning++ % 20 == 0) { 23075 ast_log(LOG_WARNING, "Timer B has been set lower than recommended. (RFC 3261, 17.1.1.2)\n"); 23076 } 23077 } 23078 } else if (!strcasecmp(v->name, "setvar")) { 23079 peer->chanvars = add_var(v->value, peer->chanvars); 23080 } else if (!strcasecmp(v->name, "qualifyfreq")) { 23081 int i; 23082 if (sscanf(v->value, "%30d", &i) == 1) { 23083 peer->qualifyfreq = i * 1000; 23084 } else { 23085 ast_log(LOG_WARNING, "Invalid qualifyfreq number '%s' at line %d of %s\n", v->value, v->lineno, config); 23086 peer->qualifyfreq = global_qualifyfreq; 23087 } 23088 } else if (!strcasecmp(v->name, "maxcallbitrate")) { 23089 peer->maxcallbitrate = atoi(v->value); 23090 if (peer->maxcallbitrate < 0) { 23091 peer->maxcallbitrate = default_maxcallbitrate; 23092 } 23093 } else if (!strcasecmp(v->name, "session-timers")) { 23094 int i = (int) str2stmode(v->value); 23095 if (i < 0) { 23096 ast_log(LOG_WARNING, "Invalid session-timers '%s' at line %d of %s\n", v->value, v->lineno, config); 23097 peer->stimer.st_mode_oper = global_st_mode; 23098 } else { 23099 peer->stimer.st_mode_oper = i; 23100 } 23101 } else if (!strcasecmp(v->name, "session-expires")) { 23102 if (sscanf(v->value, "%30d", &peer->stimer.st_max_se) != 1) { 23103 ast_log(LOG_WARNING, "Invalid session-expires '%s' at line %d of %s\n", v->value, v->lineno, config); 23104 peer->stimer.st_max_se = global_max_se; 23105 } 23106 } else if (!strcasecmp(v->name, "session-minse")) { 23107 if (sscanf(v->value, "%30d", &peer->stimer.st_min_se) != 1) { 23108 ast_log(LOG_WARNING, "Invalid session-minse '%s' at line %d of %s\n", v->value, v->lineno, config); 23109 peer->stimer.st_min_se = global_min_se; 23110 } 23111 if (peer->stimer.st_min_se < 90) { 23112 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); 23113 peer->stimer.st_min_se = global_min_se; 23114 } 23115 } else if (!strcasecmp(v->name, "session-refresher")) { 23116 int i = (int) str2strefresher(v->value); 23117 if (i < 0) { 23118 ast_log(LOG_WARNING, "Invalid session-refresher '%s' at line %d of %s\n", v->value, v->lineno, config); 23119 peer->stimer.st_ref = global_st_refresher; 23120 } else { 23121 peer->stimer.st_ref = i; 23122 } 23123 } 23124 } 23125 23126 /* These apply to devstate lookups */ 23127 if (realtime && !strcasecmp(v->name, "lastms")) { 23128 sscanf(v->value, "%30d", &peer->lastms); 23129 } else if (realtime && !strcasecmp(v->name, "ipaddr") && !ast_strlen_zero(v->value) ) { 23130 inet_aton(v->value, &(peer->addr.sin_addr)); 23131 } else if (realtime && !strcasecmp(v->name, "fullcontact")) { 23132 if (alt_fullcontact && !alt) { 23133 /* Reset, because the alternate also has a fullcontact and we 23134 * do NOT want the field value to be doubled. It might be 23135 * tempting to skip this, but the first table might not have 23136 * fullcontact and since we're here, we know that the alternate 23137 * absolutely does. */ 23138 alt_fullcontact = 0; 23139 ast_str_reset(fullcontact); 23140 } 23141 /* Reconstruct field, because realtime separates our value at the ';' */ 23142 if (fullcontact->used > 0) { 23143 ast_str_append(&fullcontact, 0, ";%s", v->value); 23144 } else { 23145 ast_str_set(&fullcontact, 0, "%s", v->value); 23146 } 23147 } else if (!strcasecmp(v->name, "qualify")) { 23148 if (!strcasecmp(v->value, "no")) { 23149 peer->maxms = 0; 23150 } else if (!strcasecmp(v->value, "yes")) { 23151 peer->maxms = default_qualify ? default_qualify : DEFAULT_MAXMS; 23152 } else if (sscanf(v->value, "%30d", &peer->maxms) != 1) { 23153 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); 23154 peer->maxms = 0; 23155 } 23156 if (realtime && !ast_test_flag(&global_flags[1], SIP_PAGE2_RTCACHEFRIENDS) && peer->maxms > 0) { 23157 /* This would otherwise cause a network storm, where the 23158 * qualify response refreshes the peer from the database, 23159 * which in turn causes another qualify to be sent, ad 23160 * infinitum. */ 23161 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); 23162 peer->maxms = 0; 23163 } 23164 } else if (!strcasecmp(v->name, "callcounter")) { 23165 peer->call_limit = ast_true(v->value) ? INT_MAX : 0; 23166 } else if (!strcasecmp(v->name, "call-limit")) { 23167 peer->call_limit = atoi(v->value); 23168 if (peer->call_limit < 0) { 23169 peer->call_limit = 0; 23170 } 23171 } else if (!strcasecmp(v->name, "busylevel")) { 23172 peer->busy_level = atoi(v->value); 23173 if (peer->busy_level < 0) { 23174 peer->busy_level = 0; 23175 } 23176 } 23177 } 23178 23179 if (!peer->default_outbound_transport) { 23180 peer->transports = SIP_TRANSPORT_UDP; 23181 peer->default_outbound_transport = SIP_TRANSPORT_UDP; 23182 } 23183 23184 /* The default transport type set during build_peer should only replace the socket.type when... 23185 * 1. Registration is not present and the socket.type and default transport types are different. 23186 * 2. The socket.type is not an acceptable transport type after rebuilding peer. 23187 * 3. The socket.type is not set yet. */ 23188 if (((peer->socket.type != peer->default_outbound_transport) && (peer->expire == -1)) || 23189 !(peer->socket.type & peer->transports) || !(peer->socket.type)) { 23190 23191 set_socket_transport(&peer->socket, peer->default_outbound_transport); 23192 } 23193 23194 if (port && !realtime && peer->host_dynamic) { 23195 peer->defaddr.sin_port = htons(port); 23196 } else if (port) { 23197 peer->addr.sin_port = htons(port); 23198 } 23199 23200 if (ast_str_strlen(fullcontact)) { 23201 ast_copy_string(peer->fullcontact, fullcontact->str, sizeof(peer->fullcontact)); 23202 peer->rt_fromcontact = TRUE; 23203 /* We have a hostname in the fullcontact, but if we don't have an 23204 * address listed on the entry (or if it's 'dynamic'), then we need to 23205 * parse the entry to obtain the IP address, so a dynamic host can be 23206 * contacted immediately after reload (as opposed to waiting for it to 23207 * register once again). But if we have an address for this peer and NAT was 23208 * specified, use that address instead. */ 23209 /* XXX May need to revisit the final argument; does the realtime DB store whether 23210 * the original contact was over TLS or not? XXX */ 23211 if (!ast_test_flag(&peer->flags[0], SIP_NAT_ROUTE) || !peer->addr.sin_addr.s_addr) { 23212 __set_address_from_contact(fullcontact->str, &peer->addr, 0); 23213 } 23214 } 23215 23216 if (srvlookup && peer->dnsmgr == NULL) { 23217 char transport[MAXHOSTNAMELEN]; 23218 char _srvlookup[MAXHOSTNAMELEN]; 23219 char *params; 23220 23221 ast_copy_string(_srvlookup, srvlookup, sizeof(_srvlookup)); 23222 if ((params = strchr(_srvlookup, ';'))) { 23223 *params++ = '\0'; 23224 } 23225 23226 snprintf(transport, sizeof(transport), "_sip._%s", get_transport(peer->socket.type)); 23227 23228 if (ast_dnsmgr_lookup(_srvlookup, &peer->addr, &peer->dnsmgr, global_srvlookup && !peer->portinuri ? transport : NULL)) { 23229 ast_log(LOG_ERROR, "srvlookup failed for host: %s, on peer %s, removing peer\n", _srvlookup, peer->name); 23230 unref_peer(peer, "getting rid of a peer pointer"); 23231 return NULL; 23232 } 23233 23234 ast_copy_string(peer->tohost, srvlookup, sizeof(peer->tohost)); 23235 } 23236 23237 if (!peer->addr.sin_port) { 23238 peer->addr.sin_port = htons(((peer->socket.type & SIP_TRANSPORT_TLS) ? STANDARD_TLS_PORT : STANDARD_SIP_PORT)); 23239 } 23240 if (!peer->defaddr.sin_port) { 23241 peer->defaddr.sin_port = htons(((peer->socket.type & SIP_TRANSPORT_TLS) ? STANDARD_TLS_PORT : STANDARD_SIP_PORT)); 23242 } 23243 if (!peer->socket.port) { 23244 peer->socket.port = htons(((peer->socket.type & SIP_TRANSPORT_TLS) ? STANDARD_TLS_PORT : STANDARD_SIP_PORT)); 23245 } 23246 23247 if (!sip_cfg.ignore_regexpire && peer->host_dynamic && realtime) { 23248 time_t nowtime = time(NULL); 23249 23250 if ((nowtime - regseconds) > 0) { 23251 destroy_association(peer); 23252 memset(&peer->addr, 0, sizeof(peer->addr)); 23253 peer->lastms = -1; 23254 ast_debug(1, "Bah, we're expired (%d/%d/%d)!\n", (int)(nowtime - regseconds), (int)regseconds, (int)nowtime); 23255 } 23256 } 23257 23258 /* Startup regular pokes */ 23259 if (!devstate_only && realtime && peer->lastms > 0) { 23260 ref_peer(peer, "schedule qualify"); 23261 sip_poke_peer(peer, 0); 23262 } 23263 23264 ast_copy_flags(&peer->flags[0], &peerflags[0], mask[0].flags); 23265 ast_copy_flags(&peer->flags[1], &peerflags[1], mask[1].flags); 23266 if (ast_test_flag(&peer->flags[1], SIP_PAGE2_ALLOWSUBSCRIBE)) { 23267 global_allowsubscribe = TRUE; /* No global ban any more */ 23268 } 23269 if (!found && peer->host_dynamic && !peer->is_realtime) { 23270 reg_source_db(peer); 23271 } 23272 23273 /* If they didn't request that MWI is sent *only* on subscribe, go ahead and 23274 * subscribe to it now. */ 23275 if (!devstate_only && !ast_test_flag(&peer->flags[1], SIP_PAGE2_SUBSCRIBEMWIONLY) && 23276 !AST_LIST_EMPTY(&peer->mailboxes)) { 23277 add_peer_mwi_subs(peer); 23278 /* Send MWI from the event cache only. This is so we can send initial 23279 * MWI if app_voicemail got loaded before chan_sip. If it is the other 23280 * way, then we will get events when app_voicemail gets loaded. */ 23281 sip_send_mwi_to_peer(peer, NULL, 1); 23282 } 23283 23284 peer->the_mark = 0; 23285 23286 ast_free_ha(oldha); 23287 if (!ast_strlen_zero(callback)) { /* build string from peer info */ 23288 char *reg_string; 23289 23290 if (asprintf(®_string, "%s?%s:%s@%s/%s", peer->name, peer->username, peer->secret, peer->tohost, callback) < 0) { 23291 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno)); 23292 } else if (reg_string) { 23293 sip_register(reg_string, 0); /* XXX TODO: count in registry_count */ 23294 ast_free(reg_string); 23295 } 23296 } 23297 return peer; 23298 }
static int build_reply_digest | ( | struct sip_pvt * | p, | |
int | method, | |||
char * | digest, | |||
int | digest_len | |||
) | [static] |
Build reply digest.
Definition at line 16335 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().
16336 { 16337 char a1[256]; 16338 char a2[256]; 16339 char a1_hash[256]; 16340 char a2_hash[256]; 16341 char resp[256]; 16342 char resp_hash[256]; 16343 char uri[256]; 16344 char opaque[256] = ""; 16345 char cnonce[80]; 16346 const char *username; 16347 const char *secret; 16348 const char *md5secret; 16349 struct sip_auth *auth = NULL; /* Realm authentication */ 16350 16351 if (!ast_strlen_zero(p->domain)) 16352 ast_copy_string(uri, p->domain, sizeof(uri)); 16353 else if (!ast_strlen_zero(p->uri)) 16354 ast_copy_string(uri, p->uri, sizeof(uri)); 16355 else 16356 snprintf(uri, sizeof(uri), "sip:%s@%s", p->username, ast_inet_ntoa(p->sa.sin_addr)); 16357 16358 snprintf(cnonce, sizeof(cnonce), "%08lx", ast_random()); 16359 16360 /* Check if we have separate auth credentials */ 16361 if(!(auth = find_realm_authentication(p->peerauth, p->realm))) /* Start with peer list */ 16362 auth = find_realm_authentication(authl, p->realm); /* If not, global list */ 16363 16364 if (auth) { 16365 ast_log(LOG_DEBUG, "use realm [%s] from peer [%s][%s]\n", auth->username, p->peername, p->username); 16366 username = auth->username; 16367 secret = auth->secret; 16368 md5secret = auth->md5secret; 16369 if (sipdebug) 16370 ast_debug(1, "Using realm %s authentication for call %s\n", p->realm, p->callid); 16371 } else { 16372 /* No authentication, use peer or register= config */ 16373 username = p->authname; 16374 secret = p->peersecret; 16375 md5secret = p->peermd5secret; 16376 } 16377 if (ast_strlen_zero(username)) /* We have no authentication */ 16378 return -1; 16379 16380 /* Calculate SIP digest response */ 16381 snprintf(a1, sizeof(a1), "%s:%s:%s", username, p->realm, secret); 16382 snprintf(a2, sizeof(a2), "%s:%s", sip_methods[method].text, uri); 16383 if (!ast_strlen_zero(md5secret)) 16384 ast_copy_string(a1_hash, md5secret, sizeof(a1_hash)); 16385 else 16386 ast_md5_hash(a1_hash, a1); 16387 ast_md5_hash(a2_hash, a2); 16388 16389 p->noncecount++; 16390 if (!ast_strlen_zero(p->qop)) 16391 snprintf(resp, sizeof(resp), "%s:%s:%08x:%s:%s:%s", a1_hash, p->nonce, p->noncecount, cnonce, "auth", a2_hash); 16392 else 16393 snprintf(resp, sizeof(resp), "%s:%s:%s", a1_hash, p->nonce, a2_hash); 16394 ast_md5_hash(resp_hash, resp); 16395 16396 /* only include the opaque string if it's set */ 16397 if (!ast_strlen_zero(p->opaque)) { 16398 snprintf(opaque, sizeof(opaque), ", opaque=\"%s\"", p->opaque); 16399 } 16400 16401 /* XXX We hard code our qop to "auth" for now. XXX */ 16402 if (!ast_strlen_zero(p->qop)) 16403 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); 16404 else 16405 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); 16406 16407 append_history(p, "AuthResp", "Auth response sent for %s in realm %s - nc %d", username, p->realm, p->noncecount); 16408 16409 return 0; 16410 }
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 11650 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, 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(), handle_request_subscribe(), and handle_response_invite().
11651 { 11652 struct sip_route *thishop, *head, *tail; 11653 int start = 0; 11654 int len; 11655 const char *rr, *contact, *c; 11656 11657 /* Once a persistant route is set, don't fool with it */ 11658 if (p->route && p->route_persistant) { 11659 ast_debug(1, "build_route: Retaining previous route: <%s>\n", p->route->hop); 11660 return; 11661 } 11662 11663 if (p->route) { 11664 free_old_route(p->route); 11665 p->route = NULL; 11666 } 11667 11668 /* We only want to create the route set the first time this is called */ 11669 p->route_persistant = 1; 11670 11671 /* Build a tailq, then assign it to p->route when done. 11672 * If backwards, we add entries from the head so they end up 11673 * in reverse order. However, we do need to maintain a correct 11674 * tail pointer because the contact is always at the end. 11675 */ 11676 head = NULL; 11677 tail = head; 11678 /* 1st we pass through all the hops in any Record-Route headers */ 11679 for (;;) { 11680 /* Each Record-Route header */ 11681 rr = __get_header(req, "Record-Route", &start); 11682 if (*rr == '\0') 11683 break; 11684 for (; (rr = strchr(rr, '<')) ; rr += len) { /* Each route entry */ 11685 ++rr; 11686 len = strcspn(rr, ">") + 1; 11687 /* Make a struct route */ 11688 if ((thishop = ast_malloc(sizeof(*thishop) + len))) { 11689 /* ast_calloc is not needed because all fields are initialized in this block */ 11690 ast_copy_string(thishop->hop, rr, len); 11691 ast_debug(2, "build_route: Record-Route hop: <%s>\n", thishop->hop); 11692 /* Link in */ 11693 if (backwards) { 11694 /* Link in at head so they end up in reverse order */ 11695 thishop->next = head; 11696 head = thishop; 11697 /* If this was the first then it'll be the tail */ 11698 if (!tail) 11699 tail = thishop; 11700 } else { 11701 thishop->next = NULL; 11702 /* Link in at the end */ 11703 if (tail) 11704 tail->next = thishop; 11705 else 11706 head = thishop; 11707 tail = thishop; 11708 } 11709 } 11710 } 11711 } 11712 11713 /* Only append the contact if we are dealing with a strict router */ 11714 if (!head || (!ast_strlen_zero(head->hop) && strstr(head->hop, ";lr") == NULL) ) { 11715 /* 2nd append the Contact: if there is one */ 11716 /* Can be multiple Contact headers, comma separated values - we just take the first */ 11717 contact = get_header(req, "Contact"); 11718 if (!ast_strlen_zero(contact)) { 11719 ast_debug(2, "build_route: Contact hop: %s\n", contact); 11720 /* Look for <: delimited address */ 11721 c = strchr(contact, '<'); 11722 if (c) { 11723 /* Take to > */ 11724 ++c; 11725 len = strcspn(c, ">") + 1; 11726 } else { 11727 /* No <> - just take the lot */ 11728 c = contact; 11729 len = strlen(contact) + 1; 11730 } 11731 if ((thishop = ast_malloc(sizeof(*thishop) + len))) { 11732 /* ast_calloc is not needed because all fields are initialized in this block */ 11733 ast_copy_string(thishop->hop, c, len); 11734 thishop->next = NULL; 11735 /* Goes at the end */ 11736 if (tail) 11737 tail->next = thishop; 11738 else 11739 head = thishop; 11740 } 11741 } 11742 } 11743 11744 /* Store as new route */ 11745 p->route = head; 11746 11747 /* For debugging dump what we ended up with */ 11748 if (sip_debug_test_pvt(p)) 11749 list_route(p->route); 11750 }
static void build_rpid | ( | struct sip_pvt * | p | ) | [static] |
Build the Remote Party-ID & From using callingpres options.
Definition at line 9944 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().
09945 { 09946 int send_pres_tags = TRUE; 09947 const char *privacy=NULL; 09948 const char *screen=NULL; 09949 char buf[256]; 09950 const char *clid = default_callerid; 09951 const char *clin = NULL; 09952 const char *fromdomain; 09953 09954 if (!ast_strlen_zero(p->rpid) || !ast_strlen_zero(p->rpid_from)) 09955 return; 09956 09957 if (p->owner && !ast_strlen_zero(p->owner->cid.cid_num)) 09958 clid = p->owner->cid.cid_num; 09959 if (p->owner && p->owner->cid.cid_name) 09960 clin = p->owner->cid.cid_name; 09961 if (ast_strlen_zero(clin)) 09962 clin = clid; 09963 09964 switch (p->callingpres) { 09965 case AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED: 09966 privacy = "off"; 09967 screen = "no"; 09968 break; 09969 case AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN: 09970 privacy = "off"; 09971 screen = "yes"; 09972 break; 09973 case AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN: 09974 privacy = "off"; 09975 screen = "no"; 09976 break; 09977 case AST_PRES_ALLOWED_NETWORK_NUMBER: 09978 privacy = "off"; 09979 screen = "yes"; 09980 break; 09981 case AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED: 09982 privacy = "full"; 09983 screen = "no"; 09984 break; 09985 case AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN: 09986 privacy = "full"; 09987 screen = "yes"; 09988 break; 09989 case AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN: 09990 privacy = "full"; 09991 screen = "no"; 09992 break; 09993 case AST_PRES_PROHIB_NETWORK_NUMBER: 09994 privacy = "full"; 09995 screen = "yes"; 09996 break; 09997 case AST_PRES_NUMBER_NOT_AVAILABLE: 09998 send_pres_tags = FALSE; 09999 break; 10000 default: 10001 ast_log(LOG_WARNING, "Unsupported callingpres (%d)\n", p->callingpres); 10002 if ((p->callingpres & AST_PRES_RESTRICTION) != AST_PRES_ALLOWED) 10003 privacy = "full"; 10004 else 10005 privacy = "off"; 10006 screen = "no"; 10007 break; 10008 } 10009 10010 fromdomain = S_OR(p->fromdomain, ast_inet_ntoa(p->ourip.sin_addr)); 10011 10012 snprintf(buf, sizeof(buf), "\"%s\" <sip:%s@%s>", clin, clid, fromdomain); 10013 if (send_pres_tags) 10014 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ";privacy=%s;screen=%s", privacy, screen); 10015 ast_string_field_set(p, rpid, buf); 10016 10017 ast_string_field_build(p, rpid_from, "\"%s\" <sip:%s@%s>;tag=%s", clin, 10018 S_OR(p->fromuser, clid), 10019 fromdomain, p->tag); 10020 }
static void build_via | ( | struct sip_pvt * | p | ) | [static] |
Build a Via header for a request.
Definition at line 3205 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().
03206 { 03207 /* Work around buggy UNIDEN UIP200 firmware */ 03208 const char *rport = ast_test_flag(&p->flags[0], SIP_NAT) & SIP_NAT_RFC3581 ? ";rport" : ""; 03209 03210 /* z9hG4bK is a magic cookie. See RFC 3261 section 8.1.1.7 */ 03211 snprintf(p->via, sizeof(p->via), "SIP/2.0/%s %s:%d;branch=z9hG4bK%08x%s", 03212 get_transport_pvt(p), 03213 ast_inet_ntoa(p->ourip.sin_addr), 03214 ntohs(p->ourip.sin_port), (int) p->branch, rport); 03215 }
static int cb_extensionstate | ( | char * | context, | |
char * | exten, | |||
int | state, | |||
void * | data | |||
) | [static] |
Callback for the devicestate notification (SUBSCRIBE) support subsystem.
Definition at line 11982 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().
11983 { 11984 struct sip_pvt *p = data; 11985 11986 sip_pvt_lock(p); 11987 11988 switch(state) { 11989 case AST_EXTENSION_DEACTIVATED: /* Retry after a while */ 11990 case AST_EXTENSION_REMOVED: /* Extension is gone */ 11991 if (p->autokillid > -1 && sip_cancel_destroy(p)) /* Remove subscription expiry for renewals */ 11992 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 11993 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); /* Delete subscription in 32 secs */ 11994 ast_verb(2, "Extension state: Watcher for hint %s %s. Notify User %s\n", exten, state == AST_EXTENSION_DEACTIVATED ? "deactivated" : "removed", p->username); 11995 p->stateid = -1; 11996 p->subscribed = NONE; 11997 append_history(p, "Subscribestatus", "%s", state == AST_EXTENSION_REMOVED ? "HintRemoved" : "Deactivated"); 11998 break; 11999 default: /* Tell user */ 12000 p->laststate = state; 12001 break; 12002 } 12003 if (p->subscribed != NONE) { /* Only send state NOTIFY if we know the format */ 12004 if (!p->pendinginvite) { 12005 transmit_state_notify(p, state, 1, FALSE); 12006 } else { 12007 /* We already have a NOTIFY sent that is not answered. Queue the state up. 12008 if many state changes happen meanwhile, we will only send a notification of the last one */ 12009 ast_set_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE); 12010 } 12011 } 12012 ast_verb(2, "Extension Changed %s[%s] new state %s for Notify User %s %s\n", exten, context, ast_extension_state2str(state), p->username, 12013 ast_test_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE) ? "(queued)" : ""); 12014 12015 sip_pvt_unlock(p); 12016 12017 return 0; 12018 }
static void change_t38_state | ( | struct sip_pvt * | p, | |
int | state | |||
) | [static] |
Change the T38 state on a SIP dialog.
Definition at line 4644 of file chan_sip.c.
References AST_CONTROL_T38_PARAMETERS, ast_debug, ast_queue_control_data(), AST_T38_NEGOTIATED, AST_T38_REFUSED, AST_T38_REQUEST_NEGOTIATE, AST_T38_TERMINATED, ast_udptl_get_far_max_ifp(), ast_udptl_set_tag(), chan, ast_control_t38_parameters::max_ifp, ast_channel::name, sip_pvt::owner, ast_control_t38_parameters::request_response, t38properties::state, sip_pvt::t38, T38_DISABLED, T38_ENABLED, T38_LOCAL_REINVITE, T38_PEER_REINVITE, t38properties::their_parms, sip_pvt::udptl, and sip_pvt::username.
Referenced by handle_response_invite(), interpret_t38_parameters(), process_sdp(), and sip_t38_abort().
04645 { 04646 int old = p->t38.state; 04647 struct ast_channel *chan = p->owner; 04648 struct ast_control_t38_parameters parameters = { .request_response = 0 }; 04649 04650 /* Don't bother changing if we are already in the state wanted */ 04651 if (old == state) 04652 return; 04653 04654 p->t38.state = state; 04655 ast_debug(2, "T38 state changed to %d on channel %s\n", p->t38.state, chan ? chan->name : "<none>"); 04656 04657 /* If no channel was provided we can't send off a control frame */ 04658 if (!chan) 04659 return; 04660 04661 /* Given the state requested and old state determine what control frame we want to queue up */ 04662 switch (state) { 04663 case T38_PEER_REINVITE: 04664 parameters = p->t38.their_parms; 04665 parameters.max_ifp = ast_udptl_get_far_max_ifp(p->udptl); 04666 parameters.request_response = AST_T38_REQUEST_NEGOTIATE; 04667 ast_udptl_set_tag(p->udptl, "SIP/%s", p->username); 04668 break; 04669 case T38_ENABLED: 04670 parameters = p->t38.their_parms; 04671 parameters.max_ifp = ast_udptl_get_far_max_ifp(p->udptl); 04672 parameters.request_response = AST_T38_NEGOTIATED; 04673 ast_udptl_set_tag(p->udptl, "SIP/%s", p->username); 04674 break; 04675 case T38_DISABLED: 04676 if (old == T38_ENABLED) { 04677 parameters.request_response = AST_T38_TERMINATED; 04678 } else if (old == T38_LOCAL_REINVITE) { 04679 parameters.request_response = AST_T38_REFUSED; 04680 } 04681 break; 04682 case T38_LOCAL_REINVITE: 04683 /* wait until we get a peer response before responding to local reinvite */ 04684 break; 04685 } 04686 04687 /* Woot we got a message, create a control frame and send it on! */ 04688 if (parameters.request_response) 04689 ast_queue_control_data(chan, AST_CONTROL_T38_PARAMETERS, ¶meters, sizeof(parameters)); 04690 }
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 11774 of file chan_sip.c.
References append_history, ast_copy_string(), AST_DYNSTR_BUILD_FAILED, ast_log(), ast_md5_hash(), ast_skip_blanks(), ast_str_set(), ast_str_thread_get(), ast_strlen_zero(), AUTH_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, set_nonce_randdata(), sip_methods, sip_scheddestroy(), sip_pvt::stalenonce, strsep(), text, transmit_response_with_auth(), TRUE, and WWW_AUTH.
Referenced by check_peer_ok(), and register_verify().
11777 { 11778 const char *response; 11779 char *reqheader, *respheader; 11780 const char *authtoken; 11781 char a1_hash[256]; 11782 char resp_hash[256]=""; 11783 char *c; 11784 int wrongnonce = FALSE; 11785 int good_response; 11786 const char *usednonce = p->randdata; 11787 struct ast_str *buf; 11788 int res; 11789 11790 /* table of recognised keywords, and their value in the digest */ 11791 enum keys { K_RESP, K_URI, K_USER, K_NONCE, K_LAST }; 11792 struct x { 11793 const char *key; 11794 const char *s; 11795 } *i, keys[] = { 11796 [K_RESP] = { "response=", "" }, 11797 [K_URI] = { "uri=", "" }, 11798 [K_USER] = { "username=", "" }, 11799 [K_NONCE] = { "nonce=", "" }, 11800 [K_LAST] = { NULL, NULL} 11801 }; 11802 11803 /* Always OK if no secret */ 11804 if (ast_strlen_zero(secret) && ast_strlen_zero(md5secret)) 11805 return AUTH_SUCCESSFUL; 11806 11807 /* Always auth with WWW-auth since we're NOT a proxy */ 11808 /* Using proxy-auth in a B2BUA may block proxy authorization in the same transaction */ 11809 response = "401 Unauthorized"; 11810 11811 /* 11812 * Note the apparent swap of arguments below, compared to other 11813 * usages of auth_headers(). 11814 */ 11815 auth_headers(WWW_AUTH, &respheader, &reqheader); 11816 11817 authtoken = get_header(req, reqheader); 11818 if (ignore && !ast_strlen_zero(p->randdata) && ast_strlen_zero(authtoken)) { 11819 /* This is a retransmitted invite/register/etc, don't reconstruct authentication 11820 information */ 11821 if (!reliable) { 11822 /* Resend message if this was NOT a reliable delivery. Otherwise the 11823 retransmission should get it */ 11824 transmit_response_with_auth(p, response, req, p->randdata, reliable, respheader, 0); 11825 /* Schedule auto destroy in 32 seconds (according to RFC 3261) */ 11826 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 11827 } 11828 return AUTH_CHALLENGE_SENT; 11829 } else if (ast_strlen_zero(p->randdata) || ast_strlen_zero(authtoken)) { 11830 /* We have no auth, so issue challenge and request authentication */ 11831 set_nonce_randdata(p, 1); /* Create nonce for challenge */ 11832 transmit_response_with_auth(p, response, req, p->randdata, reliable, respheader, 0); 11833 /* Schedule auto destroy in 32 seconds */ 11834 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 11835 return AUTH_CHALLENGE_SENT; 11836 } 11837 11838 /* --- We have auth, so check it */ 11839 11840 /* Whoever came up with the authentication section of SIP can suck my %&#$&* for not putting 11841 an example in the spec of just what it is you're doing a hash on. */ 11842 11843 if (!(buf = ast_str_thread_get(&check_auth_buf, CHECK_AUTH_BUF_INITLEN))) 11844 return AUTH_SECRET_FAILED; /*! XXX \todo need a better return code here */ 11845 11846 /* Make a copy of the response and parse it */ 11847 res = ast_str_set(&buf, 0, "%s", authtoken); 11848 11849 if (res == AST_DYNSTR_BUILD_FAILED) 11850 return AUTH_SECRET_FAILED; /*! XXX \todo need a better return code here */ 11851 11852 c = buf->str; 11853 11854 while(c && *(c = ast_skip_blanks(c)) ) { /* lookup for keys */ 11855 for (i = keys; i->key != NULL; i++) { 11856 const char *separator = ","; /* default */ 11857 11858 if (strncasecmp(c, i->key, strlen(i->key)) != 0) 11859 continue; 11860 /* Found. Skip keyword, take text in quotes or up to the separator. */ 11861 c += strlen(i->key); 11862 if (*c == '"') { /* in quotes. Skip first and look for last */ 11863 c++; 11864 separator = "\""; 11865 } 11866 i->s = c; 11867 strsep(&c, separator); 11868 break; 11869 } 11870 if (i->key == NULL) /* not found, jump after space or comma */ 11871 strsep(&c, " ,"); 11872 } 11873 11874 /* Verify that digest username matches the username we auth as */ 11875 if (strcmp(username, keys[K_USER].s)) { 11876 ast_log(LOG_WARNING, "username mismatch, have <%s>, digest has <%s>\n", 11877 username, keys[K_USER].s); 11878 /* Oops, we're trying something here */ 11879 return AUTH_USERNAME_MISMATCH; 11880 } 11881 11882 /* Verify nonce from request matches our nonce, and the nonce has not already been responded to. 11883 * If this check fails, send 401 with new nonce */ 11884 if (strcasecmp(p->randdata, keys[K_NONCE].s) || p->stalenonce) { /* XXX it was 'n'casecmp ? */ 11885 wrongnonce = TRUE; 11886 usednonce = keys[K_NONCE].s; 11887 } else { 11888 p->stalenonce = 1; /* now, since the nonce has a response, mark it as stale so it can't be sent or responded to again */ 11889 } 11890 11891 if (!ast_strlen_zero(md5secret)) 11892 ast_copy_string(a1_hash, md5secret, sizeof(a1_hash)); 11893 else { 11894 char a1[256]; 11895 snprintf(a1, sizeof(a1), "%s:%s:%s", username, global_realm, secret); 11896 ast_md5_hash(a1_hash, a1); 11897 } 11898 11899 /* compute the expected response to compare with what we received */ 11900 { 11901 char a2[256]; 11902 char a2_hash[256]; 11903 char resp[256]; 11904 11905 snprintf(a2, sizeof(a2), "%s:%s", sip_methods[sipmethod].text, 11906 S_OR(keys[K_URI].s, uri)); 11907 ast_md5_hash(a2_hash, a2); 11908 snprintf(resp, sizeof(resp), "%s:%s:%s", a1_hash, usednonce, a2_hash); 11909 ast_md5_hash(resp_hash, resp); 11910 } 11911 11912 good_response = keys[K_RESP].s && 11913 !strncasecmp(keys[K_RESP].s, resp_hash, strlen(resp_hash)); 11914 if (wrongnonce) { 11915 if (good_response) { 11916 if (sipdebug) 11917 ast_log(LOG_NOTICE, "Correct auth, but based on stale nonce received from '%s'\n", get_header(req, "To")); 11918 /* We got working auth token, based on stale nonce . */ 11919 set_nonce_randdata(p, 0); 11920 transmit_response_with_auth(p, response, req, p->randdata, reliable, respheader, TRUE); 11921 } else { 11922 /* Everything was wrong, so give the device one more try with a new challenge */ 11923 if (!req->ignore) { 11924 if (sipdebug) 11925 ast_log(LOG_NOTICE, "Bad authentication received from '%s'\n", get_header(req, "To")); 11926 set_nonce_randdata(p, 1); 11927 } else { 11928 if (sipdebug) 11929 ast_log(LOG_NOTICE, "Duplicate authentication received from '%s'\n", get_header(req, "To")); 11930 } 11931 transmit_response_with_auth(p, response, req, p->randdata, reliable, respheader, FALSE); 11932 } 11933 11934 /* Schedule auto destroy in 32 seconds */ 11935 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 11936 return AUTH_CHALLENGE_SENT; 11937 } 11938 if (good_response) { 11939 append_history(p, "AuthOK", "Auth challenge succesful for %s", username); 11940 return AUTH_SUCCESSFUL; 11941 } 11942 11943 /* Ok, we have a bad username/secret pair */ 11944 /* Tell the UAS not to re-send this authentication data, because 11945 it will continue to fail 11946 */ 11947 11948 return AUTH_SECRET_FAILED; 11949 }
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 13145 of file chan_sip.c.
References sip_peer::accountcode, accountcode, sip_peer::amaflags, sip_pvt::amaflags, ao2_t_ref, ast_apply_ha(), ast_copy_flags, ast_debug, 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_ACL_FAILED, 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_peer::ha, sip_request::ignore, 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, 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, set_t38_capabilities(), 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_T38SUPPORT, SIP_PAGE2_TEXTSUPPORT, SIP_PAGE2_VIDEOSUPPORT, SIP_PAGE2_VIDEOSUPPORT_ALWAYS, SIP_SUBSCRIBE, sip_peer::sipoptions, sip_pvt::sipoptions, sip_pvt::socket, sip_peer::subscribecontext, sip_peer::t38_maxdatagram, sip_pvt::t38_maxdatagram, sip_pvt::timer_b, sip_peer::timer_b, sip_peer::timer_t1, sip_pvt::timer_t1, sip_pvt::trtp, TRUE, sip_socket::type, sip_pvt::udptl, unref_peer(), sip_peer::username, and sip_pvt::vrtp.
Referenced by check_user_full().
13150 { 13151 enum check_auth_result res; 13152 int debug=sip_debug_test_addr(sin); 13153 struct sip_peer *peer; 13154 13155 if (sipmethod == SIP_SUBSCRIBE) { 13156 /* For subscribes, match on device name only; for other methods, 13157 * match on IP address-port of the incoming request. 13158 */ 13159 peer = find_peer(of, NULL, TRUE, FINDALLDEVICES, FALSE, 0); 13160 } else { 13161 /* First find devices based on username (avoid all type=peer's) */ 13162 peer = find_peer(of, NULL, TRUE, FINDUSERS, FALSE, 0); 13163 13164 /* Then find devices based on IP */ 13165 if (!peer) { 13166 peer = find_peer(NULL, &p->recv, TRUE, FINDPEERS, FALSE, p->socket.type); 13167 } 13168 } 13169 13170 if (!peer) { 13171 if (debug) 13172 ast_verbose("No matching peer for '%s' from '%s:%d'\n", 13173 of, ast_inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port)); 13174 return AUTH_DONT_KNOW; 13175 } 13176 if (!ast_apply_ha(peer->ha, sin)) { 13177 ast_debug(2, "Found peer '%s' for '%s', but fails host access\n", peer->name, of); 13178 unref_peer(peer, "unref_peer: check_peer_ok: from find_peer call, early return of AUTH_ACL_FAILED"); 13179 return AUTH_ACL_FAILED; 13180 } 13181 if (debug) 13182 ast_verbose("Found peer '%s' for '%s' from %s:%d\n", 13183 peer->name, of, ast_inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port)); 13184 13185 /* XXX what about p->prefs = peer->prefs; ? */ 13186 /* Set Frame packetization */ 13187 if (p->rtp) { 13188 ast_rtp_codec_setpref(p->rtp, &peer->prefs); 13189 p->autoframing = peer->autoframing; 13190 } 13191 13192 /* Take the peer */ 13193 ast_copy_flags(&p->flags[0], &peer->flags[0], SIP_FLAGS_TO_COPY); 13194 ast_copy_flags(&p->flags[1], &peer->flags[1], SIP_PAGE2_FLAGS_TO_COPY); 13195 13196 if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT) && p->udptl) { 13197 p->t38_maxdatagram = peer->t38_maxdatagram; 13198 set_t38_capabilities(p); 13199 } 13200 13201 /* Copy SIP extensions profile to peer */ 13202 /* XXX is this correct before a successful auth ? */ 13203 if (p->sipoptions) 13204 peer->sipoptions = p->sipoptions; 13205 13206 replace_cid(p, rpid_num, calleridname); 13207 do_setnat(p, ast_test_flag(&p->flags[0], SIP_NAT_ROUTE)); 13208 13209 ast_string_field_set(p, peersecret, peer->secret); 13210 ast_string_field_set(p, peermd5secret, peer->md5secret); 13211 ast_string_field_set(p, subscribecontext, peer->subscribecontext); 13212 ast_string_field_set(p, mohinterpret, peer->mohinterpret); 13213 ast_string_field_set(p, mohsuggest, peer->mohsuggest); 13214 ast_string_field_set(p, parkinglot, peer->parkinglot); 13215 if (peer->callingpres) /* Peer calling pres setting will override RPID */ 13216 p->callingpres = peer->callingpres; 13217 if (peer->maxms && peer->lastms) 13218 p->timer_t1 = peer->lastms < global_t1min ? global_t1min : peer->lastms; 13219 else 13220 p->timer_t1 = peer->timer_t1; 13221 13222 /* Set timer B to control transaction timeouts */ 13223 if (peer->timer_b) 13224 p->timer_b = peer->timer_b; 13225 else 13226 p->timer_b = 64 * p->timer_t1; 13227 13228 if (ast_test_flag(&peer->flags[0], SIP_INSECURE_INVITE)) { 13229 /* Pretend there is no required authentication */ 13230 ast_string_field_set(p, peersecret, NULL); 13231 ast_string_field_set(p, peermd5secret, NULL); 13232 } 13233 if (!(res = check_auth(p, req, peer->name, p->peersecret, p->peermd5secret, sipmethod, uri2, reliable, req->ignore))) { 13234 ast_copy_flags(&p->flags[0], &peer->flags[0], SIP_FLAGS_TO_COPY); 13235 ast_copy_flags(&p->flags[1], &peer->flags[1], SIP_PAGE2_FLAGS_TO_COPY); 13236 /* If we have a call limit, set flag */ 13237 if (peer->call_limit) 13238 ast_set_flag(&p->flags[0], SIP_CALL_LIMIT); 13239 ast_string_field_set(p, peername, peer->name); 13240 ast_string_field_set(p, authname, peer->name); 13241 13242 if (sipmethod == SIP_INVITE) { 13243 /* copy channel vars */ 13244 p->chanvars = copy_vars(peer->chanvars); 13245 } 13246 13247 if (authpeer) { 13248 ao2_t_ref(peer, 1, "copy pointer into (*authpeer)"); 13249 (*authpeer) = peer; /* Add a ref to the object here, to keep it in memory a bit longer if it is realtime */ 13250 } 13251 13252 if (!ast_strlen_zero(peer->username)) { 13253 ast_string_field_set(p, username, peer->username); 13254 /* Use the default username for authentication on outbound calls */ 13255 /* XXX this takes the name from the caller... can we override ? */ 13256 ast_string_field_set(p, authname, peer->username); 13257 } 13258 if (!ast_strlen_zero(peer->cid_num)) { 13259 char *tmp = ast_strdupa(peer->cid_num); 13260 if (global_shrinkcallerid && ast_is_shrinkable_phonenumber(tmp)) 13261 ast_shrink_phone_number(tmp); 13262 ast_string_field_set(p, cid_num, tmp); 13263 } 13264 if (!ast_strlen_zero(peer->cid_name)) 13265 ast_string_field_set(p, cid_name, peer->cid_name); 13266 ast_string_field_set(p, fullcontact, peer->fullcontact); 13267 if (!ast_strlen_zero(peer->context)) 13268 ast_string_field_set(p, context, peer->context); 13269 ast_string_field_set(p, peersecret, peer->secret); 13270 ast_string_field_set(p, peermd5secret, peer->md5secret); 13271 ast_string_field_set(p, language, peer->language); 13272 ast_string_field_set(p, accountcode, peer->accountcode); 13273 p->amaflags = peer->amaflags; 13274 p->callgroup = peer->callgroup; 13275 p->pickupgroup = peer->pickupgroup; 13276 p->capability = peer->capability; 13277 p->prefs = peer->prefs; 13278 p->jointcapability = peer->capability; 13279 if (p->peercapability) 13280 p->jointcapability &= p->peercapability; 13281 p->maxcallbitrate = peer->maxcallbitrate; 13282 if (!ast_test_flag(&p->flags[1], SIP_PAGE2_VIDEOSUPPORT_ALWAYS) && 13283 (!ast_test_flag(&p->flags[1], SIP_PAGE2_VIDEOSUPPORT) || 13284 !(p->capability & AST_FORMAT_VIDEO_MASK)) && 13285 p->vrtp) { 13286 ast_rtp_destroy(p->vrtp); 13287 p->vrtp = NULL; 13288 } 13289 if ((!ast_test_flag(&p->flags[1], SIP_PAGE2_TEXTSUPPORT) || !(p->capability & AST_FORMAT_TEXT_MASK)) && p->trtp) { 13290 ast_rtp_destroy(p->trtp); 13291 p->trtp = NULL; 13292 } 13293 if ((ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833) || 13294 (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO)) 13295 p->noncodeccapability |= AST_RTP_DTMF; 13296 else 13297 p->noncodeccapability &= ~AST_RTP_DTMF; 13298 p->jointnoncodeccapability = p->noncodeccapability; 13299 } 13300 unref_peer(peer, "check_peer_ok: unref_peer: tossing temp ptr to peer from find_peer"); 13301 return res; 13302 }
static void check_pendings | ( | struct sip_pvt * | p | ) | [static] |
Check pending actions on SIP call.
Definition at line 16782 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().
16783 { 16784 if (ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) { 16785 /* if we can't BYE, then this is really a pending CANCEL */ 16786 if (p->invitestate == INV_PROCEEDING || p->invitestate == INV_EARLY_MEDIA) 16787 transmit_request(p, SIP_CANCEL, p->lastinvite, XMIT_RELIABLE, FALSE); 16788 /* Actually don't destroy us yet, wait for the 487 on our original 16789 INVITE, but do set an autodestruct just in case we never get it. */ 16790 else { 16791 /* We have a pending outbound invite, don't send someting 16792 new in-transaction */ 16793 if (p->pendinginvite) 16794 return; 16795 16796 /* Perhaps there is an SD change INVITE outstanding */ 16797 transmit_request_with_auth(p, SIP_BYE, 0, XMIT_RELIABLE, TRUE); 16798 } 16799 ast_clear_flag(&p->flags[0], SIP_PENDINGBYE); 16800 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 16801 } else if (ast_test_flag(&p->flags[0], SIP_NEEDREINVITE)) { 16802 /* if we can't REINVITE, hold it for later */ 16803 if (p->pendinginvite || p->invitestate == INV_CALLING || p->invitestate == INV_PROCEEDING || p->invitestate == INV_EARLY_MEDIA || p->waitid > 0) { 16804 ast_debug(2, "NOT Sending pending reinvite (yet) on '%s'\n", p->callid); 16805 } else { 16806 ast_debug(2, "Sending pending reinvite on '%s'\n", p->callid); 16807 /* Didn't get to reinvite yet, so do it now */ 16808 transmit_reinvite_with_sdp(p, (p->t38.state == T38_LOCAL_REINVITE ? TRUE : FALSE), FALSE); 16809 ast_clear_flag(&p->flags[0], SIP_NEEDREINVITE); 16810 } 16811 } 16812 }
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 21427 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().
21428 { 21429 /* If we have no RTP or no active owner, no need to check timers */ 21430 if (!dialog->rtp || !dialog->owner) 21431 return; 21432 /* If the call is not in UP state or redirected outside Asterisk, no need to check timers */ 21433 21434 if (dialog->owner->_state != AST_STATE_UP || dialog->redirip.sin_addr.s_addr) 21435 return; 21436 21437 /* If the call is involved in a T38 fax session do not check RTP timeout */ 21438 if (dialog->t38.state == T38_ENABLED) 21439 return; 21440 21441 /* If we have no timers set, return now */ 21442 if ((ast_rtp_get_rtpkeepalive(dialog->rtp) == 0) && (ast_rtp_get_rtptimeout(dialog->rtp) == 0) && (ast_rtp_get_rtpholdtimeout(dialog->rtp) == 0)) 21443 return; 21444 21445 /* Check AUDIO RTP keepalives */ 21446 if (dialog->lastrtptx && ast_rtp_get_rtpkeepalive(dialog->rtp) && 21447 (t > dialog->lastrtptx + ast_rtp_get_rtpkeepalive(dialog->rtp))) { 21448 /* Need to send an empty RTP packet */ 21449 dialog->lastrtptx = time(NULL); 21450 ast_rtp_sendcng(dialog->rtp, 0); 21451 } 21452 21453 /*! \todo Check video RTP keepalives 21454 21455 Do we need to move the lastrtptx to the RTP structure to have one for audio and one 21456 for video? It really does belong to the RTP structure. 21457 */ 21458 21459 /* Check AUDIO RTP timers */ 21460 if (dialog->lastrtprx && (ast_rtp_get_rtptimeout(dialog->rtp) || ast_rtp_get_rtpholdtimeout(dialog->rtp)) && 21461 (t > dialog->lastrtprx + ast_rtp_get_rtptimeout(dialog->rtp))) { 21462 21463 /* Might be a timeout now -- see if we're on hold */ 21464 struct sockaddr_in sin; 21465 ast_rtp_get_peer(dialog->rtp, &sin); 21466 if (!ast_test_flag(&dialog->flags[1], SIP_PAGE2_CALL_ONHOLD) || (ast_rtp_get_rtpholdtimeout(dialog->rtp) && 21467 (t > dialog->lastrtprx + ast_rtp_get_rtpholdtimeout(dialog->rtp)))) { 21468 /* Needs a hangup */ 21469 if (ast_rtp_get_rtptimeout(dialog->rtp)) { 21470 while (dialog->owner && ast_channel_trylock(dialog->owner)) { 21471 sip_pvt_unlock(dialog); 21472 usleep(1); 21473 sip_pvt_lock(dialog); 21474 } 21475 ast_log(LOG_NOTICE, "Disconnecting call '%s' for lack of RTP activity in %ld seconds\n", 21476 dialog->owner->name, (long) (t - dialog->lastrtprx)); 21477 /* Issue a softhangup */ 21478 ast_softhangup_nolock(dialog->owner, AST_SOFTHANGUP_DEV); 21479 ast_channel_unlock(dialog->owner); 21480 /* forget the timeouts for this call, since a hangup 21481 has already been requested and we don't want to 21482 repeatedly request hangups 21483 */ 21484 ast_rtp_set_rtptimeout(dialog->rtp, 0); 21485 ast_rtp_set_rtpholdtimeout(dialog->rtp, 0); 21486 if (dialog->vrtp) { 21487 ast_rtp_set_rtptimeout(dialog->vrtp, 0); 21488 ast_rtp_set_rtpholdtimeout(dialog->vrtp, 0); 21489 } 21490 } 21491 } 21492 } 21493 }
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 22530 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().
22531 { 22532 struct domain *d; 22533 int result = 0; 22534 22535 AST_LIST_LOCK(&domain_list); 22536 AST_LIST_TRAVERSE(&domain_list, d, list) { 22537 if (strcasecmp(d->domain, domain)) 22538 continue; 22539 22540 if (len && !ast_strlen_zero(d->context)) 22541 ast_copy_string(context, d->context, len); 22542 22543 result = 1; 22544 break; 22545 } 22546 AST_LIST_UNLOCK(&domain_list); 22547 22548 return result; 22549 }
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 13427 of file chan_sip.c.
References check_user_full().
Referenced by handle_request_invite().
13428 { 13429 return check_user_full(p, req, sipmethod, uri, reliable, sin, NULL); 13430 }
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 13310 of file chan_sip.c.
References ast_copy_string(), ast_is_shrinkable_phonenumber(), ast_log(), ast_set_flag, ast_shrink_phone_number(), ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, 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_NAT_ROUTE, SIP_PAGE2_RPORT_PRESENT, strsep(), and terminate_uri().
Referenced by check_user(), and handle_request_subscribe().
13313 { 13314 char from[256]; 13315 char *dummy; /* dummy return value for parse_uri */ 13316 char *domain; /* dummy return value for parse_uri */ 13317 char *of; 13318 char rpid_num[50]; 13319 const char *rpid; 13320 enum check_auth_result res; 13321 char calleridname[50]; 13322 char *uri2 = ast_strdupa(uri); 13323 13324 terminate_uri(uri2); /* trim extra stuff */ 13325 13326 ast_copy_string(from, get_header(req, "From"), sizeof(from)); 13327 if (pedanticsipchecking) 13328 ast_uri_decode(from); 13329 /* XXX here tries to map the username for invite things */ 13330 memset(calleridname, 0, sizeof(calleridname)); 13331 get_calleridname(from, calleridname, sizeof(calleridname)); 13332 if (calleridname[0]) 13333 ast_string_field_set(p, cid_name, calleridname); 13334 13335 rpid = get_header(req, "Remote-Party-ID"); 13336 memset(rpid_num, 0, sizeof(rpid_num)); 13337 if (!ast_strlen_zero(rpid)) 13338 p->callingpres = get_rpid_num(rpid, rpid_num, sizeof(rpid_num)); 13339 13340 of = get_in_brackets(from); 13341 if (ast_strlen_zero(p->exten)) { 13342 char *t = uri2; 13343 if (!strncasecmp(t, "sip:", 4)) 13344 t+= 4; 13345 else if (!strncasecmp(t, "sips:", 5)) 13346 t += 5; 13347 ast_string_field_set(p, exten, t); 13348 t = strchr(p->exten, '@'); 13349 if (t) 13350 *t = '\0'; 13351 if (ast_strlen_zero(p->our_contact)) 13352 build_contact(p); 13353 } 13354 /* save the URI part of the From header */ 13355 ast_string_field_set(p, from, of); 13356 13357 13358 /* ignore all fields but name */ 13359 if (parse_uri(of, "sip:,sips:", &of, &dummy, &domain, &dummy, &dummy, NULL)) { 13360 ast_log(LOG_NOTICE, "From address missing 'sip:', using it anyway\n"); 13361 } 13362 13363 if (ast_strlen_zero(of)) { 13364 /* XXX note: the original code considered a missing @host 13365 * as a username-only URI. The SIP RFC (19.1.1) says that 13366 * this is wrong, and it should be considered as a domain-only URI. 13367 * For backward compatibility, we keep this block, but it is 13368 * really a mistake and should go away. 13369 */ 13370 of = domain; 13371 } else { 13372 char *tmp = ast_strdupa(of); 13373 /* We need to be able to handle auth-headers looking like 13374 <sip:8164444422;phone-context=+1@1.2.3.4:5060;user=phone;tag=SDadkoa01-gK0c3bdb43> 13375 */ 13376 tmp = strsep(&tmp, ";"); 13377 if (global_shrinkcallerid && ast_is_shrinkable_phonenumber(tmp)) 13378 ast_shrink_phone_number(tmp); 13379 ast_string_field_set(p, cid_num, tmp); 13380 } 13381 13382 if (global_match_auth_username) { 13383 /* 13384 * XXX This is experimental code to grab the search key from the 13385 * Auth header's username instead of the 'From' name, if available. 13386 * Do not enable this block unless you understand the side effects (if any!) 13387 * Note, the search for "username" should be done in a more robust way. 13388 * Note2, at the moment we check both fields, though maybe we should 13389 * pick one or another depending on the request ? XXX 13390 */ 13391 const char *hdr = get_header(req, "Authorization"); 13392 if (ast_strlen_zero(hdr)) 13393 hdr = get_header(req, "Proxy-Authorization"); 13394 13395 if ( !ast_strlen_zero(hdr) && (hdr = strstr(hdr, "username=\"")) ) { 13396 ast_copy_string(from, hdr + strlen("username=\""), sizeof(from)); 13397 of = from; 13398 of = strsep(&of, "\""); 13399 } 13400 } 13401 13402 res = check_peer_ok(p, of, req, sipmethod, sin, 13403 authpeer, reliable, rpid_num, calleridname, uri2); 13404 if (res != AUTH_DONT_KNOW) 13405 return res; 13406 13407 /* Finally, apply the guest policy */ 13408 if (global_allowguest) { 13409 replace_cid(p, rpid_num, calleridname); 13410 res = AUTH_SUCCESSFUL; 13411 } else if (global_alwaysauthreject) 13412 res = AUTH_FAKE_AUTH; /* reject with fake authorization request */ 13413 else 13414 res = AUTH_SECRET_FAILED; /* we don't want any guests, authentication will fail */ 13415 13416 13417 if (ast_test_flag(&p->flags[1], SIP_PAGE2_RPORT_PRESENT)) { 13418 ast_set_flag(&p->flags[0], SIP_NAT_ROUTE); 13419 } 13420 13421 return res; 13422 }
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 12977 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, port_str2int(), sip_pvt::sa, sip_debug_test_pvt(), sip_nat_mode(), SIP_PAGE2_RPORT_PRESENT, 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().
12978 { 12979 char via[512]; 12980 char *c, *pt, *maddr; 12981 struct hostent *hp; 12982 struct ast_hostent ahp; 12983 12984 ast_copy_string(via, get_header(req, "Via"), sizeof(via)); 12985 12986 /* Work on the leftmost value of the topmost Via header */ 12987 c = strchr(via, ','); 12988 if (c) 12989 *c = '\0'; 12990 12991 /* Check for rport */ 12992 c = strstr(via, ";rport"); 12993 if (c && (c[6] != '=')) /* rport query, not answer */ 12994 ast_set_flag(&p->flags[1], SIP_PAGE2_RPORT_PRESENT); 12995 12996 /* Check for maddr */ 12997 maddr = strstr(via, "maddr="); 12998 if (maddr) { 12999 maddr += 6; 13000 c = maddr + strspn(maddr, "0123456789."); 13001 *c = '\0'; 13002 } 13003 13004 c = strchr(via, ';'); 13005 if (c) 13006 *c = '\0'; 13007 13008 c = strchr(via, ' '); 13009 if (c) { 13010 *c = '\0'; 13011 c = ast_skip_blanks(c+1); 13012 if (strcasecmp(via, "SIP/2.0/UDP") && strcasecmp(via, "SIP/2.0/TCP") && strcasecmp(via, "SIP/2.0/TLS")) { 13013 ast_log(LOG_WARNING, "Don't know how to respond via '%s'\n", via); 13014 return; 13015 } 13016 pt = strchr(c, ':'); 13017 if (pt) 13018 *pt++ = '\0'; /* remember port pointer */ 13019 /* Use maddr if found */ 13020 if (maddr) 13021 c = maddr; 13022 hp = ast_gethostbyname(c, &ahp); 13023 if (!hp) { 13024 ast_log(LOG_WARNING, "'%s' is not a valid host\n", c); 13025 return; 13026 } 13027 memset(&p->sa, 0, sizeof(p->sa)); 13028 p->sa.sin_family = AF_INET; 13029 memcpy(&p->sa.sin_addr, hp->h_addr, sizeof(p->sa.sin_addr)); 13030 p->sa.sin_port = htons(port_str2int(pt, STANDARD_SIP_PORT)); 13031 13032 if (sip_debug_test_pvt(p)) { 13033 const struct sockaddr_in *dst = sip_real_dst(p); 13034 ast_verbose("Sending to %s : %d (%s)\n", ast_inet_ntoa(dst->sin_addr), ntohs(dst->sin_port), sip_nat_mode(p)); 13035 } 13036 } 13037 }
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 12947 of file chan_sip.c.
References ast_copy_string(), ast_parse_arg(), get_header(), sip_pvt::ourip, PARSE_INADDR, and strsep().
12948 { 12949 char via[256]; 12950 char *cur, *opts; 12951 12952 ast_copy_string(via, get_header(req, "Via"), sizeof(via)); 12953 12954 /* Work on the leftmost value of the topmost Via header */ 12955 opts = strchr(via, ','); 12956 if (opts) 12957 *opts = '\0'; 12958 12959 /* parse all relevant options */ 12960 opts = strchr(via, ';'); 12961 if (!opts) 12962 return; /* no options to parse */ 12963 *opts++ = '\0'; 12964 while ( (cur = strsep(&opts, ";")) ) { 12965 if (!strncmp(cur, "rport=", 6)) { 12966 int port = strtol(cur+6, NULL, 10); 12967 /* XXX add error checking */ 12968 p->ourip.sin_port = ntohs(port); 12969 } else if (!strncmp(cur, "received=", 9)) { 12970 if (ast_parse_arg(cur+9, PARSE_INADDR, &p->ourip)) 12971 ; /* XXX add error checking */ 12972 } 12973 } 12974 }
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 14156 of file chan_sip.c.
References ast_context_destroy(), ast_context_find(), ast_copy_string(), AST_MAX_CONTEXT, and strsep().
Referenced by reload_config().
14157 { 14158 char *oldcontext, *newcontext, *stalecontext, *stringp, newlist[AST_MAX_CONTEXT]; 14159 14160 while ((oldcontext = strsep(&old, "&"))) { 14161 stalecontext = '\0'; 14162 ast_copy_string(newlist, new, sizeof(newlist)); 14163 stringp = newlist; 14164 while ((newcontext = strsep(&stringp, "&"))) { 14165 if (!strcmp(newcontext, oldcontext)) { 14166 /* This is not the context you're looking for */ 14167 stalecontext = '\0'; 14168 break; 14169 } else if (strcmp(newcontext, oldcontext)) { 14170 stalecontext = oldcontext; 14171 } 14172 14173 } 14174 if (stalecontext) 14175 ast_context_destroy(ast_context_find(stalecontext), "SIP"); 14176 } 14177 }
static void clear_peer_mailboxes | ( | struct sip_peer * | peer | ) | [static] |
Destroy all peer-related mailbox subscriptions
Definition at line 4250 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().
04251 { 04252 struct sip_mailbox *mailbox; 04253 04254 while ((mailbox = AST_LIST_REMOVE_HEAD(&peer->mailboxes, entry))) 04255 destroy_mailbox(mailbox); 04256 }
static int clear_realm_authentication | ( | struct sip_auth * | authlist | ) | [static] |
Clear realm authentication list (at reload).
Definition at line 22619 of file chan_sip.c.
References ast_free, and sip_auth::next.
Referenced by build_peer(), reload_config(), sip_destroy_peer(), and unload_module().
22620 { 22621 struct sip_auth *a = authlist; 22622 struct sip_auth *b; 22623 22624 while (a) { 22625 b = a; 22626 a = a->next; 22627 ast_free(b); 22628 } 22629 22630 return 1; 22631 }
static void clear_sip_domains | ( | void | ) | [static] |
Clear our domain list (at reload).
Definition at line 22552 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().
22553 { 22554 struct domain *d; 22555 22556 AST_LIST_LOCK(&domain_list); 22557 while ((d = AST_LIST_REMOVE_HEAD(&domain_list, list))) 22558 ast_free(d); 22559 AST_LIST_UNLOCK(&domain_list); 22560 }
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 13667 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 15500 of file chan_sip.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_t_iterator_next, ast_strdup, ast_test_flag, sip_peer::flags, sip_peer::name, peers, and unref_peer().
Referenced by complete_sip_show_peer(), complete_sipnotify(), sip_do_debug(), and sip_prune_realtime().
15501 { 15502 char *result = NULL; 15503 int wordlen = strlen(word); 15504 int which = 0; 15505 struct ao2_iterator i = ao2_iterator_init(peers, 0); 15506 struct sip_peer *peer; 15507 15508 while ((peer = ao2_t_iterator_next(&i, "iterate thru peers table"))) { 15509 /* locking of the object is not required because only the name and flags are being compared */ 15510 if (!strncasecmp(word, peer->name, wordlen) && 15511 (!flags2 || ast_test_flag(&peer->flags[1], flags2)) && 15512 ++which > state) 15513 result = ast_strdup(peer->name); 15514 unref_peer(peer, "toss iterator peer ptr before break"); 15515 if (result) { 15516 break; 15517 } 15518 } 15519 ao2_iterator_destroy(&i); 15520 return result; 15521 }
static char * complete_sip_registered_peer | ( | const char * | word, | |
int | state, | |||
int | flags2 | |||
) | [static] |
Do completion on registered peer name.
Definition at line 15524 of file chan_sip.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_t_iterator_next, ast_strdup, ast_test_flag, sip_peer::expire, sip_peer::flags, sip_peer::name, peers, and unref_peer().
Referenced by complete_sip_unregister().
15525 { 15526 char *result = NULL; 15527 int wordlen = strlen(word); 15528 int which = 0; 15529 struct ao2_iterator i; 15530 struct sip_peer *peer; 15531 15532 i = ao2_iterator_init(peers, 0); 15533 while ((peer = ao2_t_iterator_next(&i, "iterate thru peers table"))) { 15534 if (!strncasecmp(word, peer->name, wordlen) && 15535 (!flags2 || ast_test_flag(&peer->flags[1], flags2)) && 15536 ++which > state && peer->expire > 0) 15537 result = ast_strdup(peer->name); 15538 if (result) { 15539 unref_peer(peer, "toss iterator peer ptr before break"); 15540 break; 15541 } 15542 unref_peer(peer, "toss iterator peer ptr"); 15543 } 15544 ao2_iterator_destroy(&i); 15545 return result; 15546 }
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 15549 of file chan_sip.c.
References complete_sipch().
Referenced by sip_show_history().
15550 { 15551 if (pos == 3) 15552 return complete_sipch(line, word, pos, state); 15553 15554 return NULL; 15555 }
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 15558 of file chan_sip.c.
References complete_sip_peer().
Referenced by sip_qualify_peer(), and sip_show_peer().
15559 { 15560 if (pos == 3) { 15561 return complete_sip_peer(word, state, 0); 15562 } 15563 15564 return NULL; 15565 }
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 14849 of file chan_sip.c.
References complete_sip_user().
Referenced by sip_show_user().
14850 { 14851 if (pos == 3) 14852 return complete_sip_user(word, state); 14853 14854 return NULL; 14855 }
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 15568 of file chan_sip.c.
References complete_sip_registered_peer().
Referenced by sip_unregister().
15569 { 15570 if (pos == 2) 15571 return complete_sip_registered_peer(word, state, 0); 15572 15573 return NULL; 15574 }
static char* complete_sip_user | ( | const char * | word, | |
int | state | |||
) | [static] |
Do completion on user name.
Definition at line 14822 of file chan_sip.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock(), ao2_unlock(), ast_strdup, peers, SIP_TYPE_USER, unref_peer(), and user.
Referenced by complete_sip_show_user().
14823 { 14824 char *result = NULL; 14825 int wordlen = strlen(word); 14826 int which = 0; 14827 struct ao2_iterator user_iter; 14828 struct sip_peer *user; 14829 14830 user_iter = ao2_iterator_init(peers, 0); 14831 while ((user = ao2_iterator_next(&user_iter))) { 14832 ao2_lock(user); 14833 if (!(user->type & SIP_TYPE_USER)) { 14834 ao2_unlock(user); 14835 unref_peer(user, "complete sip user"); 14836 continue; 14837 } 14838 /* locking of the object is not required because only the name and flags are being compared */ 14839 if (!strncasecmp(word, user->name, wordlen) && ++which > state) { 14840 result = ast_strdup(user->name); 14841 } 14842 ao2_unlock(user); 14843 unref_peer(user, "complete sip user"); 14844 } 14845 ao2_iterator_destroy(&user_iter); 14846 return result; 14847 }
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 15470 of file chan_sip.c.
References ao2_iterator_destroy(), 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().
15471 { 15472 int which=0; 15473 struct sip_pvt *cur; 15474 char *c = NULL; 15475 int wordlen = strlen(word); 15476 struct ao2_iterator i; 15477 15478 if (pos != 3) { 15479 return NULL; 15480 } 15481 15482 i = ao2_iterator_init(dialogs, 0); 15483 while ((cur = ao2_t_iterator_next(&i, "iterate thru dialogs"))) { 15484 sip_pvt_lock(cur); 15485 if (!strncasecmp(word, cur->callid, wordlen) && ++which > state) { 15486 c = ast_strdup(cur->callid); 15487 sip_pvt_unlock(cur); 15488 dialog_unref(cur, "drop ref in iterator loop break"); 15489 break; 15490 } 15491 sip_pvt_unlock(cur); 15492 dialog_unref(cur, "drop ref in iterator loop"); 15493 } 15494 ao2_iterator_destroy(&i); 15495 return c; 15496 }
static char * complete_sipnotify | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Support routine for 'sip notify' CLI.
Definition at line 15577 of file chan_sip.c.
References ast_category_browse(), ast_strdup, complete_sip_peer(), and notify_types.
Referenced by sip_cli_notify().
15578 { 15579 char *c = NULL; 15580 15581 if (pos == 2) { 15582 int which = 0; 15583 char *cat = NULL; 15584 int wordlen = strlen(word); 15585 15586 /* do completion for notify type */ 15587 15588 if (!notify_types) 15589 return NULL; 15590 15591 while ( (cat = ast_category_browse(notify_types, cat)) ) { 15592 if (!strncasecmp(word, cat, wordlen) && ++which > state) { 15593 c = ast_strdup(cat); 15594 break; 15595 } 15596 } 15597 return c; 15598 } 15599 15600 if (pos > 2) 15601 return complete_sip_peer(word, state, 0); 15602 15603 return NULL; 15604 }
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 8454 of file chan_sip.c.
References __get_header(), add_header(), and ast_strlen_zero().
Referenced by respprep().
08455 { 08456 int start = 0; 08457 int copied = 0; 08458 for (;;) { 08459 const char *tmp = __get_header(orig, field, &start); 08460 08461 if (ast_strlen_zero(tmp)) 08462 break; 08463 /* Add what we're responding to */ 08464 add_header(req, field, tmp); 08465 copied++; 08466 } 08467 return copied ? 0 : -1; 08468 }
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 8443 of file chan_sip.c.
References add_header(), ast_log(), ast_strlen_zero(), get_header(), and LOG_NOTICE.
Referenced by reqprep(), and respprep().
08444 { 08445 const char *tmp = get_header(orig, field); 08446 08447 if (!ast_strlen_zero(tmp)) /* Add what we're responding to */ 08448 return add_header(req, field, tmp); 08449 ast_log(LOG_NOTICE, "No field '%s' present to copy\n", field); 08450 return -1; 08451 }
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 9756 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().
09757 { 09758 struct ast_str *duplicate = dst->data; 09759 09760 /* First copy stuff */ 09761 memcpy(dst, src, sizeof(*dst)); 09762 dst->data = duplicate; 09763 09764 /* All these + 1's are to account for the need to include the NULL terminator 09765 * Using typical string functions like ast_copy_string or ast_str_set will not 09766 * work in this case because the src's data string is riddled with \0's all over 09767 * the place and so a memcpy is the only way to accurately copy the string 09768 */ 09769 09770 if (!dst->data && !(dst->data = ast_str_create(src->data->used + 1))) 09771 return; 09772 else if (dst->data->len < src->data->used + 1) 09773 ast_str_make_space(&dst->data, src->data->used + 1); 09774 09775 memcpy(dst->data->str, src->data->str, src->data->used + 1); 09776 dst->data->used = src->data->used; 09777 }
static void copy_socket_data | ( | struct sip_socket * | to_sock, | |
const struct sip_socket * | from_sock | |||
) | [static] |
Definition at line 4706 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().
04707 { 04708 if (to_sock->tcptls_session) { 04709 ao2_ref(to_sock->tcptls_session, -1); 04710 to_sock->tcptls_session = NULL; 04711 } 04712 04713 if (from_sock->tcptls_session) { 04714 ao2_ref(from_sock->tcptls_session, +1); 04715 } 04716 04717 *to_sock = *from_sock; 04718 }
static struct ast_variable* copy_vars | ( | struct ast_variable * | src | ) | [static] |
duplicate a list of channel variables,
Definition at line 13117 of file chan_sip.c.
References ast_variable_new(), and ast_variable::next.
Referenced by check_peer_ok().
13118 { 13119 struct ast_variable *res = NULL, *tmp, *v = NULL; 13120 13121 for (v = src ; v ; v = v->next) { 13122 if ((tmp = ast_variable_new(v->name, v->value, v->file))) { 13123 tmp->next = res; 13124 res = tmp; 13125 } 13126 } 13127 return res; 13128 }
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 8478 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().
08479 { 08480 int copied = 0; 08481 int start = 0; 08482 08483 for (;;) { 08484 char new[512]; 08485 const char *oh = __get_header(orig, field, &start); 08486 08487 if (ast_strlen_zero(oh)) 08488 break; 08489 08490 if (!copied) { /* Only check for empty rport in topmost via header */ 08491 char leftmost[512], *others, *rport; 08492 08493 /* Only work on leftmost value */ 08494 ast_copy_string(leftmost, oh, sizeof(leftmost)); 08495 others = strchr(leftmost, ','); 08496 if (others) 08497 *others++ = '\0'; 08498 08499 /* Find ;rport; (empty request) */ 08500 rport = strstr(leftmost, ";rport"); 08501 if (rport && *(rport+6) == '=') 08502 rport = NULL; /* We already have a parameter to rport */ 08503 08504 /* Check rport if NAT=yes or NAT=rfc3581 (which is the default setting) */ 08505 if (rport && ((ast_test_flag(&p->flags[0], SIP_NAT) == SIP_NAT_ALWAYS) || (ast_test_flag(&p->flags[0], SIP_NAT) == SIP_NAT_RFC3581))) { 08506 /* We need to add received port - rport */ 08507 char *end; 08508 08509 rport = strstr(leftmost, ";rport"); 08510 08511 if (rport) { 08512 end = strchr(rport + 1, ';'); 08513 if (end) 08514 memmove(rport, end, strlen(end) + 1); 08515 else 08516 *rport = '\0'; 08517 } 08518 08519 /* Add rport to first VIA header if requested */ 08520 snprintf(new, sizeof(new), "%s;received=%s;rport=%d%s%s", 08521 leftmost, ast_inet_ntoa(p->recv.sin_addr), 08522 ntohs(p->recv.sin_port), 08523 others ? "," : "", others ? others : ""); 08524 } else { 08525 /* We should *always* add a received to the topmost via */ 08526 snprintf(new, sizeof(new), "%s;received=%s%s%s", 08527 leftmost, ast_inet_ntoa(p->recv.sin_addr), 08528 others ? "," : "", others ? others : ""); 08529 } 08530 oh = new; /* the header to copy */ 08531 } /* else add the following via headers untouched */ 08532 add_header(req, field, oh); 08533 copied++; 08534 } 08535 if (!copied) { 08536 ast_log(LOG_NOTICE, "No header field '%s' present to copy\n", field); 08537 return -1; 08538 } 08539 return 0; 08540 }
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 4868 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, port_str2int(), sip_pvt::portinuri, sip_pvt::recv, ref_proxy(), sip_pvt::sa, service, set_socket_transport(), 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().
04869 { 04870 struct hostent *hp; 04871 struct ast_hostent ahp; 04872 struct sip_peer *peer; 04873 char *port; 04874 int portno = 0; 04875 char host[MAXHOSTNAMELEN], *hostn; 04876 char peername[256]; 04877 int srv_ret = 0; 04878 04879 ast_copy_string(peername, opeer, sizeof(peername)); 04880 port = strchr(peername, ':'); 04881 if (port) { 04882 *port++ = '\0'; 04883 dialog->portinuri = 1; 04884 } 04885 dialog->sa.sin_family = AF_INET; 04886 dialog->timer_t1 = global_t1; /* Default SIP retransmission timer T1 (RFC 3261) */ 04887 dialog->timer_b = global_timer_b; /* Default SIP transaction timer B (RFC 3261) */ 04888 peer = find_peer(peername, NULL, TRUE, FINDPEERS, FALSE, 0); 04889 04890 if (peer) { 04891 int res; 04892 if (newdialog) { 04893 set_socket_transport(&dialog->socket, 0); 04894 } 04895 res = create_addr_from_peer(dialog, peer); 04896 if (!ast_strlen_zero(port)) { 04897 if ((portno = atoi(port))) { 04898 dialog->sa.sin_port = dialog->recv.sin_port = htons(portno); 04899 } 04900 } 04901 unref_peer(peer, "create_addr: unref peer from find_peer hashtab lookup"); 04902 return res; 04903 } 04904 04905 do_setnat(dialog, ast_test_flag(&dialog->flags[0], SIP_NAT) & SIP_NAT_ROUTE); 04906 04907 ast_string_field_set(dialog, tohost, peername); 04908 04909 /* Get the outbound proxy information */ 04910 ref_proxy(dialog, obproxy_get(dialog, NULL)); 04911 04912 if (sin) { 04913 /* This address should be updated using dnsmgr */ 04914 memcpy(&dialog->sa.sin_addr, &sin->sin_addr, sizeof(dialog->sa.sin_addr)); 04915 if (!sin->sin_port) { 04916 portno = port_str2int(port, (dialog->socket.type == SIP_TRANSPORT_TLS) ? STANDARD_TLS_PORT : STANDARD_SIP_PORT); 04917 } else { 04918 portno = ntohs(sin->sin_port); 04919 } 04920 } else { 04921 04922 /* Let's see if we can find the host in DNS. First try DNS SRV records, 04923 then hostname lookup */ 04924 /*! \todo Fix this function. When we ask SRC, we should check all transports 04925 In the future, we should first check NAPTR to find out transport preference 04926 */ 04927 hostn = peername; 04928 /* Section 4.2 of RFC 3263 specifies that if a port number is specified, then 04929 * an A record lookup should be used instead of SRV. 04930 */ 04931 if (!port && global_srvlookup) { 04932 char service[MAXHOSTNAMELEN]; 04933 int tportno; 04934 04935 snprintf(service, sizeof(service), "_sip._%s.%s", get_transport(dialog->socket.type), peername); 04936 srv_ret = ast_get_srv(NULL, host, sizeof(host), &tportno, service); 04937 if (srv_ret > 0) { 04938 hostn = host; 04939 portno = tportno; 04940 } 04941 } 04942 if (!portno) 04943 portno = port_str2int(port, (dialog->socket.type == SIP_TRANSPORT_TLS) ? STANDARD_TLS_PORT : STANDARD_SIP_PORT); 04944 hp = ast_gethostbyname(hostn, &ahp); 04945 if (!hp) { 04946 ast_log(LOG_WARNING, "No such host: %s\n", peername); 04947 return -1; 04948 } 04949 memcpy(&dialog->sa.sin_addr, hp->h_addr, sizeof(dialog->sa.sin_addr)); 04950 } 04951 04952 if (!dialog->socket.type) 04953 set_socket_transport(&dialog->socket, SIP_TRANSPORT_UDP); 04954 if (!dialog->socket.port) 04955 dialog->socket.port = bindaddr.sin_port; 04956 dialog->sa.sin_port = htons(portno); 04957 dialog->recv = dialog->sa; 04958 return 0; 04959 }
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 4727 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, 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, 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::portinuri, sip_pvt::portinuri, 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_peer::t38_maxdatagram, sip_pvt::t38_maxdatagram, 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().
04728 { 04729 /* this checks that the dialog is contacting the peer on a valid 04730 * transport type based on the peers transport configuration, 04731 * otherwise, this function bails out */ 04732 if (dialog->socket.type && check_request_transport(peer, dialog)) 04733 return -1; 04734 copy_socket_data(&dialog->socket, &peer->socket); 04735 04736 if ((peer->addr.sin_addr.s_addr || peer->defaddr.sin_addr.s_addr) && 04737 (!peer->maxms || ((peer->lastms >= 0) && (peer->lastms <= peer->maxms)))) { 04738 dialog->sa = (peer->addr.sin_addr.s_addr) ? peer->addr : peer->defaddr; 04739 dialog->recv = dialog->sa; 04740 } else 04741 return -1; 04742 04743 ast_copy_flags(&dialog->flags[0], &peer->flags[0], SIP_FLAGS_TO_COPY); 04744 ast_copy_flags(&dialog->flags[1], &peer->flags[1], SIP_PAGE2_FLAGS_TO_COPY); 04745 dialog->capability = peer->capability; 04746 if (!ast_test_flag(&dialog->flags[1], SIP_PAGE2_VIDEOSUPPORT_ALWAYS) && 04747 (!ast_test_flag(&dialog->flags[1], SIP_PAGE2_VIDEOSUPPORT) || 04748 !(dialog->capability & AST_FORMAT_VIDEO_MASK)) && 04749 dialog->vrtp) { 04750 ast_rtp_destroy(dialog->vrtp); 04751 dialog->vrtp = NULL; 04752 } 04753 if (!ast_test_flag(&dialog->flags[1], SIP_PAGE2_TEXTSUPPORT) && dialog->trtp) { 04754 ast_rtp_destroy(dialog->trtp); 04755 dialog->trtp = NULL; 04756 } 04757 dialog->prefs = peer->prefs; 04758 if (ast_test_flag(&dialog->flags[1], SIP_PAGE2_T38SUPPORT)) { 04759 if (!dialog->udptl) { 04760 /* t38pt_udptl was enabled in the peer and not in [general] */ 04761 dialog->udptl = ast_udptl_new_with_bindaddr(sched, io, 0, bindaddr.sin_addr); 04762 } 04763 dialog->t38_maxdatagram = peer->t38_maxdatagram; 04764 set_t38_capabilities(dialog); 04765 } else if (dialog->udptl) { 04766 ast_udptl_destroy(dialog->udptl); 04767 dialog->udptl = NULL; 04768 } 04769 do_setnat(dialog, ast_test_flag(&dialog->flags[0], SIP_NAT) & SIP_NAT_ROUTE); 04770 04771 if (dialog->rtp) { /* Audio */ 04772 ast_rtp_setdtmf(dialog->rtp, ast_test_flag(&dialog->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833); 04773 ast_rtp_setdtmfcompensate(dialog->rtp, ast_test_flag(&dialog->flags[1], SIP_PAGE2_RFC2833_COMPENSATE)); 04774 ast_rtp_set_rtptimeout(dialog->rtp, peer->rtptimeout); 04775 ast_rtp_set_rtpholdtimeout(dialog->rtp, peer->rtpholdtimeout); 04776 ast_rtp_set_rtpkeepalive(dialog->rtp, peer->rtpkeepalive); 04777 /* Set Frame packetization */ 04778 ast_rtp_codec_setpref(dialog->rtp, &dialog->prefs); 04779 dialog->autoframing = peer->autoframing; 04780 } 04781 if (dialog->vrtp) { /* Video */ 04782 ast_rtp_setdtmf(dialog->vrtp, 0); 04783 ast_rtp_setdtmfcompensate(dialog->vrtp, 0); 04784 ast_rtp_set_rtptimeout(dialog->vrtp, peer->rtptimeout); 04785 ast_rtp_set_rtpholdtimeout(dialog->vrtp, peer->rtpholdtimeout); 04786 ast_rtp_set_rtpkeepalive(dialog->vrtp, peer->rtpkeepalive); 04787 } 04788 if (dialog->trtp) { /* Realtime text */ 04789 ast_rtp_setdtmf(dialog->trtp, 0); 04790 ast_rtp_setdtmfcompensate(dialog->trtp, 0); 04791 ast_rtp_set_rtptimeout(dialog->trtp, peer->rtptimeout); 04792 ast_rtp_set_rtpholdtimeout(dialog->trtp, peer->rtpholdtimeout); 04793 ast_rtp_set_rtpkeepalive(dialog->trtp, peer->rtpkeepalive); 04794 } 04795 04796 ast_string_field_set(dialog, peername, peer->name); 04797 ast_string_field_set(dialog, authname, peer->username); 04798 ast_string_field_set(dialog, username, peer->username); 04799 ast_string_field_set(dialog, peersecret, peer->secret); 04800 ast_string_field_set(dialog, peermd5secret, peer->md5secret); 04801 ast_string_field_set(dialog, mohsuggest, peer->mohsuggest); 04802 ast_string_field_set(dialog, mohinterpret, peer->mohinterpret); 04803 ast_string_field_set(dialog, tohost, peer->tohost); 04804 ast_string_field_set(dialog, fullcontact, peer->fullcontact); 04805 ast_string_field_set(dialog, context, peer->context); 04806 ast_string_field_set(dialog, parkinglot, peer->parkinglot); 04807 ref_proxy(dialog, obproxy_get(dialog, peer)); 04808 dialog->callgroup = peer->callgroup; 04809 dialog->pickupgroup = peer->pickupgroup; 04810 dialog->allowtransfer = peer->allowtransfer; 04811 dialog->jointnoncodeccapability = dialog->noncodeccapability; 04812 dialog->rtptimeout = peer->rtptimeout; 04813 dialog->peerauth = peer->auth; 04814 dialog->maxcallbitrate = peer->maxcallbitrate; 04815 if (ast_strlen_zero(dialog->tohost)) 04816 ast_string_field_set(dialog, tohost, ast_inet_ntoa(dialog->sa.sin_addr)); 04817 if (!ast_strlen_zero(peer->fromdomain)) { 04818 ast_string_field_set(dialog, fromdomain, peer->fromdomain); 04819 if (!dialog->initreq.headers) { 04820 char *c; 04821 char *tmpcall = ast_strdupa(dialog->callid); 04822 /* this sure looks to me like we are going to change the callid on this dialog!! */ 04823 c = strchr(tmpcall, '@'); 04824 if (c) { 04825 *c = '\0'; 04826 ao2_t_unlink(dialogs, dialog, "About to change the callid -- remove the old name"); 04827 ast_string_field_build(dialog, callid, "%s@%s", tmpcall, peer->fromdomain); 04828 ao2_t_link(dialogs, dialog, "New dialog callid -- inserted back into table"); 04829 } 04830 } 04831 } 04832 if (!ast_strlen_zero(peer->fromuser)) 04833 ast_string_field_set(dialog, fromuser, peer->fromuser); 04834 if (!ast_strlen_zero(peer->language)) 04835 ast_string_field_set(dialog, language, peer->language); 04836 /* Set timer T1 to RTT for this peer (if known by qualify=) */ 04837 /* Minimum is settable or default to 100 ms */ 04838 /* If there is a maxms and lastms from a qualify use that over a manual T1 04839 value. Otherwise, use the peer's T1 value. */ 04840 if (peer->maxms && peer->lastms) 04841 dialog->timer_t1 = peer->lastms < global_t1min ? global_t1min : peer->lastms; 04842 else 04843 dialog->timer_t1 = peer->timer_t1; 04844 04845 /* Set timer B to control transaction timeouts, the peer setting is the default and overrides 04846 the known timer */ 04847 if (peer->timer_b) 04848 dialog->timer_b = peer->timer_b; 04849 else 04850 dialog->timer_b = 64 * dialog->timer_t1; 04851 04852 if ((ast_test_flag(&dialog->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833) || 04853 (ast_test_flag(&dialog->flags[0], SIP_DTMF) == SIP_DTMF_AUTO)) 04854 dialog->noncodeccapability |= AST_RTP_DTMF; 04855 else 04856 dialog->noncodeccapability &= ~AST_RTP_DTMF; 04857 if (peer->call_limit) 04858 ast_set_flag(&dialog->flags[0], SIP_CALL_LIMIT); 04859 if (!dialog->portinuri) 04860 dialog->portinuri = peer->portinuri; 04861 04862 return 0; 04863 }
static void destroy_association | ( | struct sip_peer * | peer | ) | [static] |
Remove registration data from realtime database or AST/DB when registration expires.
Definition at line 11200 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().
11201 { 11202 int realtimeregs = ast_check_realtime("sipregs"); 11203 char *tablename = (realtimeregs) ? "sipregs" : "sippeers"; 11204 11205 if (!sip_cfg.ignore_regexpire) { 11206 if (peer->rt_fromcontact && sip_cfg.peer_rtupdate) { 11207 ast_update_realtime(tablename, "name", peer->name, "fullcontact", "", "ipaddr", "", "port", "", "regseconds", "0", peer->deprecated_username ? "username" : "defaultuser", "", "regserver", "", "useragent", "", "lastms", "", SENTINEL); 11208 } else { 11209 ast_db_del("SIP/Registry", peer->name); 11210 } 11211 } 11212 }
static void destroy_mailbox | ( | struct sip_mailbox * | mailbox | ) | [static] |
Destroy mailbox subscriptions
Definition at line 4238 of file chan_sip.c.
References ast_event_unsubscribe(), ast_free, and mailbox.
Referenced by clear_peer_mailboxes().
04239 { 04240 if (mailbox->mailbox) 04241 ast_free(mailbox->mailbox); 04242 if (mailbox->context) 04243 ast_free(mailbox->context); 04244 if (mailbox->event_sub) 04245 ast_event_unsubscribe(mailbox->event_sub); 04246 ast_free(mailbox); 04247 }
static int determine_firstline_parts | ( | struct sip_request * | req | ) | [static] |
Parse first line of incoming SIP request.
Definition at line 9810 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.
09811 { 09812 char *e = ast_skip_blanks(req->data->str); /* there shouldn't be any */ 09813 char *local_rlPart1; 09814 09815 if (!*e) 09816 return -1; 09817 req->rlPart1 = e - req->data->str; /* method or protocol */ 09818 local_rlPart1 = e; 09819 e = ast_skip_nonblanks(e); 09820 if (*e) 09821 *e++ = '\0'; 09822 /* Get URI or status code */ 09823 e = ast_skip_blanks(e); 09824 if ( !*e ) 09825 return -1; 09826 ast_trim_blanks(e); 09827 09828 if (!strcasecmp(local_rlPart1, "SIP/2.0") ) { /* We have a response */ 09829 if (strlen(e) < 3) /* status code is 3 digits */ 09830 return -1; 09831 req->rlPart2 = e - req->data->str; 09832 } else { /* We have a request */ 09833 if ( *e == '<' ) { /* XXX the spec says it must not be in <> ! */ 09834 ast_debug(3, "Oops. Bogus uri in <> %s\n", e); 09835 e++; 09836 if (!*e) 09837 return -1; 09838 } 09839 req->rlPart2 = e - req->data->str; /* URI */ 09840 e = ast_skip_nonblanks(e); 09841 if (*e) 09842 *e++ = '\0'; 09843 e = ast_skip_blanks(e); 09844 if (strcasecmp(e, "SIP/2.0") ) { 09845 ast_debug(3, "Skipping packet - Bad request protocol %s\n", e); 09846 return -1; 09847 } 09848 } 09849 return 1; 09850 }
static int dialog_cmp_cb | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 1793 of file chan_sip.c.
References sip_pvt::callid, CMP_MATCH, and CMP_STOP.
Referenced by load_module().
01794 { 01795 struct sip_pvt *pvt = obj, *pvt2 = arg; 01796 01797 return !strcasecmp(pvt->callid, pvt2->callid) ? CMP_MATCH | CMP_STOP : 0; 01798 }
static int dialog_dump_func | ( | void * | userobj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 14072 of file chan_sip.c.
References ao2_t_ref, ast_cli(), and sip_pvt::callid.
Referenced by sip_show_objects().
14073 { 14074 struct sip_pvt *pvt = userobj; 14075 int refc = ao2_t_ref(userobj, 0, ""); 14076 int *fd = arg; 14077 14078 ast_cli(*fd, "name: %s\ntype: dialog\nobjflags: %d\nrefcount: %d\n\n", 14079 pvt->callid, 0, refc); 14080 return 0; 14081 }
static int dialog_hash_cb | ( | const void * | obj, | |
const int | flags | |||
) | [static] |
Definition at line 1783 of file chan_sip.c.
References ast_str_case_hash(), and sip_pvt::callid.
Referenced by load_module().
01784 { 01785 const struct sip_pvt *pvt = obj; 01786 01787 return ast_str_case_hash(pvt->callid); 01788 }
static int dialog_needdestroy | ( | void * | dialogobj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 14187 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().
14188 { 14189 struct sip_pvt *dialog = dialogobj; 14190 time_t *t = arg; 14191 14192 /* log_show_lock(ao2_object_get_lockaddr(dialog)); this is an example of how to use log_show_lock() */ 14193 14194 if (sip_pvt_trylock(dialog)) { 14195 /* In very short-duration calls via sipp, 14196 this path gets executed fairly frequently (3% or so) even in low load 14197 situations; the routines we most commonly fight for a lock with: 14198 sip_answer (7 out of 9) 14199 sip_hangup (2 out of 9) 14200 */ 14201 ao2_unlock(dialogs); 14202 usleep(1); 14203 ao2_lock(dialogs); 14204 14205 /* I had previously returned CMP_STOP here; but changed it to return 14206 a zero instead, because there is no need to stop at the first sign 14207 of trouble. The old algorithm would restart in such circumstances, 14208 but there is no need for this now in astobj2-land. We'll 14209 just skip over this element this time, and catch it on the 14210 next traversal, which is about once a second or so. See the 14211 ao2_callback call in do_monitor. We don't want the number of 14212 dialogs to back up too much between runs. 14213 */ 14214 return 0; 14215 } 14216 14217 /* Check RTP timeouts and kill calls if we have a timeout set and do not get RTP */ 14218 check_rtp_timeout(dialog, *t); 14219 14220 /* If we have sessions that needs to be destroyed, do it now */ 14221 /* Check if we have outstanding requests not responsed to or an active call 14222 - if that's the case, wait with destruction */ 14223 if (dialog->needdestroy && !dialog->packets && !dialog->owner) { 14224 /* We absolutely cannot destroy the rtp struct while a bridge is active or we WILL crash */ 14225 if (dialog->rtp && ast_rtp_get_bridged(dialog->rtp)) { 14226 ast_debug(2, "Bridge still active. Delaying destruction of SIP dialog '%s' Method: %s\n", dialog->callid, sip_methods[dialog->method].text); 14227 sip_pvt_unlock(dialog); 14228 return 0; 14229 } 14230 14231 if (dialog->vrtp && ast_rtp_get_bridged(dialog->vrtp)) { 14232 ast_debug(2, "Bridge still active. Delaying destroy of SIP dialog '%s' Method: %s\n", dialog->callid, sip_methods[dialog->method].text); 14233 sip_pvt_unlock(dialog); 14234 return 0; 14235 } 14236 14237 sip_pvt_unlock(dialog); 14238 /* no, the unlink should handle this: dialog_unref(dialog, "needdestroy: one more refcount decrement to allow dialog to be destroyed"); */ 14239 /* the CMP_MATCH will unlink this dialog from the dialog hash table */ 14240 dialog_unlink_all(dialog, TRUE, FALSE); 14241 return 0; /* the unlink_all should unlink this from the table, so.... no need to return a match */ 14242 } 14243 14244 sip_pvt_unlock(dialog); 14245 14246 return 0; 14247 }
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(), transmit_register(), and update_provisional_keepalive().
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 2793 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, sip_pkt::data, 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::provisional_keepalive_sched_id, 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().
02794 { 02795 struct sip_pkt *cp; 02796 02797 dialog_ref(dialog, "Let's bump the count in the unlink so it doesn't accidentally become dead before we are done"); 02798 02799 ao2_t_unlink(dialogs, dialog, "unlinking dialog via ao2_unlink"); 02800 02801 /* Unlink us from the owner (channel) if we have one */ 02802 if (dialog->owner) { 02803 if (lockowner) 02804 ast_channel_lock(dialog->owner); 02805 ast_debug(1, "Detaching from channel %s\n", dialog->owner->name); 02806 dialog->owner->tech_pvt = dialog_unref(dialog->owner->tech_pvt, "resetting channel dialog ptr in unlink_all"); 02807 if (lockowner) 02808 ast_channel_unlock(dialog->owner); 02809 } 02810 if (dialog->registry) { 02811 if (dialog->registry->call == dialog) 02812 dialog->registry->call = dialog_unref(dialog->registry->call, "nulling out the registry's call dialog field in unlink_all"); 02813 dialog->registry = registry_unref(dialog->registry, "delete dialog->registry"); 02814 } 02815 if (dialog->stateid > -1) { 02816 ast_extension_state_del(dialog->stateid, NULL); 02817 dialog_unref(dialog, "removing extension_state, should unref the associated dialog ptr that was stored there."); 02818 dialog->stateid = -1; /* shouldn't we 'zero' this out? */ 02819 } 02820 /* Remove link from peer to subscription of MWI */ 02821 if (dialog->relatedpeer && dialog->relatedpeer->mwipvt == dialog) 02822 dialog->relatedpeer->mwipvt = dialog_unref(dialog->relatedpeer->mwipvt, "delete ->relatedpeer->mwipvt"); 02823 if (dialog->relatedpeer && dialog->relatedpeer->call == dialog) 02824 dialog->relatedpeer->call = dialog_unref(dialog->relatedpeer->call, "unset the relatedpeer->call field in tandem with relatedpeer field itself"); 02825 02826 /* remove all current packets in this dialog */ 02827 while((cp = dialog->packets)) { 02828 dialog->packets = dialog->packets->next; 02829 AST_SCHED_DEL(sched, cp->retransid); 02830 dialog_unref(cp->owner, "remove all current packets in this dialog, and the pointer to the dialog too as part of __sip_destroy"); 02831 if (cp->data) { 02832 ast_free(cp->data); 02833 } 02834 ast_free(cp); 02835 } 02836 02837 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")); 02838 02839 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")); 02840 02841 if (dialog->autokillid > -1) 02842 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")); 02843 02844 if (dialog->request_queue_sched_id > -1) { 02845 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")); 02846 } 02847 02848 AST_SCHED_DEL_UNREF(sched, dialog->provisional_keepalive_sched_id, dialog_unref(dialog, "when you delete the provisional_keepalive_sched_id, you should dec the refcount for the stored dialog ptr")); 02849 02850 if (dialog->t38id > -1) { 02851 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")); 02852 } 02853 02854 dialog_unref(dialog, "Let's unbump the count in the unlink so the poor pvt can disappear if it is time"); 02855 return NULL; 02856 }
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(), interpret_t38_parameters(), manager_sipnotify(), proc_session_timer(), queue_request(), reload_config(), restart_session_timer(), retrans_pkt(), send_response(), sip_call(), sip_cancel_destroy(), sip_cli_notify(), sip_destroy_peer(), sip_hangup(), 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(), transmit_register(), and update_provisional_keepalive().
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 21499 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, and sipsock_read().
21500 { 21501 int res; 21502 time_t t; 21503 int reloading; 21504 21505 /* Add an I/O event to our SIP UDP socket */ 21506 if (sipsock > -1) 21507 sipsock_read_id = ast_io_add(io, sipsock, sipsock_read, AST_IO_IN, NULL); 21508 21509 /* From here on out, we die whenever asked */ 21510 for(;;) { 21511 /* Check for a reload request */ 21512 ast_mutex_lock(&sip_reload_lock); 21513 reloading = sip_reloading; 21514 sip_reloading = FALSE; 21515 ast_mutex_unlock(&sip_reload_lock); 21516 if (reloading) { 21517 ast_verb(1, "Reloading SIP\n"); 21518 sip_do_reload(sip_reloadreason); 21519 21520 /* Change the I/O fd of our UDP socket */ 21521 if (sipsock > -1) { 21522 if (sipsock_read_id) 21523 sipsock_read_id = ast_io_change(io, sipsock_read_id, sipsock, NULL, 0, NULL); 21524 else 21525 sipsock_read_id = ast_io_add(io, sipsock, sipsock_read, AST_IO_IN, NULL); 21526 } else if (sipsock_read_id) { 21527 ast_io_remove(io, sipsock_read_id); 21528 sipsock_read_id = NULL; 21529 } 21530 } 21531 21532 /* Check for dialogs needing to be killed */ 21533 t = time(NULL); 21534 /* don't scan the dialogs list if it hasn't been a reasonable period 21535 of time since the last time we did it (when MWI is being sent, we can 21536 get back to this point every millisecond or less) 21537 */ 21538 ao2_t_callback(dialogs, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, dialog_needdestroy, &t, 21539 "callback to remove dialogs w/needdestroy"); 21540 21541 /* the old methodology would be to restart the search for dialogs to delete with every 21542 dialog that was found and destroyed, probably because the list contents would change, 21543 so we'd need to restart. This isn't the best thing to do with callbacks. */ 21544 21545 /* XXX TODO The scheduler usage in this module does not have sufficient 21546 * synchronization being done between running the scheduler and places 21547 * scheduling tasks. As it is written, any scheduled item may not run 21548 * any sooner than about 1 second, regardless of whether a sooner time 21549 * was asked for. */ 21550 21551 pthread_testcancel(); 21552 /* Wait for sched or io */ 21553 res = ast_sched_wait(sched); 21554 if ((res < 0) || (res > 1000)) 21555 res = 1000; 21556 res = ast_io_wait(io, res); 21557 if (res > 20) 21558 ast_debug(1, "chan_sip: ast_io_wait ran %d all at once\n", res); 21559 ast_mutex_lock(&monlock); 21560 res = ast_sched_runq(sched); 21561 if (res >= 20) 21562 ast_debug(1, "chan_sip: ast_sched_runq ran %d all at once\n", res); 21563 ast_mutex_unlock(&monlock); 21564 } 21565 21566 /* Never reached */ 21567 return NULL; 21568 }
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 16235 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().
16236 { 16237 char *header, *respheader; 16238 char digest[1024]; 16239 16240 if (!p->options && !(p->options = ast_calloc(1, sizeof(*p->options)))) 16241 return -2; 16242 16243 p->authtries++; 16244 auth_headers(code, &header, &respheader); 16245 ast_debug(2, "Auth attempt %d on %s\n", p->authtries, sip_methods[sipmethod].text); 16246 memset(digest, 0, sizeof(digest)); 16247 if (reply_digest(p, req, header, sipmethod, digest, sizeof(digest) )) { 16248 /* No way to authenticate */ 16249 return -1; 16250 } 16251 /* Now we have a reply digest */ 16252 p->options->auth = digest; 16253 p->options->authheader = respheader; 16254 return transmit_invite(p, sipmethod, sipmethod == SIP_INVITE, init); 16255 }
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 16211 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().
16212 { 16213 char *header, *respheader; 16214 char digest[1024]; 16215 16216 p->authtries++; 16217 auth_headers(code, &header, &respheader); 16218 memset(digest, 0, sizeof(digest)); 16219 if (reply_digest(p, req, header, SIP_REGISTER, digest, sizeof(digest))) { 16220 /* There's nothing to use for authentication */ 16221 /* No digest challenge in request */ 16222 if (sip_debug_test_pvt(p) && p->registry) 16223 ast_verbose("No authentication challenge, sending blank registration to domain/host name %s\n", p->registry->hostname); 16224 /* No old challenge */ 16225 return -1; 16226 } 16227 if (p->do_history) 16228 append_history(p, "RegistryAuth", "Try: %d", p->authtries); 16229 if (sip_debug_test_pvt(p) && p->registry) 16230 ast_verbose("Responding to challenge, registration to domain/host name %s\n", p->registry->hostname); 16231 return transmit_register(p->registry, SIP_REGISTER, digest, respheader); 16232 }
static void do_setnat | ( | struct sip_pvt * | p, | |
int | natflags | |||
) | [static] |
Set nat mode on the various data sockets.
Definition at line 4621 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().
04622 { 04623 const char *mode = natflags ? "On" : "Off"; 04624 04625 if (p->rtp) { 04626 ast_debug(1, "Setting NAT on RTP to %s\n", mode); 04627 ast_rtp_setnat(p->rtp, natflags); 04628 } 04629 if (p->vrtp) { 04630 ast_debug(1, "Setting NAT on VRTP to %s\n", mode); 04631 ast_rtp_setnat(p->vrtp, natflags); 04632 } 04633 if (p->udptl) { 04634 ast_debug(1, "Setting NAT on UDPTL to %s\n", mode); 04635 ast_udptl_setnat(p->udptl, natflags); 04636 } 04637 if (p->trtp) { 04638 ast_debug(1, "Setting NAT on TRTP to %s\n", mode); 04639 ast_rtp_setnat(p->trtp, natflags); 04640 } 04641 }
static const char * domain_mode_to_text | ( | const enum domain_mode | mode | ) | [static] |
Print domain mode to cli.
Definition at line 14405 of file chan_sip.c.
References SIP_DOMAIN_AUTO, and SIP_DOMAIN_CONFIG.
Referenced by sip_show_domains().
14406 { 14407 switch (mode) { 14408 case SIP_DOMAIN_AUTO: 14409 return "[Automatic]"; 14410 case SIP_DOMAIN_CONFIG: 14411 return "[Configured]"; 14412 } 14413 14414 return ""; 14415 }
static const char * dtmfmode2str | ( | int | mode | ) | const [static] |
Convert DTMF mode to printable string.
Definition at line 14128 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 11228 of file chan_sip.c.
References sip_peer::addr, ao2_ref, ao2_t_unlink, ast_debug, AST_DEVICE_UNKNOWN, ast_devstate_changed(), ast_test_flag, sip_peer::default_outbound_transport, destroy_association(), EVENT_FLAG_SYSTEM, sip_peer::expire, FALSE, sip_peer::flags, sip_peer::is_realtime, manager_event, sip_peer::name, peers, peers_by_ip, sip_peer::portinuri, register_peer_exten(), sip_peer::selfdestruct, set_socket_transport(), SIP_PAGE2_RTAUTOCLEAR, sip_peer::socket, sip_socket::tcptls_session, and unref_peer().
Referenced by parse_register_contact(), reg_source_db(), sip_show_sched(), and sip_unregister().
11229 { 11230 struct sip_peer *peer = (struct sip_peer *)data; 11231 11232 if (!peer) /* Hmmm. We have no peer. Weird. */ 11233 return 0; 11234 11235 peer->expire = -1; 11236 peer->portinuri = 0; 11237 memset(&peer->addr, 0, sizeof(peer->addr)); 11238 11239 destroy_association(peer); /* remove registration data from storage */ 11240 set_socket_transport(&peer->socket, peer->default_outbound_transport); 11241 11242 if (peer->socket.tcptls_session) { 11243 ao2_ref(peer->socket.tcptls_session, -1); 11244 peer->socket.tcptls_session = NULL; 11245 } 11246 11247 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: SIP\r\nPeer: SIP/%s\r\nPeerStatus: Unregistered\r\nCause: Expired\r\n", peer->name); 11248 register_peer_exten(peer, FALSE); /* Remove regexten */ 11249 ast_devstate_changed(AST_DEVICE_UNKNOWN, "SIP/%s", peer->name); 11250 11251 /* Do we need to release this peer from memory? 11252 Only for realtime peers and autocreated peers 11253 */ 11254 if (peer->is_realtime) 11255 ast_debug(3, "-REALTIME- peer expired registration. Name: %s. Realtime peer objects now %d\n", peer->name, rpeerobjs); 11256 11257 if (peer->selfdestruct || 11258 ast_test_flag(&peer->flags[1], SIP_PAGE2_RTAUTOCLEAR)) { 11259 ao2_t_unlink(peers, peer, "ao2_unlink of peer from peers table"); 11260 if (peer->addr.sin_addr.s_addr) { 11261 ao2_t_unlink(peers_by_ip, peer, "ao2_unlink of peer from peers_by_ip table"); 11262 } 11263 } 11264 11265 unref_peer(peer, "removing peer ref for expire_register"); 11266 11267 return 0; 11268 }
static void extract_uri | ( | struct sip_pvt * | p, | |
struct sip_request * | req | |||
) | [static] |
Check Contact: URI of SIP message.
Definition at line 9911 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().
09912 { 09913 char stripped[SIPBUFSIZE]; 09914 char *c; 09915 09916 ast_copy_string(stripped, get_header(req, "Contact"), sizeof(stripped)); 09917 c = get_in_brackets(stripped); 09918 /* Cut the URI at the at sign after the @, not in the username part */ 09919 c = remove_uri_parameters(c); 09920 if (!ast_strlen_zero(c)) 09921 ast_string_field_set(p, uri, c); 09922 09923 }
static const char* faxec2str | ( | int | faxec | ) | [static] |
Definition at line 14575 of file chan_sip.c.
References faxecmodes, and map_x_s().
Referenced by _sip_show_peer(), and sip_show_settings().
14576 { 14577 return map_x_s(faxecmodes, faxec, "Unknown"); 14578 }
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 6457 of file chan_sip.c.
References aliases, and ARRAY_LEN.
06458 { 06459 /*! \brief Structure for conversion between compressed SIP and "normal" SIP */ 06460 static const struct cfalias { 06461 char * const fullname; 06462 char * const shortname; 06463 } aliases[] = { 06464 { "Content-Type", "c" }, 06465 { "Content-Encoding", "e" }, 06466 { "From", "f" }, 06467 { "Call-ID", "i" }, 06468 { "Contact", "m" }, 06469 { "Content-Length", "l" }, 06470 { "Subject", "s" }, 06471 { "To", "t" }, 06472 { "Supported", "k" }, 06473 { "Refer-To", "r" }, 06474 { "Referred-By", "b" }, 06475 { "Allow-Events", "u" }, 06476 { "Event", "o" }, 06477 { "Via", "v" }, 06478 { "Accept-Contact", "a" }, 06479 { "Reject-Contact", "j" }, 06480 { "Request-Disposition", "d" }, 06481 { "Session-Expires", "x" }, 06482 { "Identity", "y" }, 06483 { "Identity-Info", "n" }, 06484 }; 06485 int x; 06486 06487 for (x = 0; x < ARRAY_LEN(aliases); x++) { 06488 if (!strcasecmp(aliases[x].fullname, name)) 06489 return aliases[x].shortname; 06490 } 06491 06492 return _default; 06493 }
static int find_by_name | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 4547 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().
04548 { 04549 struct sip_peer *search = obj; 04550 struct peer_finding_info *pfi = arg; 04551 04552 /* Usernames in SIP uri's are case sensitive. Domains are not */ 04553 if (strcmp(search->name, pfi->tmp_peer.name)) { 04554 return 0; 04555 } 04556 04557 switch (pfi->which_objects) { 04558 case FINDUSERS: 04559 if (!(search->type & SIP_TYPE_USER)) { 04560 return 0; 04561 } 04562 break; 04563 case FINDPEERS: 04564 if (!(search->type & SIP_TYPE_PEER)) { 04565 return 0; 04566 } 04567 break; 04568 case FINDALLDEVICES: 04569 break; 04570 } 04571 04572 return CMP_MATCH | CMP_STOP; 04573 }
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 6934 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().
06935 { 06936 struct sip_pvt *p = NULL; 06937 char *tag = ""; /* note, tag is never NULL */ 06938 char totag[128]; 06939 char fromtag[128]; 06940 struct find_call_cb_arg arg; 06941 const char *callid = get_header(req, "Call-ID"); 06942 const char *from = get_header(req, "From"); 06943 const char *to = get_header(req, "To"); 06944 const char *cseq = get_header(req, "Cseq"); 06945 struct sip_pvt *sip_pvt_ptr; 06946 06947 /* Call-ID, to, from and Cseq are required by RFC 3261. (Max-forwards and via too - ignored now) */ 06948 /* get_header always returns non-NULL so we must use ast_strlen_zero() */ 06949 if (ast_strlen_zero(callid) || ast_strlen_zero(to) || 06950 ast_strlen_zero(from) || ast_strlen_zero(cseq)) 06951 return NULL; /* Invalid packet */ 06952 06953 arg.method = req->method; 06954 arg.callid = callid; 06955 arg.fromtag = fromtag; 06956 arg.totag = totag; 06957 arg.tag = ""; /* make sure tag is never NULL */ 06958 06959 if (pedanticsipchecking) { 06960 /* In principle Call-ID's uniquely identify a call, but with a forking SIP proxy 06961 we need more to identify a branch - so we have to check branch, from 06962 and to tags to identify a call leg. 06963 For Asterisk to behave correctly, you need to turn on pedanticsipchecking 06964 in sip.conf 06965 */ 06966 if (gettag(req, "To", totag, sizeof(totag))) 06967 req->has_to_tag = 1; /* Used in handle_request/response */ 06968 gettag(req, "From", fromtag, sizeof(fromtag)); 06969 06970 tag = (req->method == SIP_RESPONSE) ? totag : fromtag; 06971 06972 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); 06973 06974 /* All messages must always have From: tag */ 06975 if (ast_strlen_zero(fromtag)) { 06976 ast_debug(5, "%s request has no from tag, dropping callid: %s from: %s\n", sip_methods[req->method].text , callid, from ); 06977 return NULL; 06978 } 06979 /* reject requests that must always have a To: tag */ 06980 if (ast_strlen_zero(totag) && (req->method == SIP_ACK || req->method == SIP_BYE || req->method == SIP_INFO )) { 06981 ast_debug(5, "%s must have a to tag. dropping callid: %s from: %s\n", sip_methods[req->method].text , callid, from ); 06982 return NULL; 06983 } 06984 } 06985 06986 restartsearch: 06987 if (!pedanticsipchecking) { 06988 struct sip_pvt tmp_dialog = { 06989 .callid = callid, 06990 }; 06991 sip_pvt_ptr = ao2_t_find(dialogs, &tmp_dialog, OBJ_POINTER, "ao2_find in dialogs"); 06992 if (sip_pvt_ptr) { /* well, if we don't find it-- what IS in there? */ 06993 /* Found the call */ 06994 sip_pvt_lock(sip_pvt_ptr); 06995 return sip_pvt_ptr; 06996 } 06997 } else { /* in pedantic mode! -- do the fancy linear search */ 06998 ao2_lock(dialogs); 06999 p = ao2_t_callback(dialogs, 0 /* single, data */, find_call_cb, &arg, "pedantic linear search for dialog"); 07000 if (p) { 07001 if (sip_pvt_trylock(p)) { 07002 ao2_unlock(dialogs); 07003 usleep(1); 07004 goto restartsearch; 07005 } 07006 ao2_unlock(dialogs); 07007 return p; 07008 } 07009 ao2_unlock(dialogs); 07010 } 07011 07012 /* See if the method is capable of creating a dialog */ 07013 if (sip_methods[intended_method].can_create == CAN_CREATE_DIALOG) { 07014 if (intended_method == SIP_REFER) { 07015 /* We do support REFER, but not outside of a dialog yet */ 07016 transmit_response_using_temp(callid, sin, 1, intended_method, req, "603 Declined (no dialog)"); 07017 } else if (intended_method == SIP_NOTIFY) { 07018 /* We do not support out-of-dialog NOTIFY either, 07019 like voicemail notification, so cancel that early */ 07020 transmit_response_using_temp(callid, sin, 1, intended_method, req, "489 Bad event"); 07021 } else { 07022 /* Ok, time to create a new SIP dialog object, a pvt */ 07023 if ((p = sip_alloc(callid, sin, 1, intended_method, req))) { 07024 /* Ok, we've created a dialog, let's go and process it */ 07025 sip_pvt_lock(p); 07026 } else { 07027 /* We have a memory or file/socket error (can't allocate RTP sockets or something) so we're not 07028 getting a dialog from sip_alloc. 07029 07030 Without a dialog we can't retransmit and handle ACKs and all that, but at least 07031 send an error message. 07032 07033 Sorry, we apologize for the inconvienience 07034 */ 07035 transmit_response_using_temp(callid, sin, 1, intended_method, req, "500 Server internal error"); 07036 ast_debug(4, "Failed allocating SIP dialog, sending 500 Server internal error and giving up\n"); 07037 } 07038 } 07039 return p; /* can be NULL */ 07040 } else if( sip_methods[intended_method].can_create == CAN_CREATE_DIALOG_UNSUPPORTED_METHOD) { 07041 /* A method we do not support, let's take it on the volley */ 07042 transmit_response_using_temp(callid, sin, 1, intended_method, req, "501 Method Not Implemented"); 07043 ast_debug(2, "Got a request with unsupported SIP method.\n"); 07044 } else if (intended_method != SIP_RESPONSE && intended_method != SIP_ACK) { 07045 /* This is a request outside of a dialog that we don't know about */ 07046 transmit_response_using_temp(callid, sin, 1, intended_method, req, "481 Call leg/transaction does not exist"); 07047 ast_debug(2, "That's odd... Got a request in unknown dialog. Callid %s\n", callid ? callid : "<unknown>"); 07048 } 07049 /* We do not respond to responses for dialogs that we don't know about, we just drop 07050 the session quickly */ 07051 if (intended_method == SIP_RESPONSE) 07052 ast_debug(2, "That's odd... Got a response on a call we dont know about. Callid %s\n", callid ? callid : "<unknown>"); 07053 07054 return NULL; 07055 }
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 6893 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().
06894 { 06895 struct sip_pvt *p = __pvt; 06896 struct find_call_cb_arg *arg = __arg; 06897 /* In pedantic, we do not want packets with bad syntax to be connected to a PVT */ 06898 int found = FALSE; 06899 06900 if (!ast_strlen_zero(p->callid)) { /* XXX double check, do we allow match on empty p->callid ? */ 06901 if (arg->method == SIP_REGISTER) 06902 found = (!strcmp(p->callid, arg->callid)); 06903 else { 06904 found = !strcmp(p->callid, arg->callid); 06905 if (pedanticsipchecking && found) { 06906 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); 06907 } 06908 } 06909 06910 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); 06911 06912 /* If we get a new request within an existing to-tag - check the to tag as well */ 06913 if (pedanticsipchecking && found && arg->method != SIP_RESPONSE) { /* SIP Request */ 06914 if (p->tag[0] == '\0' && arg->totag[0]) { 06915 /* We have no to tag, but they have. Wrong dialog */ 06916 found = FALSE; 06917 } else if (arg->totag[0]) { /* Both have tags, compare them */ 06918 if (strcmp(arg->totag, p->tag)) { 06919 found = FALSE; /* This is not our packet */ 06920 } 06921 } 06922 if (!found) 06923 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); 06924 } 06925 } 06926 return found; 06927 }
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 3933 of file chan_sip.c.
References s.
Referenced by get_in_brackets().
03934 { 03935 char last_char = '\0'; 03936 const char *s; 03937 for (s = start; *s && s != lim; last_char = *s++) { 03938 if (*s == '"' && last_char != '\\') 03939 break; 03940 } 03941 return s; 03942 }
static struct sip_peer * find_peer | ( | const char * | peer, | |
struct sockaddr_in * | sin, | |||
int | realtime, | |||
int | which_objects, | |||
int | devstate_only, | |||
int | transport | |||
) | [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 4588 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, peers_by_ip, realtime_peer(), SIP_INSECURE_PORT, peer_finding_info::tmp_peer, sip_peer::transports, and peer_finding_info::which_objects.
04589 { 04590 struct sip_peer *p = NULL; 04591 04592 if (peer) { 04593 struct peer_finding_info pfi = { 04594 .which_objects = which_objects, 04595 }; 04596 ast_copy_string(pfi.tmp_peer.name, peer, sizeof(pfi.tmp_peer.name)); 04597 p = ao2_t_callback(peers, OBJ_POINTER, find_by_name, &pfi, "ao2_callback in peers table"); 04598 } else if (sin) { /* search by addr? */ 04599 struct sip_peer tmp_peer; 04600 tmp_peer.addr.sin_addr.s_addr = sin->sin_addr.s_addr; 04601 tmp_peer.addr.sin_port = sin->sin_port; 04602 tmp_peer.flags[0].flags = 0; 04603 tmp_peer.transports = transport; 04604 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); */ 04605 if (!p) { 04606 ast_set_flag(&tmp_peer.flags[0], SIP_INSECURE_PORT); 04607 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); */ 04608 if (p) { 04609 return p; 04610 } 04611 } 04612 } 04613 04614 if (!p && (realtime || devstate_only)) 04615 p = realtime_peer(peer, sin, devstate_only); 04616 04617 return p; 04618 }
static struct sip_auth * find_realm_authentication | ( | struct sip_auth * | authlist, | |
const char * | realm | |||
) | [static] |
Find authentication for a specific realm.
Definition at line 22634 of file chan_sip.c.
References sip_auth::next, and sip_auth::realm.
Referenced by build_reply_digest().
22635 { 22636 struct sip_auth *a; 22637 22638 for (a = authlist; a; a = a->next) { 22639 if (!strcasecmp(a->realm, realm)) 22640 break; 22641 } 22642 22643 return a; 22644 }
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 7298 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_count, sip_request::sdp_start, strcasestr(), and TRUE.
Referenced by handle_incoming(), handle_request_invite(), handle_response(), and handle_response_invite().
07299 { 07300 const char *content_type; 07301 const char *content_length; 07302 const char *search; 07303 char *boundary; 07304 unsigned int x; 07305 int boundaryisquoted = FALSE; 07306 int found_application_sdp = FALSE; 07307 int found_end_of_headers = FALSE; 07308 07309 content_length = get_header(req, "Content-Length"); 07310 07311 if (!ast_strlen_zero(content_length)) { 07312 if (sscanf(content_length, "%30u", &x) != 1) { 07313 ast_log(LOG_WARNING, "Invalid Content-Length: %s\n", content_length); 07314 return 0; 07315 } 07316 07317 /* Content-Length of zero means there can't possibly be an 07318 SDP here, even if the Content-Type says there is */ 07319 if (x == 0) 07320 return 0; 07321 } 07322 07323 content_type = get_header(req, "Content-Type"); 07324 07325 /* if the body contains only SDP, this is easy */ 07326 if (!strncasecmp(content_type, "application/sdp", 15)) { 07327 req->sdp_start = 0; 07328 req->sdp_count = req->lines; 07329 return req->lines ? 1 : 0; 07330 } 07331 07332 /* if it's not multipart/mixed, there cannot be an SDP */ 07333 if (strncasecmp(content_type, "multipart/mixed", 15)) 07334 return 0; 07335 07336 /* if there is no boundary marker, it's invalid */ 07337 if ((search = strcasestr(content_type, ";boundary="))) 07338 search += 10; 07339 else if ((search = strcasestr(content_type, "; boundary="))) 07340 search += 11; 07341 else 07342 return 0; 07343 07344 if (ast_strlen_zero(search)) 07345 return 0; 07346 07347 /* If the boundary is quoted with ", remove quote */ 07348 if (*search == '\"') { 07349 search++; 07350 boundaryisquoted = TRUE; 07351 } 07352 07353 /* make a duplicate of the string, with two extra characters 07354 at the beginning */ 07355 boundary = ast_strdupa(search - 2); 07356 boundary[0] = boundary[1] = '-'; 07357 /* Remove final quote */ 07358 if (boundaryisquoted) 07359 boundary[strlen(boundary) - 1] = '\0'; 07360 07361 /* search for the boundary marker, the empty line delimiting headers from 07362 sdp part and the end boundry if it exists */ 07363 07364 for (x = 0; x < (req->lines); x++) { 07365 char *line = REQ_OFFSET_TO_STR(req, line[x]); 07366 if (!strncasecmp(line, boundary, strlen(boundary))){ 07367 if (found_application_sdp && found_end_of_headers) { 07368 req->sdp_count = (x - 1) - req->sdp_start; 07369 return 1; 07370 } 07371 found_application_sdp = FALSE; 07372 } 07373 if (!strcasecmp(line, "Content-Type: application/sdp")) 07374 found_application_sdp = TRUE; 07375 07376 if (ast_strlen_zero(line)) { 07377 if (found_application_sdp && !found_end_of_headers){ 07378 req->sdp_start = x; 07379 found_end_of_headers = TRUE; 07380 } 07381 } 07382 } 07383 if (found_application_sdp && found_end_of_headers) { 07384 req->sdp_count = x - req->sdp_start; 07385 return TRUE; 07386 } 07387 return FALSE; 07388 }
static int find_sip_method | ( | const char * | msg | ) | [static] |
find_sip_method: Find SIP method from header
Definition at line 2998 of file chan_sip.c.
References ARRAY_LEN, ast_strlen_zero(), cfsip_methods::id, method_match(), and sip_methods.
Referenced by __sip_pretend_ack(), handle_request_do(), handle_response(), and sip_hangup().
02999 { 03000 int i, res = 0; 03001 03002 if (ast_strlen_zero(msg)) 03003 return 0; 03004 for (i = 1; i < ARRAY_LEN(sip_methods) && !res; i++) { 03005 if (method_match(i, msg)) 03006 res = sip_methods[i].id; 03007 } 03008 return res; 03009 }
static struct cfsubscription_types * find_subscription_type | ( | enum subscriptiontype | subtype | ) | [static] |
Find subscription type in array.
Definition at line 15356 of file chan_sip.c.
References ARRAY_LEN, and subscription_types.
Referenced by transmit_state_notify().
15357 { 15358 int i; 15359 15360 for (i = 1; i < ARRAY_LEN(subscription_types); i++) { 15361 if (subscription_types[i].type == subtype) { 15362 return &subscription_types[i]; 15363 } 15364 } 15365 return &subscription_types[0]; 15366 }
static void free_old_route | ( | struct sip_route * | route | ) | [static] |
Remove route from route list.
Definition at line 11627 of file chan_sip.c.
References ast_free, sip_route::next, and sip_request::next.
Referenced by __sip_destroy(), and build_route().
11628 { 11629 struct sip_route *next; 11630 11631 while (route) { 11632 next = route->next; 11633 ast_free(route); 11634 route = next; 11635 } 11636 }
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 16477 of file chan_sip.c.
References ast_copy_string(), ast_log(), ast_strlen_zero(), check_sip_domain(), and LOG_WARNING.
16478 { 16479 if (ast_strlen_zero(data)) { 16480 ast_log(LOG_WARNING, "CHECKSIPDOMAIN requires an argument - A domain name\n"); 16481 return -1; 16482 } 16483 if (check_sip_domain(data, NULL, 0)) 16484 ast_copy_string(buf, data, len); 16485 else 16486 buf[0] = '\0'; 16487 return 0; 16488 }
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 16413 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.
16414 { 16415 struct sip_pvt *p; 16416 const char *content = NULL; 16417 AST_DECLARE_APP_ARGS(args, 16418 AST_APP_ARG(header); 16419 AST_APP_ARG(number); 16420 ); 16421 int i, number, start = 0; 16422 16423 if (ast_strlen_zero(data)) { 16424 ast_log(LOG_WARNING, "This function requires a header name.\n"); 16425 return -1; 16426 } 16427 16428 ast_channel_lock(chan); 16429 if (!IS_SIP_TECH(chan->tech)) { 16430 ast_log(LOG_WARNING, "This function can only be used on SIP channels.\n"); 16431 ast_channel_unlock(chan); 16432 return -1; 16433 } 16434 16435 AST_STANDARD_APP_ARGS(args, data); 16436 if (!args.number) { 16437 number = 1; 16438 } else { 16439 sscanf(args.number, "%30d", &number); 16440 if (number < 1) 16441 number = 1; 16442 } 16443 16444 p = chan->tech_pvt; 16445 16446 /* If there is no private structure, this channel is no longer alive */ 16447 if (!p) { 16448 ast_channel_unlock(chan); 16449 return -1; 16450 } 16451 16452 for (i = 0; i < number; i++) 16453 content = __get_header(&p->initreq, args.header, &start); 16454 16455 if (ast_strlen_zero(content)) { 16456 ast_channel_unlock(chan); 16457 return -1; 16458 } 16459 16460 ast_copy_string(buf, content, len); 16461 ast_channel_unlock(chan); 16462 16463 return 0; 16464 }
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 16621 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.
16622 { 16623 struct sip_pvt *p; 16624 static int deprecated = 0; 16625 16626 *buf = 0; 16627 16628 if (!data) { 16629 ast_log(LOG_WARNING, "This function requires a parameter name.\n"); 16630 return -1; 16631 } 16632 16633 ast_channel_lock(chan); 16634 if (!IS_SIP_TECH(chan->tech)) { 16635 ast_log(LOG_WARNING, "This function can only be used on SIP channels.\n"); 16636 ast_channel_unlock(chan); 16637 return -1; 16638 } 16639 16640 if (deprecated++ % 20 == 0) { 16641 /* Deprecated in 1.6.1 */ 16642 ast_log(LOG_WARNING, "SIPCHANINFO() is deprecated. Please transition to using CHANNEL().\n"); 16643 } 16644 16645 p = chan->tech_pvt; 16646 16647 /* If there is no private structure, this channel is no longer alive */ 16648 if (!p) { 16649 ast_channel_unlock(chan); 16650 return -1; 16651 } 16652 16653 if (!strcasecmp(data, "peerip")) { 16654 ast_copy_string(buf, p->sa.sin_addr.s_addr ? ast_inet_ntoa(p->sa.sin_addr) : "", len); 16655 } else if (!strcasecmp(data, "recvip")) { 16656 ast_copy_string(buf, p->recv.sin_addr.s_addr ? ast_inet_ntoa(p->recv.sin_addr) : "", len); 16657 } else if (!strcasecmp(data, "from")) { 16658 ast_copy_string(buf, p->from, len); 16659 } else if (!strcasecmp(data, "uri")) { 16660 ast_copy_string(buf, p->uri, len); 16661 } else if (!strcasecmp(data, "useragent")) { 16662 ast_copy_string(buf, p->useragent, len); 16663 } else if (!strcasecmp(data, "peername")) { 16664 ast_copy_string(buf, p->peername, len); 16665 } else if (!strcasecmp(data, "t38passthrough")) { 16666 if (p->t38.state == T38_DISABLED) { 16667 ast_copy_string(buf, "0", len); 16668 } else { /* T38 is offered or enabled in this call */ 16669 ast_copy_string(buf, "1", len); 16670 } 16671 } else { 16672 ast_channel_unlock(chan); 16673 return -1; 16674 } 16675 ast_channel_unlock(chan); 16676 16677 return 0; 16678 }
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 16502 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.
16503 { 16504 struct sip_peer *peer; 16505 char *colname; 16506 16507 if ((colname = strchr(data, ':'))) { /*! \todo Will be deprecated after 1.4 */ 16508 static int deprecation_warning = 0; 16509 *colname++ = '\0'; 16510 if (deprecation_warning++ % 10 == 0) 16511 ast_log(LOG_WARNING, "SIPPEER(): usage of ':' to separate arguments is deprecated. Please use ',' instead.\n"); 16512 } else if ((colname = strchr(data, ','))) 16513 *colname++ = '\0'; 16514 else 16515 colname = "ip"; 16516 16517 if (!(peer = find_peer(data, NULL, TRUE, FINDPEERS, FALSE, 0))) 16518 return -1; 16519 16520 if (!strcasecmp(colname, "ip")) { 16521 ast_copy_string(buf, peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "", len); 16522 } else if (!strcasecmp(colname, "port")) { 16523 snprintf(buf, len, "%d", ntohs(peer->addr.sin_port)); 16524 } else if (!strcasecmp(colname, "status")) { 16525 peer_status(peer, buf, len); 16526 } else if (!strcasecmp(colname, "language")) { 16527 ast_copy_string(buf, peer->language, len); 16528 } else if (!strcasecmp(colname, "regexten")) { 16529 ast_copy_string(buf, peer->regexten, len); 16530 } else if (!strcasecmp(colname, "limit")) { 16531 snprintf(buf, len, "%d", peer->call_limit); 16532 } else if (!strcasecmp(colname, "busylevel")) { 16533 snprintf(buf, len, "%d", peer->busy_level); 16534 } else if (!strcasecmp(colname, "curcalls")) { 16535 snprintf(buf, len, "%d", peer->inUse); 16536 } else if (!strcasecmp(colname, "accountcode")) { 16537 ast_copy_string(buf, peer->accountcode, len); 16538 } else if (!strcasecmp(colname, "callgroup")) { 16539 ast_print_group(buf, len, peer->callgroup); 16540 } else if (!strcasecmp(colname, "pickupgroup")) { 16541 ast_print_group(buf, len, peer->pickupgroup); 16542 } else if (!strcasecmp(colname, "useragent")) { 16543 ast_copy_string(buf, peer->useragent, len); 16544 } else if (!strcasecmp(colname, "mailbox")) { 16545 struct ast_str *mailbox_str = ast_str_alloca(512); 16546 peer_mailboxes_to_str(&mailbox_str, peer); 16547 ast_copy_string(buf, mailbox_str->str, len); 16548 } else if (!strcasecmp(colname, "context")) { 16549 ast_copy_string(buf, peer->context, len); 16550 } else if (!strcasecmp(colname, "expire")) { 16551 snprintf(buf, len, "%d", peer->expire); 16552 } else if (!strcasecmp(colname, "dynamic")) { 16553 ast_copy_string(buf, peer->host_dynamic ? "yes" : "no", len); 16554 } else if (!strcasecmp(colname, "callerid_name")) { 16555 ast_copy_string(buf, peer->cid_name, len); 16556 } else if (!strcasecmp(colname, "callerid_num")) { 16557 ast_copy_string(buf, peer->cid_num, len); 16558 } else if (!strcasecmp(colname, "codecs")) { 16559 ast_getformatname_multiple(buf, len -1, peer->capability); 16560 } else if (!strncasecmp(colname, "chanvar[", 8)) { 16561 char *chanvar=colname + 8; 16562 struct ast_variable *v; 16563 16564 chanvar = strsep(&chanvar, "]"); 16565 for (v = peer->chanvars ; v ; v = v->next) 16566 if (!strcasecmp(v->name, chanvar)) 16567 ast_copy_string(buf, v->value, len); 16568 } else if (!strncasecmp(colname, "codec[", 6)) { 16569 char *codecnum; 16570 int codec = 0; 16571 16572 codecnum = colname + 6; /* move past the '[' */ 16573 codecnum = strsep(&codecnum, "]"); /* trim trailing ']' if any */ 16574 if((codec = ast_codec_pref_index(&peer->prefs, atoi(codecnum)))) { 16575 ast_copy_string(buf, ast_getformatname(codec), len); 16576 } else { 16577 buf[0] = '\0'; 16578 } 16579 } else { 16580 buf[0] = '\0'; 16581 } 16582 16583 unref_peer(peer, "unref_peer from function_sippeer, just before return"); 16584 16585 return 0; 16586 }
static char * generate_random_string | ( | char * | buf, | |
size_t | size | |||
) | [static] |
Generate 32 byte random string for callid's etc.
Definition at line 6674 of file chan_sip.c.
References ast_random().
Referenced by build_callid_pvt(), and build_callid_registry().
06675 { 06676 long val[4]; 06677 int x; 06678 06679 for (x=0; x<4; x++) 06680 val[x] = ast_random(); 06681 snprintf(buf, size, "%08lx%08lx%08lx%08lx", val[0], val[1], val[2], val[3]); 06682 06683 return buf; 06684 }
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 12874 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().
12875 { 12876 char tmp[256] = "", *c, *a; 12877 struct sip_request *req = oreq ? oreq : &p->initreq; 12878 struct sip_refer *referdata = NULL; 12879 const char *transfer_context = NULL; 12880 12881 if (!p->refer && !sip_refer_allocate(p)) 12882 return -1; 12883 12884 referdata = p->refer; 12885 12886 ast_copy_string(tmp, get_header(req, "Also"), sizeof(tmp)); 12887 c = get_in_brackets(tmp); 12888 12889 if (pedanticsipchecking) 12890 ast_uri_decode(c); 12891 12892 if (!strncasecmp(c, "sip:", 4)) { 12893 c += 4; 12894 } else if (!strncasecmp(c, "sips:", 5)) { 12895 c += 5; 12896 } else { 12897 ast_log(LOG_WARNING, "Huh? Not a SIP header in Also: transfer (%s)?\n", c); 12898 return -1; 12899 } 12900 12901 if ((a = strchr(c, ';'))) /* Remove arguments */ 12902 *a = '\0'; 12903 12904 if ((a = strchr(c, '@'))) { /* Separate Domain */ 12905 *a++ = '\0'; 12906 ast_copy_string(referdata->refer_to_domain, a, sizeof(referdata->refer_to_domain)); 12907 } 12908 12909 if (sip_debug_test_pvt(p)) 12910 ast_verbose("Looking for %s in %s\n", c, p->context); 12911 12912 if (p->owner) /* Mimic behaviour in res_features.c */ 12913 transfer_context = pbx_builtin_getvar_helper(p->owner, "TRANSFER_CONTEXT"); 12914 12915 /* By default, use the context in the channel sending the REFER */ 12916 if (ast_strlen_zero(transfer_context)) { 12917 transfer_context = S_OR(p->owner->macrocontext, 12918 S_OR(p->context, default_context)); 12919 } 12920 if (ast_exists_extension(NULL, transfer_context, c, 1, NULL)) { 12921 /* This is a blind transfer */ 12922 ast_debug(1, "SIP Bye-also transfer to Extension %s@%s \n", c, transfer_context); 12923 ast_copy_string(referdata->refer_to, c, sizeof(referdata->refer_to)); 12924 ast_copy_string(referdata->referred_by, "", sizeof(referdata->referred_by)); 12925 ast_copy_string(referdata->refer_contact, "", sizeof(referdata->refer_contact)); 12926 referdata->refer_call = dialog_unref(referdata->refer_call, "unreffing referdata->refer_call"); 12927 /* Set new context */ 12928 ast_string_field_set(p, context, transfer_context); 12929 return 0; 12930 } else if (ast_canmatch_extension(NULL, p->context, c, 1, NULL)) { 12931 return 1; 12932 } 12933 12934 return -1; 12935 }
static char* get_body | ( | struct sip_request * | req, | |
char * | name | |||
) | [static] |
Get a specific line from the message body.
Definition at line 6441 of file chan_sip.c.
References get_body_by_line(), sip_request::lines, and REQ_OFFSET_TO_STR.
Referenced by handle_request_info().
06442 { 06443 int x; 06444 int len = strlen(name); 06445 char *r; 06446 06447 for (x = 0; x < req->lines; x++) { 06448 r = get_body_by_line(REQ_OFFSET_TO_STR(req, line[x]), name, len); 06449 if (r[0] != '\0') 06450 return r; 06451 } 06452 06453 return ""; 06454 }
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 6386 of file chan_sip.c.
References ast_skip_blanks().
Referenced by get_body(), and get_sdp_iterate().
06387 { 06388 if (!strncasecmp(line, name, nameLen) && line[nameLen] == '=') 06389 return ast_skip_blanks(line + nameLen + 1); 06390 06391 return ""; 06392 }
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 21342 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().
21343 { 21344 struct sip_mailbox *mailbox; 21345 21346 AST_LIST_TRAVERSE(&peer->mailboxes, mailbox, entry) { 21347 struct ast_event *event; 21348 event = ast_event_get_cached(AST_EVENT_MWI, 21349 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox->mailbox, 21350 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, S_OR(mailbox->context, "default"), 21351 AST_EVENT_IE_END); 21352 if (!event) 21353 continue; 21354 *new += ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS); 21355 *old += ast_event_get_ie_uint(event, AST_EVENT_IE_OLDMSGS); 21356 ast_event_destroy(event); 21357 } 21358 21359 return (*new || *old) ? 0 : 1; 21360 }
static char * get_calleridname | ( | const char * | input, | |
char * | output, | |||
size_t | outputsize | |||
) | [static] |
Get caller id name from SIP headers.
Definition at line 13040 of file chan_sip.c.
References ast_copy_string(), and ast_skip_blanks().
Referenced by check_user_full().
13041 { 13042 const char *end = strchr(input, '<'); /* first_bracket */ 13043 const char *tmp = strchr(input, '"'); /* first quote */ 13044 int bytes = 0; 13045 int maxbytes = outputsize - 1; 13046 13047 if (!end || end == input) /* we require a part in brackets */ 13048 return NULL; 13049 13050 end--; /* move just before "<" */ 13051 13052 if (tmp && tmp <= end) { 13053 /* The quote (tmp) precedes the bracket (end+1). 13054 * Find the matching quote and return the content. 13055 */ 13056 end = strchr(tmp+1, '"'); 13057 if (!end) 13058 return NULL; 13059 bytes = (int) (end - tmp); 13060 /* protect the output buffer */ 13061 if (bytes > maxbytes) 13062 bytes = maxbytes; 13063 ast_copy_string(output, tmp + 1, bytes); 13064 } else { 13065 /* No quoted string, or it is inside brackets. */ 13066 /* clear the empty characters in the begining*/ 13067 input = ast_skip_blanks(input); 13068 /* clear the empty characters in the end */ 13069 while(*end && *end < 33 && end > input) 13070 end--; 13071 if (end >= input) { 13072 bytes = (int) (end - input) + 2; 13073 /* protect the output buffer */ 13074 if (bytes > maxbytes) 13075 bytes = maxbytes; 13076 ast_copy_string(output, input, bytes); 13077 } else 13078 return NULL; 13079 } 13080 return output; 13081 }
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 12483 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, sip_pvt::flags, 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_PAGE2_HAVEPEERCONTEXT, SIP_REFER, SIP_SUBSCRIBE, strsep(), and sip_pvt::subscribecontext.
Referenced by handle_request_invite(), handle_request_options(), and handle_request_subscribe().
12484 { 12485 char tmp[256] = "", *uri, *a; 12486 char tmpf[256] = "", *from = NULL; 12487 struct sip_request *req; 12488 char *colon; 12489 char *decoded_uri; 12490 12491 req = oreq; 12492 if (!req) 12493 req = &p->initreq; 12494 12495 /* Find the request URI */ 12496 if (req->rlPart2) 12497 ast_copy_string(tmp, REQ_OFFSET_TO_STR(req, rlPart2), sizeof(tmp)); 12498 12499 if (pedanticsipchecking) 12500 ast_uri_decode(tmp); 12501 12502 uri = get_in_brackets(tmp); 12503 12504 if (!strncasecmp(uri, "sip:", 4)) { 12505 uri += 4; 12506 } else if (!strncasecmp(uri, "sips:", 5)) { 12507 uri += 5; 12508 } else { 12509 ast_log(LOG_WARNING, "Huh? Not a SIP header (%s)?\n", uri); 12510 return -1; 12511 } 12512 12513 /* Now find the From: caller ID and name */ 12514 /* XXX Why is this done in get_destination? Isn't it already done? 12515 Needs to be checked 12516 */ 12517 ast_copy_string(tmpf, get_header(req, "From"), sizeof(tmpf)); 12518 if (!ast_strlen_zero(tmpf)) { 12519 if (pedanticsipchecking) 12520 ast_uri_decode(tmpf); 12521 from = get_in_brackets(tmpf); 12522 } 12523 12524 if (!ast_strlen_zero(from)) { 12525 if (!strncasecmp(from, "sip:", 4)) { 12526 from += 4; 12527 } else if (!strncasecmp(from, "sips:", 5)) { 12528 from += 5; 12529 } else { 12530 ast_log(LOG_WARNING, "Huh? Not a SIP header (%s)?\n", from); 12531 return -1; 12532 } 12533 if ((a = strchr(from, '@'))) 12534 *a++ = '\0'; 12535 else 12536 a = from; /* just a domain */ 12537 from = strsep(&from, ";"); /* Remove userinfo options */ 12538 a = strsep(&a, ";"); /* Remove URI options */ 12539 ast_string_field_set(p, fromdomain, a); 12540 } 12541 12542 /* Skip any options and find the domain */ 12543 12544 /* Get the target domain */ 12545 if ((a = strchr(uri, '@'))) { 12546 *a++ = '\0'; 12547 } else { /* No username part */ 12548 a = uri; 12549 uri = "s"; /* Set extension to "s" */ 12550 } 12551 colon = strchr(a, ':'); /* Remove :port */ 12552 if (colon) 12553 *colon = '\0'; 12554 12555 uri = strsep(&uri, ";"); /* Remove userinfo options */ 12556 a = strsep(&a, ";"); /* Remove URI options */ 12557 12558 ast_string_field_set(p, domain, a); 12559 12560 if (!AST_LIST_EMPTY(&domain_list)) { 12561 char domain_context[AST_MAX_EXTENSION]; 12562 12563 domain_context[0] = '\0'; 12564 if (!check_sip_domain(p->domain, domain_context, sizeof(domain_context))) { 12565 if (!allow_external_domains && (req->method == SIP_INVITE || req->method == SIP_REFER)) { 12566 ast_debug(1, "Got SIP %s to non-local domain '%s'; refusing request.\n", sip_methods[req->method].text, p->domain); 12567 return -2; 12568 } 12569 } 12570 /* If we don't have a peer (i.e. we're a guest call), 12571 * overwrite the original context */ 12572 if (!ast_test_flag(&p->flags[1], SIP_PAGE2_HAVEPEERCONTEXT) && !ast_strlen_zero(domain_context)) 12573 ast_string_field_set(p, context, domain_context); 12574 } 12575 12576 /* If the request coming in is a subscription and subscribecontext has been specified use it */ 12577 if (req->method == SIP_SUBSCRIBE && !ast_strlen_zero(p->subscribecontext)) 12578 ast_string_field_set(p, context, p->subscribecontext); 12579 12580 if (sip_debug_test_pvt(p)) 12581 ast_verbose("Looking for %s in %s (domain %s)\n", uri, p->context, p->domain); 12582 12583 /* If this is a subscription we actually just need to see if a hint exists for the extension */ 12584 if (req->method == SIP_SUBSCRIBE) { 12585 char hint[AST_MAX_EXTENSION]; 12586 return (ast_get_hint(hint, sizeof(hint), NULL, 0, NULL, p->context, p->exten) ? 0 : -1); 12587 } else { 12588 decoded_uri = ast_strdupa(uri); 12589 ast_uri_decode(decoded_uri); 12590 /* Check the dialplan for the username part of the request URI, 12591 the domain will be stored in the SIPDOMAIN variable 12592 Since extensions.conf can have unescaped characters, try matching a decoded 12593 uri in addition to the non-decoded uri 12594 Return 0 if we have a matching extension */ 12595 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)) || 12596 !strcmp(decoded_uri, ast_pickup_ext())) { 12597 if (!oreq) 12598 ast_string_field_set(p, exten, decoded_uri); 12599 return 0; 12600 } 12601 } 12602 12603 /* Return 1 for pickup extension or overlap dialling support (if we support it) */ 12604 if((ast_test_flag(&global_flags[1], SIP_PAGE2_ALLOWOVERLAP) && 12605 ast_canmatch_extension(NULL, p->context, decoded_uri, 1, S_OR(p->cid_num, from))) || 12606 !strncmp(decoded_uri, ast_pickup_ext(), strlen(decoded_uri))) { 12607 return 1; 12608 } 12609 12610 return -1; 12611 }
static const char * get_header | ( | const struct sip_request * | req, | |
const char * | name | |||
) | [static] |
Get header from SIP request.
Definition at line 6534 of file chan_sip.c.
References __get_header().
06535 { 06536 int start = 0; 06537 return __get_header(req, name, &start); 06538 }
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 3956 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().
03957 { 03958 const char *parse = tmp; 03959 char *first_bracket; 03960 03961 /* 03962 * Skip any quoted text until we find the part in brackets. 03963 * On any error give up and return the full string. 03964 */ 03965 while ( (first_bracket = strchr(parse, '<')) ) { 03966 char *first_quote = strchr(parse, '"'); 03967 03968 if (!first_quote || first_quote > first_bracket) 03969 break; /* no need to look at quoted part */ 03970 /* the bracket is within quotes, so ignore it */ 03971 parse = find_closing_quote(first_quote + 1, NULL); 03972 if (!*parse) { /* not found, return full string ? */ 03973 /* XXX or be robust and return in-bracket part ? */ 03974 ast_log(LOG_WARNING, "No closing quote found in '%s'\n", tmp); 03975 break; 03976 } 03977 parse++; 03978 } 03979 if (first_bracket) { 03980 char *second_bracket = strchr(first_bracket + 1, '>'); 03981 if (second_bracket) { 03982 *second_bracket = '\0'; 03983 tmp = first_bracket + 1; 03984 } else { 03985 ast_log(LOG_WARNING, "No closing bracket found in '%s'\n", tmp); 03986 } 03987 } 03988 03989 return tmp; 03990 }
static struct ast_variable * get_insecure_variable_from_config | ( | struct ast_config * | config | ) | [static] |
Definition at line 4319 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.
04320 { 04321 struct ast_variable *var = NULL; 04322 struct ast_flags flags = {0}; 04323 char *cat = NULL; 04324 const char *insecure; 04325 while ((cat = ast_category_browse(cfg, cat))) { 04326 insecure = ast_variable_retrieve(cfg, cat, "insecure"); 04327 set_insecure_flags(&flags, insecure, -1); 04328 if (ast_test_flag(&flags, SIP_INSECURE_PORT)) { 04329 var = ast_category_root(cfg, cat); 04330 break; 04331 } 04332 } 04333 return var; 04334 }
static int get_ip_and_port_from_sdp | ( | struct sip_request * | req, | |
const enum media_type | media, | |||
struct sockaddr_in * | sin | |||
) | [static] |
Definition at line 7397 of file chan_sip.c.
References ast_gethostbyname(), ast_log(), ast_strlen_zero(), get_sdp_iterate(), hp, LOG_WARNING, SDP_AUDIO, sip_request::sdp_start, and SDP_VIDEO.
Referenced by handle_request_invite().
07398 { 07399 const char *m; 07400 const char *c; 07401 int miterator = req->sdp_start; 07402 int citerator = req->sdp_start; 07403 int x = 0; 07404 int numberofports; 07405 int len; 07406 char host[258] = ""; /*Initialize to empty so we will know if we have any input */ 07407 struct ast_hostent audiohp; 07408 struct hostent *hp; 07409 07410 c = get_sdp_iterate(&citerator, req, "c"); 07411 if (sscanf(c, "IN IP4 %256s", host) != 1) { 07412 ast_log(LOG_WARNING, "Invalid host in c= line, '%s'\n", c); 07413 /* Continue since there may be a valid host in a c= line specific to the audio stream */ 07414 } 07415 /* We only want the m and c lines for audio */ 07416 for (m = get_sdp_iterate(&miterator, req, "m"); !ast_strlen_zero(m); m = get_sdp_iterate(&miterator, req, "m")) { 07417 if ((media == SDP_AUDIO && ((sscanf(m, "audio %30u/%30u RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) || 07418 (sscanf(m, "audio %30u RTP/AVP %n", &x, &len) == 1 && len > 0))) || 07419 (media == SDP_VIDEO && ((sscanf(m, "video %30u/%30u RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) || 07420 (sscanf(m, "video %30u RTP/AVP %n", &x, &len) == 1 && len > 0)))) { 07421 /* See if there's a c= line for this media stream. 07422 * XXX There is no guarantee that we'll be grabbing the c= line for this 07423 * particular media stream here. However, this is the same logic used in process_sdp. 07424 */ 07425 c = get_sdp_iterate(&citerator, req, "c"); 07426 if (!ast_strlen_zero(c)) { 07427 sscanf(c, "IN IP4 %256s", host); 07428 } 07429 break; 07430 } 07431 } 07432 07433 if (ast_strlen_zero(host) || x == 0) { 07434 ast_log(LOG_WARNING, "Failed to read an alternate host or port in SDP. Expect %s problems\n", media == SDP_AUDIO ? "audio" : "video"); 07435 return -1; 07436 } 07437 07438 hp = ast_gethostbyname(host, &audiohp); 07439 if (!hp) { 07440 ast_log(LOG_WARNING, "Could not look up IP address of alternate hostname. Expect %s problems\n", media == SDP_AUDIO? "audio" : "video"); 07441 return -1; 07442 } 07443 07444 memcpy(&sin->sin_addr, hp->h_addr, sizeof(sin->sin_addr)); 07445 sin->sin_port = htons(x); 07446 return 0; 07447 }
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 13433 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().
13434 { 13435 int x; 13436 int y; 13437 13438 buf[0] = '\0'; 13439 /*XXX isn't strlen(buf) going to always be 0? */ 13440 y = len - strlen(buf) - 5; 13441 if (y < 0) 13442 y = 0; 13443 for (x = 0; x < req->lines; x++) { 13444 char *line = REQ_OFFSET_TO_STR(req, line[x]); 13445 strncat(buf, line, y); /* safe */ 13446 y -= strlen(line) + 1; 13447 if (y < 0) 13448 y = 0; 13449 if (y != 0 && addnewline) 13450 strcat(buf, "\n"); /* safe */ 13451 } 13452 return 0; 13453 }
static const char * get_name_from_variable | ( | struct ast_variable * | var, | |
const char * | newpeername | |||
) | [static] |
Definition at line 4336 of file chan_sip.c.
References ast_variable::name, ast_variable::next, ast_variable::value, and var.
04337 { 04338 struct ast_variable *tmp; 04339 for (tmp = var; tmp; tmp = tmp->next) { 04340 if (!newpeername && !strcasecmp(tmp->name, "name")) 04341 newpeername = tmp->value; 04342 } 04343 return newpeername; 04344 }
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 9330 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().
09333 { 09334 /* First, get our address */ 09335 ast_rtp_get_us(p->rtp, sin); 09336 if (p->vrtp) 09337 ast_rtp_get_us(p->vrtp, vsin); 09338 if (p->trtp) 09339 ast_rtp_get_us(p->trtp, tsin); 09340 09341 /* Now, try to figure out where we want them to send data */ 09342 /* Is this a re-invite to move the media out, then use the original offer from caller */ 09343 if (p->redirip.sin_addr.s_addr) { /* If we have a redirection IP, use it */ 09344 dest->sin_port = p->redirip.sin_port; 09345 dest->sin_addr = p->redirip.sin_addr; 09346 } else { 09347 dest->sin_addr = p->ourip.sin_addr; 09348 dest->sin_port = sin->sin_port; 09349 } 09350 if (needvideo) { 09351 /* Determine video destination */ 09352 if (p->vredirip.sin_addr.s_addr) { 09353 vdest->sin_addr = p->vredirip.sin_addr; 09354 vdest->sin_port = p->vredirip.sin_port; 09355 } else { 09356 vdest->sin_addr = p->ourip.sin_addr; 09357 vdest->sin_port = vsin->sin_port; 09358 } 09359 } 09360 09361 }
static int get_rdnis | ( | struct sip_pvt * | p, | |
struct sip_request * | oreq | |||
) | [static] |
Get referring dnis.
Definition at line 12416 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().
12417 { 12418 char tmp[256], *exten, *rexten, *rdomain; 12419 char *params, *reason = NULL; 12420 struct sip_request *req; 12421 12422 req = oreq ? oreq : &p->initreq; 12423 12424 ast_copy_string(tmp, get_header(req, "Diversion"), sizeof(tmp)); 12425 if (ast_strlen_zero(tmp)) 12426 return 0; 12427 12428 params = strchr(tmp, ';'); 12429 12430 exten = get_in_brackets(tmp); 12431 if (!strncasecmp(exten, "sip:", 4)) { 12432 exten += 4; 12433 } else if (!strncasecmp(exten, "sips:", 5)) { 12434 exten += 5; 12435 } else { 12436 ast_log(LOG_WARNING, "Huh? Not an RDNIS SIP header (%s)?\n", exten); 12437 return -1; 12438 } 12439 12440 /* Get diversion-reason param if present */ 12441 if (params) { 12442 *params = '\0'; /* Cut off parameters */ 12443 params++; 12444 while (*params == ';' || *params == ' ') 12445 params++; 12446 /* Check if we have a reason parameter */ 12447 if ((reason = strcasestr(params, "reason="))) { 12448 reason+=7; 12449 /* Remove enclosing double-quotes */ 12450 if (*reason == '"') 12451 ast_strip_quoted(reason, "\"", "\""); 12452 if (!ast_strlen_zero(reason)) { 12453 sip_set_redirstr(p, reason); 12454 if (p->owner) { 12455 pbx_builtin_setvar_helper(p->owner, "__PRIREDIRECTREASON", p->redircause); 12456 pbx_builtin_setvar_helper(p->owner, "__SIPREDIRECTREASON", reason); 12457 } 12458 } 12459 } 12460 } 12461 12462 rdomain = exten; 12463 rexten = strsep(&rdomain, "@"); /* trim anything after @ */ 12464 if (p->owner) 12465 pbx_builtin_setvar_helper(p->owner, "__SIPRDNISDOMAIN", rdomain); 12466 12467 if (sip_debug_test_pvt(p)) 12468 ast_verbose("RDNIS for this call is is %s (reason %s)\n", exten, reason ? reason : ""); 12469 12470 ast_string_field_set(p, rdnis, rexten); 12471 12472 return 0; 12473 }
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 12698 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().
12699 { 12700 12701 const char *p_referred_by = NULL; 12702 char *h_refer_to = NULL; 12703 char *h_referred_by = NULL; 12704 char *refer_to; 12705 const char *p_refer_to; 12706 char *referred_by_uri = NULL; 12707 char *ptr; 12708 struct sip_request *req = NULL; 12709 const char *transfer_context = NULL; 12710 struct sip_refer *referdata; 12711 12712 12713 req = outgoing_req; 12714 referdata = transferer->refer; 12715 12716 if (!req) 12717 req = &transferer->initreq; 12718 12719 p_refer_to = get_header(req, "Refer-To"); 12720 if (ast_strlen_zero(p_refer_to)) { 12721 ast_log(LOG_WARNING, "Refer-To Header missing. Skipping transfer.\n"); 12722 return -2; /* Syntax error */ 12723 } 12724 h_refer_to = ast_strdupa(p_refer_to); 12725 refer_to = get_in_brackets(h_refer_to); 12726 if (pedanticsipchecking) 12727 ast_uri_decode(refer_to); 12728 12729 if (!strncasecmp(refer_to, "sip:", 4)) { 12730 refer_to += 4; /* Skip sip: */ 12731 } else if (!strncasecmp(refer_to, "sips:", 5)) { 12732 refer_to += 5; 12733 } else { 12734 ast_log(LOG_WARNING, "Can't transfer to non-sip: URI. (Refer-to: %s)?\n", refer_to); 12735 return -3; 12736 } 12737 12738 /* Get referred by header if it exists */ 12739 p_referred_by = get_header(req, "Referred-By"); 12740 12741 /* Give useful transfer information to the dialplan */ 12742 if (transferer->owner) { 12743 struct ast_channel *peer = ast_bridged_channel(transferer->owner); 12744 if (peer) { 12745 pbx_builtin_setvar_helper(peer, "SIPREFERRINGCONTEXT", transferer->context); 12746 pbx_builtin_setvar_helper(peer, "SIPREFERREDBYHDR", p_referred_by); 12747 } 12748 } 12749 12750 if (!ast_strlen_zero(p_referred_by)) { 12751 char *lessthan; 12752 h_referred_by = ast_strdupa(p_referred_by); 12753 if (pedanticsipchecking) 12754 ast_uri_decode(h_referred_by); 12755 12756 /* Store referrer's caller ID name */ 12757 ast_copy_string(referdata->referred_by_name, h_referred_by, sizeof(referdata->referred_by_name)); 12758 if ((lessthan = strchr(referdata->referred_by_name, '<'))) { 12759 *(lessthan - 1) = '\0'; /* Space */ 12760 } 12761 12762 referred_by_uri = get_in_brackets(h_referred_by); 12763 if (!strncasecmp(referred_by_uri, "sip:", 4)) { 12764 referred_by_uri += 4; /* Skip sip: */ 12765 } else if (!strncasecmp(referred_by_uri, "sips:", 5)) { 12766 referred_by_uri += 5; /* Skip sips: */ 12767 } else { 12768 ast_log(LOG_WARNING, "Huh? Not a sip: header (Referred-by: %s). Skipping.\n", referred_by_uri); 12769 referred_by_uri = NULL; 12770 } 12771 } 12772 12773 /* Check for arguments in the refer_to header */ 12774 if ((ptr = strcasestr(refer_to, "replaces="))) { 12775 char *to = NULL, *from = NULL; 12776 12777 /* This is an attended transfer */ 12778 referdata->attendedtransfer = 1; 12779 ast_copy_string(referdata->replaces_callid, ptr+9, sizeof(referdata->replaces_callid)); 12780 ast_uri_decode(referdata->replaces_callid); 12781 if ((ptr = strchr(referdata->replaces_callid, ';'))) /* Find options */ { 12782 *ptr++ = '\0'; 12783 } 12784 12785 if (ptr) { 12786 /* Find the different tags before we destroy the string */ 12787 to = strcasestr(ptr, "to-tag="); 12788 from = strcasestr(ptr, "from-tag="); 12789 } 12790 12791 /* Grab the to header */ 12792 if (to) { 12793 ptr = to + 7; 12794 if ((to = strchr(ptr, '&'))) 12795 *to = '\0'; 12796 if ((to = strchr(ptr, ';'))) 12797 *to = '\0'; 12798 ast_copy_string(referdata->replaces_callid_totag, ptr, sizeof(referdata->replaces_callid_totag)); 12799 } 12800 12801 if (from) { 12802 ptr = from + 9; 12803 if ((to = strchr(ptr, '&'))) 12804 *to = '\0'; 12805 if ((to = strchr(ptr, ';'))) 12806 *to = '\0'; 12807 ast_copy_string(referdata->replaces_callid_fromtag, ptr, sizeof(referdata->replaces_callid_fromtag)); 12808 } 12809 12810 if (!pedanticsipchecking) 12811 ast_debug(2, "Attended transfer: Will use Replace-Call-ID : %s (No check of from/to tags)\n", referdata->replaces_callid ); 12812 else 12813 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>" ); 12814 } 12815 12816 if ((ptr = strchr(refer_to, '@'))) { /* Separate domain */ 12817 char *urioption = NULL, *domain; 12818 *ptr++ = '\0'; 12819 12820 if ((urioption = strchr(ptr, ';'))) /* Separate urioptions */ 12821 *urioption++ = '\0'; 12822 12823 domain = ptr; 12824 if ((ptr = strchr(domain, ':'))) /* Remove :port */ 12825 *ptr = '\0'; 12826 12827 /* Save the domain for the dial plan */ 12828 ast_copy_string(referdata->refer_to_domain, domain, sizeof(referdata->refer_to_domain)); 12829 if (urioption) 12830 ast_copy_string(referdata->refer_to_urioption, urioption, sizeof(referdata->refer_to_urioption)); 12831 } 12832 12833 if ((ptr = strchr(refer_to, ';'))) /* Remove options */ 12834 *ptr = '\0'; 12835 ast_copy_string(referdata->refer_to, refer_to, sizeof(referdata->refer_to)); 12836 12837 if (referred_by_uri) { 12838 if ((ptr = strchr(referred_by_uri, ';'))) /* Remove options */ 12839 *ptr = '\0'; 12840 ast_copy_string(referdata->referred_by, referred_by_uri, sizeof(referdata->referred_by)); 12841 } else { 12842 referdata->referred_by[0] = '\0'; 12843 } 12844 12845 /* Determine transfer context */ 12846 if (transferer->owner) /* Mimic behaviour in res_features.c */ 12847 transfer_context = pbx_builtin_getvar_helper(transferer->owner, "TRANSFER_CONTEXT"); 12848 12849 /* By default, use the context in the channel sending the REFER */ 12850 if (ast_strlen_zero(transfer_context)) { 12851 transfer_context = S_OR(transferer->owner->macrocontext, 12852 S_OR(transferer->context, default_context)); 12853 } 12854 12855 ast_copy_string(referdata->refer_to_context, transfer_context, sizeof(referdata->refer_to_context)); 12856 12857 /* Either an existing extension or the parking extension */ 12858 if (referdata->attendedtransfer || ast_exists_extension(NULL, transfer_context, refer_to, 1, NULL) ) { 12859 if (sip_debug_test_pvt(transferer)) { 12860 ast_verbose("SIP transfer to extension %s@%s by %s\n", refer_to, transfer_context, referred_by_uri); 12861 } 12862 /* We are ready to transfer to the extension */ 12863 return 0; 12864 } 12865 if (sip_debug_test_pvt(transferer)) 12866 ast_verbose("Failed SIP Transfer to non-existing extension %s in context %s\n n", refer_to, transfer_context); 12867 12868 /* Failure, we can't find this extension */ 12869 return -1; 12870 }
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 13087 of file chan_sip.c.
References ast_copy_string(), and AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED.
Referenced by check_user_full().
13088 { 13089 char *start; 13090 char *end; 13091 13092 start = strchr(input, ':'); 13093 if (!start) { 13094 output[0] = '\0'; 13095 return 0; 13096 } 13097 start++; 13098 13099 /* we found "number" */ 13100 ast_copy_string(output, start, maxlen); 13101 output[maxlen-1] = '\0'; 13102 13103 end = strchr(output, '@'); 13104 if (end) 13105 *end = '\0'; 13106 else 13107 output[0] = '\0'; 13108 if (strstr(input, "privacy=full") || strstr(input, "privacy=uri")) 13109 return AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED; 13110 13111 return 0; 13112 }
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 6398 of file chan_sip.c.
References get_body_by_line(), REQ_OFFSET_TO_STR, sip_request::sdp_count, and sip_request::sdp_start.
06399 { 06400 int len = strlen(name); 06401 06402 while (*start < (req->sdp_start + req->sdp_count)) { 06403 const char *r = get_body_by_line(REQ_OFFSET_TO_STR(req, line[(*start)++]), name, len); 06404 if (r[0] != '\0') 06405 return r; 06406 } 06407 06408 /* if the line was not found, ensure that *start points past the SDP */ 06409 (*start)++; 06410 06411 return ""; 06412 }
static char get_sdp_line | ( | int * | start, | |
int | stop, | |||
struct sip_request * | req, | |||
const char ** | value | |||
) | [static] |
Fetches the next valid SDP line between the 'start' line (inclusive) and the 'stop' line (exclusive). Returns the type ('a', 'c', ...) and matching line in reference 'start' is updated with the next line number.
Definition at line 6419 of file chan_sip.c.
References ast_skip_blanks(), REQ_OFFSET_TO_STR, sip_request::sdp_count, and sip_request::sdp_start.
Referenced by process_sdp().
06420 { 06421 char type = '\0'; 06422 const char *line = NULL; 06423 06424 if (stop > (req->sdp_start + req->sdp_count)) { 06425 stop = req->sdp_start + req->sdp_count; 06426 } 06427 06428 while (*start < stop) { 06429 line = REQ_OFFSET_TO_STR(req, line[(*start)++]); 06430 if (line[1] == '=') { 06431 type = line[0]; 06432 *value = ast_skip_blanks(line + 2); 06433 break; 06434 } 06435 } 06436 06437 return type; 06438 }
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 12616 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().
12617 { 12618 struct sip_pvt *sip_pvt_ptr; 12619 struct sip_pvt tmp_dialog = { 12620 .callid = callid, 12621 }; 12622 12623 if (totag) 12624 ast_debug(4, "Looking for callid %s (fromtag %s totag %s)\n", callid, fromtag ? fromtag : "<no fromtag>", totag ? totag : "<no totag>"); 12625 12626 /* Search dialogs and find the match */ 12627 12628 sip_pvt_ptr = ao2_t_find(dialogs, &tmp_dialog, OBJ_POINTER, "ao2_find of dialog in dialogs table"); 12629 if (sip_pvt_ptr) { 12630 /* Go ahead and lock it (and its owner) before returning */ 12631 sip_pvt_lock(sip_pvt_ptr); 12632 if (pedanticsipchecking) { 12633 unsigned char frommismatch = 0, tomismatch = 0; 12634 12635 if (ast_strlen_zero(fromtag)) { 12636 sip_pvt_unlock(sip_pvt_ptr); 12637 ast_debug(4, "Matched %s call for callid=%s - no from tag specified, pedantic check fails\n", 12638 sip_pvt_ptr->outgoing_call == TRUE ? "OUTGOING": "INCOMING", sip_pvt_ptr->callid); 12639 return NULL; 12640 } 12641 12642 if (ast_strlen_zero(totag)) { 12643 sip_pvt_unlock(sip_pvt_ptr); 12644 ast_debug(4, "Matched %s call for callid=%s - no to tag specified, pedantic check fails\n", 12645 sip_pvt_ptr->outgoing_call == TRUE ? "OUTGOING": "INCOMING", sip_pvt_ptr->callid); 12646 return NULL; 12647 } 12648 /* RFC 3891 12649 * > 3. User Agent Server Behavior: Receiving a Replaces Header 12650 * > The Replaces header contains information used to match an existing 12651 * > SIP dialog (call-id, to-tag, and from-tag). Upon receiving an INVITE 12652 * > with a Replaces header, the User Agent (UA) attempts to match this 12653 * > information with a confirmed or early dialog. The User Agent Server 12654 * > (UAS) matches the to-tag and from-tag parameters as if they were tags 12655 * > present in an incoming request. In other words, the to-tag parameter 12656 * > is compared to the local tag, and the from-tag parameter is compared 12657 * > to the remote tag. 12658 * 12659 * Thus, the totag is always compared to the local tag, regardless if 12660 * this our call is an incoming or outgoing call. 12661 */ 12662 frommismatch = !!strcmp(fromtag, sip_pvt_ptr->theirtag); 12663 tomismatch = !!strcmp(totag, sip_pvt_ptr->tag); 12664 if (frommismatch || tomismatch) { 12665 sip_pvt_unlock(sip_pvt_ptr); 12666 if (frommismatch) { 12667 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", 12668 sip_pvt_ptr->outgoing_call == TRUE ? "OUTGOING": "INCOMING", sip_pvt_ptr->callid, 12669 fromtag, sip_pvt_ptr->theirtag); 12670 } 12671 if (tomismatch) { 12672 ast_debug(4, "Matched %s call for callid=%s - pedantic to tag check fails; their tag is %s our tag is %s\n", 12673 sip_pvt_ptr->outgoing_call == TRUE ? "OUTGOING": "INCOMING", sip_pvt_ptr->callid, 12674 totag, sip_pvt_ptr->tag); 12675 } 12676 return NULL; 12677 } 12678 } 12679 12680 if (totag) 12681 ast_debug(4, "Matched %s call - their tag is %s Our tag is %s\n", 12682 sip_pvt_ptr->outgoing_call == TRUE ? "OUTGOING": "INCOMING", 12683 sip_pvt_ptr->theirtag, sip_pvt_ptr->tag); 12684 12685 /* deadlock avoidance... */ 12686 while (sip_pvt_ptr->owner && ast_channel_trylock(sip_pvt_ptr->owner)) { 12687 sip_pvt_unlock(sip_pvt_ptr); 12688 usleep(1); 12689 sip_pvt_lock(sip_pvt_ptr); 12690 } 12691 } 12692 12693 return sip_pvt_ptr; 12694 }
static const char* get_transport | ( | enum sip_transport | t | ) | [inline, static] |
Definition at line 3141 of file chan_sip.c.
References SIP_TRANSPORT_TCP, SIP_TRANSPORT_TLS, and SIP_TRANSPORT_UDP.
Referenced by _sip_show_peer(), ast_sip_ouraddrfor(), build_contact(), build_peer(), create_addr(), get_transport_pvt(), handle_request_do(), parse_moved_contact(), sip_show_tcp(), transmit_notify_with_mwi(), and transmit_register().
03142 { 03143 switch (t) { 03144 case SIP_TRANSPORT_UDP: 03145 return "UDP"; 03146 case SIP_TRANSPORT_TCP: 03147 return "TCP"; 03148 case SIP_TRANSPORT_TLS: 03149 return "TLS"; 03150 } 03151 03152 return "UNKNOWN"; 03153 }
static const char* get_transport_list | ( | struct sip_peer * | peer | ) | [inline, static] |
Definition at line 3121 of file chan_sip.c.
References SIP_TRANSPORT_TCP, SIP_TRANSPORT_TLS, SIP_TRANSPORT_UDP, and sip_peer::transports.
03121 { 03122 switch (peer->transports) { 03123 case SIP_TRANSPORT_UDP: 03124 return "UDP"; 03125 case SIP_TRANSPORT_TCP: 03126 return "TCP"; 03127 case SIP_TRANSPORT_TLS: 03128 return "TLS"; 03129 case SIP_TRANSPORT_UDP | SIP_TRANSPORT_TCP: 03130 return "TCP,UDP"; 03131 case SIP_TRANSPORT_UDP | SIP_TRANSPORT_TLS: 03132 return "TLS,UDP"; 03133 case SIP_TRANSPORT_TCP | SIP_TRANSPORT_TLS: 03134 return "TLS,TCP"; 03135 default: 03136 return peer->transports ? 03137 "TLS,TCP,UDP" : "UNKNOWN"; 03138 } 03139 }
static const char* get_transport_pvt | ( | struct sip_pvt * | p | ) | [inline, static] |
Definition at line 3155 of file chan_sip.c.
References get_transport(), sip_pvt::outboundproxy, set_socket_transport(), sip_pvt::socket, sip_proxy::transport, and sip_socket::type.
Referenced by __sip_xmit(), and build_via().
03156 { 03157 if (p->outboundproxy && p->outboundproxy->transport) { 03158 set_socket_transport(&p->socket, p->outboundproxy->transport); 03159 } 03160 03161 return get_transport(p->socket.type); 03162 }
static int get_transport_str2enum | ( | const char * | transport | ) | [static] |
Return int representing a bit field of transport types found in const char *transport.
Definition at line 3100 of file chan_sip.c.
References ast_strlen_zero(), SIP_TRANSPORT_TCP, SIP_TRANSPORT_TLS, and SIP_TRANSPORT_UDP.
Referenced by __set_address_from_contact(), and parse_register_contact().
03101 { 03102 int res = 0; 03103 03104 if (ast_strlen_zero(transport)) { 03105 return res; 03106 } 03107 03108 if (!strcasecmp(transport, "udp")) { 03109 res |= SIP_TRANSPORT_UDP; 03110 } 03111 if (!strcasecmp(transport, "tcp")) { 03112 res |= SIP_TRANSPORT_TCP; 03113 } 03114 if (!strcasecmp(transport, "tls")) { 03115 res |= SIP_TRANSPORT_TLS; 03116 } 03117 03118 return res; 03119 }
static const char * gettag | ( | const struct sip_request * | req, | |
const char * | header, | |||
char * | tagbuf, | |||
int | tagbufsize | |||
) | [static] |
Get tag from packet.
Definition at line 18151 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().
18152 { 18153 const char *thetag; 18154 18155 if (!tagbuf) 18156 return NULL; 18157 tagbuf[0] = '\0'; /* reset the buffer */ 18158 thetag = get_header(req, header); 18159 thetag = strcasestr(thetag, ";tag="); 18160 if (thetag) { 18161 thetag += 5; 18162 ast_copy_string(tagbuf, thetag, tagbufsize); 18163 return strsep(&tagbuf, ";"); 18164 } 18165 return NULL; 18166 }
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 22384 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_FAX_DETECT, SIP_PAGE2_IGNORESDPVERSION, SIP_PAGE2_RFC2833_COMPENSATE, SIP_PAGE2_TEXTSUPPORT, 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().
22385 { 22386 int res = 1; 22387 22388 if (!strcasecmp(v->name, "trustrpid")) { 22389 ast_set_flag(&mask[0], SIP_TRUSTRPID); 22390 ast_set2_flag(&flags[0], ast_true(v->value), SIP_TRUSTRPID); 22391 } else if (!strcasecmp(v->name, "sendrpid")) { 22392 ast_set_flag(&mask[0], SIP_SENDRPID); 22393 ast_set2_flag(&flags[0], ast_true(v->value), SIP_SENDRPID); 22394 } else if (!strcasecmp(v->name, "g726nonstandard")) { 22395 ast_set_flag(&mask[0], SIP_G726_NONSTANDARD); 22396 ast_set2_flag(&flags[0], ast_true(v->value), SIP_G726_NONSTANDARD); 22397 } else if (!strcasecmp(v->name, "useclientcode")) { 22398 ast_set_flag(&mask[0], SIP_USECLIENTCODE); 22399 ast_set2_flag(&flags[0], ast_true(v->value), SIP_USECLIENTCODE); 22400 } else if (!strcasecmp(v->name, "dtmfmode")) { 22401 ast_set_flag(&mask[0], SIP_DTMF); 22402 ast_clear_flag(&flags[0], SIP_DTMF); 22403 if (!strcasecmp(v->value, "inband")) 22404 ast_set_flag(&flags[0], SIP_DTMF_INBAND); 22405 else if (!strcasecmp(v->value, "rfc2833")) 22406 ast_set_flag(&flags[0], SIP_DTMF_RFC2833); 22407 else if (!strcasecmp(v->value, "info")) 22408 ast_set_flag(&flags[0], SIP_DTMF_INFO); 22409 else if (!strcasecmp(v->value, "shortinfo")) 22410 ast_set_flag(&flags[0], SIP_DTMF_SHORTINFO); 22411 else if (!strcasecmp(v->value, "auto")) 22412 ast_set_flag(&flags[0], SIP_DTMF_AUTO); 22413 else { 22414 ast_log(LOG_WARNING, "Unknown dtmf mode '%s' on line %d, using rfc2833\n", v->value, v->lineno); 22415 ast_set_flag(&flags[0], SIP_DTMF_RFC2833); 22416 } 22417 } else if (!strcasecmp(v->name, "nat")) { 22418 ast_set_flag(&mask[0], SIP_NAT); 22419 ast_clear_flag(&flags[0], SIP_NAT); 22420 if (!strcasecmp(v->value, "never")) 22421 ast_set_flag(&flags[0], SIP_NAT_NEVER); 22422 else if (!strcasecmp(v->value, "route")) 22423 ast_set_flag(&flags[0], SIP_NAT_ROUTE); 22424 else if (ast_true(v->value)) 22425 ast_set_flag(&flags[0], SIP_NAT_ALWAYS); 22426 else 22427 ast_set_flag(&flags[0], SIP_NAT_RFC3581); 22428 } else if (!strcasecmp(v->name, "canreinvite")) { 22429 ast_set_flag(&mask[0], SIP_REINVITE); 22430 ast_clear_flag(&flags[0], SIP_REINVITE); 22431 if (ast_true(v->value)) { 22432 ast_set_flag(&flags[0], SIP_CAN_REINVITE | SIP_CAN_REINVITE_NAT); 22433 } else if (!ast_false(v->value)) { 22434 char buf[64]; 22435 char *word, *next = buf; 22436 22437 ast_copy_string(buf, v->value, sizeof(buf)); 22438 while ((word = strsep(&next, ","))) { 22439 if (!strcasecmp(word, "update")) { 22440 ast_set_flag(&flags[0], SIP_REINVITE_UPDATE | SIP_CAN_REINVITE); 22441 } else if (!strcasecmp(word, "nonat")) { 22442 ast_set_flag(&flags[0], SIP_CAN_REINVITE); 22443 ast_clear_flag(&flags[0], SIP_CAN_REINVITE_NAT); 22444 } else { 22445 ast_log(LOG_WARNING, "Unknown canreinvite mode '%s' on line %d\n", v->value, v->lineno); 22446 } 22447 } 22448 } 22449 } else if (!strcasecmp(v->name, "insecure")) { 22450 ast_set_flag(&mask[0], SIP_INSECURE); 22451 ast_clear_flag(&flags[0], SIP_INSECURE); 22452 set_insecure_flags(&flags[0], v->value, v->lineno); 22453 } else if (!strcasecmp(v->name, "progressinband")) { 22454 ast_set_flag(&mask[0], SIP_PROG_INBAND); 22455 ast_clear_flag(&flags[0], SIP_PROG_INBAND); 22456 if (ast_true(v->value)) 22457 ast_set_flag(&flags[0], SIP_PROG_INBAND_YES); 22458 else if (strcasecmp(v->value, "never")) 22459 ast_set_flag(&flags[0], SIP_PROG_INBAND_NO); 22460 } else if (!strcasecmp(v->name, "promiscredir")) { 22461 ast_set_flag(&mask[0], SIP_PROMISCREDIR); 22462 ast_set2_flag(&flags[0], ast_true(v->value), SIP_PROMISCREDIR); 22463 } else if (!strcasecmp(v->name, "videosupport")) { 22464 if (!strcasecmp(v->value, "always")) { 22465 ast_set_flag(&mask[1], SIP_PAGE2_VIDEOSUPPORT_ALWAYS); 22466 ast_set_flag(&flags[1], SIP_PAGE2_VIDEOSUPPORT_ALWAYS); 22467 } else { 22468 ast_set_flag(&mask[1], SIP_PAGE2_VIDEOSUPPORT); 22469 ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_VIDEOSUPPORT); 22470 } 22471 } else if (!strcasecmp(v->name, "textsupport")) { 22472 ast_set_flag(&mask[1], SIP_PAGE2_TEXTSUPPORT); 22473 ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_TEXTSUPPORT); 22474 res = 1; 22475 } else if (!strcasecmp(v->name, "allowoverlap")) { 22476 ast_set_flag(&mask[1], SIP_PAGE2_ALLOWOVERLAP); 22477 ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_ALLOWOVERLAP); 22478 } else if (!strcasecmp(v->name, "allowsubscribe")) { 22479 ast_set_flag(&mask[1], SIP_PAGE2_ALLOWSUBSCRIBE); 22480 ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_ALLOWSUBSCRIBE); 22481 } else if (!strcasecmp(v->name, "ignoresdpversion")) { 22482 ast_set_flag(&mask[1], SIP_PAGE2_IGNORESDPVERSION); 22483 ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_IGNORESDPVERSION); 22484 } else if (!strcasecmp(v->name, "rfc2833compensate")) { 22485 ast_set_flag(&mask[1], SIP_PAGE2_RFC2833_COMPENSATE); 22486 ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_RFC2833_COMPENSATE); 22487 } else if (!strcasecmp(v->name, "buggymwi")) { 22488 ast_set_flag(&mask[1], SIP_PAGE2_BUGGY_MWI); 22489 ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_BUGGY_MWI); 22490 } else if (!strcasecmp(v->name, "faxdetect")) { 22491 ast_set_flag(&mask[1], SIP_PAGE2_FAX_DETECT); 22492 ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_FAX_DETECT); 22493 } else 22494 res = 0; 22495 22496 return res; 22497 }
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 20650 of file chan_sip.c.
References __sip_ack(), 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, LOG_DEBUG, LOG_ERROR, LOG_NOTICE, LOG_WARNING, sip_request::method, sip_pvt::method, sip_pvt::needdestroy, option_debug, 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().
20651 { 20652 /* Called with p->lock held, as well as p->owner->lock if appropriate, keeping things 20653 relatively static */ 20654 const char *cmd; 20655 const char *cseq; 20656 const char *useragent; 20657 int seqno; 20658 int len; 20659 int respid; 20660 int res = 0; 20661 int debug = sip_debug_test_pvt(p); 20662 char *e; 20663 int error = 0; 20664 int oldmethod = p->method; 20665 int acked = 0; 20666 20667 /* Get Method and Cseq */ 20668 cseq = get_header(req, "Cseq"); 20669 cmd = REQ_OFFSET_TO_STR(req, header[0]); 20670 20671 /* Must have Cseq */ 20672 if (ast_strlen_zero(cmd) || ast_strlen_zero(cseq)) { 20673 ast_log(LOG_ERROR, "Missing Cseq. Dropping this SIP message, it's incomplete.\n"); 20674 error = 1; 20675 } 20676 if (!error && sscanf(cseq, "%30d%n", &seqno, &len) != 1) { 20677 ast_log(LOG_ERROR, "No seqno in '%s'. Dropping incomplete message.\n", cmd); 20678 error = 1; 20679 } 20680 if (error) { 20681 if (!p->initreq.headers) /* New call */ 20682 p->needdestroy = 1; /* Make sure we destroy this dialog */ 20683 return -1; 20684 } 20685 /* Get the command XXX */ 20686 20687 cmd = REQ_OFFSET_TO_STR(req, rlPart1); 20688 e = ast_skip_blanks(REQ_OFFSET_TO_STR(req, rlPart2)); 20689 20690 /* Save useragent of the client */ 20691 useragent = get_header(req, "User-Agent"); 20692 if (!ast_strlen_zero(useragent)) 20693 ast_string_field_set(p, useragent, useragent); 20694 20695 /* Find out SIP method for incoming request */ 20696 if (req->method == SIP_RESPONSE) { /* Response to our request */ 20697 /* ignore means "don't do anything with it" but still have to 20698 * respond appropriately. 20699 * But in this case this is a response already, so we really 20700 * have nothing to do with this message, and even setting the 20701 * ignore flag is pointless. 20702 */ 20703 if (ast_strlen_zero(e)) { 20704 return 0; 20705 } 20706 if (sscanf(e, "%30d %n", &respid, &len) != 1) { 20707 ast_log(LOG_WARNING, "Invalid response: '%s'\n", e); 20708 return 0; 20709 } 20710 if (respid <= 0) { 20711 ast_log(LOG_WARNING, "Invalid SIP response code: '%d'\n", respid); 20712 return 0; 20713 } 20714 if (p->ocseq && (p->ocseq < seqno)) { 20715 if (option_debug) 20716 ast_log(LOG_DEBUG, "Ignoring out of order response %d (expecting %d)\n", seqno, p->ocseq); 20717 return -1; 20718 } else { 20719 if ((respid == 200) || ((respid >= 300) && (respid <= 399))) { 20720 extract_uri(p, req); 20721 } 20722 handle_response(p, respid, e + len, req, seqno); 20723 } 20724 return 0; 20725 } 20726 20727 /* New SIP request coming in 20728 (could be new request in existing SIP dialog as well...) 20729 */ 20730 20731 p->method = req->method; /* Find out which SIP method they are using */ 20732 ast_debug(4, "**** Received %s (%d) - Command in SIP %s\n", sip_methods[p->method].text, sip_methods[p->method].id, cmd); 20733 20734 if (p->icseq && (p->icseq > seqno) ) { 20735 if (p->pendinginvite && seqno == p->pendinginvite && (req->method == SIP_ACK || req->method == SIP_CANCEL)) { 20736 ast_debug(2, "Got CANCEL or ACK on INVITE with transactions in between.\n"); 20737 } else { 20738 ast_debug(1, "Ignoring too old SIP packet packet %d (expecting >= %d)\n", seqno, p->icseq); 20739 if (req->method != SIP_ACK) 20740 transmit_response(p, "503 Server error", req); /* We must respond according to RFC 3261 sec 12.2 */ 20741 return -1; 20742 } 20743 } else if (p->icseq && 20744 p->icseq == seqno && 20745 req->method != SIP_ACK && 20746 (p->method != SIP_CANCEL || p->alreadygone)) { 20747 /* ignore means "don't do anything with it" but still have to 20748 respond appropriately. We do this if we receive a repeat of 20749 the last sequence number */ 20750 req->ignore = 1; 20751 ast_debug(3, "Ignoring SIP message because of retransmit (%s Seqno %d, ours %d)\n", sip_methods[p->method].text, p->icseq, seqno); 20752 } 20753 20754 if (seqno >= p->icseq) 20755 /* Next should follow monotonically (but not necessarily 20756 incrementally -- thanks again to the genius authors of SIP -- 20757 increasing */ 20758 p->icseq = seqno; 20759 20760 /* Find their tag if we haven't got it */ 20761 if (ast_strlen_zero(p->theirtag)) { 20762 char tag[128]; 20763 20764 gettag(req, "From", tag, sizeof(tag)); 20765 ast_string_field_set(p, theirtag, tag); 20766 } 20767 snprintf(p->lastmsg, sizeof(p->lastmsg), "Rx: %s", cmd); 20768 20769 if (pedanticsipchecking) { 20770 /* If this is a request packet without a from tag, it's not 20771 correct according to RFC 3261 */ 20772 /* Check if this a new request in a new dialog with a totag already attached to it, 20773 RFC 3261 - section 12.2 - and we don't want to mess with recovery */ 20774 if (!p->initreq.headers && req->has_to_tag) { 20775 /* If this is a first request and it got a to-tag, it is not for us */ 20776 if (!req->ignore && req->method == SIP_INVITE) { 20777 transmit_response_reliable(p, "481 Call/Transaction Does Not Exist", req); 20778 /* Will cease to exist after ACK */ 20779 } else if (req->method != SIP_ACK) { 20780 transmit_response(p, "481 Call/Transaction Does Not Exist", req); 20781 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 20782 } else { 20783 ast_debug(1, "Got ACK for unknown dialog... strange.\n"); 20784 } 20785 return res; 20786 } 20787 } 20788 20789 if (!e && (p->method == SIP_INVITE || p->method == SIP_SUBSCRIBE || p->method == SIP_REGISTER || p->method == SIP_NOTIFY)) { 20790 transmit_response(p, "400 Bad request", req); 20791 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 20792 return -1; 20793 } 20794 20795 /* Handle various incoming SIP methods in requests */ 20796 switch (p->method) { 20797 case SIP_OPTIONS: 20798 res = handle_request_options(p, req); 20799 break; 20800 case SIP_INVITE: 20801 res = handle_request_invite(p, req, debug, seqno, sin, recount, e, nounlock); 20802 break; 20803 case SIP_REFER: 20804 res = handle_request_refer(p, req, debug, seqno, nounlock); 20805 break; 20806 case SIP_CANCEL: 20807 res = handle_request_cancel(p, req); 20808 break; 20809 case SIP_BYE: 20810 res = handle_request_bye(p, req); 20811 break; 20812 case SIP_MESSAGE: 20813 res = handle_request_message(p, req); 20814 break; 20815 case SIP_SUBSCRIBE: 20816 res = handle_request_subscribe(p, req, sin, seqno, e); 20817 break; 20818 case SIP_REGISTER: 20819 res = handle_request_register(p, req, sin, e); 20820 break; 20821 case SIP_INFO: 20822 if (req->debug) 20823 ast_verbose("Receiving INFO!\n"); 20824 if (!req->ignore) 20825 handle_request_info(p, req); 20826 else /* if ignoring, transmit response */ 20827 transmit_response(p, "200 OK", req); 20828 break; 20829 case SIP_NOTIFY: 20830 res = handle_request_notify(p, req, sin, seqno, e); 20831 break; 20832 case SIP_ACK: 20833 /* Make sure we don't ignore this */ 20834 if (seqno == p->pendinginvite) { 20835 p->invitestate = INV_TERMINATED; 20836 p->pendinginvite = 0; 20837 acked = __sip_ack(p, seqno, 1 /* response */, 0); 20838 if (find_sdp(req)) { 20839 if (process_sdp(p, req, SDP_T38_NONE)) 20840 return -1; 20841 } 20842 check_pendings(p); 20843 } else if (p->glareinvite == seqno) { 20844 /* handle ack for the 491 pending sent for glareinvite */ 20845 p->glareinvite = 0; 20846 acked = __sip_ack(p, seqno, 1, 0); 20847 } 20848 if (!acked) { 20849 /* Got an ACK that did not match anything. Ignore 20850 * silently and restore previous method */ 20851 p->method = oldmethod; 20852 } 20853 if (!p->lastinvite && ast_strlen_zero(p->randdata)) 20854 p->needdestroy = 1; 20855 break; 20856 default: 20857 transmit_response_with_allow(p, "501 Method Not Implemented", req, 0); 20858 ast_log(LOG_NOTICE, "Unknown SIP command '%s' from '%s'\n", 20859 cmd, ast_inet_ntoa(p->sa.sin_addr)); 20860 /* If this is some new method, and we don't have a call, destroy it now */ 20861 if (!p->initreq.headers) 20862 p->needdestroy = 1; 20863 break; 20864 } 20865 return res; 20866 }
static int handle_invite_replaces | ( | struct sip_pvt * | p, | |
struct sip_request * | req, | |||
int | debug, | |||
int | seqno, | |||
struct sockaddr_in * | sin, | |||
int * | nounlock | |||
) | [static] |
Handle the transfer part of INVITE with a replaces: header, meaning a target pickup or an attended transfer. Used only once. XXX 'ignore' is unused.
Definition at line 18351 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_do_masquerade(), ast_hangup(), ast_log(), ast_quiet_chan(), ast_set_flag, ast_setstate(), ast_state2str(), AST_STATE_DOWN, AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, DEFAULT_TRANS_TIMEOUT, dialog_unref(), FALSE, sip_pvt::flags, ast_channel::hangupcause, 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_lock, sip_pvt_unlock, sip_scheddestroy(), ast_channel::tech_pvt, transmit_response(), transmit_response_reliable(), transmit_response_with_sdp(), and XMIT_RELIABLE.
Referenced by handle_request_invite().
18352 { 18353 int earlyreplace = 0; 18354 int oneleggedreplace = 0; /* Call with no bridge, propably IVR or voice message */ 18355 struct ast_channel *c = p->owner; /* Our incoming call */ 18356 struct ast_channel *replacecall = p->refer->refer_call->owner; /* The channel we're about to take over */ 18357 struct ast_channel *targetcall; /* The bridge to the take-over target */ 18358 18359 struct ast_channel *test; 18360 18361 /* Check if we're in ring state */ 18362 if (replacecall->_state == AST_STATE_RING) 18363 earlyreplace = 1; 18364 18365 /* Check if we have a bridge */ 18366 if (!(targetcall = ast_bridged_channel(replacecall))) { 18367 /* We have no bridge */ 18368 if (!earlyreplace) { 18369 ast_debug(2, " Attended transfer attempted to replace call with no bridge (maybe ringing). Channel %s!\n", replacecall->name); 18370 oneleggedreplace = 1; 18371 } 18372 } 18373 if (targetcall && targetcall->_state == AST_STATE_RINGING) 18374 ast_debug(4, "SIP transfer: Target channel is in ringing state\n"); 18375 18376 if (targetcall) 18377 ast_debug(4, "SIP transfer: Invite Replace incoming channel should bridge to channel %s while hanging up channel %s\n", targetcall->name, replacecall->name); 18378 else 18379 ast_debug(4, "SIP transfer: Invite Replace incoming channel should replace and hang up channel %s (one call leg)\n", replacecall->name); 18380 18381 if (req->ignore) { 18382 ast_log(LOG_NOTICE, "Ignoring this INVITE with replaces in a stupid way.\n"); 18383 /* We should answer something here. If we are here, the 18384 call we are replacing exists, so an accepted 18385 can't harm */ 18386 transmit_response_with_sdp(p, "200 OK", req, XMIT_RELIABLE, FALSE); 18387 /* Do something more clever here */ 18388 if (c) { 18389 *nounlock = 1; 18390 ast_channel_unlock(c); 18391 } 18392 ast_channel_unlock(replacecall); 18393 sip_pvt_unlock(p->refer->refer_call); 18394 return 1; 18395 } 18396 if (!c) { 18397 /* What to do if no channel ??? */ 18398 ast_log(LOG_ERROR, "Unable to create new channel. Invite/replace failed.\n"); 18399 transmit_response_reliable(p, "503 Service Unavailable", req); 18400 append_history(p, "Xfer", "INVITE/Replace Failed. No new channel."); 18401 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 18402 ast_channel_unlock(replacecall); 18403 sip_pvt_unlock(p->refer->refer_call); 18404 return 1; 18405 } 18406 append_history(p, "Xfer", "INVITE/Replace received"); 18407 /* We have three channels to play with 18408 channel c: New incoming call 18409 targetcall: Call from PBX to target 18410 p->refer->refer_call: SIP pvt dialog from transferer to pbx. 18411 replacecall: The owner of the previous 18412 We need to masq C into refer_call to connect to 18413 targetcall; 18414 If we are talking to internal audio stream, target call is null. 18415 */ 18416 18417 /* Fake call progress */ 18418 transmit_response(p, "100 Trying", req); 18419 ast_setstate(c, AST_STATE_RING); 18420 18421 /* Masquerade the new call into the referred call to connect to target call 18422 Targetcall is not touched by the masq */ 18423 18424 /* Answer the incoming call and set channel to UP state */ 18425 transmit_response_with_sdp(p, "200 OK", req, XMIT_RELIABLE, FALSE); 18426 18427 ast_setstate(c, AST_STATE_UP); 18428 18429 /* Stop music on hold and other generators */ 18430 ast_quiet_chan(replacecall); 18431 ast_quiet_chan(targetcall); 18432 ast_debug(4, "Invite/Replaces: preparing to masquerade %s into %s\n", c->name, replacecall->name); 18433 18434 /* Make sure that the masq does not free our PVT for the old call */ 18435 if (! earlyreplace && ! oneleggedreplace ) 18436 ast_set_flag(&p->refer->refer_call->flags[0], SIP_DEFER_BYE_ON_TRANSFER); /* Delay hangup */ 18437 18438 /* Prepare the masquerade - if this does not happen, we will be gone */ 18439 if(ast_channel_masquerade(replacecall, c)) 18440 ast_log(LOG_ERROR, "Failed to masquerade C into Replacecall\n"); 18441 else 18442 ast_debug(4, "Invite/Replaces: Going to masquerade %s into %s\n", c->name, replacecall->name); 18443 18444 /* C should now be in place of replacecall */ 18445 if (ast_do_masquerade(replacecall)) { 18446 ast_log(LOG_WARNING, "Failed to perform masquerade with INVITE replaces\n"); 18447 } 18448 18449 if (earlyreplace || oneleggedreplace ) { 18450 c->hangupcause = AST_CAUSE_SWITCH_CONGESTION; 18451 } 18452 18453 ast_setstate(c, AST_STATE_DOWN); 18454 ast_debug(4, "After transfer:----------------------------\n"); 18455 ast_debug(4, " -- C: %s State %s\n", c->name, ast_state2str(c->_state)); 18456 if (replacecall) 18457 ast_debug(4, " -- replacecall: %s State %s\n", replacecall->name, ast_state2str(replacecall->_state)); 18458 if (p->owner) { 18459 ast_debug(4, " -- P->owner: %s State %s\n", p->owner->name, ast_state2str(p->owner->_state)); 18460 test = ast_bridged_channel(p->owner); 18461 if (test) 18462 ast_debug(4, " -- Call bridged to P->owner: %s State %s\n", test->name, ast_state2str(test->_state)); 18463 else 18464 ast_debug(4, " -- No call bridged to C->owner \n"); 18465 } else 18466 ast_debug(4, " -- No channel yet \n"); 18467 ast_debug(4, "End After transfer:----------------------------\n"); 18468 18469 /* unlock sip pvt and owner so hangup can do its thing */ 18470 ast_channel_unlock(replacecall); 18471 ast_channel_unlock(c); 18472 sip_pvt_unlock(p->refer->refer_call); 18473 sip_pvt_unlock(p); 18474 *nounlock = 1; 18475 18476 /* The call should be down with no ast_channel, so hang it up */ 18477 c->tech_pvt = dialog_unref(c->tech_pvt, "unref dialog c->tech_pvt"); 18478 ast_hangup(c); 18479 sip_pvt_lock(p); /* lock PVT structure again after hangup */ 18480 18481 return 0; 18482 }
static int handle_request_bye | ( | struct sip_pvt * | p, | |
struct sip_request * | req | |||
) | [static] |
Handle incoming BYE request.
Definition at line 20119 of file chan_sip.c.
References __sip_pretend_ack(), append_history, ast_async_goto(), ast_bridged_channel(), AST_CAUSE_PROTOCOL_ERROR, ast_channel_trylock, ast_channel_unlock, 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_pvt_lock, sip_pvt_unlock, 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().
20120 { 20121 struct ast_channel *c=NULL; 20122 int res; 20123 struct ast_channel *bridged_to; 20124 20125 /* If we have an INCOMING invite that we haven't answered, terminate that transaction */ 20126 if (p->pendinginvite && !ast_test_flag(&p->flags[0], SIP_OUTGOING) && !req->ignore) { 20127 transmit_response_reliable(p, "487 Request Terminated", &p->initreq); 20128 } 20129 20130 __sip_pretend_ack(p); 20131 20132 p->invitestate = INV_TERMINATED; 20133 20134 copy_request(&p->initreq, req); 20135 if (sipdebug) 20136 ast_debug(1, "Initializing initreq for method %s - callid %s\n", sip_methods[req->method].text, p->callid); 20137 check_via(p, req); 20138 sip_alreadygone(p); 20139 20140 /* Get RTCP quality before end of call */ 20141 if (p->do_history || p->owner) { 20142 struct ast_channel *bridge = p->owner ? ast_bridged_channel(p->owner) : NULL; 20143 char *videoqos, *textqos; 20144 20145 /* We need to get the lock on bridge because ast_rtp_set_vars will attempt 20146 * to lock the bridge. This may get hairy... 20147 */ 20148 while (bridge && ast_channel_trylock(bridge)) { 20149 ast_channel_unlock(p->owner); 20150 do { 20151 /* Can't use DEADLOCK_AVOIDANCE since p is an ao2 object */ 20152 sip_pvt_unlock(p); 20153 usleep(1); 20154 sip_pvt_lock(p); 20155 } while (p->owner && ast_channel_trylock(p->owner)); 20156 bridge = p->owner ? ast_bridged_channel(p->owner) : NULL; 20157 } 20158 20159 if (p->rtp) { 20160 if (p->do_history) { 20161 char *audioqos, 20162 *audioqos_jitter, 20163 *audioqos_loss, 20164 *audioqos_rtt; 20165 20166 audioqos = ast_rtp_get_quality(p->rtp, NULL, RTPQOS_SUMMARY); 20167 audioqos_jitter = ast_rtp_get_quality(p->rtp, NULL, RTPQOS_JITTER); 20168 audioqos_loss = ast_rtp_get_quality(p->rtp, NULL, RTPQOS_LOSS); 20169 audioqos_rtt = ast_rtp_get_quality(p->rtp, NULL, RTPQOS_RTT); 20170 20171 append_history(p, "RTCPaudio", "Quality:%s", audioqos); 20172 append_history(p, "RTCPaudioJitter", "Quality:%s", audioqos_jitter); 20173 append_history(p, "RTCPaudioLoss", "Quality:%s", audioqos_loss); 20174 append_history(p, "RTCPaudioRTT", "Quality:%s", audioqos_rtt); 20175 } 20176 20177 if (p->owner) { 20178 ast_rtp_set_vars(p->owner, p->rtp); 20179 } 20180 } 20181 20182 if (bridge) { 20183 struct sip_pvt *q = bridge->tech_pvt; 20184 20185 if (IS_SIP_TECH(bridge->tech) && q && q->rtp) 20186 ast_rtp_set_vars(bridge, q->rtp); 20187 ast_channel_unlock(bridge); 20188 } 20189 20190 if (p->vrtp) { 20191 videoqos = ast_rtp_get_quality(p->vrtp, NULL, RTPQOS_SUMMARY); 20192 if (p->do_history) 20193 append_history(p, "RTCPvideo", "Quality:%s", videoqos); 20194 if (p->owner) 20195 pbx_builtin_setvar_helper(p->owner, "RTPVIDEOQOS", videoqos); 20196 } 20197 20198 if (p->trtp) { 20199 textqos = ast_rtp_get_quality(p->trtp, NULL, RTPQOS_SUMMARY); 20200 if (p->do_history) 20201 append_history(p, "RTCPtext", "Quality:%s", textqos); 20202 if (p->owner) 20203 pbx_builtin_setvar_helper(p->owner, "RTPTEXTQOS", textqos); 20204 } 20205 } 20206 20207 stop_media_flows(p); /* Immediately stop RTP, VRTP and UDPTL as applicable */ 20208 stop_session_timer(p); /* Stop Session-Timer */ 20209 20210 if (!ast_strlen_zero(get_header(req, "Also"))) { 20211 ast_log(LOG_NOTICE, "Client '%s' using deprecated BYE/Also transfer method. Ask vendor to support REFER instead\n", 20212 ast_inet_ntoa(p->recv.sin_addr)); 20213 if (ast_strlen_zero(p->context)) 20214 ast_string_field_set(p, context, default_context); 20215 res = get_also_info(p, req); 20216 if (!res) { 20217 c = p->owner; 20218 if (c) { 20219 bridged_to = ast_bridged_channel(c); 20220 if (bridged_to) { 20221 /* Don't actually hangup here... */ 20222 ast_queue_control(c, AST_CONTROL_UNHOLD); 20223 ast_async_goto(bridged_to, p->context, p->refer->refer_to, 1); 20224 } else 20225 ast_queue_hangup(p->owner); 20226 } 20227 } else { 20228 ast_log(LOG_WARNING, "Invalid transfer information from '%s'\n", ast_inet_ntoa(p->recv.sin_addr)); 20229 if (p->owner) 20230 ast_queue_hangup_with_cause(p->owner, AST_CAUSE_PROTOCOL_ERROR); 20231 } 20232 } else if (p->owner) { 20233 ast_queue_hangup(p->owner); 20234 ast_debug(3, "Received bye, issuing owner hangup\n"); 20235 } else { 20236 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 20237 ast_debug(3, "Received bye, no owner, selfdestruct soon.\n"); 20238 } 20239 ast_clear_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED); 20240 transmit_response(p, "200 OK", req); 20241 20242 return 1; 20243 }
static int handle_request_cancel | ( | struct sip_pvt * | p, | |
struct sip_request * | req | |||
) | [static] |
Handle incoming CANCEL request.
Definition at line 19943 of file chan_sip.c.
References __sip_pretend_ack(), ast_debug, ast_free, ast_queue_hangup(), AST_SCHED_DEL, AST_STATE_UP, ast_test_flag, check_via(), DEC_CALL_LIMIT, DEFAULT_TRANS_TIMEOUT, INV_CANCELLED, INV_TERMINATED, sip_pvt::invitestate, sip_pkt::next, sip_dual::req, sip_pkt::response_code, sip_pkt::retransid, sched, sip_pkt::seqno, sip_alreadygone(), SIP_INC_COUNT, SIP_PAGE2_CALL_ONHOLD, sip_scheddestroy(), stop_media_flows(), transmit_response(), transmit_response_reliable(), UNLINK, and update_call_counter().
Referenced by handle_incoming().
19944 { 19945 19946 check_via(p, req); 19947 sip_alreadygone(p); 19948 19949 /* At this point, we could have cancelled the invite at the same time 19950 as the other side sends a CANCEL. Our final reply with error code 19951 might not have been received by the other side before the CANCEL 19952 was sent, so let's just give up retransmissions and waiting for 19953 ACK on our error code. The call is hanging up any way. */ 19954 if (p->invitestate == INV_TERMINATED) 19955 __sip_pretend_ack(p); 19956 else 19957 p->invitestate = INV_CANCELLED; 19958 19959 if (p->owner && p->owner->_state == AST_STATE_UP) { 19960 /* This call is up, cancel is ignored, we need a bye */ 19961 transmit_response(p, "200 OK", req); 19962 ast_debug(1, "Got CANCEL on an answered call. Ignoring... \n"); 19963 return 0; 19964 } 19965 19966 if (ast_test_flag(&p->flags[0], SIP_INC_COUNT) || ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD)) 19967 update_call_counter(p, DEC_CALL_LIMIT); 19968 19969 stop_media_flows(p); /* Immediately stop RTP, VRTP and UDPTL as applicable */ 19970 if (p->owner) 19971 ast_queue_hangup(p->owner); 19972 else 19973 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 19974 if (p->initreq.len > 0) { 19975 struct sip_pkt *pkt, *prev_pkt; 19976 /* If the CANCEL we are receiving is a retransmission, and we already have scheduled 19977 * a reliable 487, then we don't want to schedule another one on top of the previous 19978 * one. 19979 * 19980 * As odd as this may sound, we can't rely on the previously-transmitted "reliable" 19981 * response in this situation. What if we've sent all of our reliable responses 19982 * already and now all of a sudden, we get this second CANCEL? 19983 * 19984 * The only way to do this correctly is to cancel our previously-scheduled reliably- 19985 * transmitted response and send a new one in its place. 19986 */ 19987 for (pkt = p->packets, prev_pkt = NULL; pkt; prev_pkt = pkt, pkt = pkt->next) { 19988 if (pkt->seqno == p->lastinvite && pkt->response_code == 487) { 19989 AST_SCHED_DEL(sched, pkt->retransid); 19990 UNLINK(pkt, p->packets, prev_pkt); 19991 ast_free(pkt); 19992 break; 19993 } 19994 } 19995 transmit_response_reliable(p, "487 Request Terminated", &p->initreq); 19996 transmit_response(p, "200 OK", req); 19997 return 1; 19998 } else { 19999 transmit_response(p, "481 Call Leg Does Not Exist", req); 20000 return 0; 20001 } 20002 }
static int handle_request_do | ( | struct sip_request * | req, | |
struct sockaddr_in * | sin | |||
) | [static] |
Definition at line 21008 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().
21009 { 21010 struct sip_pvt *p; 21011 int recount = 0; 21012 int nounlock = 0; 21013 int lockretry; 21014 21015 if (sip_debug_test_addr(sin)) /* Set the debug flag early on packet level */ 21016 req->debug = 1; 21017 if (pedanticsipchecking) 21018 req->len = lws2sws(req->data->str, req->len); /* Fix multiline headers */ 21019 if (req->debug) { 21020 ast_verbose("\n<--- SIP read from %s://%s:%d --->\n%s\n<------------->\n", 21021 get_transport(req->socket.type), ast_inet_ntoa(sin->sin_addr), 21022 ntohs(sin->sin_port), req->data->str); 21023 } 21024 21025 if (parse_request(req) == -1) { /* Bad packet, can't parse */ 21026 ast_str_reset(req->data); /* nulling this out is NOT a good idea here. */ 21027 return 1; 21028 } 21029 req->method = find_sip_method(REQ_OFFSET_TO_STR(req, rlPart1)); 21030 21031 if (req->debug) 21032 ast_verbose("--- (%d headers %d lines)%s ---\n", req->headers, req->lines, (req->headers + req->lines == 0) ? " Nat keepalive" : ""); 21033 21034 if (req->headers < 2) { /* Must have at least two headers */ 21035 ast_str_reset(req->data); /* nulling this out is NOT a good idea here. */ 21036 return 1; 21037 } 21038 21039 /* Process request, with netlock held, and with usual deadlock avoidance */ 21040 for (lockretry = 10; lockretry > 0; lockretry--) { 21041 ast_mutex_lock(&netlock); 21042 21043 /* Find the active SIP dialog or create a new one */ 21044 p = find_call(req, sin, req->method); /* returns p locked */ 21045 if (p == NULL) { 21046 ast_debug(1, "Invalid SIP message - rejected , no callid, len %d\n", req->len); 21047 ast_mutex_unlock(&netlock); 21048 return 1; 21049 } 21050 21051 copy_socket_data(&p->socket, &req->socket); 21052 21053 /* Go ahead and lock the owner if it has one -- we may need it */ 21054 /* becaues this is deadlock-prone, we need to try and unlock if failed */ 21055 if (!p->owner || !ast_channel_trylock(p->owner)) 21056 break; /* locking succeeded */ 21057 21058 if (lockretry != 1) { 21059 sip_pvt_unlock(p); 21060 ao2_t_ref(p, -1, "release p (from find_call) inside lockretry loop"); /* we'll look for it again, but p is dead now */ 21061 ast_mutex_unlock(&netlock); 21062 /* Sleep for a very short amount of time */ 21063 usleep(1); 21064 } 21065 } 21066 p->recv = *sin; 21067 21068 if (p->do_history) /* This is a request or response, note what it was for */ 21069 append_history(p, "Rx", "%s / %s / %s", req->data->str, get_header(req, "CSeq"), REQ_OFFSET_TO_STR(req, rlPart2)); 21070 21071 if (!lockretry) { 21072 if (!queue_request(p, req)) { 21073 /* the request has been queued for later handling */ 21074 sip_pvt_unlock(p); 21075 ao2_t_ref(p, -1, "release p (from find_call) after queueing request"); 21076 ast_mutex_unlock(&netlock); 21077 return 1; 21078 } 21079 21080 if (p->owner) 21081 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 ??? - ")); 21082 ast_log(LOG_ERROR, "SIP transaction failed: %s \n", p->callid); 21083 if (req->method != SIP_ACK) 21084 transmit_response(p, "503 Server error", req); /* We must respond according to RFC 3261 sec 12.2 */ 21085 /* XXX We could add retry-after to make sure they come back */ 21086 append_history(p, "LockFail", "Owner lock failed, transaction failed."); 21087 sip_pvt_unlock(p); 21088 ao2_t_ref(p, -1, "release p (from find_call) at end of lockretry"); /* p is gone after the return */ 21089 ast_mutex_unlock(&netlock); 21090 return 1; 21091 } 21092 21093 /* if there are queued requests on this sip_pvt, process them first, so that everything is 21094 handled in order 21095 */ 21096 if (!AST_LIST_EMPTY(&p->request_queue)) { 21097 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")); 21098 process_request_queue(p, &recount, &nounlock); 21099 } 21100 21101 if (handle_incoming(p, req, sin, &recount, &nounlock) == -1) { 21102 /* Request failed */ 21103 ast_debug(1, "SIP message could not be handled, bad request: %-70.70s\n", p->callid[0] ? p->callid : "<no callid>"); 21104 } 21105 21106 if (recount) 21107 ast_update_use_count(); 21108 21109 if (p->owner && !nounlock) 21110 ast_channel_unlock(p->owner); 21111 sip_pvt_unlock(p); 21112 ast_mutex_unlock(&netlock); 21113 ao2_t_ref(p, -1, "throw away dialog ptr from find_call at end of routine"); /* p is gone after the return */ 21114 return 1; 21115 }
static void handle_request_info | ( | struct sip_pvt * | p, | |
struct sip_request * | req | |||
) | [static] |
Receive SIP INFO Message.
Definition at line 15807 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().
15808 { 15809 char buf[1024]; 15810 unsigned int event; 15811 const char *c = get_header(req, "Content-Type"); 15812 15813 /* Need to check the media/type */ 15814 if (!strcasecmp(c, "application/dtmf-relay") || 15815 !strcasecmp(c, "application/vnd.nortelnetworks.digits")) { 15816 unsigned int duration = 0; 15817 15818 if (!p->owner) { /* not a PBX call */ 15819 transmit_response(p, "481 Call leg/transaction does not exist", req); 15820 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 15821 return; 15822 } 15823 15824 /* Try getting the "signal=" part */ 15825 if (ast_strlen_zero(c = get_body(req, "Signal")) && ast_strlen_zero(c = get_body(req, "d"))) { 15826 ast_log(LOG_WARNING, "Unable to retrieve DTMF signal from INFO message from %s\n", p->callid); 15827 transmit_response(p, "200 OK", req); /* Should return error */ 15828 return; 15829 } else { 15830 ast_copy_string(buf, c, sizeof(buf)); 15831 } 15832 15833 if (!ast_strlen_zero((c = get_body(req, "Duration")))) 15834 duration = atoi(c); 15835 if (!duration) 15836 duration = 100; /* 100 ms */ 15837 15838 15839 if (ast_strlen_zero(buf)) { 15840 transmit_response(p, "200 OK", req); 15841 return; 15842 } 15843 15844 if (buf[0] == '*') 15845 event = 10; 15846 else if (buf[0] == '#') 15847 event = 11; 15848 else if ((buf[0] >= 'A') && (buf[0] <= 'D')) 15849 event = 12 + buf[0] - 'A'; 15850 else if (buf[0] == '!') 15851 event = 16; 15852 else 15853 event = atoi(buf); 15854 if (event == 16) { 15855 /* send a FLASH event */ 15856 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_FLASH, }; 15857 ast_queue_frame(p->owner, &f); 15858 if (sipdebug) 15859 ast_verbose("* DTMF-relay event received: FLASH\n"); 15860 } else { 15861 /* send a DTMF event */ 15862 struct ast_frame f = { AST_FRAME_DTMF, }; 15863 if (event < 10) { 15864 f.subclass = '0' + event; 15865 } else if (event < 11) { 15866 f.subclass = '*'; 15867 } else if (event < 12) { 15868 f.subclass = '#'; 15869 } else if (event < 16) { 15870 f.subclass = 'A' + (event - 12); 15871 } 15872 f.len = duration; 15873 ast_queue_frame(p->owner, &f); 15874 if (sipdebug) 15875 ast_verbose("* DTMF-relay event received: %c\n", f.subclass); 15876 } 15877 transmit_response(p, "200 OK", req); 15878 return; 15879 } else if (!strcasecmp(c, "application/dtmf")) { 15880 /*! \todo Note: Doesn't read the duration of the DTMF. Should be fixed. */ 15881 unsigned int duration = 0; 15882 15883 if (!p->owner) { /* not a PBX call */ 15884 transmit_response(p, "481 Call leg/transaction does not exist", req); 15885 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 15886 return; 15887 } 15888 15889 get_msg_text(buf, sizeof(buf), req, TRUE); 15890 duration = 100; /* 100 ms */ 15891 15892 if (ast_strlen_zero(buf)) { 15893 transmit_response(p, "200 OK", req); 15894 return; 15895 } 15896 event = atoi(buf); 15897 if (event == 16) { 15898 /* send a FLASH event */ 15899 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_FLASH, }; 15900 ast_queue_frame(p->owner, &f); 15901 if (sipdebug) 15902 ast_verbose("* DTMF-relay event received: FLASH\n"); 15903 } else { 15904 /* send a DTMF event */ 15905 struct ast_frame f = { AST_FRAME_DTMF, }; 15906 if (event < 10) { 15907 f.subclass = '0' + event; 15908 } else if (event < 11) { 15909 f.subclass = '*'; 15910 } else if (event < 12) { 15911 f.subclass = '#'; 15912 } else if (event < 16) { 15913 f.subclass = 'A' + (event - 12); 15914 } 15915 f.len = duration; 15916 ast_queue_frame(p->owner, &f); 15917 if (sipdebug) 15918 ast_verbose("* DTMF-relay event received: %c\n", f.subclass); 15919 } 15920 transmit_response(p, "200 OK", req); 15921 return; 15922 15923 } else if (!strcasecmp(c, "application/media_control+xml")) { 15924 /* Eh, we'll just assume it's a fast picture update for now */ 15925 if (p->owner) 15926 ast_queue_control(p->owner, AST_CONTROL_VIDUPDATE); 15927 transmit_response(p, "200 OK", req); 15928 return; 15929 } else if (!ast_strlen_zero(c = get_header(req, "X-ClientCode"))) { 15930 /* Client code (from SNOM phone) */ 15931 if (ast_test_flag(&p->flags[0], SIP_USECLIENTCODE)) { 15932 if (p->owner && p->owner->cdr) 15933 ast_cdr_setuserfield(p->owner, c); 15934 if (p->owner && ast_bridged_channel(p->owner) && ast_bridged_channel(p->owner)->cdr) 15935 ast_cdr_setuserfield(ast_bridged_channel(p->owner), c); 15936 transmit_response(p, "200 OK", req); 15937 } else { 15938 transmit_response(p, "403 Forbidden", req); 15939 } 15940 return; 15941 } else if (!ast_strlen_zero(c = get_header(req, "Record"))) { 15942 /* INFO messages generated by some phones to start/stop recording 15943 on phone calls. 15944 OEJ: I think this should be something that is enabled/disabled 15945 per device. I don't want incoming callers to record calls in my 15946 pbx. 15947 */ 15948 /* first, get the feature string, if it exists */ 15949 struct ast_call_feature *feat; 15950 int j; 15951 struct ast_frame f = { AST_FRAME_DTMF, }; 15952 15953 ast_rdlock_call_features(); 15954 feat = ast_find_call_feature("automon"); 15955 if (!feat || ast_strlen_zero(feat->exten)) { 15956 ast_log(LOG_WARNING, "Recording requested, but no One Touch Monitor registered. (See features.conf)\n"); 15957 /* 403 means that we don't support this feature, so don't request it again */ 15958 transmit_response(p, "403 Forbidden", req); 15959 ast_unlock_call_features(); 15960 return; 15961 } 15962 /* Send the feature code to the PBX as DTMF, just like the handset had sent it */ 15963 f.len = 100; 15964 for (j=0; j < strlen(feat->exten); j++) { 15965 f.subclass = feat->exten[j]; 15966 ast_queue_frame(p->owner, &f); 15967 if (sipdebug) 15968 ast_verbose("* DTMF-relay event faked: %c\n", f.subclass); 15969 } 15970 ast_unlock_call_features(); 15971 15972 ast_debug(1, "Got a Request to Record the channel, state %s\n", c); 15973 transmit_response(p, "200 OK", req); 15974 return; 15975 } else if (ast_strlen_zero(c = get_header(req, "Content-Length")) || !strcasecmp(c, "0")) { 15976 /* This is probably just a packet making sure the signalling is still up, just send back a 200 OK */ 15977 transmit_response(p, "200 OK", req); 15978 return; 15979 } 15980 15981 /* Other type of INFO message, not really understood by Asterisk */ 15982 /* if (get_msg_text(buf, sizeof(buf), req)) { */ 15983 15984 ast_log(LOG_WARNING, "Unable to parse INFO message from %s. Content %s\n", p->callid, buf); 15985 transmit_response(p, "415 Unsupported media type", req); 15986 return; 15987 }
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 18787 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_CONTROL_BUSY, AST_CONTROL_SRCUPDATE, 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_control(), ast_queue_frame(), ast_rtp_set_alt_peer(), ast_rtp_setdtmf(), ast_rtp_setdtmfcompensate(), ast_sched_add(), 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_udptl_new_with_bindaddr(), ast_uri_decode(), ast_verbose, AUTH_CHALLENGE_SENT, AUTH_FAKE_AUTH, sip_pvt::autokillid, build_contact(), build_route(), ast_channel::call_forward, sip_pvt::callid, sip_pvt::capability, check_user(), check_via(), context, sip_pvt::context, copy_request(), 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_ip_and_port_from_sdp(), get_rdnis(), get_sip_pvt_byid_locked(), sip_pvt::glareinvite, handle_invite_replaces(), ast_channel::hangupcause, sip_request::headers, sip_request::ignore, INC_CALL_LIMIT, sip_pvt::initreq, INV_COMPLETED, INV_CONFIRMED, INV_PROCEEDING, INV_TERMINATED, sip_pvt::invitestate, io, sip_pvt::jointcapability, sip_pvt::lastinvite, LOG_ERROR, LOG_NOTICE, LOG_WARNING, make_our_tag(), sip_request::method, msg, ast_channel::name, sip_pvt::owner, 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_pvt::rtp, S_OR, sched, SDP_AUDIO, SDP_T38_INITIATE, SDP_VIDEO, sip_pvt::session_modify, SESSION_TIMER_MODE_ACCEPT, SESSION_TIMER_MODE_ORIGINATE, SESSION_TIMER_MODE_REFUSE, SESSION_TIMER_REFRESHER_AUTO, SESSION_TIMER_REFRESHER_UAS, set_t38_capabilities(), 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_PAGE2_T38SUPPORT, 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, sip_pvt::t38_maxdatagram, T38_PEER_REINVITE, sip_pvt::t38id, sip_pvt::tag, transmit_fake_auth_response(), transmit_provisional_response(), transmit_response(), transmit_response_reliable(), transmit_response_with_minse(), transmit_response_with_sdp(), transmit_response_with_t38_sdp(), transmit_response_with_unsupported(), TRUE, sip_pvt::udptl, update_call_counter(), sip_pvt::username, sip_pvt::vrtp, XMIT_CRITICAL, XMIT_RELIABLE, and XMIT_UNRELIABLE.
Referenced by handle_incoming().
18788 { 18789 int res = 1; 18790 int gotdest; 18791 const char *p_replaces; 18792 char *replace_id = NULL; 18793 int refer_locked = 0; 18794 const char *required; 18795 unsigned int required_profile = 0; 18796 struct ast_channel *c = NULL; /* New channel */ 18797 int reinvite = 0; 18798 int rtn; 18799 18800 const char *p_uac_se_hdr; /* UAC's Session-Expires header string */ 18801 const char *p_uac_min_se; /* UAC's requested Min-SE interval (char string) */ 18802 int uac_max_se = -1; /* UAC's Session-Expires in integer format */ 18803 int uac_min_se = -1; /* UAC's Min-SE in integer format */ 18804 int st_active = FALSE; /* Session-Timer on/off boolean */ 18805 int st_interval = 0; /* Session-Timer negotiated refresh interval */ 18806 enum st_refresher st_ref; /* Session-Timer session refresher */ 18807 int dlg_min_se = -1; 18808 st_ref = SESSION_TIMER_REFRESHER_AUTO; 18809 18810 /* Find out what they support */ 18811 if (!p->sipoptions) { 18812 const char *supported = get_header(req, "Supported"); 18813 if (!ast_strlen_zero(supported)) 18814 parse_sip_options(p, supported); 18815 } 18816 18817 /* Find out what they require */ 18818 required = get_header(req, "Require"); 18819 if (!ast_strlen_zero(required)) { 18820 required_profile = parse_sip_options(NULL, required); 18821 if (required_profile && !(required_profile & (SIP_OPT_REPLACES | SIP_OPT_TIMER))) { 18822 /* At this point we only support REPLACES and Session-Timer */ 18823 transmit_response_with_unsupported(p, "420 Bad extension (unsupported)", req, required); 18824 ast_log(LOG_WARNING, "Received SIP INVITE with unsupported required extension: %s\n", required); 18825 p->invitestate = INV_COMPLETED; 18826 if (!p->lastinvite) 18827 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 18828 res = -1; 18829 goto request_invite_cleanup; 18830 } 18831 } 18832 18833 /* The option tags may be present in Supported: or Require: headers. 18834 Include the Require: option tags for further processing as well */ 18835 p->sipoptions |= required_profile; 18836 p->reqsipoptions = required_profile; 18837 18838 /* Check if this is a loop */ 18839 if (ast_test_flag(&p->flags[0], SIP_OUTGOING) && p->owner && (p->invitestate != INV_TERMINATED && p->invitestate != INV_CONFIRMED)) { 18840 /* This is a call to ourself. Send ourselves an error code and stop 18841 processing immediately, as SIP really has no good mechanism for 18842 being able to call yourself */ 18843 /* If pedantic is on, we need to check the tags. If they're different, this is 18844 in fact a forked call through a SIP proxy somewhere. */ 18845 int different; 18846 char *initial_rlPart2 = REQ_OFFSET_TO_STR(&p->initreq, rlPart2); 18847 char *this_rlPart2 = REQ_OFFSET_TO_STR(req, rlPart2); 18848 if (pedanticsipchecking) 18849 different = sip_uri_cmp(initial_rlPart2, this_rlPart2); 18850 else 18851 different = strcmp(initial_rlPart2, this_rlPart2); 18852 if (!different) { 18853 transmit_response(p, "482 Loop Detected", req); 18854 p->invitestate = INV_COMPLETED; 18855 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 18856 res = 0; 18857 goto request_invite_cleanup; 18858 } else { 18859 /*! This is a spiral. What we need to do is to just change the outgoing INVITE 18860 * so that it now routes to the new Request URI. Since we created the INVITE ourselves 18861 * that should be all we need to do. 18862 * 18863 * \todo XXX This needs to be reviewed. YOu don't change the request URI really, you route the packet 18864 * correctly instead... 18865 */ 18866 char *uri = ast_strdupa(this_rlPart2); 18867 char *at = strchr(uri, '@'); 18868 char *peerorhost; 18869 ast_debug(2, "Potential spiral detected. Original RURI was %s, new RURI is %s\n", initial_rlPart2, this_rlPart2); 18870 transmit_response(p, "100 Trying", req); 18871 if (at) { 18872 *at = '\0'; 18873 } 18874 /* Parse out "sip:" */ 18875 if ((peerorhost = strchr(uri, ':'))) { 18876 *peerorhost++ = '\0'; 18877 } 18878 ast_string_field_set(p, theirtag, NULL); 18879 /* Treat this as if there were a call forward instead... 18880 */ 18881 ast_string_field_set(p->owner, call_forward, peerorhost); 18882 ast_queue_control(p->owner, AST_CONTROL_BUSY); 18883 res = 0; 18884 goto request_invite_cleanup; 18885 } 18886 } 18887 18888 if (!req->ignore && p->pendinginvite) { 18889 if (!ast_test_flag(&p->flags[0], SIP_OUTGOING) && (p->invitestate == INV_COMPLETED || p->invitestate == INV_TERMINATED)) { 18890 /* What do these circumstances mean? We have received an INVITE for an "incoming" dialog for which we 18891 * have sent a final response. We have not yet received an ACK, though (which is why p->pendinginvite is non-zero). 18892 * We also know that the INVITE is not a retransmission, because otherwise the "ignore" flag would be set. 18893 * This means that either we are receiving a reinvite for a terminated dialog, or we are receiving an INVITE with 18894 * credentials based on one we challenged earlier. 18895 * 18896 * The action to take in either case is to treat the INVITE as though it contains an implicit ACK for the previous 18897 * transaction. Calling __sip_ack will take care of this by clearing the p->pendinginvite and removing the response 18898 * from the previous transaction from the list of outstanding packets. 18899 */ 18900 __sip_ack(p, p->pendinginvite, 1, 0); 18901 } else { 18902 /* We already have a pending invite. Sorry. You are on hold. */ 18903 p->glareinvite = seqno; 18904 if (p->rtp && find_sdp(req)) { 18905 struct sockaddr_in sin; 18906 if (get_ip_and_port_from_sdp(req, SDP_AUDIO, &sin)) { 18907 ast_log(LOG_WARNING, "Failed to set an alternate media source on glared reinvite. Audio may not work properly on this call.\n"); 18908 } else { 18909 ast_rtp_set_alt_peer(p->rtp, &sin); 18910 } 18911 if (p->vrtp) { 18912 if (get_ip_and_port_from_sdp(req, SDP_VIDEO, &sin)) { 18913 ast_log(LOG_WARNING, "Failed to set an alternate media source on glared reinvite. Video may not work properly on this call.\n"); 18914 } else { 18915 ast_rtp_set_alt_peer(p->vrtp, &sin); 18916 } 18917 } 18918 } 18919 transmit_response_reliable(p, "491 Request Pending", req); 18920 ast_debug(1, "Got INVITE on call where we already have pending INVITE, deferring that - %s\n", p->callid); 18921 /* Don't destroy dialog here */ 18922 res = 0; 18923 goto request_invite_cleanup; 18924 } 18925 } 18926 18927 p_replaces = get_header(req, "Replaces"); 18928 if (!ast_strlen_zero(p_replaces)) { 18929 /* We have a replaces header */ 18930 char *ptr; 18931 char *fromtag = NULL; 18932 char *totag = NULL; 18933 char *start, *to; 18934 int error = 0; 18935 18936 if (p->owner) { 18937 ast_debug(3, "INVITE w Replaces on existing call? Refusing action. [%s]\n", p->callid); 18938 transmit_response_reliable(p, "400 Bad request", req); /* The best way to not not accept the transfer */ 18939 /* Do not destroy existing call */ 18940 res = -1; 18941 goto request_invite_cleanup; 18942 } 18943 18944 if (sipdebug) 18945 ast_debug(3, "INVITE part of call transfer. Replaces [%s]\n", p_replaces); 18946 /* Create a buffer we can manipulate */ 18947 replace_id = ast_strdupa(p_replaces); 18948 ast_uri_decode(replace_id); 18949 18950 if (!p->refer && !sip_refer_allocate(p)) { 18951 transmit_response_reliable(p, "500 Server Internal Error", req); 18952 append_history(p, "Xfer", "INVITE/Replace Failed. Out of memory."); 18953 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 18954 p->invitestate = INV_COMPLETED; 18955 res = -1; 18956 goto request_invite_cleanup; 18957 } 18958 18959 /* Todo: (When we find phones that support this) 18960 if the replaces header contains ";early-only" 18961 we can only replace the call in early 18962 stage, not after it's up. 18963 18964 If it's not in early mode, 486 Busy. 18965 */ 18966 18967 /* Skip leading whitespace */ 18968 replace_id = ast_skip_blanks(replace_id); 18969 18970 start = replace_id; 18971 while ( (ptr = strsep(&start, ";")) ) { 18972 ptr = ast_skip_blanks(ptr); /* XXX maybe unnecessary ? */ 18973 if ( (to = strcasestr(ptr, "to-tag=") ) ) 18974 totag = to + 7; /* skip the keyword */ 18975 else if ( (to = strcasestr(ptr, "from-tag=") ) ) { 18976 fromtag = to + 9; /* skip the keyword */ 18977 fromtag = strsep(&fromtag, "&"); /* trim what ? */ 18978 } 18979 } 18980 18981 if (sipdebug) 18982 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>"); 18983 18984 18985 /* Try to find call that we are replacing 18986 If we have a Replaces header, we need to cancel that call if we succeed with this call 18987 */ 18988 if ((p->refer->refer_call = get_sip_pvt_byid_locked(replace_id, totag, fromtag)) == NULL) { 18989 ast_log(LOG_NOTICE, "Supervised transfer attempted to replace non-existent call id (%s)!\n", replace_id); 18990 transmit_response_reliable(p, "481 Call Leg Does Not Exist (Replaces)", req); 18991 error = 1; 18992 } else { 18993 refer_locked = 1; 18994 } 18995 18996 /* At this point, bot the pvt and the owner of the call to be replaced is locked */ 18997 18998 /* The matched call is the call from the transferer to Asterisk . 18999 We want to bridge the bridged part of the call to the 19000 incoming invite, thus taking over the refered call */ 19001 19002 if (p->refer->refer_call == p) { 19003 ast_log(LOG_NOTICE, "INVITE with replaces into it's own call id (%s == %s)!\n", replace_id, p->callid); 19004 p->refer->refer_call = dialog_unref(p->refer->refer_call, "unref dialog p->refer->refer_call"); 19005 transmit_response_reliable(p, "400 Bad request", req); /* The best way to not not accept the transfer */ 19006 error = 1; 19007 } 19008 19009 if (!error && !p->refer->refer_call->owner) { 19010 /* Oops, someting wrong anyway, no owner, no call */ 19011 ast_log(LOG_NOTICE, "Supervised transfer attempted to replace non-existing call id (%s)!\n", replace_id); 19012 /* Check for better return code */ 19013 transmit_response_reliable(p, "481 Call Leg Does Not Exist (Replace)", req); 19014 error = 1; 19015 } 19016 19017 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 ) { 19018 ast_log(LOG_NOTICE, "Supervised transfer attempted to replace non-ringing or active call id (%s)!\n", replace_id); 19019 transmit_response_reliable(p, "603 Declined (Replaces)", req); 19020 error = 1; 19021 } 19022 19023 if (error) { /* Give up this dialog */ 19024 append_history(p, "Xfer", "INVITE/Replace Failed."); 19025 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 19026 sip_pvt_unlock(p); 19027 if (p->refer->refer_call) { 19028 sip_pvt_unlock(p->refer->refer_call); 19029 if (p->refer->refer_call->owner) { 19030 ast_channel_unlock(p->refer->refer_call->owner); 19031 } 19032 } 19033 refer_locked = 0; 19034 p->invitestate = INV_COMPLETED; 19035 res = -1; 19036 goto request_invite_cleanup; 19037 } 19038 } 19039 19040 /* Check if this is an INVITE that sets up a new dialog or 19041 a re-invite in an existing dialog */ 19042 19043 if (!req->ignore) { 19044 int newcall = (p->initreq.headers ? TRUE : FALSE); 19045 19046 if (sip_cancel_destroy(p)) 19047 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 19048 /* This also counts as a pending invite */ 19049 p->pendinginvite = seqno; 19050 check_via(p, req); 19051 19052 copy_request(&p->initreq, req); /* Save this INVITE as the transaction basis */ 19053 if (sipdebug) 19054 ast_debug(1, "Initializing initreq for method %s - callid %s\n", sip_methods[req->method].text, p->callid); 19055 if (!p->owner) { /* Not a re-invite */ 19056 if (debug) 19057 ast_verbose("Using INVITE request as basis request - %s\n", p->callid); 19058 if (newcall) 19059 append_history(p, "Invite", "New call: %s", p->callid); 19060 parse_ok_contact(p, req); 19061 } else { /* Re-invite on existing call */ 19062 ast_clear_flag(&p->flags[0], SIP_OUTGOING); /* This is now an inbound dialog */ 19063 /* Handle SDP here if we already have an owner */ 19064 if (find_sdp(req)) { 19065 if (process_sdp(p, req, SDP_T38_INITIATE)) { 19066 transmit_response_reliable(p, "488 Not acceptable here", req); 19067 if (!p->lastinvite) 19068 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 19069 res = -1; 19070 goto request_invite_cleanup; 19071 } 19072 ast_queue_control(p->owner, AST_CONTROL_SRCUPDATE); 19073 } else { 19074 p->jointcapability = p->capability; 19075 ast_debug(1, "Hm.... No sdp for the moment\n"); 19076 } 19077 if (p->do_history) /* This is a response, note what it was for */ 19078 append_history(p, "ReInv", "Re-invite received"); 19079 } 19080 } else if (debug) 19081 ast_verbose("Ignoring this INVITE request\n"); 19082 19083 19084 if (!p->lastinvite && !req->ignore && !p->owner) { 19085 /* This is a new invite */ 19086 /* Handle authentication if this is our first invite */ 19087 res = check_user(p, req, SIP_INVITE, e, XMIT_RELIABLE, sin); 19088 if (res == AUTH_CHALLENGE_SENT) { 19089 p->invitestate = INV_COMPLETED; /* Needs to restart in another INVITE transaction */ 19090 res = 0; 19091 goto request_invite_cleanup; 19092 } 19093 if (res < 0) { /* Something failed in authentication */ 19094 if (res == AUTH_FAKE_AUTH) { 19095 ast_log(LOG_NOTICE, "Sending fake auth rejection for device %s\n", get_header(req, "From")); 19096 transmit_fake_auth_response(p, SIP_INVITE, req, XMIT_RELIABLE); 19097 } else { 19098 ast_log(LOG_NOTICE, "Failed to authenticate device %s\n", get_header(req, "From")); 19099 transmit_response_reliable(p, "403 Forbidden", req); 19100 } 19101 p->invitestate = INV_COMPLETED; 19102 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 19103 ast_string_field_set(p, theirtag, NULL); 19104 res = 0; 19105 goto request_invite_cleanup; 19106 } 19107 19108 /* If T38 is needed but not present, then make it magically appear */ 19109 if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT) && !p->udptl && (p->udptl = ast_udptl_new_with_bindaddr(sched, io, 0, bindaddr.sin_addr))) { 19110 p->t38_maxdatagram = global_t38_maxdatagram; 19111 set_t38_capabilities(p); 19112 } 19113 19114 /* We have a succesful authentication, process the SDP portion if there is one */ 19115 if (find_sdp(req)) { 19116 if (process_sdp(p, req, SDP_T38_INITIATE)) { 19117 /* Unacceptable codecs */ 19118 transmit_response_reliable(p, "488 Not acceptable here", req); 19119 p->invitestate = INV_COMPLETED; 19120 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 19121 ast_debug(1, "No compatible codecs for this SIP call.\n"); 19122 res = -1; 19123 goto request_invite_cleanup; 19124 } 19125 } else { /* No SDP in invite, call control session */ 19126 p->jointcapability = p->capability; 19127 ast_debug(2, "No SDP in Invite, third party call control\n"); 19128 } 19129 19130 /* Queue NULL frame to prod ast_rtp_bridge if appropriate */ 19131 /* This seems redundant ... see !p-owner above */ 19132 if (p->owner) 19133 ast_queue_frame(p->owner, &ast_null_frame); 19134 19135 19136 /* Initialize the context if it hasn't been already */ 19137 if (ast_strlen_zero(p->context)) 19138 ast_string_field_set(p, context, default_context); 19139 19140 19141 /* Check number of concurrent calls -vs- incoming limit HERE */ 19142 ast_debug(1, "Checking SIP call limits for device %s\n", p->username); 19143 if ((res = update_call_counter(p, INC_CALL_LIMIT))) { 19144 if (res < 0) { 19145 ast_log(LOG_NOTICE, "Failed to place call for device %s, too many calls\n", p->username); 19146 transmit_response_reliable(p, "480 Temporarily Unavailable (Call limit) ", req); 19147 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 19148 p->invitestate = INV_COMPLETED; 19149 } 19150 res = 0; 19151 goto request_invite_cleanup; 19152 } 19153 gotdest = get_destination(p, NULL); /* Get destination right away */ 19154 get_rdnis(p, NULL); /* Get redirect information */ 19155 extract_uri(p, req); /* Get the Contact URI */ 19156 build_contact(p); /* Build our contact header */ 19157 19158 if (p->rtp) { 19159 ast_rtp_setdtmf(p->rtp, ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833); 19160 ast_rtp_setdtmfcompensate(p->rtp, ast_test_flag(&p->flags[1], SIP_PAGE2_RFC2833_COMPENSATE)); 19161 } 19162 19163 if (!replace_id && gotdest) { /* No matching extension found */ 19164 if (gotdest == 1 && ast_test_flag(&p->flags[1], SIP_PAGE2_ALLOWOVERLAP)) 19165 transmit_response_reliable(p, "484 Address Incomplete", req); 19166 else { 19167 char *decoded_exten = ast_strdupa(p->exten); 19168 19169 transmit_response_reliable(p, "404 Not Found", req); 19170 ast_uri_decode(decoded_exten); 19171 ast_log(LOG_NOTICE, "Call from '%s' to extension" 19172 " '%s' rejected because extension not found in context '%s'.\n", 19173 S_OR(p->username, p->peername), decoded_exten, p->context); 19174 } 19175 p->invitestate = INV_COMPLETED; 19176 update_call_counter(p, DEC_CALL_LIMIT); 19177 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 19178 res = 0; 19179 goto request_invite_cleanup; 19180 } else { 19181 19182 /* If no extension was specified, use the s one */ 19183 /* Basically for calling to IP/Host name only */ 19184 if (ast_strlen_zero(p->exten)) 19185 ast_string_field_set(p, exten, "s"); 19186 /* Initialize our tag */ 19187 19188 make_our_tag(p->tag, sizeof(p->tag)); 19189 /* First invitation - create the channel */ 19190 c = sip_new(p, AST_STATE_DOWN, S_OR(p->peername, NULL)); 19191 *recount = 1; 19192 19193 /* Save Record-Route for any later requests we make on this dialogue */ 19194 build_route(p, req, 0); 19195 19196 if (c) { 19197 /* Pre-lock the call */ 19198 ast_channel_lock(c); 19199 } 19200 } 19201 } else { 19202 if (sipdebug) { 19203 if (!req->ignore) 19204 ast_debug(2, "Got a SIP re-invite for call %s\n", p->callid); 19205 else 19206 ast_debug(2, "Got a SIP re-transmit of INVITE for call %s\n", p->callid); 19207 } 19208 if (!req->ignore) 19209 reinvite = 1; 19210 c = p->owner; 19211 } 19212 19213 /* Session-Timers */ 19214 if (p->sipoptions & SIP_OPT_TIMER) { 19215 /* The UAC has requested session-timers for this session. Negotiate 19216 the session refresh interval and who will be the refresher */ 19217 ast_debug(2, "Incoming INVITE with 'timer' option enabled\n"); 19218 19219 /* Allocate Session-Timers struct w/in the dialog */ 19220 if (!p->stimer) 19221 sip_st_alloc(p); 19222 19223 /* Parse the Session-Expires header */ 19224 p_uac_se_hdr = get_header(req, "Session-Expires"); 19225 if (!ast_strlen_zero(p_uac_se_hdr)) { 19226 rtn = parse_session_expires(p_uac_se_hdr, &uac_max_se, &st_ref); 19227 if (rtn != 0) { 19228 transmit_response_reliable(p, "400 Session-Expires Invalid Syntax", req); 19229 p->invitestate = INV_COMPLETED; 19230 if (!p->lastinvite) { 19231 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 19232 } 19233 res = -1; 19234 goto request_invite_cleanup; 19235 } 19236 } 19237 19238 /* Parse the Min-SE header */ 19239 p_uac_min_se = get_header(req, "Min-SE"); 19240 if (!ast_strlen_zero(p_uac_min_se)) { 19241 rtn = parse_minse(p_uac_min_se, &uac_min_se); 19242 if (rtn != 0) { 19243 transmit_response_reliable(p, "400 Min-SE Invalid Syntax", req); 19244 p->invitestate = INV_COMPLETED; 19245 if (!p->lastinvite) { 19246 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 19247 } 19248 res = -1; 19249 goto request_invite_cleanup; 19250 } 19251 } 19252 19253 dlg_min_se = st_get_se(p, FALSE); 19254 switch (st_get_mode(p)) { 19255 case SESSION_TIMER_MODE_ACCEPT: 19256 case SESSION_TIMER_MODE_ORIGINATE: 19257 if (uac_max_se > 0 && uac_max_se < dlg_min_se) { 19258 transmit_response_with_minse(p, "422 Session Interval Too Small", req, dlg_min_se); 19259 p->invitestate = INV_COMPLETED; 19260 if (!p->lastinvite) { 19261 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 19262 } 19263 res = -1; 19264 goto request_invite_cleanup; 19265 } 19266 19267 p->stimer->st_active_peer_ua = TRUE; 19268 st_active = TRUE; 19269 if (st_ref == SESSION_TIMER_REFRESHER_AUTO) { 19270 st_ref = st_get_refresher(p); 19271 } 19272 19273 if (uac_max_se > 0) { 19274 int dlg_max_se = st_get_se(p, TRUE); 19275 if (dlg_max_se >= uac_min_se) { 19276 st_interval = (uac_max_se < dlg_max_se) ? uac_max_se : dlg_max_se; 19277 } else { 19278 st_interval = uac_max_se; 19279 } 19280 } else { 19281 /* Set to default max value */ 19282 st_interval = global_max_se; 19283 } 19284 break; 19285 19286 case SESSION_TIMER_MODE_REFUSE: 19287 if (p->reqsipoptions & SIP_OPT_TIMER) { 19288 transmit_response_with_unsupported(p, "420 Option Disabled", req, required); 19289 ast_log(LOG_WARNING, "Received SIP INVITE with supported but disabled option: %s\n", required); 19290 p->invitestate = INV_COMPLETED; 19291 if (!p->lastinvite) { 19292 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 19293 } 19294 res = -1; 19295 goto request_invite_cleanup; 19296 } 19297 break; 19298 19299 default: 19300 ast_log(LOG_ERROR, "Internal Error %d at %s:%d\n", st_get_mode(p), __FILE__, __LINE__); 19301 break; 19302 } 19303 } else { 19304 /* The UAC did not request session-timers. Asterisk (UAS), will now decide 19305 (based on session-timer-mode in sip.conf) whether to run session-timers for 19306 this session or not. */ 19307 switch (st_get_mode(p)) { 19308 case SESSION_TIMER_MODE_ORIGINATE: 19309 st_active = TRUE; 19310 st_interval = st_get_se(p, TRUE); 19311 st_ref = SESSION_TIMER_REFRESHER_UAS; 19312 p->stimer->st_active_peer_ua = FALSE; 19313 break; 19314 19315 default: 19316 break; 19317 } 19318 } 19319 19320 if (reinvite == 0) { 19321 /* Session-Timers: Start session refresh timer based on negotiation/config */ 19322 if (st_active == TRUE) { 19323 p->stimer->st_active = TRUE; 19324 p->stimer->st_interval = st_interval; 19325 p->stimer->st_ref = st_ref; 19326 start_session_timer(p); 19327 } 19328 } else { 19329 if (p->stimer->st_active == TRUE) { 19330 /* Session-Timers: A re-invite request sent within a dialog will serve as 19331 a refresh request, no matter whether the re-invite was sent for refreshing 19332 the session or modifying it.*/ 19333 ast_debug (2, "Restarting session-timers on a refresh - %s\n", p->callid); 19334 19335 /* The UAC may be adjusting the session-timers mid-session */ 19336 if (st_interval > 0) { 19337 p->stimer->st_interval = st_interval; 19338 p->stimer->st_ref = st_ref; 19339 } 19340 19341 restart_session_timer(p); 19342 if (p->stimer->st_expirys > 0) { 19343 p->stimer->st_expirys--; 19344 } 19345 } 19346 } 19347 19348 if (!req->ignore && p) 19349 p->lastinvite = seqno; 19350 19351 if (replace_id) { /* Attended transfer or call pickup - we're the target */ 19352 /* Go and take over the target call */ 19353 if (sipdebug) 19354 ast_debug(4, "Sending this call to the invite/replcaes handler %s\n", p->callid); 19355 res = handle_invite_replaces(p, req, debug, seqno, sin, nounlock); 19356 refer_locked = 0; 19357 goto request_invite_cleanup; 19358 19359 } 19360 19361 19362 if (c) { /* We have a call -either a new call or an old one (RE-INVITE) */ 19363 enum ast_channel_state c_state = c->_state; 19364 19365 if (c_state != AST_STATE_UP && reinvite && 19366 (p->invitestate == INV_TERMINATED || p->invitestate == INV_CONFIRMED)) { 19367 /* If these conditions are true, and the channel is still in the 'ringing' 19368 * state, then this likely means that we have a situation where the initial 19369 * INVITE transaction has completed *but* the channel's state has not yet been 19370 * changed to UP. The reason this could happen is if the reinvite is received 19371 * on the SIP socket prior to an application calling ast_read on this channel 19372 * to read the answer frame we earlier queued on it. In this case, the reinvite 19373 * is completely legitimate so we need to handle this the same as if the channel 19374 * were already UP. Thus we are purposely falling through to the AST_STATE_UP case. 19375 */ 19376 c_state = AST_STATE_UP; 19377 } 19378 19379 switch(c_state) { 19380 case AST_STATE_DOWN: 19381 ast_debug(2, "%s: New call is still down.... Trying... \n", c->name); 19382 transmit_provisional_response(p, "100 Trying", req, 0); 19383 p->invitestate = INV_PROCEEDING; 19384 ast_setstate(c, AST_STATE_RING); 19385 if (strcmp(p->exten, ast_pickup_ext())) { /* Call to extension -start pbx on this call */ 19386 enum ast_pbx_result result; 19387 19388 result = ast_pbx_start(c); 19389 19390 switch(result) { 19391 case AST_PBX_FAILED: 19392 ast_log(LOG_WARNING, "Failed to start PBX :(\n"); 19393 p->invitestate = INV_COMPLETED; 19394 transmit_response_reliable(p, "503 Unavailable", req); 19395 break; 19396 case AST_PBX_CALL_LIMIT: 19397 ast_log(LOG_WARNING, "Failed to start PBX (call limit reached) \n"); 19398 p->invitestate = INV_COMPLETED; 19399 transmit_response_reliable(p, "480 Temporarily Unavailable", req); 19400 break; 19401 case AST_PBX_SUCCESS: 19402 /* nothing to do */ 19403 break; 19404 } 19405 19406 if (result) { 19407 19408 /* Unlock locks so ast_hangup can do its magic */ 19409 ast_channel_unlock(c); 19410 sip_pvt_unlock(p); 19411 ast_hangup(c); 19412 sip_pvt_lock(p); 19413 c = NULL; 19414 } 19415 } else { /* Pickup call in call group */ 19416 ast_channel_unlock(c); 19417 *nounlock = 1; 19418 if (ast_pickup_call(c)) { 19419 ast_log(LOG_NOTICE, "Nothing to pick up for %s\n", p->callid); 19420 transmit_response_reliable(p, "503 Unavailable", req); 19421 sip_alreadygone(p); 19422 /* Unlock locks so ast_hangup can do its magic */ 19423 sip_pvt_unlock(p); 19424 c->hangupcause = AST_CAUSE_CALL_REJECTED; 19425 } else { 19426 sip_pvt_unlock(p); 19427 ast_setstate(c, AST_STATE_DOWN); 19428 c->hangupcause = AST_CAUSE_NORMAL_CLEARING; 19429 } 19430 p->invitestate = INV_COMPLETED; 19431 ast_hangup(c); 19432 sip_pvt_lock(p); 19433 c = NULL; 19434 } 19435 break; 19436 case AST_STATE_RING: 19437 transmit_provisional_response(p, "100 Trying", req, 0); 19438 p->invitestate = INV_PROCEEDING; 19439 break; 19440 case AST_STATE_RINGING: 19441 transmit_provisional_response(p, "180 Ringing", req, 0); 19442 p->invitestate = INV_PROCEEDING; 19443 break; 19444 case AST_STATE_UP: 19445 ast_debug(2, "%s: This call is UP.... \n", c->name); 19446 19447 transmit_response(p, "100 Trying", req); 19448 19449 if (p->t38.state == T38_PEER_REINVITE) { 19450 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.")); 19451 } else if (p->t38.state == T38_ENABLED) { 19452 ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED); 19453 transmit_response_with_t38_sdp(p, "200 OK", req, (reinvite ? XMIT_RELIABLE : (req->ignore ? XMIT_UNRELIABLE : XMIT_CRITICAL))); 19454 } else if (p->t38.state == T38_DISABLED) { 19455 /* If this is not a re-invite or something to ignore - it's critical */ 19456 ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED); 19457 transmit_response_with_sdp(p, "200 OK", req, (reinvite ? XMIT_RELIABLE : (req->ignore ? XMIT_UNRELIABLE : XMIT_CRITICAL)), p->session_modify == TRUE ? FALSE:TRUE); 19458 } 19459 19460 p->invitestate = INV_TERMINATED; 19461 break; 19462 default: 19463 ast_log(LOG_WARNING, "Don't know how to handle INVITE in state %d\n", c->_state); 19464 transmit_response(p, "100 Trying", req); 19465 break; 19466 } 19467 } else { 19468 if (p && (p->autokillid == -1)) { 19469 const char *msg; 19470 19471 if (!p->jointcapability) 19472 msg = "488 Not Acceptable Here (codec error)"; 19473 else { 19474 ast_log(LOG_NOTICE, "Unable to create/find SIP channel for this INVITE\n"); 19475 msg = "503 Unavailable"; 19476 } 19477 transmit_response_reliable(p, msg, req); 19478 p->invitestate = INV_COMPLETED; 19479 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 19480 } 19481 } 19482 19483 request_invite_cleanup: 19484 19485 if (refer_locked && p->refer && p->refer->refer_call) { 19486 sip_pvt_unlock(p->refer->refer_call); 19487 if (p->refer->refer_call->owner) { 19488 ast_channel_unlock(p->refer->refer_call->owner); 19489 } 19490 } 19491 19492 return res; 19493 }
static int handle_request_message | ( | struct sip_pvt * | p, | |
struct sip_request * | req | |||
) | [static] |
Handle incoming MESSAGE request.
Definition at line 20246 of file chan_sip.c.
References ast_verbose, sip_request::debug, sip_request::ignore, receive_message(), and transmit_response().
Referenced by handle_incoming().
20247 { 20248 if (!req->ignore) { 20249 if (req->debug) 20250 ast_verbose("Receiving message!\n"); 20251 receive_message(p, req); 20252 } else 20253 transmit_response(p, "202 Accepted", req); 20254 return 1; 20255 }
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 18169 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().
18170 { 18171 /* This is mostly a skeleton for future improvements */ 18172 /* Mostly created to return proper answers on notifications on outbound REFER's */ 18173 int res = 0; 18174 const char *event = get_header(req, "Event"); 18175 char *eventid = NULL; 18176 char *sep; 18177 18178 if( (sep = strchr(event, ';')) ) { /* XXX bug here - overwriting string ? */ 18179 *sep++ = '\0'; 18180 eventid = sep; 18181 } 18182 18183 if (sipdebug) 18184 ast_debug(2, "Got NOTIFY Event: %s\n", event); 18185 18186 if (strcmp(event, "refer")) { 18187 /* We don't understand this event. */ 18188 /* Here's room to implement incoming voicemail notifications :-) */ 18189 transmit_response(p, "489 Bad event", req); 18190 res = -1; 18191 } else { 18192 /* Save nesting depth for now, since there might be other events we will 18193 support in the future */ 18194 18195 /* Handle REFER notifications */ 18196 18197 char buf[1024]; 18198 char *cmd, *code; 18199 int respcode; 18200 int success = TRUE; 18201 18202 /* EventID for each transfer... EventID is basically the REFER cseq 18203 18204 We are getting notifications on a call that we transfered 18205 We should hangup when we are getting a 200 OK in a sipfrag 18206 Check if we have an owner of this event */ 18207 18208 /* Check the content type */ 18209 if (strncasecmp(get_header(req, "Content-Type"), "message/sipfrag", strlen("message/sipfrag"))) { 18210 /* We need a sipfrag */ 18211 transmit_response(p, "400 Bad request", req); 18212 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 18213 return -1; 18214 } 18215 18216 /* Get the text of the attachment */ 18217 if (get_msg_text(buf, sizeof(buf), req, TRUE)) { 18218 ast_log(LOG_WARNING, "Unable to retrieve attachment from NOTIFY %s\n", p->callid); 18219 transmit_response(p, "400 Bad request", req); 18220 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 18221 return -1; 18222 } 18223 18224 /* 18225 From the RFC... 18226 A minimal, but complete, implementation can respond with a single 18227 NOTIFY containing either the body: 18228 SIP/2.0 100 Trying 18229 18230 if the subscription is pending, the body: 18231 SIP/2.0 200 OK 18232 if the reference was successful, the body: 18233 SIP/2.0 503 Service Unavailable 18234 if the reference failed, or the body: 18235 SIP/2.0 603 Declined 18236 18237 if the REFER request was accepted before approval to follow the 18238 reference could be obtained and that approval was subsequently denied 18239 (see Section 2.4.7). 18240 18241 If there are several REFERs in the same dialog, we need to 18242 match the ID of the event header... 18243 */ 18244 ast_debug(3, "* SIP Transfer NOTIFY Attachment: \n---%s\n---\n", buf); 18245 cmd = ast_skip_blanks(buf); 18246 code = cmd; 18247 /* We are at SIP/2.0 */ 18248 while(*code && (*code > 32)) { /* Search white space */ 18249 code++; 18250 } 18251 *code++ = '\0'; 18252 code = ast_skip_blanks(code); 18253 sep = code; 18254 sep++; 18255 while(*sep && (*sep > 32)) { /* Search white space */ 18256 sep++; 18257 } 18258 *sep++ = '\0'; /* Response string */ 18259 respcode = atoi(code); 18260 switch (respcode) { 18261 case 100: /* Trying: */ 18262 case 101: /* dialog establishment */ 18263 /* Don't do anything yet */ 18264 break; 18265 case 183: /* Ringing: */ 18266 /* Don't do anything yet */ 18267 break; 18268 case 200: /* OK: The new call is up, hangup this call */ 18269 /* Hangup the call that we are replacing */ 18270 break; 18271 case 301: /* Moved permenantly */ 18272 case 302: /* Moved temporarily */ 18273 /* Do we get the header in the packet in this case? */ 18274 success = FALSE; 18275 break; 18276 case 503: /* Service Unavailable: The new call failed */ 18277 /* Cancel transfer, continue the call */ 18278 success = FALSE; 18279 break; 18280 case 603: /* Declined: Not accepted */ 18281 /* Cancel transfer, continue the current call */ 18282 success = FALSE; 18283 break; 18284 } 18285 if (!success) { 18286 ast_log(LOG_NOTICE, "Transfer failed. Sorry. Nothing further to do with this call\n"); 18287 } 18288 18289 /* Confirm that we received this packet */ 18290 transmit_response(p, "200 OK", req); 18291 }; 18292 18293 if (!p->lastinvite) 18294 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 18295 18296 return res; 18297 }
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 18302 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().
18303 { 18304 int res; 18305 18306 /*! XXX get_destination assumes we're already authenticated. This means that a request from 18307 a known device (peer) will end up in the wrong context if this is out-of-dialog. 18308 However, we want to handle OPTIONS as light as possible, so we might want to have 18309 a configuration option whether we care or not. Some devices use this for testing 18310 capabilities, which means that we need to match device to answer with proper 18311 capabilities (including SDP). 18312 \todo Fix handle_request_options device handling with optional authentication 18313 (this needs to be fixed in 1.4 as well) 18314 */ 18315 18316 if (p->lastinvite) { 18317 /* if this is a request in an active dialog, just confirm that the dialog exists. */ 18318 transmit_response_with_allow(p, "200 OK", req, 0); 18319 return 0; 18320 } 18321 18322 res = get_destination(p, req); 18323 build_contact(p); 18324 18325 if (ast_strlen_zero(p->context)) 18326 ast_string_field_set(p, context, default_context); 18327 18328 if (ast_shutting_down()) 18329 transmit_response_with_allow(p, "503 Unavailable", req, 0); 18330 else if (res < 0) 18331 transmit_response_with_allow(p, "404 Not Found", req, 0); 18332 else 18333 transmit_response_with_allow(p, "200 OK", req, 0); 18334 18335 /* Destroy if this OPTIONS was the opening request, but not if 18336 it's in the middle of a normal call flow. */ 18337 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 18338 18339 return res; 18340 }
static int handle_request_refer | ( | struct sip_pvt * | p, | |
struct sip_request * | req, | |||
int | debug, | |||
int | seqno, | |||
int * | nounlock | |||
) | [static] |
Definition at line 19660 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().
19661 { 19662 struct sip_dual current; /* Chan1: Call between asterisk and transferer */ 19663 /* Chan2: Call between asterisk and transferee */ 19664 19665 int res = 0; 19666 current.req.data = NULL; 19667 19668 if (req->debug) 19669 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"); 19670 19671 if (!p->owner) { 19672 /* This is a REFER outside of an existing SIP dialog */ 19673 /* We can't handle that, so decline it */ 19674 ast_debug(3, "Call %s: Declined REFER, outside of dialog...\n", p->callid); 19675 transmit_response(p, "603 Declined (No dialog)", req); 19676 if (!req->ignore) { 19677 append_history(p, "Xfer", "Refer failed. Outside of dialog."); 19678 sip_alreadygone(p); 19679 p->needdestroy = 1; 19680 } 19681 return 0; 19682 } 19683 19684 19685 /* Check if transfer is allowed from this device */ 19686 if (p->allowtransfer == TRANSFER_CLOSED ) { 19687 /* Transfer not allowed, decline */ 19688 transmit_response(p, "603 Declined (policy)", req); 19689 append_history(p, "Xfer", "Refer failed. Allowtransfer == closed."); 19690 /* Do not destroy SIP session */ 19691 return 0; 19692 } 19693 19694 if (!req->ignore && ast_test_flag(&p->flags[0], SIP_GOTREFER)) { 19695 /* Already have a pending REFER */ 19696 transmit_response(p, "491 Request pending", req); 19697 append_history(p, "Xfer", "Refer failed. Request pending."); 19698 return 0; 19699 } 19700 19701 /* Allocate memory for call transfer data */ 19702 if (!p->refer && !sip_refer_allocate(p)) { 19703 transmit_response(p, "500 Internal Server Error", req); 19704 append_history(p, "Xfer", "Refer failed. Memory allocation error."); 19705 return -3; 19706 } 19707 19708 res = get_refer_info(p, req); /* Extract headers */ 19709 19710 p->refer->status = REFER_SENT; 19711 19712 if (res != 0) { 19713 switch (res) { 19714 case -2: /* Syntax error */ 19715 transmit_response(p, "400 Bad Request (Refer-to missing)", req); 19716 append_history(p, "Xfer", "Refer failed. Refer-to missing."); 19717 if (req->debug) 19718 ast_debug(1, "SIP transfer to black hole can't be handled (no refer-to: )\n"); 19719 break; 19720 case -3: 19721 transmit_response(p, "603 Declined (Non sip: uri)", req); 19722 append_history(p, "Xfer", "Refer failed. Non SIP uri"); 19723 if (req->debug) 19724 ast_debug(1, "SIP transfer to non-SIP uri denied\n"); 19725 break; 19726 default: 19727 /* Refer-to extension not found, fake a failed transfer */ 19728 transmit_response(p, "202 Accepted", req); 19729 append_history(p, "Xfer", "Refer failed. Bad extension."); 19730 transmit_notify_with_sipfrag(p, seqno, "404 Not found", TRUE); 19731 ast_clear_flag(&p->flags[0], SIP_GOTREFER); 19732 if (req->debug) 19733 ast_debug(1, "SIP transfer to bad extension: %s\n", p->refer->refer_to); 19734 break; 19735 } 19736 return 0; 19737 } 19738 if (ast_strlen_zero(p->context)) 19739 ast_string_field_set(p, context, default_context); 19740 19741 /* If we do not support SIP domains, all transfers are local */ 19742 if (allow_external_domains && check_sip_domain(p->refer->refer_to_domain, NULL, 0)) { 19743 p->refer->localtransfer = 1; 19744 if (sipdebug) 19745 ast_debug(3, "This SIP transfer is local : %s\n", p->refer->refer_to_domain); 19746 } else if (AST_LIST_EMPTY(&domain_list) || check_sip_domain(p->refer->refer_to_domain, NULL, 0)) { 19747 /* This PBX doesn't bother with SIP domains or domain is local, so this transfer is local */ 19748 p->refer->localtransfer = 1; 19749 } else if (sipdebug) 19750 ast_debug(3, "This SIP transfer is to a remote SIP extension (remote domain %s)\n", p->refer->refer_to_domain); 19751 19752 /* Is this a repeat of a current request? Ignore it */ 19753 /* Don't know what else to do right now. */ 19754 if (req->ignore) 19755 return res; 19756 19757 /* If this is a blind transfer, we have the following 19758 channels to work with: 19759 - chan1, chan2: The current call between transferer and transferee (2 channels) 19760 - target_channel: A new call from the transferee to the target (1 channel) 19761 We need to stay tuned to what happens in order to be able 19762 to bring back the call to the transferer */ 19763 19764 /* If this is a attended transfer, we should have all call legs within reach: 19765 - chan1, chan2: The call between the transferer and transferee (2 channels) 19766 - target_channel, targetcall_pvt: The call between the transferer and the target (2 channels) 19767 We want to bridge chan2 with targetcall_pvt! 19768 19769 The replaces call id in the refer message points 19770 to the call leg between Asterisk and the transferer. 19771 So we need to connect the target and the transferee channel 19772 and hangup the two other channels silently 19773 19774 If the target is non-local, the call ID could be on a remote 19775 machine and we need to send an INVITE with replaces to the 19776 target. We basically handle this as a blind transfer 19777 and let the sip_call function catch that we need replaces 19778 header in the INVITE. 19779 */ 19780 19781 19782 /* Get the transferer's channel */ 19783 current.chan1 = p->owner; 19784 19785 /* Find the other part of the bridge (2) - transferee */ 19786 current.chan2 = ast_bridged_channel(current.chan1); 19787 19788 if (sipdebug) 19789 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>"); 19790 19791 if (!current.chan2 && !p->refer->attendedtransfer) { 19792 /* No bridged channel, propably IVR or echo or similar... */ 19793 /* Guess we should masquerade or something here */ 19794 /* Until we figure it out, refuse transfer of such calls */ 19795 if (sipdebug) 19796 ast_debug(3, "Refused SIP transfer on non-bridged channel.\n"); 19797 p->refer->status = REFER_FAILED; 19798 append_history(p, "Xfer", "Refer failed. Non-bridged channel."); 19799 transmit_response(p, "603 Declined", req); 19800 return -1; 19801 } 19802 19803 if (current.chan2) { 19804 if (sipdebug) 19805 ast_debug(4, "Got SIP transfer, applying to bridged peer '%s'\n", current.chan2->name); 19806 19807 ast_queue_control(current.chan1, AST_CONTROL_UNHOLD); 19808 } 19809 19810 ast_set_flag(&p->flags[0], SIP_GOTREFER); 19811 19812 /* Attended transfer: Find all call legs and bridge transferee with target*/ 19813 if (p->refer->attendedtransfer) { 19814 if ((res = local_attended_transfer(p, ¤t, req, seqno))) 19815 return res; /* We're done with the transfer */ 19816 /* Fall through for remote transfers that we did not find locally */ 19817 if (sipdebug) 19818 ast_debug(4, "SIP attended transfer: Still not our call - generating INVITE with replaces\n"); 19819 /* Fallthrough if we can't find the call leg internally */ 19820 } 19821 19822 19823 /* Parking a call */ 19824 if (p->refer->localtransfer && !strcmp(p->refer->refer_to, ast_parking_ext())) { 19825 /* Must release c's lock now, because it will not longer be accessible after the transfer! */ 19826 *nounlock = 1; 19827 ast_channel_unlock(current.chan1); 19828 copy_request(¤t.req, req); 19829 ast_clear_flag(&p->flags[0], SIP_GOTREFER); 19830 p->refer->status = REFER_200OK; 19831 append_history(p, "Xfer", "REFER to call parking."); 19832 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", 19833 current.chan1->name, 19834 current.chan1->uniqueid, 19835 p->callid, 19836 current.chan2->name, 19837 current.chan2->uniqueid, 19838 p->refer->refer_to); 19839 if (sipdebug) 19840 ast_debug(4, "SIP transfer to parking: trying to park %s. Parked by %s\n", current.chan2->name, current.chan1->name); 19841 sip_park(current.chan2, current.chan1, req, seqno); 19842 return res; 19843 } 19844 19845 /* Blind transfers and remote attended xfers */ 19846 transmit_response(p, "202 Accepted", req); 19847 19848 if (current.chan1 && current.chan2) { 19849 ast_debug(3, "chan1->name: %s\n", current.chan1->name); 19850 pbx_builtin_setvar_helper(current.chan1, "BLINDTRANSFER", current.chan2->name); 19851 } 19852 if (current.chan2) { 19853 pbx_builtin_setvar_helper(current.chan2, "BLINDTRANSFER", current.chan1->name); 19854 pbx_builtin_setvar_helper(current.chan2, "SIPDOMAIN", p->refer->refer_to_domain); 19855 pbx_builtin_setvar_helper(current.chan2, "SIPTRANSFER", "yes"); 19856 /* One for the new channel */ 19857 pbx_builtin_setvar_helper(current.chan2, "_SIPTRANSFER", "yes"); 19858 /* Attended transfer to remote host, prepare headers for the INVITE */ 19859 if (p->refer->referred_by) 19860 pbx_builtin_setvar_helper(current.chan2, "_SIPTRANSFER_REFERER", p->refer->referred_by); 19861 } 19862 /* Generate a Replaces string to be used in the INVITE during attended transfer */ 19863 if (!ast_strlen_zero(p->refer->replaces_callid)) { 19864 char tempheader[SIPBUFSIZE]; 19865 snprintf(tempheader, sizeof(tempheader), "%s%s%s%s%s", p->refer->replaces_callid, 19866 p->refer->replaces_callid_totag ? ";to-tag=" : "", 19867 p->refer->replaces_callid_totag, 19868 p->refer->replaces_callid_fromtag ? ";from-tag=" : "", 19869 p->refer->replaces_callid_fromtag); 19870 if (current.chan2) 19871 pbx_builtin_setvar_helper(current.chan2, "_SIPTRANSFER_REPLACES", tempheader); 19872 } 19873 /* Must release lock now, because it will not longer 19874 be accessible after the transfer! */ 19875 *nounlock = 1; 19876 ast_channel_unlock(current.chan1); 19877 19878 /* Connect the call */ 19879 19880 /* FAKE ringing if not attended transfer */ 19881 if (!p->refer->attendedtransfer) 19882 transmit_notify_with_sipfrag(p, seqno, "183 Ringing", FALSE); 19883 19884 /* For blind transfer, this will lead to a new call */ 19885 /* For attended transfer to remote host, this will lead to 19886 a new SIP call with a replaces header, if the dial plan allows it 19887 */ 19888 if (!current.chan2) { 19889 /* We have no bridge, so we're talking with Asterisk somehow */ 19890 /* We need to masquerade this call */ 19891 /* What to do to fix this situation: 19892 * Set up the new call in a new channel 19893 * Let the new channel masq into this channel 19894 Please add that code here :-) 19895 */ 19896 p->refer->status = REFER_FAILED; 19897 transmit_notify_with_sipfrag(p, seqno, "503 Service Unavailable (can't handle one-legged xfers)", TRUE); 19898 ast_clear_flag(&p->flags[0], SIP_GOTREFER); 19899 append_history(p, "Xfer", "Refer failed (only bridged calls)."); 19900 return -1; 19901 } 19902 ast_set_flag(&p->flags[0], SIP_DEFER_BYE_ON_TRANSFER); /* Delay hangup */ 19903 19904 19905 /* For blind transfers, move the call to the new extensions. For attended transfers on multiple 19906 servers - generate an INVITE with Replaces. Either way, let the dial plan decided */ 19907 res = ast_async_goto(current.chan2, p->refer->refer_to_context, p->refer->refer_to, 1); 19908 19909 if (!res) { 19910 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", 19911 current.chan1->name, 19912 current.chan1->uniqueid, 19913 p->callid, 19914 current.chan2->name, 19915 current.chan2->uniqueid, 19916 p->refer->refer_to, p->refer->refer_to_context); 19917 /* Success - we have a new channel */ 19918 ast_debug(3, "%s transfer succeeded. Telling transferer.\n", p->refer->attendedtransfer? "Attended" : "Blind"); 19919 transmit_notify_with_sipfrag(p, seqno, "200 Ok", TRUE); 19920 if (p->refer->localtransfer) 19921 p->refer->status = REFER_200OK; 19922 if (p->owner) 19923 p->owner->hangupcause = AST_CAUSE_NORMAL_CLEARING; 19924 append_history(p, "Xfer", "Refer succeeded."); 19925 ast_clear_flag(&p->flags[0], SIP_GOTREFER); 19926 /* Do not hangup call, the other side do that when we say 200 OK */ 19927 /* We could possibly implement a timer here, auto congestion */ 19928 res = 0; 19929 } else { 19930 ast_clear_flag(&p->flags[0], SIP_DEFER_BYE_ON_TRANSFER); /* Don't delay hangup */ 19931 ast_debug(3, "%s transfer failed. Resuming original call.\n", p->refer->attendedtransfer? "Attended" : "Blind"); 19932 append_history(p, "Xfer", "Refer failed."); 19933 /* Failure of some kind */ 19934 p->refer->status = REFER_FAILED; 19935 transmit_notify_with_sipfrag(p, seqno, "503 Service Unavailable", TRUE); 19936 ast_clear_flag(&p->flags[0], SIP_GOTREFER); 19937 res = -1; 19938 } 19939 return res; 19940 }
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 20594 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().
20595 { 20596 enum check_auth_result res; 20597 20598 /* Use this as the basis */ 20599 copy_request(&p->initreq, req); 20600 if (sipdebug) 20601 ast_debug(4, "Initializing initreq for method %s - callid %s\n", sip_methods[req->method].text, p->callid); 20602 check_via(p, req); 20603 if ((res = register_verify(p, sin, req, e)) < 0) { 20604 const char *reason; 20605 20606 switch (res) { 20607 case AUTH_SECRET_FAILED: 20608 reason = "Wrong password"; 20609 break; 20610 case AUTH_USERNAME_MISMATCH: 20611 reason = "Username/auth name mismatch"; 20612 break; 20613 case AUTH_NOT_FOUND: 20614 reason = "No matching peer found"; 20615 break; 20616 case AUTH_UNKNOWN_DOMAIN: 20617 reason = "Not a local domain"; 20618 break; 20619 case AUTH_PEER_NOT_DYNAMIC: 20620 reason = "Peer is not supposed to register"; 20621 break; 20622 case AUTH_ACL_FAILED: 20623 reason = "Device does not match ACL"; 20624 break; 20625 case AUTH_BAD_TRANSPORT: 20626 reason = "Device not configured to use this transport type"; 20627 break; 20628 default: 20629 reason = "Unknown failure"; 20630 break; 20631 } 20632 ast_log(LOG_NOTICE, "Registration from '%s' failed for '%s' - %s\n", 20633 get_header(req, "To"), ast_inet_ntoa(sin->sin_addr), 20634 reason); 20635 append_history(p, "RegRequest", "Failed : Account %s : %s", get_header(req, "To"), reason); 20636 } else 20637 append_history(p, "RegRequest", "Succeeded : Account %s", get_header(req, "To")); 20638 20639 if (res < 1) { 20640 /* Destroy the session, but keep us around for just a bit in case they don't 20641 get our 200 OK */ 20642 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 20643 } 20644 return res; 20645 }
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 20270 of file chan_sip.c.
References add_peer_mwi_subs(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_lock(), ao2_t_iterator_next, ao2_t_ref, ao2_unlock(), append_history, ast_debug, AST_EXTENSION_REMOVED, ast_extension_state(), ast_extension_state2str(), ast_extension_state_add(), ast_extension_state_del(), ast_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(), build_route(), 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().
20271 { 20272 int gotdest = 0; 20273 int res = 0; 20274 int firststate = AST_EXTENSION_REMOVED; 20275 struct sip_peer *authpeer = NULL; 20276 const char *eventheader = get_header(req, "Event"); /* Get Event package name */ 20277 const char *acceptheader = get_header(req, "Accept"); 20278 int resubscribe = (p->subscribed != NONE); 20279 char *temp, *event; 20280 struct ao2_iterator i; 20281 20282 if (p->initreq.headers) { 20283 /* We already have a dialog */ 20284 if (p->initreq.method != SIP_SUBSCRIBE) { 20285 /* This is a SUBSCRIBE within another SIP dialog, which we do not support */ 20286 /* For transfers, this could happen, but since we haven't seen it happening, let us just refuse this */ 20287 transmit_response(p, "403 Forbidden (within dialog)", req); 20288 /* Do not destroy session, since we will break the call if we do */ 20289 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); 20290 return 0; 20291 } else if (req->debug) { 20292 if (resubscribe) 20293 ast_debug(1, "Got a re-subscribe on existing subscription %s\n", p->callid); 20294 else 20295 ast_debug(1, "Got a new subscription %s (possibly with auth)\n", p->callid); 20296 } 20297 } 20298 20299 /* Check if we have a global disallow setting on subscriptions. 20300 if so, we don't have to check peer settings after auth, which saves a lot of processing 20301 */ 20302 if (!global_allowsubscribe) { 20303 transmit_response(p, "403 Forbidden (policy)", req); 20304 p->needdestroy = 1; 20305 return 0; 20306 } 20307 20308 if (!req->ignore && !resubscribe) { /* Set up dialog, new subscription */ 20309 const char *to = get_header(req, "To"); 20310 char totag[128]; 20311 20312 /* Check to see if a tag was provided, if so this is actually a resubscription of a dialog we no longer know about */ 20313 if (!ast_strlen_zero(to) && gettag(req, "To", totag, sizeof(totag))) { 20314 if (req->debug) 20315 ast_verbose("Received resubscription for a dialog we no longer know about. Telling remote side to subscribe again.\n"); 20316 transmit_response(p, "481 Subscription does not exist", req); 20317 p->needdestroy = 1; 20318 return 0; 20319 } 20320 20321 /* Use this as the basis */ 20322 if (req->debug) 20323 ast_verbose("Creating new subscription\n"); 20324 20325 copy_request(&p->initreq, req); 20326 if (sipdebug) 20327 ast_debug(4, "Initializing initreq for method %s - callid %s\n", sip_methods[req->method].text, p->callid); 20328 check_via(p, req); 20329 build_route(p, req, 0); 20330 } else if (req->debug && req->ignore) 20331 ast_verbose("Ignoring this SUBSCRIBE request\n"); 20332 20333 /* Find parameters to Event: header value and remove them for now */ 20334 if (ast_strlen_zero(eventheader)) { 20335 transmit_response(p, "489 Bad Event", req); 20336 ast_debug(2, "Received SIP subscribe for unknown event package: <none>\n"); 20337 p->needdestroy = 1; 20338 return 0; 20339 } 20340 20341 if ( (strchr(eventheader, ';'))) { 20342 event = ast_strdupa(eventheader); /* Since eventheader is a const, we can't change it */ 20343 temp = strchr(event, ';'); 20344 *temp = '\0'; /* Remove any options for now */ 20345 /* We might need to use them later :-) */ 20346 } else 20347 event = (char *) eventheader; /* XXX is this legal ? */ 20348 20349 /* Handle authentication */ 20350 res = check_user_full(p, req, SIP_SUBSCRIBE, e, 0, sin, &authpeer); 20351 /* if an authentication response was sent, we are done here */ 20352 if (res == AUTH_CHALLENGE_SENT) /* authpeer = NULL here */ 20353 return 0; 20354 if (res < 0) { 20355 if (res == AUTH_FAKE_AUTH) { 20356 ast_log(LOG_NOTICE, "Sending fake auth rejection for device %s\n", get_header(req, "From")); 20357 transmit_fake_auth_response(p, SIP_SUBSCRIBE, req, XMIT_UNRELIABLE); 20358 } else { 20359 ast_log(LOG_NOTICE, "Failed to authenticate device %s for SUBSCRIBE\n", get_header(req, "From")); 20360 transmit_response_reliable(p, "403 Forbidden", req); 20361 } 20362 p->needdestroy = 1; 20363 return 0; 20364 } 20365 20366 /* At this point, authpeer cannot be NULL. Remember we hold a reference, 20367 * so we must release it when done. 20368 * XXX must remove all the checks for authpeer == NULL. 20369 */ 20370 20371 /* Check if this device is allowed to subscribe at all */ 20372 if (!ast_test_flag(&p->flags[1], SIP_PAGE2_ALLOWSUBSCRIBE)) { 20373 transmit_response(p, "403 Forbidden (policy)", req); 20374 p->needdestroy = 1; 20375 if (authpeer) 20376 unref_peer(authpeer, "unref_peer, from handle_request_subscribe (authpeer 1)"); 20377 return 0; 20378 } 20379 20380 if (strcmp(event, "message-summary")) { 20381 /* Get destination right away */ 20382 gotdest = get_destination(p, NULL); 20383 } 20384 20385 /* Get full contact header - this needs to be used as a request URI in NOTIFY's */ 20386 parse_ok_contact(p, req); 20387 20388 build_contact(p); 20389 if (gotdest) { 20390 transmit_response(p, "404 Not Found", req); 20391 p->needdestroy = 1; 20392 if (authpeer) 20393 unref_peer(authpeer, "unref_peer, from handle_request_subscribe (authpeer 2)"); 20394 return 0; 20395 } 20396 20397 /* Initialize tag for new subscriptions */ 20398 if (ast_strlen_zero(p->tag)) 20399 make_our_tag(p->tag, sizeof(p->tag)); 20400 20401 if (!strcmp(event, "presence") || !strcmp(event, "dialog")) { /* Presence, RFC 3842 */ 20402 unsigned int pidf_xml; 20403 20404 if (authpeer) /* We do not need the authpeer any more */ 20405 unref_peer(authpeer, "unref_peer, from handle_request_subscribe (authpeer 2)"); 20406 20407 /* Header from Xten Eye-beam Accept: multipart/related, application/rlmi+xml, application/pidf+xml, application/xpidf+xml */ 20408 20409 pidf_xml = strstr(acceptheader, "application/pidf+xml") ? 1 : 0; 20410 20411 /* Older versions of Polycom firmware will claim pidf+xml, but really 20412 * they only support xpidf+xml. */ 20413 if (pidf_xml && strstr(p->useragent, "Polycom")) { 20414 p->subscribed = XPIDF_XML; 20415 } else if (pidf_xml) { 20416 p->subscribed = PIDF_XML; /* RFC 3863 format */ 20417 } else if (strstr(acceptheader, "application/dialog-info+xml")) { 20418 p->subscribed = DIALOG_INFO_XML; 20419 /* IETF draft: draft-ietf-sipping-dialog-package-05.txt */ 20420 } else if (strstr(acceptheader, "application/cpim-pidf+xml")) { 20421 p->subscribed = CPIM_PIDF_XML; /* RFC 3863 format */ 20422 } else if (strstr(acceptheader, "application/xpidf+xml")) { 20423 p->subscribed = XPIDF_XML; /* Early pre-RFC 3863 format with MSN additions (Microsoft Messenger) */ 20424 } else if (ast_strlen_zero(acceptheader)) { 20425 if (p->subscribed == NONE) { /* if the subscribed field is not already set, and there is no accept header... */ 20426 transmit_response(p, "489 Bad Event", req); 20427 20428 ast_log(LOG_WARNING, "SUBSCRIBE failure: no Accept header: pvt: stateid: %d, laststate: %d, dialogver: %d, subscribecont: '%s', subscribeuri: '%s'\n", 20429 p->stateid, p->laststate, p->dialogver, p->subscribecontext, p->subscribeuri); 20430 p->needdestroy = 1; 20431 return 0; 20432 } 20433 /* if p->subscribed is non-zero, then accept is not obligatory; according to rfc 3265 section 3.1.3, at least. 20434 so, we'll just let it ride, keeping the value from a previous subscription, and not abort the subscription */ 20435 } else { 20436 /* Can't find a format for events that we know about */ 20437 char mybuf[200]; 20438 snprintf(mybuf, sizeof(mybuf), "489 Bad Event (format %s)", acceptheader); 20439 transmit_response(p, mybuf, req); 20440 20441 ast_log(LOG_WARNING, "SUBSCRIBE failure: unrecognized format: '%s' pvt: subscribed: %d, stateid: %d, laststate: %d, dialogver: %d, subscribecont: '%s', subscribeuri: '%s'\n", 20442 acceptheader, (int)p->subscribed, p->stateid, p->laststate, p->dialogver, p->subscribecontext, p->subscribeuri); 20443 p->needdestroy = 1; 20444 return 0; 20445 } 20446 } else if (!strcmp(event, "message-summary")) { 20447 if (!ast_strlen_zero(acceptheader) && strcmp(acceptheader, "application/simple-message-summary")) { 20448 /* Format requested that we do not support */ 20449 transmit_response(p, "406 Not Acceptable", req); 20450 ast_debug(2, "Received SIP mailbox subscription for unknown format: %s\n", acceptheader); 20451 p->needdestroy = 1; 20452 if (authpeer) 20453 unref_peer(authpeer, "unref_peer, from handle_request_subscribe (authpeer 3)"); 20454 return 0; 20455 } 20456 /* Looks like they actually want a mailbox status 20457 This version of Asterisk supports mailbox subscriptions 20458 The subscribed URI needs to exist in the dial plan 20459 In most devices, this is configurable to the voicemailmain extension you use 20460 */ 20461 if (!authpeer || AST_LIST_EMPTY(&authpeer->mailboxes)) { 20462 transmit_response(p, "404 Not found (no mailbox)", req); 20463 p->needdestroy = 1; 20464 ast_log(LOG_NOTICE, "Received SIP subscribe for peer without mailbox: %s\n", authpeer->name); 20465 if (authpeer) 20466 unref_peer(authpeer, "unref_peer, from handle_request_subscribe (authpeer 4)"); 20467 return 0; 20468 } 20469 20470 p->subscribed = MWI_NOTIFICATION; 20471 if (ast_test_flag(&authpeer->flags[1], SIP_PAGE2_SUBSCRIBEMWIONLY)) { 20472 add_peer_mwi_subs(authpeer); 20473 } 20474 if (authpeer->mwipvt && authpeer->mwipvt != p) { /* Destroy old PVT if this is a new one */ 20475 /* We only allow one subscription per peer */ 20476 dialog_unlink_all(authpeer->mwipvt, TRUE, TRUE); 20477 authpeer->mwipvt = dialog_unref(authpeer->mwipvt, "unref dialog authpeer->mwipvt"); 20478 /* sip_destroy(authpeer->mwipvt); */ 20479 } 20480 if (authpeer->mwipvt) 20481 dialog_unref(authpeer->mwipvt, "Unref previously stored mwipvt dialog pointer"); 20482 authpeer->mwipvt = dialog_ref(p, "setting peers' mwipvt to p"); /* Link from peer to pvt UH- should this be dialog_ref()? */ 20483 if (p->relatedpeer) 20484 unref_peer(p->relatedpeer, "Unref previously stored relatedpeer ptr"); 20485 p->relatedpeer = ref_peer(authpeer, "setting dialog's relatedpeer pointer"); /* already refcounted...Link from pvt to peer UH- should this be dialog_ref()? */ 20486 /* Do not release authpeer here */ 20487 } else { /* At this point, Asterisk does not understand the specified event */ 20488 transmit_response(p, "489 Bad Event", req); 20489 ast_debug(2, "Received SIP subscribe for unknown event package: %s\n", event); 20490 p->needdestroy = 1; 20491 if (authpeer) 20492 unref_peer(authpeer, "unref_peer, from handle_request_subscribe (authpeer 5)"); 20493 return 0; 20494 } 20495 20496 /* Add subscription for extension state from the PBX core */ 20497 if (p->subscribed != MWI_NOTIFICATION && !resubscribe) { 20498 if (p->stateid > -1) { 20499 ast_extension_state_del(p->stateid, cb_extensionstate); 20500 /* we need to dec the refcount, now that the extensionstate is removed */ 20501 dialog_unref(p, "the extensionstate containing this dialog ptr was deleted"); 20502 } 20503 p->stateid = ast_extension_state_add(p->context, p->exten, cb_extensionstate, dialog_ref(p,"copying dialog ptr into extension state struct")); 20504 } 20505 20506 if (!req->ignore && p) 20507 p->lastinvite = seqno; 20508 if (p && !p->needdestroy) { 20509 p->expiry = atoi(get_header(req, "Expires")); 20510 20511 /* check if the requested expiry-time is within the approved limits from sip.conf */ 20512 if (p->expiry > max_expiry) 20513 p->expiry = max_expiry; 20514 if (p->expiry < min_expiry && p->expiry > 0) 20515 p->expiry = min_expiry; 20516 20517 if (sipdebug) { 20518 if (p->subscribed == MWI_NOTIFICATION && p->relatedpeer) 20519 ast_debug(2, "Adding subscription for mailbox notification - peer %s\n", p->relatedpeer->name); 20520 else 20521 ast_debug(2, "Adding subscription for extension %s context %s for peer %s\n", p->exten, p->context, p->username); 20522 } 20523 if (p->autokillid > -1 && sip_cancel_destroy(p)) /* Remove subscription expiry for renewals */ 20524 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 20525 if (p->expiry > 0) 20526 sip_scheddestroy(p, (p->expiry + 10) * 1000); /* Set timer for destruction of call at expiration */ 20527 20528 if (p->subscribed == MWI_NOTIFICATION) { 20529 ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED); 20530 transmit_response(p, "200 OK", req); 20531 if (p->relatedpeer) { /* Send first notification */ 20532 ao2_lock(p->relatedpeer); /* was WRLOCK */ 20533 sip_send_mwi_to_peer(p->relatedpeer, NULL, 0); 20534 ao2_unlock(p->relatedpeer); 20535 } 20536 } else { 20537 struct sip_pvt *p_old; 20538 20539 if ((firststate = ast_extension_state(NULL, p->context, p->exten)) < 0) { 20540 20541 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)); 20542 transmit_response(p, "404 Not found", req); 20543 p->needdestroy = 1; 20544 return 0; 20545 } 20546 ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED); 20547 transmit_response(p, "200 OK", req); 20548 transmit_state_notify(p, firststate, 1, FALSE); /* Send first notification */ 20549 append_history(p, "Subscribestatus", "%s", ast_extension_state2str(firststate)); 20550 /* hide the 'complete' exten/context in the refer_to field for later display */ 20551 ast_string_field_build(p, subscribeuri, "%s@%s", p->exten, p->context); 20552 20553 /* remove any old subscription from this peer for the same exten/context, 20554 as the peer has obviously forgotten about it and it's wasteful to wait 20555 for it to expire and send NOTIFY messages to the peer only to have them 20556 ignored (or generate errors) 20557 */ 20558 i = ao2_iterator_init(dialogs, 0); 20559 while ((p_old = ao2_t_iterator_next(&i, "iterate thru dialogs"))) { 20560 if (p_old == p) { 20561 ao2_t_ref(p_old, -1, "toss dialog ptr from iterator_next before continue"); 20562 continue; 20563 } 20564 if (p_old->initreq.method != SIP_SUBSCRIBE) { 20565 ao2_t_ref(p_old, -1, "toss dialog ptr from iterator_next before continue"); 20566 continue; 20567 } 20568 if (p_old->subscribed == NONE) { 20569 ao2_t_ref(p_old, -1, "toss dialog ptr from iterator_next before continue"); 20570 continue; 20571 } 20572 sip_pvt_lock(p_old); 20573 if (!strcmp(p_old->username, p->username)) { 20574 if (!strcmp(p_old->exten, p->exten) && 20575 !strcmp(p_old->context, p->context)) { 20576 p_old->needdestroy = 1; 20577 sip_pvt_unlock(p_old); 20578 ao2_t_ref(p_old, -1, "toss dialog ptr from iterator_next before break"); 20579 break; 20580 } 20581 } 20582 sip_pvt_unlock(p_old); 20583 ao2_t_ref(p_old, -1, "toss dialog ptr from iterator_next"); 20584 } 20585 ao2_iterator_destroy(&i); 20586 } 20587 if (!p->expiry) 20588 p->needdestroy = 1; 20589 } 20590 return 1; 20591 }
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 17460 of file chan_sip.c.
References __sip_ack(), __sip_semi_ack(), append_history, 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, SIP_TRANSPORT_UDP, sip_pvt::socket, stop_media_flows(), sip_pvt::subscribed, text, sip_pvt::theirtag, transmit_request(), sip_socket::type, and XMIT_UNRELIABLE.
17461 { 17462 struct ast_channel *owner; 17463 int sipmethod; 17464 int res = 1; 17465 const char *c = get_header(req, "Cseq"); 17466 /* 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 */ 17467 char *c_copy = ast_strdupa(c); 17468 /* Skip the Cseq and its subsequent spaces */ 17469 const char *msg = ast_skip_blanks(ast_skip_nonblanks(c_copy)); 17470 17471 if (!msg) 17472 msg = ""; 17473 17474 sipmethod = find_sip_method(msg); 17475 17476 owner = p->owner; 17477 if (owner) 17478 owner->hangupcause = hangup_sip2cause(resp); 17479 17480 if (p->socket.type == SIP_TRANSPORT_UDP) { 17481 int ack_res; 17482 17483 /* Acknowledge whatever it is destined for */ 17484 if ((resp >= 100) && (resp <= 199)) { 17485 ack_res = __sip_semi_ack(p, seqno, 0, sipmethod); 17486 } else { 17487 ack_res = __sip_ack(p, seqno, 0, sipmethod); 17488 } 17489 17490 if (ack_res == FALSE) { 17491 append_history(p, "Ignore", "Ignoring this retransmit\n"); 17492 return; 17493 } 17494 } 17495 17496 /* If this is a NOTIFY for a subscription clear the flag that indicates that we have a NOTIFY pending */ 17497 if (!p->owner && sipmethod == SIP_NOTIFY && p->pendinginvite) 17498 p->pendinginvite = 0; 17499 17500 /* Get their tag if we haven't already */ 17501 if (ast_strlen_zero(p->theirtag) || (resp >= 200)) { 17502 char tag[128]; 17503 17504 gettag(req, "To", tag, sizeof(tag)); 17505 ast_string_field_set(p, theirtag, tag); 17506 } 17507 /* This needs to be configurable on a channel/peer level, 17508 not mandatory for all communication. Sadly enough, NAT implementations 17509 are not so stable so we can always rely on these headers. 17510 Temporarily disabled, while waiting for fix. 17511 Fix assigned to Rizzo :-) 17512 */ 17513 /* check_via_response(p, req); */ 17514 17515 /* RFC 3261 Section 15 specifies that if we receive a 408 or 481 17516 * in response to a BYE, then we should end the current dialog 17517 * and session. It is known that at least one phone manufacturer 17518 * potentially will send a 404 in response to a BYE, so we'll be 17519 * liberal in what we accept and end the dialog and session if we 17520 * receive any of those responses to a BYE. 17521 */ 17522 if ((resp == 404 || resp == 408 || resp == 481) && sipmethod == SIP_BYE) { 17523 p->needdestroy = 1; 17524 return; 17525 } 17526 17527 if (p->relatedpeer && p->method == SIP_OPTIONS) { 17528 /* We don't really care what the response is, just that it replied back. 17529 Well, as long as it's not a 100 response... since we might 17530 need to hang around for something more "definitive" */ 17531 if (resp != 100) 17532 handle_response_peerpoke(p, resp, req); 17533 } else if (ast_test_flag(&p->flags[0], SIP_OUTGOING)) { 17534 switch(resp) { 17535 case 100: /* 100 Trying */ 17536 case 101: /* 101 Dialog establishment */ 17537 if (sipmethod == SIP_INVITE) 17538 handle_response_invite(p, resp, rest, req, seqno); 17539 break; 17540 case 183: /* 183 Session Progress */ 17541 if (sipmethod == SIP_INVITE) 17542 handle_response_invite(p, resp, rest, req, seqno); 17543 break; 17544 case 180: /* 180 Ringing */ 17545 if (sipmethod == SIP_INVITE) 17546 handle_response_invite(p, resp, rest, req, seqno); 17547 break; 17548 case 182: /* 182 Queued */ 17549 if (sipmethod == SIP_INVITE) 17550 handle_response_invite(p, resp, rest, req, seqno); 17551 break; 17552 case 200: /* 200 OK */ 17553 p->authtries = 0; /* Reset authentication counter */ 17554 if (sipmethod == SIP_MESSAGE || sipmethod == SIP_INFO) { 17555 /* We successfully transmitted a message 17556 or a video update request in INFO */ 17557 /* Nothing happens here - the message is inside a dialog */ 17558 } else if (sipmethod == SIP_INVITE) { 17559 handle_response_invite(p, resp, rest, req, seqno); 17560 } else if (sipmethod == SIP_NOTIFY) { 17561 handle_response_notify(p, resp, rest, req, seqno); 17562 } else if (sipmethod == SIP_REGISTER) 17563 res = handle_response_register(p, resp, rest, req, seqno); 17564 else if (sipmethod == SIP_BYE) { /* Ok, we're ready to go */ 17565 p->needdestroy = 1; 17566 ast_clear_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED); 17567 } else if (sipmethod == SIP_SUBSCRIBE) { 17568 ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED); 17569 } 17570 break; 17571 case 202: /* Transfer accepted */ 17572 if (sipmethod == SIP_REFER) 17573 handle_response_refer(p, resp, rest, req, seqno); 17574 break; 17575 case 401: /* Not www-authorized on SIP method */ 17576 case 407: /* Proxy auth required */ 17577 if (sipmethod == SIP_INVITE) 17578 handle_response_invite(p, resp, rest, req, seqno); 17579 else if (sipmethod == SIP_NOTIFY) 17580 handle_response_notify(p, resp, rest, req, seqno); 17581 else if (sipmethod == SIP_REFER) 17582 handle_response_refer(p, resp, rest, req, seqno); 17583 else if (p->registry && sipmethod == SIP_REGISTER) 17584 res = handle_response_register(p, resp, rest, req, seqno); 17585 else if (sipmethod == SIP_BYE) { 17586 if (p->options) 17587 p->options->auth_type = resp; 17588 if (ast_strlen_zero(p->authname)) { 17589 ast_log(LOG_WARNING, "Asked to authenticate %s, to %s:%d but we have no matching peer!\n", 17590 msg, ast_inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port)); 17591 p->needdestroy = 1; 17592 } else if ((p->authtries == MAX_AUTHTRIES) || do_proxy_auth(p, req, resp, sipmethod, 0)) { 17593 ast_log(LOG_NOTICE, "Failed to authenticate on %s to '%s'\n", msg, get_header(&p->initreq, "From")); 17594 p->needdestroy = 1; 17595 } 17596 } else { 17597 ast_log(LOG_WARNING, "Got authentication request (%d) on %s to '%s'\n", resp, sip_methods[sipmethod].text, get_header(req, "To")); 17598 p->needdestroy = 1; 17599 } 17600 break; 17601 case 403: /* Forbidden - we failed authentication */ 17602 if (sipmethod == SIP_INVITE) 17603 handle_response_invite(p, resp, rest, req, seqno); 17604 else if (p->registry && sipmethod == SIP_REGISTER) 17605 res = handle_response_register(p, resp, rest, req, seqno); 17606 else { 17607 ast_log(LOG_WARNING, "Forbidden - maybe wrong password on authentication for %s\n", msg); 17608 p->needdestroy = 1; 17609 } 17610 break; 17611 case 404: /* Not found */ 17612 if (p->registry && sipmethod == SIP_REGISTER) 17613 res = handle_response_register(p, resp, rest, req, seqno); 17614 else if (sipmethod == SIP_INVITE) 17615 handle_response_invite(p, resp, rest, req, seqno); 17616 else if (owner) 17617 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 17618 break; 17619 case 423: /* Interval too brief */ 17620 if (sipmethod == SIP_REGISTER) 17621 res = handle_response_register(p, resp, rest, req, seqno); 17622 break; 17623 case 408: /* Request timeout - terminate dialog */ 17624 if (sipmethod == SIP_INVITE) 17625 handle_response_invite(p, resp, rest, req, seqno); 17626 else if (sipmethod == SIP_REGISTER) 17627 res = handle_response_register(p, resp, rest, req, seqno); 17628 else if (sipmethod == SIP_BYE) { 17629 p->needdestroy = 1; 17630 ast_debug(4, "Got timeout on bye. Thanks for the answer. Now, kill this call\n"); 17631 } else { 17632 if (owner) 17633 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 17634 p->needdestroy = 1; 17635 } 17636 break; 17637 17638 case 422: /* Session-Timers: Session Interval Too Small */ 17639 if (sipmethod == SIP_INVITE) { 17640 handle_response_invite(p, resp, rest, req, seqno); 17641 } 17642 break; 17643 17644 case 481: /* Call leg does not exist */ 17645 if (sipmethod == SIP_INVITE) { 17646 handle_response_invite(p, resp, rest, req, seqno); 17647 } else if (sipmethod == SIP_REFER) { 17648 handle_response_refer(p, resp, rest, req, seqno); 17649 } else if (sipmethod == SIP_BYE) { 17650 /* The other side has no transaction to bye, 17651 just assume it's all right then */ 17652 ast_log(LOG_WARNING, "Remote host can't match request %s to call '%s'. Giving up.\n", sip_methods[sipmethod].text, p->callid); 17653 } else if (sipmethod == SIP_CANCEL) { 17654 /* The other side has no transaction to cancel, 17655 just assume it's all right then */ 17656 ast_log(LOG_WARNING, "Remote host can't match request %s to call '%s'. Giving up.\n", sip_methods[sipmethod].text, p->callid); 17657 } else { 17658 ast_log(LOG_WARNING, "Remote host can't match request %s to call '%s'. Giving up.\n", sip_methods[sipmethod].text, p->callid); 17659 /* Guessing that this is not an important request */ 17660 } 17661 break; 17662 case 487: 17663 if (sipmethod == SIP_INVITE) 17664 handle_response_invite(p, resp, rest, req, seqno); 17665 break; 17666 case 415: /* Unsupported media type */ 17667 case 488: /* Not acceptable here - codec error */ 17668 case 606: /* Not Acceptable */ 17669 if (sipmethod == SIP_INVITE) 17670 handle_response_invite(p, resp, rest, req, seqno); 17671 break; 17672 case 491: /* Pending */ 17673 if (sipmethod == SIP_INVITE) 17674 handle_response_invite(p, resp, rest, req, seqno); 17675 else { 17676 ast_debug(1, "Got 491 on %s, unspported. Call ID %s\n", sip_methods[sipmethod].text, p->callid); 17677 p->needdestroy = 1; 17678 } 17679 break; 17680 case 501: /* Not Implemented */ 17681 if (sipmethod == SIP_INVITE) 17682 handle_response_invite(p, resp, rest, req, seqno); 17683 else if (sipmethod == SIP_REFER) 17684 handle_response_refer(p, resp, rest, req, seqno); 17685 else 17686 ast_log(LOG_WARNING, "Host '%s' does not implement '%s'\n", ast_inet_ntoa(p->sa.sin_addr), msg); 17687 break; 17688 case 603: /* Declined transfer */ 17689 if (sipmethod == SIP_REFER) { 17690 handle_response_refer(p, resp, rest, req, seqno); 17691 break; 17692 } 17693 /* Fallthrough */ 17694 default: 17695 if ((resp >= 300) && (resp < 700)) { 17696 /* Fatal response */ 17697 if ((resp != 487)) 17698 ast_verb(3, "Got SIP response %d \"%s\" back from %s\n", resp, rest, ast_inet_ntoa(p->sa.sin_addr)); 17699 17700 if (sipmethod == SIP_INVITE) 17701 stop_media_flows(p); /* Immediately stop RTP, VRTP and UDPTL as applicable */ 17702 17703 /* XXX Locking issues?? XXX */ 17704 switch(resp) { 17705 case 300: /* Multiple Choices */ 17706 case 301: /* Moved permanently */ 17707 case 302: /* Moved temporarily */ 17708 case 305: /* Use Proxy */ 17709 parse_moved_contact(p, req); 17710 /* Fall through */ 17711 case 486: /* Busy here */ 17712 case 600: /* Busy everywhere */ 17713 case 603: /* Decline */ 17714 if (p->owner) 17715 ast_queue_control(p->owner, AST_CONTROL_BUSY); 17716 break; 17717 case 482: /*! 17718 \note SIP is incapable of performing a hairpin call, which 17719 is yet another failure of not having a layer 2 (again, YAY 17720 IETF for thinking ahead). So we treat this as a call 17721 forward and hope we end up at the right place... */ 17722 ast_debug(1, "Hairpin detected, setting up call forward for what it's worth\n"); 17723 if (p->owner) 17724 ast_string_field_build(p->owner, call_forward, 17725 "Local/%s@%s", p->username, p->context); 17726 /* Fall through */ 17727 case 480: /* Temporarily Unavailable */ 17728 case 404: /* Not Found */ 17729 case 410: /* Gone */ 17730 case 400: /* Bad Request */ 17731 case 500: /* Server error */ 17732 if (sipmethod == SIP_REFER) { 17733 handle_response_refer(p, resp, rest, req, seqno); 17734 break; 17735 } 17736 /* Fall through */ 17737 case 502: /* Bad gateway */ 17738 case 503: /* Service Unavailable */ 17739 case 504: /* Server Timeout */ 17740 if (owner) 17741 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 17742 break; 17743 default: 17744 /* Send hangup */ 17745 if (owner && sipmethod != SIP_MESSAGE && sipmethod != SIP_INFO && sipmethod != SIP_BYE) 17746 ast_queue_hangup_with_cause(p->owner, AST_CAUSE_PROTOCOL_ERROR); 17747 break; 17748 } 17749 /* ACK on invite */ 17750 if (sipmethod == SIP_INVITE) 17751 transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); 17752 if (sipmethod != SIP_MESSAGE && sipmethod != SIP_INFO) 17753 sip_alreadygone(p); 17754 if (!p->owner) 17755 p->needdestroy = 1; 17756 } else if ((resp >= 100) && (resp < 200)) { 17757 if (sipmethod == SIP_INVITE) { 17758 if (!req->ignore && sip_cancel_destroy(p)) 17759 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 17760 if (find_sdp(req)) 17761 process_sdp(p, req, SDP_T38_NONE); 17762 if (p->owner) { 17763 /* Queue a progress frame */ 17764 ast_queue_control(p->owner, AST_CONTROL_PROGRESS); 17765 } 17766 } 17767 } else 17768 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)); 17769 } 17770 } else { 17771 /* Responses to OUTGOING SIP requests on INCOMING calls 17772 get handled here. As well as out-of-call message responses */ 17773 if (req->debug) 17774 ast_verbose("SIP Response message for INCOMING dialog %s arrived\n", msg); 17775 17776 if (sipmethod == SIP_INVITE && resp == 200) { 17777 /* Tags in early session is replaced by the tag in 200 OK, which is 17778 the final reply to our INVITE */ 17779 char tag[128]; 17780 17781 gettag(req, "To", tag, sizeof(tag)); 17782 ast_string_field_set(p, theirtag, tag); 17783 } 17784 17785 switch(resp) { 17786 case 200: 17787 if (sipmethod == SIP_INVITE) { 17788 handle_response_invite(p, resp, rest, req, seqno); 17789 } else if (sipmethod == SIP_CANCEL) { 17790 ast_debug(1, "Got 200 OK on CANCEL\n"); 17791 17792 /* Wait for 487, then destroy */ 17793 } else if (sipmethod == SIP_NOTIFY) { 17794 /* They got the notify, this is the end */ 17795 if (p->owner) { 17796 if (p->refer) { 17797 ast_debug(1, "Got 200 OK on NOTIFY for transfer\n"); 17798 } else 17799 ast_log(LOG_WARNING, "Notify answer on an owned channel?\n"); 17800 /* ast_queue_hangup(p->owner); Disabled */ 17801 } else { 17802 if (!p->subscribed && !p->refer) 17803 p->needdestroy = 1; 17804 if (ast_test_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE)) { 17805 /* Ready to send the next state we have on queue */ 17806 ast_clear_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE); 17807 cb_extensionstate((char *)p->context, (char *)p->exten, p->laststate, (void *) p); 17808 } 17809 } 17810 } else if (sipmethod == SIP_BYE) 17811 p->needdestroy = 1; 17812 else if (sipmethod == SIP_MESSAGE || sipmethod == SIP_INFO) 17813 /* We successfully transmitted a message or 17814 a video update request in INFO */ 17815 ; 17816 else if (sipmethod == SIP_BYE) 17817 /* Ok, we're ready to go */ 17818 p->needdestroy = 1; 17819 break; 17820 case 202: /* Transfer accepted */ 17821 if (sipmethod == SIP_REFER) 17822 handle_response_refer(p, resp, rest, req, seqno); 17823 break; 17824 case 401: /* www-auth */ 17825 case 407: 17826 if (sipmethod == SIP_REFER) 17827 handle_response_refer(p, resp, rest, req, seqno); 17828 else if (sipmethod == SIP_INVITE) 17829 handle_response_invite(p, resp, rest, req, seqno); 17830 else if (sipmethod == SIP_BYE) { 17831 if (p->authtries == MAX_AUTHTRIES || do_proxy_auth(p, req, resp, sipmethod, 0)) { 17832 ast_log(LOG_NOTICE, "Failed to authenticate on %s to '%s'\n", msg, get_header(&p->initreq, "From")); 17833 p->needdestroy = 1; 17834 } 17835 } 17836 break; 17837 case 481: /* Call leg does not exist */ 17838 if (sipmethod == SIP_INVITE) { 17839 /* Re-invite failed */ 17840 handle_response_invite(p, resp, rest, req, seqno); 17841 } else if (sipmethod == SIP_BYE) { 17842 p->needdestroy = 1; 17843 } else if (sipdebug) { 17844 ast_debug(1, "Remote host can't match request %s to call '%s'. Giving up\n", sip_methods[sipmethod].text, p->callid); 17845 } 17846 break; 17847 case 501: /* Not Implemented */ 17848 if (sipmethod == SIP_INVITE) 17849 handle_response_invite(p, resp, rest, req, seqno); 17850 else if (sipmethod == SIP_REFER) 17851 handle_response_refer(p, resp, rest, req, seqno); 17852 break; 17853 case 603: /* Declined transfer */ 17854 if (sipmethod == SIP_REFER) { 17855 handle_response_refer(p, resp, rest, req, seqno); 17856 break; 17857 } 17858 /* Fallthrough */ 17859 default: /* Errors without handlers */ 17860 if ((resp >= 100) && (resp < 200)) { 17861 if (sipmethod == SIP_INVITE) { /* re-invite */ 17862 if (!req->ignore && sip_cancel_destroy(p)) 17863 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 17864 } 17865 } 17866 if ((resp >= 300) && (resp < 700)) { 17867 if ((resp != 487)) 17868 ast_verb(3, "Incoming call: Got SIP response %d \"%s\" back from %s\n", resp, rest, ast_inet_ntoa(p->sa.sin_addr)); 17869 switch(resp) { 17870 case 415: /* Unsupported media type */ 17871 case 488: /* Not acceptable here - codec error */ 17872 case 603: /* Decline */ 17873 case 500: /* Server error */ 17874 case 502: /* Bad gateway */ 17875 case 503: /* Service Unavailable */ 17876 case 504: /* Server timeout */ 17877 17878 /* re-invite failed */ 17879 if (sipmethod == SIP_INVITE && sip_cancel_destroy(p)) 17880 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 17881 break; 17882 } 17883 } 17884 break; 17885 } 17886 } 17887 }
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 16833 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().
16834 { 16835 int outgoing = ast_test_flag(&p->flags[0], SIP_OUTGOING); 16836 int res = 0; 16837 int xmitres = 0; 16838 int reinvite = (p->owner && p->owner->_state == AST_STATE_UP); 16839 char *p_hdrval; 16840 int rtn; 16841 16842 if (reinvite) 16843 ast_debug(4, "SIP response %d to RE-invite on %s call %s\n", resp, outgoing ? "outgoing" : "incoming", p->callid); 16844 else 16845 ast_debug(4, "SIP response %d to standard invite\n", resp); 16846 16847 if (p->alreadygone) { /* This call is already gone */ 16848 ast_debug(1, "Got response on call that is already terminated: %s (ignoring)\n", p->callid); 16849 return; 16850 } 16851 16852 /* Acknowledge sequence number - This only happens on INVITE from SIP-call */ 16853 /* Don't auto congest anymore since we've gotten something useful back */ 16854 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")); 16855 16856 /* RFC3261 says we must treat every 1xx response (but not 100) 16857 that we don't recognize as if it was 183. 16858 */ 16859 if (resp > 100 && resp < 200 && resp!=101 && resp != 180 && resp != 182 && resp != 183) 16860 resp = 183; 16861 16862 /* Any response between 100 and 199 is PROCEEDING */ 16863 if (resp >= 100 && resp < 200 && p->invitestate == INV_CALLING) 16864 p->invitestate = INV_PROCEEDING; 16865 16866 /* Final response, not 200 ? */ 16867 if (resp >= 300 && (p->invitestate == INV_CALLING || p->invitestate == INV_PROCEEDING || p->invitestate == INV_EARLY_MEDIA )) 16868 p->invitestate = INV_COMPLETED; 16869 16870 /* Final response, clear out pending invite */ 16871 if ((resp == 200 || resp >= 300) && p->pendinginvite && seqno == p->pendinginvite) 16872 p->pendinginvite = 0; 16873 16874 switch (resp) { 16875 case 100: /* Trying */ 16876 case 101: /* Dialog establishment */ 16877 if (!req->ignore && p->invitestate != INV_CANCELLED && sip_cancel_destroy(p)) 16878 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 16879 check_pendings(p); 16880 break; 16881 16882 case 180: /* 180 Ringing */ 16883 case 182: /* 182 Queued */ 16884 if (!req->ignore && p->invitestate != INV_CANCELLED && sip_cancel_destroy(p)) 16885 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 16886 if (!req->ignore && p->owner) { 16887 ast_queue_control(p->owner, AST_CONTROL_RINGING); 16888 if (p->owner->_state != AST_STATE_UP) { 16889 ast_setstate(p->owner, AST_STATE_RINGING); 16890 } 16891 } 16892 if (find_sdp(req)) { 16893 if (p->invitestate != INV_CANCELLED) 16894 p->invitestate = INV_EARLY_MEDIA; 16895 res = process_sdp(p, req, SDP_T38_NONE); 16896 if (!req->ignore && p->owner) { 16897 /* Queue a progress frame only if we have SDP in 180 or 182 */ 16898 ast_queue_control(p->owner, AST_CONTROL_PROGRESS); 16899 } 16900 } 16901 check_pendings(p); 16902 break; 16903 16904 case 183: /* Session progress */ 16905 if (!req->ignore && (p->invitestate != INV_CANCELLED) && sip_cancel_destroy(p)) 16906 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 16907 if (find_sdp(req)) { 16908 if (p->invitestate != INV_CANCELLED) 16909 p->invitestate = INV_EARLY_MEDIA; 16910 res = process_sdp(p, req, SDP_T38_NONE); 16911 if (!req->ignore && p->owner) { 16912 /* Queue a progress frame */ 16913 ast_queue_control(p->owner, AST_CONTROL_PROGRESS); 16914 } 16915 } else { 16916 /* Alcatel PBXs are known to send 183s with no SDP after sending 16917 * a 100 Trying response. We're just going to treat this sort of thing 16918 * the same as we would treat a 180 Ringing 16919 */ 16920 if (!req->ignore && p->owner) { 16921 ast_queue_control(p->owner, AST_CONTROL_RINGING); 16922 } 16923 } 16924 check_pendings(p); 16925 break; 16926 16927 case 200: /* 200 OK on invite - someone's answering our call */ 16928 if (!req->ignore && (p->invitestate != INV_CANCELLED) && sip_cancel_destroy(p)) 16929 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 16930 p->authtries = 0; 16931 if (find_sdp(req)) { 16932 if ((res = process_sdp(p, req, SDP_T38_ACCEPT)) && !req->ignore) 16933 if (!reinvite) 16934 /* This 200 OK's SDP is not acceptable, so we need to ack, then hangup */ 16935 /* For re-invites, we try to recover */ 16936 ast_set_flag(&p->flags[0], SIP_PENDINGBYE); 16937 } 16938 16939 /* Parse contact header for continued conversation */ 16940 /* When we get 200 OK, we know which device (and IP) to contact for this call */ 16941 /* This is important when we have a SIP proxy between us and the phone */ 16942 if (outgoing) { 16943 update_call_counter(p, DEC_CALL_RINGING); 16944 parse_ok_contact(p, req); 16945 /* Save Record-Route for any later requests we make on this dialogue */ 16946 if (!reinvite) 16947 build_route(p, req, 1); 16948 16949 if(set_address_from_contact(p)) { 16950 /* Bad contact - we don't know how to reach this device */ 16951 /* We need to ACK, but then send a bye */ 16952 if (!p->route && !req->ignore) 16953 ast_set_flag(&p->flags[0], SIP_PENDINGBYE); 16954 } 16955 16956 } 16957 16958 if (!req->ignore && p->owner) { 16959 if (!reinvite) { 16960 ast_queue_control(p->owner, AST_CONTROL_ANSWER); 16961 if (global_callevents) 16962 manager_event(EVENT_FLAG_SYSTEM, "ChannelUpdate", 16963 "Channel: %s\r\nChanneltype: %s\r\nUniqueid: %s\r\nSIPcallid: %s\r\nSIPfullcontact: %s\r\nPeername: %s\r\n", 16964 p->owner->name, "SIP", p->owner->uniqueid, p->callid, p->fullcontact, p->peername); 16965 } else { /* RE-invite */ 16966 ast_queue_frame(p->owner, &ast_null_frame); 16967 } 16968 } else { 16969 /* It's possible we're getting an 200 OK after we've tried to disconnect 16970 by sending CANCEL */ 16971 /* First send ACK, then send bye */ 16972 if (!req->ignore) 16973 ast_set_flag(&p->flags[0], SIP_PENDINGBYE); 16974 } 16975 16976 /* Check for Session-Timers related headers */ 16977 if (st_get_mode(p) != SESSION_TIMER_MODE_REFUSE && p->outgoing_call == TRUE && !reinvite) { 16978 p_hdrval = (char*)get_header(req, "Session-Expires"); 16979 if (!ast_strlen_zero(p_hdrval)) { 16980 /* UAS supports Session-Timers */ 16981 enum st_refresher tmp_st_ref = SESSION_TIMER_REFRESHER_AUTO; 16982 int tmp_st_interval = 0; 16983 rtn = parse_session_expires(p_hdrval, &tmp_st_interval, &tmp_st_ref); 16984 if (rtn != 0) { 16985 ast_set_flag(&p->flags[0], SIP_PENDINGBYE); 16986 } 16987 if (tmp_st_ref == SESSION_TIMER_REFRESHER_UAC || 16988 tmp_st_ref == SESSION_TIMER_REFRESHER_UAS) { 16989 p->stimer->st_ref = tmp_st_ref; 16990 } 16991 if (tmp_st_interval) { 16992 p->stimer->st_interval = tmp_st_interval; 16993 } 16994 p->stimer->st_active = TRUE; 16995 p->stimer->st_active_peer_ua = TRUE; 16996 start_session_timer(p); 16997 } else { 16998 /* UAS doesn't support Session-Timers */ 16999 if (st_get_mode(p) == SESSION_TIMER_MODE_ORIGINATE) { 17000 p->stimer->st_ref = SESSION_TIMER_REFRESHER_UAC; 17001 p->stimer->st_active_peer_ua = FALSE; 17002 start_session_timer(p); 17003 } 17004 } 17005 } 17006 17007 17008 /* If I understand this right, the branch is different for a non-200 ACK only */ 17009 p->invitestate = INV_TERMINATED; 17010 ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED); 17011 xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, TRUE); 17012 check_pendings(p); 17013 break; 17014 17015 case 407: /* Proxy authentication */ 17016 case 401: /* Www auth */ 17017 /* First we ACK */ 17018 xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); 17019 if (p->options) 17020 p->options->auth_type = resp; 17021 17022 /* Then we AUTH */ 17023 ast_string_field_set(p, theirtag, NULL); /* forget their old tag, so we don't match tags when getting response */ 17024 if (!req->ignore) { 17025 if (p->authtries < MAX_AUTHTRIES) 17026 p->invitestate = INV_CALLING; 17027 if (p->authtries == MAX_AUTHTRIES || do_proxy_auth(p, req, resp, SIP_INVITE, 1)) { 17028 ast_log(LOG_NOTICE, "Failed to authenticate on INVITE to '%s'\n", get_header(&p->initreq, "From")); 17029 p->needdestroy = 1; 17030 sip_alreadygone(p); 17031 if (p->owner) 17032 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 17033 } 17034 } 17035 break; 17036 17037 case 403: /* Forbidden */ 17038 /* First we ACK */ 17039 xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); 17040 ast_log(LOG_WARNING, "Received response: \"Forbidden\" from '%s'\n", get_header(&p->initreq, "From")); 17041 if (!req->ignore && p->owner) 17042 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 17043 p->needdestroy = 1; 17044 sip_alreadygone(p); 17045 break; 17046 17047 case 404: /* Not found */ 17048 xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); 17049 if (p->owner && !req->ignore) 17050 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 17051 sip_alreadygone(p); 17052 break; 17053 17054 case 408: /* Request timeout */ 17055 case 481: /* Call leg does not exist */ 17056 /* Could be REFER caused INVITE with replaces */ 17057 ast_log(LOG_WARNING, "Re-invite to non-existing call leg on other UA. SIP dialog '%s'. Giving up.\n", p->callid); 17058 xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); 17059 if (p->owner) 17060 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 17061 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 17062 break; 17063 17064 case 422: /* Session-Timers: Session interval too small */ 17065 xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); 17066 ast_string_field_set(p, theirtag, NULL); 17067 proc_422_rsp(p, req); 17068 break; 17069 17070 case 487: /* Cancelled transaction */ 17071 /* We have sent CANCEL on an outbound INVITE 17072 This transaction is already scheduled to be killed by sip_hangup(). 17073 */ 17074 xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); 17075 if (p->owner && !req->ignore) { 17076 ast_queue_hangup_with_cause(p->owner, AST_CAUSE_NORMAL_CLEARING); 17077 append_history(p, "Hangup", "Got 487 on CANCEL request from us. Queued AST hangup request"); 17078 } else if (!req->ignore) { 17079 update_call_counter(p, DEC_CALL_LIMIT); 17080 append_history(p, "Hangup", "Got 487 on CANCEL request from us on call without owner. Killing this dialog."); 17081 p->needdestroy = 1; 17082 sip_alreadygone(p); 17083 } 17084 break; 17085 case 415: /* Unsupported media type */ 17086 case 488: /* Not acceptable here */ 17087 case 606: /* Not Acceptable */ 17088 xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); 17089 if (p->udptl && p->t38.state == T38_LOCAL_REINVITE) { 17090 change_t38_state(p, T38_DISABLED); 17091 /* Try to reset RTP timers */ 17092 ast_rtp_set_rtptimers_onhold(p->rtp); 17093 17094 /* Trigger a reinvite back to audio */ 17095 transmit_reinvite_with_sdp(p, FALSE, FALSE); 17096 } else { 17097 /* We can't set up this call, so give up */ 17098 if (p->owner && !req->ignore) 17099 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 17100 p->needdestroy = 1; 17101 /* If there's no dialog to end, then mark p as already gone */ 17102 if (!reinvite) 17103 sip_alreadygone(p); 17104 } 17105 break; 17106 case 491: /* Pending */ 17107 xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); 17108 if (p->owner && !req->ignore) { 17109 if (p->owner->_state != AST_STATE_UP) { 17110 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 17111 p->needdestroy = 1; 17112 } else { 17113 /* This is a re-invite that failed. */ 17114 /* Reset the flag after a while 17115 */ 17116 int wait; 17117 /* RFC 3261, if owner of call, wait between 2.1 to 4 seconds, 17118 * if not owner of call, wait 0 to 2 seconds */ 17119 if (p->outgoing_call) { 17120 wait = 2100 + ast_random() % 2000; 17121 } else { 17122 wait = ast_random() % 2000; 17123 } 17124 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.")); 17125 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); 17126 ast_debug(2, "Reinvite race. Waiting %d secs before retry\n", wait); 17127 } 17128 } 17129 break; 17130 17131 case 501: /* Not implemented */ 17132 xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); 17133 if (p->owner) 17134 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 17135 break; 17136 } 17137 if (xmitres == XMIT_ERROR) 17138 ast_log(LOG_WARNING, "Could not transmit message in dialog %s\n", p->callid); 17139 }
static void handle_response_notify | ( | struct sip_pvt * | p, | |
int | resp, | |||
char * | rest, | |||
struct sip_request * | req, | |||
int | seqno | |||
) | [static] |
Definition at line 17144 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().
17145 { 17146 switch (resp) { 17147 case 200: /* Notify accepted */ 17148 /* They got the notify, this is the end */ 17149 if (p->owner) { 17150 if (!p->refer) { 17151 ast_log(LOG_WARNING, "Notify answer on an owned channel? - %s\n", p->owner->name); 17152 ast_queue_hangup_with_cause(p->owner, AST_CAUSE_NORMAL_UNSPECIFIED); 17153 } else { 17154 ast_debug(4, "Got OK on REFER Notify message\n"); 17155 } 17156 } else { 17157 if (p->subscribed == NONE) { 17158 ast_debug(4, "Got 200 accepted on NOTIFY\n"); 17159 p->needdestroy = 1; 17160 } 17161 if (ast_test_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE)) { 17162 /* Ready to send the next state we have on queue */ 17163 ast_clear_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE); 17164 cb_extensionstate((char *)p->context, (char *)p->exten, p->laststate, (void *) p); 17165 } 17166 } 17167 break; 17168 case 401: /* Not www-authorized on SIP method */ 17169 case 407: /* Proxy auth */ 17170 if (!p->notify_headers) { 17171 break; /* Only device notify can use NOTIFY auth */ 17172 } 17173 ast_string_field_set(p, theirtag, NULL); 17174 if (ast_strlen_zero(p->authname)) { 17175 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)); 17176 p->needdestroy = 1; 17177 } 17178 if (p->authtries > 1 || do_proxy_auth(p, req, resp, SIP_NOTIFY, 0)) { 17179 ast_log(LOG_NOTICE, "Failed to authenticate on NOTYFY to '%s'\n", get_header(&p->initreq, "From")); 17180 p->needdestroy = 1; 17181 } 17182 break; 17183 } 17184 }
static void handle_response_peerpoke | ( | struct sip_pvt * | p, | |
int | resp, | |||
struct sip_request * | req | |||
) | [static] |
Handle qualification responses (OPTIONS).
Definition at line 17390 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().
17391 { 17392 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! */ 17393 int statechanged, is_reachable, was_reachable; 17394 int pingtime = ast_tvdiff_ms(ast_tvnow(), peer->ps); 17395 17396 /* 17397 * Compute the response time to a ping (goes in peer->lastms.) 17398 * -1 means did not respond, 0 means unknown, 17399 * 1..maxms is a valid response, >maxms means late response. 17400 */ 17401 if (pingtime < 1) /* zero = unknown, so round up to 1 */ 17402 pingtime = 1; 17403 17404 /* Now determine new state and whether it has changed. 17405 * Use some helper variables to simplify the writing 17406 * of the expressions. 17407 */ 17408 was_reachable = peer->lastms > 0 && peer->lastms <= peer->maxms; 17409 is_reachable = pingtime <= peer->maxms; 17410 statechanged = peer->lastms == 0 /* yes, unknown before */ 17411 || was_reachable != is_reachable; 17412 17413 peer->lastms = pingtime; 17414 peer->call = dialog_unref(peer->call, "unref dialog peer->call"); 17415 if (statechanged) { 17416 const char *s = is_reachable ? "Reachable" : "Lagged"; 17417 char str_lastms[20]; 17418 snprintf(str_lastms, sizeof(str_lastms), "%d", pingtime); 17419 17420 ast_log(LOG_NOTICE, "Peer '%s' is now %s. (%dms / %dms)\n", 17421 peer->name, s, pingtime, peer->maxms); 17422 ast_devstate_changed(AST_DEVICE_UNKNOWN, "SIP/%s", peer->name); 17423 if (sip_cfg.peer_rtupdate) { 17424 ast_update_realtime(ast_check_realtime("sipregs") ? "sipregs" : "sippeers", "name", peer->name, "lastms", str_lastms, SENTINEL); 17425 } 17426 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", 17427 "ChannelType: SIP\r\nPeer: SIP/%s\r\nPeerStatus: %s\r\nTime: %d\r\n", 17428 peer->name, s, pingtime); 17429 if (is_reachable && global_regextenonqualify) 17430 register_peer_exten(peer, TRUE); 17431 } 17432 17433 p->needdestroy = 1; 17434 17435 /* Try again eventually */ 17436 AST_SCHED_REPLACE_UNREF(peer->pokeexpire, sched, 17437 is_reachable ? peer->qualifyfreq : DEFAULT_FREQ_NOTOK, 17438 sip_poke_peer_s, peer, 17439 unref_peer(_data, "removing poke peer ref"), 17440 unref_peer(peer, "removing poke peer ref"), 17441 ref_peer(peer, "adding poke peer ref")); 17442 }
static void handle_response_refer | ( | struct sip_pvt * | p, | |
int | resp, | |||
char * | rest, | |||
struct sip_request * | req, | |||
int | seqno | |||
) | [static] |
Definition at line 17189 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().
17190 { 17191 /* If no refer structure exists, then do nothing */ 17192 if (!p->refer) 17193 return; 17194 17195 switch (resp) { 17196 case 202: /* Transfer accepted */ 17197 /* We need to do something here */ 17198 /* The transferee is now sending INVITE to target */ 17199 p->refer->status = REFER_ACCEPTED; 17200 /* Now wait for next message */ 17201 ast_debug(3, "Got 202 accepted on transfer\n"); 17202 /* We should hang along, waiting for NOTIFY's here */ 17203 break; 17204 17205 case 401: /* Not www-authorized on SIP method */ 17206 case 407: /* Proxy auth */ 17207 if (ast_strlen_zero(p->authname)) { 17208 ast_log(LOG_WARNING, "Asked to authenticate REFER to %s:%d but we have no matching peer or realm auth!\n", 17209 ast_inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port)); 17210 p->needdestroy = 1; 17211 } 17212 if (p->authtries > 1 || do_proxy_auth(p, req, resp, SIP_REFER, 0)) { 17213 ast_log(LOG_NOTICE, "Failed to authenticate on REFER to '%s'\n", get_header(&p->initreq, "From")); 17214 p->refer->status = REFER_NOAUTH; 17215 p->needdestroy = 1; 17216 } 17217 break; 17218 case 481: /* Call leg does not exist */ 17219 17220 /* A transfer with Replaces did not work */ 17221 /* OEJ: We should Set flag, cancel the REFER, go back 17222 to original call - but right now we can't */ 17223 ast_log(LOG_WARNING, "Remote host can't match REFER request to call '%s'. Giving up.\n", p->callid); 17224 if (p->owner) 17225 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 17226 p->needdestroy = 1; 17227 break; 17228 17229 case 500: /* Server error */ 17230 case 501: /* Method not implemented */ 17231 /* Return to the current call onhold */ 17232 /* Status flag needed to be reset */ 17233 ast_log(LOG_NOTICE, "SIP transfer to %s failed, call miserably fails. \n", p->refer->refer_to); 17234 p->needdestroy = 1; 17235 p->refer->status = REFER_FAILED; 17236 break; 17237 case 603: /* Transfer declined */ 17238 ast_log(LOG_NOTICE, "SIP transfer to %s declined, call miserably fails. \n", p->refer->refer_to); 17239 p->refer->status = REFER_FAILED; 17240 p->needdestroy = 1; 17241 break; 17242 } 17243 }
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 17246 of file chan_sip.c.
References __get_header(), ast_debug, ast_log(), AST_SCHED_DEL_UNREF, AST_SCHED_REPLACE_UNREF, ast_strlen_zero(), ast_tvnow(), sip_pvt::authtries, sip_registry::call, sip_pvt::callid, sip_registry::configured_expiry, 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().
17247 { 17248 int expires, expires_ms; 17249 struct sip_registry *r; 17250 r=p->registry; 17251 17252 switch (resp) { 17253 case 401: /* Unauthorized */ 17254 if (p->authtries == MAX_AUTHTRIES || do_register_auth(p, req, resp)) { 17255 ast_log(LOG_NOTICE, "Failed to authenticate on REGISTER to '%s@%s' (Tries %d)\n", p->registry->username, p->registry->hostname, p->authtries); 17256 p->needdestroy = 1; 17257 } 17258 break; 17259 case 403: /* Forbidden */ 17260 ast_log(LOG_WARNING, "Forbidden - wrong password on authentication for REGISTER for '%s' to '%s'\n", p->registry->username, p->registry->hostname); 17261 AST_SCHED_DEL_UNREF(sched, r->timeout, registry_unref(r, "reg ptr unref from handle_response_register 403")); 17262 r->regstate = REG_STATE_NOAUTH; 17263 p->needdestroy = 1; 17264 break; 17265 case 404: /* Not found */ 17266 ast_log(LOG_WARNING, "Got 404 Not found on SIP register to service %s@%s, giving up\n", p->registry->username, p->registry->hostname); 17267 p->needdestroy = 1; 17268 if (r->call) 17269 r->call = dialog_unref(r->call, "unsetting registry->call pointer-- case 404"); 17270 r->regstate = REG_STATE_REJECTED; 17271 AST_SCHED_DEL_UNREF(sched, r->timeout, registry_unref(r, "reg ptr unref from handle_response_register 404")); 17272 break; 17273 case 407: /* Proxy auth */ 17274 if (p->authtries == MAX_AUTHTRIES || do_register_auth(p, req, resp)) { 17275 ast_log(LOG_NOTICE, "Failed to authenticate on REGISTER to '%s' (tries '%d')\n", get_header(&p->initreq, "From"), p->authtries); 17276 p->needdestroy = 1; 17277 } 17278 break; 17279 case 408: /* Request timeout */ 17280 /* Got a timeout response, so reset the counter of failed responses */ 17281 if (r) { 17282 r->regattempts = 0; 17283 } else { 17284 ast_log(LOG_WARNING, "Got a 408 response to our REGISTER on call %s after we had destroyed the registry object\n", p->callid); 17285 } 17286 break; 17287 case 423: /* Interval too brief */ 17288 r->expiry = atoi(get_header(req, "Min-Expires")); 17289 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); 17290 AST_SCHED_DEL_UNREF(sched, r->timeout, registry_unref(r, "reg ptr unref from handle_response_register 423")); 17291 if (r->call) { 17292 r->call = dialog_unref(r->call, "unsetting registry->call pointer-- case 423"); 17293 p->needdestroy = 1; 17294 } 17295 if (r->expiry > max_expiry) { 17296 ast_log(LOG_WARNING, "Required expiration time from %s@%s is too high, giving up\n", p->registry->username, p->registry->hostname); 17297 r->expiry = r->configured_expiry; 17298 r->regstate = REG_STATE_REJECTED; 17299 } else { 17300 r->regstate = REG_STATE_UNREGISTERED; 17301 transmit_register(r, SIP_REGISTER, NULL, NULL); 17302 } 17303 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)); 17304 break; 17305 case 479: /* SER: Not able to process the URI - address is wrong in register*/ 17306 ast_log(LOG_WARNING, "Got error 479 on register to %s@%s, giving up (check config)\n", p->registry->username, p->registry->hostname); 17307 p->needdestroy = 1; 17308 if (r->call) 17309 r->call = dialog_unref(r->call, "unsetting registry->call pointer-- case 479"); 17310 r->regstate = REG_STATE_REJECTED; 17311 AST_SCHED_DEL_UNREF(sched, r->timeout, registry_unref(r, "reg ptr unref from handle_response_register 479")); 17312 break; 17313 case 200: /* 200 OK */ 17314 if (!r) { 17315 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)); 17316 p->needdestroy = 1; 17317 return 0; 17318 } 17319 17320 r->regstate = REG_STATE_REGISTERED; 17321 r->regtime = ast_tvnow(); /* Reset time of last succesful registration */ 17322 manager_event(EVENT_FLAG_SYSTEM, "Registry", "ChannelType: SIP\r\nDomain: %s\r\nStatus: %s\r\n", r->hostname, regstate2str(r->regstate)); 17323 r->regattempts = 0; 17324 ast_debug(1, "Registration successful\n"); 17325 if (r->timeout > -1) { 17326 ast_debug(1, "Cancelling timeout %d\n", r->timeout); 17327 } 17328 AST_SCHED_DEL_UNREF(sched, r->timeout, registry_unref(r, "reg ptr unref from handle_response_register 200")); 17329 if (r->call) 17330 r->call = dialog_unref(r->call, "unsetting registry->call pointer-- case 200"); 17331 p->registry = registry_unref(p->registry, "unref registry entry p->registry"); 17332 /* Let this one hang around until we have all the responses */ 17333 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 17334 /* p->needdestroy = 1; */ 17335 17336 /* set us up for re-registering 17337 * figure out how long we got registered for 17338 * according to section 6.13 of RFC, contact headers override 17339 * expires headers, so check those first */ 17340 expires = 0; 17341 17342 /* XXX todo: try to save the extra call */ 17343 if (!ast_strlen_zero(get_header(req, "Contact"))) { 17344 const char *contact = NULL; 17345 const char *tmptmp = NULL; 17346 int start = 0; 17347 for(;;) { 17348 contact = __get_header(req, "Contact", &start); 17349 /* this loop ensures we get a contact header about our register request */ 17350 if(!ast_strlen_zero(contact)) { 17351 if( (tmptmp=strstr(contact, p->our_contact))) { 17352 contact=tmptmp; 17353 break; 17354 } 17355 } else 17356 break; 17357 } 17358 tmptmp = strcasestr(contact, "expires="); 17359 if (tmptmp) { 17360 if (sscanf(tmptmp + 8, "%30d;", &expires) != 1) 17361 expires = 0; 17362 } 17363 17364 } 17365 if (!expires) 17366 expires=atoi(get_header(req, "expires")); 17367 if (!expires) 17368 expires=default_expiry; 17369 17370 expires_ms = expires * 1000; 17371 if (expires <= EXPIRY_GUARD_LIMIT) 17372 expires_ms -= MAX((expires_ms * EXPIRY_GUARD_PCT), EXPIRY_GUARD_MIN); 17373 else 17374 expires_ms -= EXPIRY_GUARD_SECS * 1000; 17375 if (sipdebug) 17376 ast_log(LOG_NOTICE, "Outbound Registration: Expiry for %s is %d sec (Scheduling reregistration in %d s)\n", r->hostname, expires, expires_ms/1000); 17377 17378 r->refresh= (int) expires_ms / 1000; 17379 17380 /* Schedule re-registration before we expire */ 17381 AST_SCHED_REPLACE_UNREF(r->expire, sched, expires_ms, sip_reregister, r, 17382 registry_unref(_data,"unref in REPLACE del fail"), 17383 registry_unref(r,"unref in REPLACE add fail"), 17384 registry_addref(r,"The Addition side of REPLACE")); 17385 } 17386 return 1; 17387 }
static int handle_t38_options | ( | struct ast_flags * | flags, | |
struct ast_flags * | mask, | |||
struct ast_variable * | v, | |||
int * | maxdatagram | |||
) | [static] |
Handle T.38 configuration options common to users and peers.
Definition at line 22339 of file chan_sip.c.
References ast_clear_flag, ast_log(), ast_set2_flag, ast_set_flag, ast_strdupa, ast_true(), buf, ast_channel::flags, ast_variable::lineno, LOG_WARNING, ast_variable::name, ast_channel::next, SIP_PAGE2_T38SUPPORT, SIP_PAGE2_T38SUPPORT_UDPTL, SIP_PAGE2_T38SUPPORT_UDPTL_FEC, SIP_PAGE2_T38SUPPORT_UDPTL_REDUNDANCY, SIP_PAGE2_UDPTL_DESTINATION, strsep(), and ast_variable::value.
Referenced by build_peer().
22341 { 22342 int res = 1; 22343 22344 if (!strcasecmp(v->name, "t38pt_udptl")) { 22345 char *buf = ast_strdupa(v->value); 22346 char *word, *next = buf; 22347 22348 ast_set_flag(&mask[1], SIP_PAGE2_T38SUPPORT); 22349 22350 while ((word = strsep(&next, ","))) { 22351 if (ast_true(word) || !strcasecmp(word, "fec")) { 22352 ast_clear_flag(&flags[1], SIP_PAGE2_T38SUPPORT); 22353 ast_set_flag(&flags[1], SIP_PAGE2_T38SUPPORT_UDPTL_FEC); 22354 } else if (!strcasecmp(word, "redundancy")) { 22355 ast_clear_flag(&flags[1], SIP_PAGE2_T38SUPPORT); 22356 ast_set_flag(&flags[1], SIP_PAGE2_T38SUPPORT_UDPTL_REDUNDANCY); 22357 } else if (!strcasecmp(word, "none")) { 22358 ast_clear_flag(&flags[1], SIP_PAGE2_T38SUPPORT); 22359 ast_set_flag(&flags[1], SIP_PAGE2_T38SUPPORT_UDPTL); 22360 } else if (!strncasecmp(word, "maxdatagram=", 12)) { 22361 if (sscanf(&word[12], "%30u", maxdatagram) != 1) { 22362 ast_log(LOG_WARNING, "Invalid maxdatagram '%s' at line %d of %s\n", v->value, v->lineno, config); 22363 *maxdatagram = global_t38_maxdatagram; 22364 } 22365 } 22366 } 22367 } else if (!strcasecmp(v->name, "t38pt_usertpsource")) { 22368 ast_set_flag(&mask[1], SIP_PAGE2_UDPTL_DESTINATION); 22369 ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_UDPTL_DESTINATION); 22370 } else { 22371 res = 0; 22372 } 22373 22374 return res; 22375 }
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 5502 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().
05503 { 05504 switch (cause) { 05505 case AST_CAUSE_UNALLOCATED: /* 1 */ 05506 case AST_CAUSE_NO_ROUTE_DESTINATION: /* 3 IAX2: Can't find extension in context */ 05507 case AST_CAUSE_NO_ROUTE_TRANSIT_NET: /* 2 */ 05508 return "404 Not Found"; 05509 case AST_CAUSE_CONGESTION: /* 34 */ 05510 case AST_CAUSE_SWITCH_CONGESTION: /* 42 */ 05511 return "503 Service Unavailable"; 05512 case AST_CAUSE_NO_USER_RESPONSE: /* 18 */ 05513 return "408 Request Timeout"; 05514 case AST_CAUSE_NO_ANSWER: /* 19 */ 05515 case AST_CAUSE_UNREGISTERED: /* 20 */ 05516 return "480 Temporarily unavailable"; 05517 case AST_CAUSE_CALL_REJECTED: /* 21 */ 05518 return "403 Forbidden"; 05519 case AST_CAUSE_NUMBER_CHANGED: /* 22 */ 05520 return "410 Gone"; 05521 case AST_CAUSE_NORMAL_UNSPECIFIED: /* 31 */ 05522 return "480 Temporarily unavailable"; 05523 case AST_CAUSE_INVALID_NUMBER_FORMAT: 05524 return "484 Address incomplete"; 05525 case AST_CAUSE_USER_BUSY: 05526 return "486 Busy here"; 05527 case AST_CAUSE_FAILURE: 05528 return "500 Server internal failure"; 05529 case AST_CAUSE_FACILITY_REJECTED: /* 29 */ 05530 return "501 Not Implemented"; 05531 case AST_CAUSE_CHAN_NOT_IMPLEMENTED: 05532 return "503 Service Unavailable"; 05533 /* Used in chan_iax2 */ 05534 case AST_CAUSE_DESTINATION_OUT_OF_ORDER: 05535 return "502 Bad Gateway"; 05536 case AST_CAUSE_BEARERCAPABILITY_NOTAVAIL: /* Can't find codec to connect to host */ 05537 return "488 Not Acceptable Here"; 05538 05539 case AST_CAUSE_NOTDEFINED: 05540 default: 05541 ast_debug(1, "AST hangup cause %d (no match found in SIP)\n", cause); 05542 return NULL; 05543 } 05544 05545 /* Never reached */ 05546 return 0; 05547 }
static int hangup_sip2cause | ( | int | cause | ) | [static] |
Convert SIP hangup causes to Asterisk hangup causes.
Definition at line 5390 of file chan_sip.c.
References AST_CAUSE_BEARERCAPABILITY_NOTAVAIL, AST_CAUSE_BUSY, AST_CAUSE_CALL_REJECTED, AST_CAUSE_CONGESTION, AST_CAUSE_DESTINATION_OUT_OF_ORDER, AST_CAUSE_FACILITY_REJECTED, AST_CAUSE_FAILURE, AST_CAUSE_INTERWORKING, AST_CAUSE_INVALID_NUMBER_FORMAT, AST_CAUSE_NO_ANSWER, AST_CAUSE_NO_ROUTE_DESTINATION, AST_CAUSE_NO_USER_RESPONSE, AST_CAUSE_NORMAL, AST_CAUSE_NORMAL_TEMPORARY_FAILURE, AST_CAUSE_NUMBER_CHANGED, AST_CAUSE_RECOVERY_ON_TIMER_EXPIRE, AST_CAUSE_UNALLOCATED, and AST_CAUSE_USER_BUSY.
Referenced by handle_response().
05391 { 05392 /* Possible values taken from causes.h */ 05393 05394 switch(cause) { 05395 case 401: /* Unauthorized */ 05396 return AST_CAUSE_CALL_REJECTED; 05397 case 403: /* Not found */ 05398 return AST_CAUSE_CALL_REJECTED; 05399 case 404: /* Not found */ 05400 return AST_CAUSE_UNALLOCATED; 05401 case 405: /* Method not allowed */ 05402 return AST_CAUSE_INTERWORKING; 05403 case 407: /* Proxy authentication required */ 05404 return AST_CAUSE_CALL_REJECTED; 05405 case 408: /* No reaction */ 05406 return AST_CAUSE_NO_USER_RESPONSE; 05407 case 409: /* Conflict */ 05408 return AST_CAUSE_NORMAL_TEMPORARY_FAILURE; 05409 case 410: /* Gone */ 05410 return AST_CAUSE_NUMBER_CHANGED; 05411 case 411: /* Length required */ 05412 return AST_CAUSE_INTERWORKING; 05413 case 413: /* Request entity too large */ 05414 return AST_CAUSE_INTERWORKING; 05415 case 414: /* Request URI too large */ 05416 return AST_CAUSE_INTERWORKING; 05417 case 415: /* Unsupported media type */ 05418 return AST_CAUSE_INTERWORKING; 05419 case 420: /* Bad extension */ 05420 return AST_CAUSE_NO_ROUTE_DESTINATION; 05421 case 480: /* No answer */ 05422 return AST_CAUSE_NO_ANSWER; 05423 case 481: /* No answer */ 05424 return AST_CAUSE_INTERWORKING; 05425 case 482: /* Loop detected */ 05426 return AST_CAUSE_INTERWORKING; 05427 case 483: /* Too many hops */ 05428 return AST_CAUSE_NO_ANSWER; 05429 case 484: /* Address incomplete */ 05430 return AST_CAUSE_INVALID_NUMBER_FORMAT; 05431 case 485: /* Ambiguous */ 05432 return AST_CAUSE_UNALLOCATED; 05433 case 486: /* Busy everywhere */ 05434 return AST_CAUSE_BUSY; 05435 case 487: /* Request terminated */ 05436 return AST_CAUSE_INTERWORKING; 05437 case 488: /* No codecs approved */ 05438 return AST_CAUSE_BEARERCAPABILITY_NOTAVAIL; 05439 case 491: /* Request pending */ 05440 return AST_CAUSE_INTERWORKING; 05441 case 493: /* Undecipherable */ 05442 return AST_CAUSE_INTERWORKING; 05443 case 500: /* Server internal failure */ 05444 return AST_CAUSE_FAILURE; 05445 case 501: /* Call rejected */ 05446 return AST_CAUSE_FACILITY_REJECTED; 05447 case 502: 05448 return AST_CAUSE_DESTINATION_OUT_OF_ORDER; 05449 case 503: /* Service unavailable */ 05450 return AST_CAUSE_CONGESTION; 05451 case 504: /* Gateway timeout */ 05452 return AST_CAUSE_RECOVERY_ON_TIMER_EXPIRE; 05453 case 505: /* SIP version not supported */ 05454 return AST_CAUSE_INTERWORKING; 05455 case 600: /* Busy everywhere */ 05456 return AST_CAUSE_USER_BUSY; 05457 case 603: /* Decline */ 05458 return AST_CAUSE_CALL_REJECTED; 05459 case 604: /* Does not exist anywhere */ 05460 return AST_CAUSE_UNALLOCATED; 05461 case 606: /* Not acceptable */ 05462 return AST_CAUSE_BEARERCAPABILITY_NOTAVAIL; 05463 default: 05464 return AST_CAUSE_NORMAL; 05465 } 05466 /* Never reached */ 05467 return 0; 05468 }
static int init_req | ( | struct sip_request * | req, | |
int | sipmethod, | |||
const char * | recip | |||
) | [static] |
Initialize SIP request.
Definition at line 8650 of file chan_sip.c.
References ast_str_create(), ast_str_set(), sip_methods, SIP_MIN_PACKET, and cfsip_methods::text.
08651 { 08652 /* Initialize a request */ 08653 memset(req, 0, sizeof(*req)); 08654 if (!(req->data = ast_str_create(SIP_MIN_PACKET))) 08655 return -1; 08656 req->method = sipmethod; 08657 req->header[0] = 0; 08658 ast_str_set(&req->data, 0, "%s %s SIP/2.0\r\n", sip_methods[sipmethod].text, recip); 08659 req->len = req->data->used; 08660 req->headers++; 08661 return 0; 08662 }
static int init_resp | ( | struct sip_request * | resp, | |
const char * | msg | |||
) | [static] |
Initialize SIP response, based on SIP request.
Definition at line 8635 of file chan_sip.c.
References ast_str_create(), ast_str_set(), SIP_MIN_PACKET, and SIP_RESPONSE.
08636 { 08637 /* Initialize a response */ 08638 memset(resp, 0, sizeof(*resp)); 08639 resp->method = SIP_RESPONSE; 08640 if (!(resp->data = ast_str_create(SIP_MIN_PACKET))) 08641 return -1; 08642 resp->header[0] = 0; 08643 ast_str_set(&resp->data, 0, "SIP/2.0 %s\r\n", msg); 08644 resp->len = resp->data->used; 08645 resp->headers++; 08646 return 0; 08647 }
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 2892 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().
02893 { 02894 if (p->initreq.headers) 02895 ast_debug(1, "Initializing already initialized SIP dialog %s (presumably reinvite)\n", p->callid); 02896 else 02897 ast_debug(1, "Initializing initreq for method %s - callid %s\n", sip_methods[req->method].text, p->callid); 02898 /* Use this as the basis */ 02899 copy_request(&p->initreq, req); 02900 parse_request(&p->initreq); 02901 if (req->debug) 02902 ast_verbose("Initreq: %d headers, %d lines\n", p->initreq.headers, p->initreq.lines); 02903 }
static void initreqprep | ( | struct sip_request * | req, | |
struct sip_pvt * | p, | |||
int | sipmethod | |||
) | [static] |
Initiate new SIP request to peer/user.
Definition at line 10023 of file chan_sip.c.
References add_header(), add_route(), 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, FROMDOMAIN_INVALID, 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::portinuri, sip_pvt::route, 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, 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().
10024 { 10025 struct ast_str *invite = ast_str_alloca(256); 10026 char from[256]; 10027 char to[256]; 10028 char tmp_n[SIPBUFSIZE/2]; /* build a local copy of 'n' if needed */ 10029 char tmp_l[SIPBUFSIZE/2]; /* build a local copy of 'l' if needed */ 10030 const char *l = NULL; /* XXX what is this, exactly ? */ 10031 const char *n = NULL; /* XXX what is this, exactly ? */ 10032 const char *d = NULL; /* domain in from header */ 10033 const char *urioptions = ""; 10034 int ourport; 10035 10036 if (ast_test_flag(&p->flags[0], SIP_USEREQPHONE)) { 10037 const char *s = p->username; /* being a string field, cannot be NULL */ 10038 10039 /* Test p->username against allowed characters in AST_DIGIT_ANY 10040 If it matches the allowed characters list, then sipuser = ";user=phone" 10041 If not, then sipuser = "" 10042 */ 10043 /* + is allowed in first position in a tel: uri */ 10044 if (*s == '+') 10045 s++; 10046 for (; *s; s++) { 10047 if (!strchr(AST_DIGIT_ANYNUM, *s) ) 10048 break; 10049 } 10050 /* If we have only digits, add ;user=phone to the uri */ 10051 if (!*s) 10052 urioptions = ";user=phone"; 10053 } 10054 10055 10056 snprintf(p->lastmsg, sizeof(p->lastmsg), "Init: %s", sip_methods[sipmethod].text); 10057 10058 d = S_OR(p->fromdomain, ast_inet_ntoa(p->ourip.sin_addr)); 10059 if (p->owner) { 10060 l = p->owner->cid.cid_num; 10061 n = p->owner->cid.cid_name; 10062 } 10063 /* if we are not sending RPID and user wants his callerid restricted */ 10064 if (!ast_test_flag(&p->flags[0], SIP_SENDRPID) && 10065 ((p->callingpres & AST_PRES_RESTRICTION) != AST_PRES_ALLOWED)) { 10066 l = CALLERID_UNKNOWN; 10067 n = l; 10068 d = FROMDOMAIN_INVALID; 10069 } 10070 if (ast_strlen_zero(l)) 10071 l = default_callerid; 10072 if (ast_strlen_zero(n)) 10073 n = l; 10074 /* Allow user to be overridden */ 10075 if (!ast_strlen_zero(p->fromuser)) 10076 l = p->fromuser; 10077 else /* Save for any further attempts */ 10078 ast_string_field_set(p, fromuser, l); 10079 10080 /* Allow user to be overridden */ 10081 if (!ast_strlen_zero(p->fromname)) 10082 n = p->fromname; 10083 else /* Save for any further attempts */ 10084 ast_string_field_set(p, fromname, n); 10085 10086 if (pedanticsipchecking) { 10087 ast_uri_encode(n, tmp_n, sizeof(tmp_n), 0); 10088 n = tmp_n; 10089 ast_uri_encode(l, tmp_l, sizeof(tmp_l), 0); 10090 l = tmp_l; 10091 } 10092 10093 ourport = ntohs(p->ourip.sin_port); 10094 if (!sip_standard_port(p->socket.type, ourport) && ast_strlen_zero(p->fromdomain)) 10095 snprintf(from, sizeof(from), "\"%s\" <sip:%s@%s:%d>;tag=%s", n, l, d, ourport, p->tag); 10096 else 10097 snprintf(from, sizeof(from), "\"%s\" <sip:%s@%s>;tag=%s", n, l, d, p->tag); 10098 10099 /* If we're calling a registered SIP peer, use the fullcontact to dial to the peer */ 10100 if (!ast_strlen_zero(p->fullcontact)) { 10101 /* If we have full contact, trust it */ 10102 ast_str_append(&invite, 0, "%s", p->fullcontact); 10103 } else { 10104 /* Otherwise, use the username while waiting for registration */ 10105 ast_str_append(&invite, 0, "sip:"); 10106 if (!ast_strlen_zero(p->username)) { 10107 n = p->username; 10108 if (pedanticsipchecking) { 10109 ast_uri_encode(n, tmp_n, sizeof(tmp_n), 0); 10110 n = tmp_n; 10111 } 10112 ast_str_append(&invite, 0, "%s@", n); 10113 } 10114 ast_str_append(&invite, 0, "%s", p->tohost); 10115 if (p->portinuri) 10116 ast_str_append(&invite, 0, ":%d", ntohs(p->sa.sin_port)); 10117 ast_str_append(&invite, 0, "%s", urioptions); 10118 } 10119 10120 /* If custom URI options have been provided, append them */ 10121 if (p->options && !ast_strlen_zero(p->options->uri_options)) 10122 ast_str_append(&invite, 0, ";%s", p->options->uri_options); 10123 10124 /* This is the request URI, which is the next hop of the call 10125 which may or may not be the destination of the call 10126 */ 10127 ast_string_field_set(p, uri, invite->str); 10128 10129 if (!ast_strlen_zero(p->todnid)) { 10130 /*! \todo Need to add back the VXML URL here at some point, possibly use build_string for all this junk */ 10131 if (!strchr(p->todnid, '@')) { 10132 /* We have no domain in the dnid */ 10133 snprintf(to, sizeof(to), "<sip:%s@%s>%s%s", p->todnid, p->tohost, ast_strlen_zero(p->theirtag) ? "" : ";tag=", p->theirtag); 10134 } else { 10135 snprintf(to, sizeof(to), "<sip:%s>%s%s", p->todnid, ast_strlen_zero(p->theirtag) ? "" : ";tag=", p->theirtag); 10136 } 10137 } else { 10138 if (sipmethod == SIP_NOTIFY && !ast_strlen_zero(p->theirtag)) { 10139 /* If this is a NOTIFY, use the From: tag in the subscribe (RFC 3265) */ 10140 snprintf(to, sizeof(to), "<%s%s>;tag=%s", (strncasecmp(p->uri, "sip:", 4) ? "sip:" : ""), p->uri, p->theirtag); 10141 } else if (p->options && p->options->vxml_url) { 10142 /* If there is a VXML URL append it to the SIP URL */ 10143 snprintf(to, sizeof(to), "<%s>;%s", p->uri, p->options->vxml_url); 10144 } else 10145 snprintf(to, sizeof(to), "<%s>", p->uri); 10146 } 10147 10148 init_req(req, sipmethod, p->uri); 10149 /* now tmp_n is available so reuse it to build the CSeq */ 10150 snprintf(tmp_n, sizeof(tmp_n), "%d %s", ++p->ocseq, sip_methods[sipmethod].text); 10151 10152 add_header(req, "Via", p->via); 10153 add_header(req, "Max-Forwards", DEFAULT_MAX_FORWARDS); 10154 /* This will be a no-op most of the time. However, under certain circumstances, 10155 * NOTIFY messages will use this function for preparing the request and should 10156 * have Route headers present. 10157 */ 10158 add_route(req, p->route); 10159 10160 /* Build Remote Party-ID and From */ 10161 if (ast_test_flag(&p->flags[0], SIP_SENDRPID) && (sipmethod == SIP_INVITE)) { 10162 build_rpid(p); 10163 add_header(req, "From", p->rpid_from); 10164 } else 10165 add_header(req, "From", from); 10166 add_header(req, "To", to); 10167 ast_string_field_set(p, exten, l); 10168 build_contact(p); 10169 add_header(req, "Contact", p->our_contact); 10170 add_header(req, "Call-ID", p->callid); 10171 add_header(req, "CSeq", tmp_n); 10172 if (!ast_strlen_zero(global_useragent)) 10173 add_header(req, "User-Agent", global_useragent); 10174 if (!ast_strlen_zero(p->rpid)) 10175 add_header(req, "Remote-Party-ID", p->rpid); 10176 }
static const char * insecure2str | ( | int | mode | ) | const [static] |
Convert Insecure setting to printable string.
Definition at line 14148 of file chan_sip.c.
References insecurestr, and map_x_s().
Referenced by _sip_show_peer().
14149 { 14150 return map_x_s(insecurestr, mode, "<error>"); 14151 }
static void interpret_t38_parameters | ( | struct sip_pvt * | p, | |
const struct ast_control_t38_parameters * | parameters | |||
) | [static] |
Helper function which updates T.38 capability information and triggers a reinvite.
Definition at line 6016 of file chan_sip.c.
References AST_SCHED_DEL_UNREF, ast_set_flag, AST_T38_NEGOTIATED, AST_T38_REFUSED, AST_T38_REQUEST_NEGOTIATE, AST_T38_REQUEST_TERMINATE, AST_T38_TERMINATED, ast_test_flag, ast_udptl_set_local_max_ifp(), change_t38_state(), dialog_unref(), FALSE, ast_control_t38_parameters::fill_bit_removal, sip_pvt::flags, sip_pvt::initreq, ast_control_t38_parameters::max_ifp, MIN, t38properties::our_parms, sip_pvt::pendinginvite, ast_control_t38_parameters::rate_management, ast_control_t38_parameters::request_response, sched, SIP_NEEDREINVITE, SIP_PAGE2_T38SUPPORT, SIP_PENDINGBYE, t38properties::state, sip_pvt::t38, T38_DISABLED, T38_ENABLED, T38_LOCAL_REINVITE, T38_PEER_REINVITE, sip_pvt::t38id, t38properties::their_parms, ast_control_t38_parameters::transcoding_jbig, ast_control_t38_parameters::transcoding_mmr, transmit_reinvite_with_sdp(), transmit_response_reliable(), transmit_response_with_t38_sdp(), TRUE, sip_pvt::udptl, ast_control_t38_parameters::version, and XMIT_CRITICAL.
Referenced by sip_indicate().
06017 { 06018 if (!ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT)) { 06019 return; 06020 } 06021 switch (parameters->request_response) { 06022 case AST_T38_NEGOTIATED: 06023 case AST_T38_REQUEST_NEGOTIATE: /* Request T38 */ 06024 /* Negotiation can not take place without a valid max_ifp value. */ 06025 if (!parameters->max_ifp) { 06026 change_t38_state(p, T38_DISABLED); 06027 if (p->t38.state == T38_PEER_REINVITE) { 06028 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")); 06029 transmit_response_reliable(p, "488 Not acceptable here", &p->initreq); 06030 } 06031 break; 06032 } else if (p->t38.state == T38_PEER_REINVITE) { 06033 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")); 06034 p->t38.our_parms = *parameters; 06035 /* modify our parameters to conform to the peer's parameters, 06036 * based on the rules in the ITU T.38 recommendation 06037 */ 06038 if (!p->t38.their_parms.fill_bit_removal) { 06039 p->t38.our_parms.fill_bit_removal = FALSE; 06040 } 06041 if (!p->t38.their_parms.transcoding_mmr) { 06042 p->t38.our_parms.transcoding_mmr = FALSE; 06043 } 06044 if (!p->t38.their_parms.transcoding_jbig) { 06045 p->t38.our_parms.transcoding_jbig = FALSE; 06046 } 06047 p->t38.our_parms.version = MIN(p->t38.our_parms.version, p->t38.their_parms.version); 06048 p->t38.our_parms.rate_management = p->t38.their_parms.rate_management; 06049 ast_udptl_set_local_max_ifp(p->udptl, p->t38.our_parms.max_ifp); 06050 change_t38_state(p, T38_ENABLED); 06051 transmit_response_with_t38_sdp(p, "200 OK", &p->initreq, XMIT_CRITICAL); 06052 } else if (p->t38.state != T38_ENABLED) { 06053 p->t38.our_parms = *parameters; 06054 ast_udptl_set_local_max_ifp(p->udptl, p->t38.our_parms.max_ifp); 06055 change_t38_state(p, T38_LOCAL_REINVITE); 06056 if (!p->pendinginvite) { 06057 transmit_reinvite_with_sdp(p, TRUE, FALSE); 06058 } else if (!ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) { 06059 ast_set_flag(&p->flags[0], SIP_NEEDREINVITE); 06060 } 06061 } 06062 break; 06063 case AST_T38_TERMINATED: 06064 case AST_T38_REFUSED: 06065 case AST_T38_REQUEST_TERMINATE: /* Shutdown T38 */ 06066 if (p->t38.state == T38_PEER_REINVITE) { 06067 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")); 06068 change_t38_state(p, T38_DISABLED); 06069 transmit_response_reliable(p, "488 Not acceptable here", &p->initreq); 06070 } else if (p->t38.state == T38_ENABLED) 06071 transmit_reinvite_with_sdp(p, FALSE, FALSE); 06072 break; 06073 default: 06074 break; 06075 } 06076 }
static void list_route | ( | struct sip_route * | route | ) | [static] |
List all routes - mostly for debugging.
Definition at line 11639 of file chan_sip.c.
References ast_verbose, sip_route::hop, and sip_route::next.
Referenced by build_route().
11640 { 11641 if (!route) 11642 ast_verbose("list_route: no route\n"); 11643 else { 11644 for (;route; route = route->next) 11645 ast_verbose("list_route: hop: <%s>\n", route->hop); 11646 } 11647 }
static int load_module | ( | void | ) | [static] |
PBX load module - initialization.
Definition at line 24682 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, 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, 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, sippeer_function, threadt, threadt_cmp_cb(), and threadt_hash_cb().
24683 { 24684 ast_verbose("SIP channel loading...\n"); 24685 /* the fact that ao2_containers can't resize automatically is a major worry! */ 24686 /* if the number of objects gets above MAX_XXX_BUCKETS, things will slow down */ 24687 peers = ao2_t_container_alloc(hash_peer_size, peer_hash_cb, peer_cmp_cb, "allocate peers"); 24688 peers_by_ip = ao2_t_container_alloc(hash_peer_size, peer_iphash_cb, peer_ipcmp_cb, "allocate peers_by_ip"); 24689 dialogs = ao2_t_container_alloc(hash_dialog_size, dialog_hash_cb, dialog_cmp_cb, "allocate dialogs"); 24690 threadt = ao2_t_container_alloc(hash_dialog_size, threadt_hash_cb, threadt_cmp_cb, "allocate threadt table"); 24691 24692 ASTOBJ_CONTAINER_INIT(®l); /* Registry object list -- not searched for anything */ 24693 24694 if (!(sched = sched_context_create())) { 24695 ast_log(LOG_ERROR, "Unable to create scheduler context\n"); 24696 return AST_MODULE_LOAD_FAILURE; 24697 } 24698 24699 if (!(io = io_context_create())) { 24700 ast_log(LOG_ERROR, "Unable to create I/O context\n"); 24701 sched_context_destroy(sched); 24702 return AST_MODULE_LOAD_FAILURE; 24703 } 24704 24705 sip_reloadreason = CHANNEL_MODULE_LOAD; 24706 24707 if(reload_config(sip_reloadreason)) /* Load the configuration from sip.conf */ 24708 return AST_MODULE_LOAD_DECLINE; 24709 24710 /* Prepare the version that does not require DTMF BEGIN frames. 24711 * We need to use tricks such as memcpy and casts because the variable 24712 * has const fields. 24713 */ 24714 memcpy(&sip_tech_info, &sip_tech, sizeof(sip_tech)); 24715 memset((void *) &sip_tech_info.send_digit_begin, 0, sizeof(sip_tech_info.send_digit_begin)); 24716 24717 /* Make sure we can register our sip channel type */ 24718 if (ast_channel_register(&sip_tech)) { 24719 ast_log(LOG_ERROR, "Unable to register channel type 'SIP'\n"); 24720 io_context_destroy(io); 24721 sched_context_destroy(sched); 24722 return AST_MODULE_LOAD_FAILURE; 24723 } 24724 24725 /* Register all CLI functions for SIP */ 24726 ast_cli_register_multiple(cli_sip, sizeof(cli_sip)/ sizeof(struct ast_cli_entry)); 24727 24728 /* Tell the RTP subdriver that we're here */ 24729 ast_rtp_proto_register(&sip_rtp); 24730 24731 /* Tell the UDPTL subdriver that we're here */ 24732 ast_udptl_proto_register(&sip_udptl); 24733 24734 /* Register dialplan applications */ 24735 ast_register_application(app_dtmfmode, sip_dtmfmode, synopsis_dtmfmode, descrip_dtmfmode); 24736 ast_register_application(app_sipaddheader, sip_addheader, synopsis_sipaddheader, descrip_sipaddheader); 24737 24738 /* Register dialplan functions */ 24739 ast_custom_function_register(&sip_header_function); 24740 ast_custom_function_register(&sippeer_function); 24741 ast_custom_function_register(&sipchaninfo_function); 24742 ast_custom_function_register(&checksipdomain_function); 24743 24744 /* Register manager commands */ 24745 ast_manager_register2("SIPpeers", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_sip_show_peers, 24746 "List SIP peers (text format)", mandescr_show_peers); 24747 ast_manager_register2("SIPshowpeer", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_sip_show_peer, 24748 "Show SIP peer (text format)", mandescr_show_peer); 24749 ast_manager_register2("SIPqualifypeer", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_sip_qualify_peer, 24750 "Show SIP peer (text format)", mandescr_show_peer); /*! \todo Fix this XXX This must be all wrong XXXX */ 24751 ast_manager_register2("SIPshowregistry", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_show_registry, 24752 "Show SIP registrations (text format)", mandescr_show_registry); 24753 ast_manager_register2("SIPnotify", EVENT_FLAG_SYSTEM, manager_sipnotify, 24754 "Send a SIP notify", mandescr_sipnotify); 24755 sip_poke_all_peers(); 24756 sip_send_all_registers(); 24757 24758 /* And start the monitor for the first time */ 24759 restart_monitor(); 24760 24761 ast_realtime_require_field(ast_check_realtime("sipregs") ? "sipregs" : "sippeers", 24762 "name", RQ_CHAR, 10, 24763 "ipaddr", RQ_CHAR, 15, 24764 "port", RQ_UINTEGER2, 5, 24765 "regseconds", RQ_INTEGER4, 11, 24766 "defaultuser", RQ_CHAR, 10, 24767 "fullcontact", RQ_CHAR, 35, 24768 "regserver", RQ_CHAR, 20, 24769 "useragent", RQ_CHAR, 20, 24770 "lastms", RQ_INTEGER4, 11, 24771 SENTINEL); 24772 24773 return AST_MODULE_LOAD_SUCCESS; 24774 }
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 19497 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().
19498 { 19499 struct sip_dual target; /* Chan 1: Call from tranferer to Asterisk */ 19500 /* Chan 2: Call from Asterisk to target */ 19501 int res = 0; 19502 struct sip_pvt *targetcall_pvt; 19503 19504 /* Check if the call ID of the replaces header does exist locally */ 19505 if (!(targetcall_pvt = get_sip_pvt_byid_locked(transferer->refer->replaces_callid, transferer->refer->replaces_callid_totag, 19506 transferer->refer->replaces_callid_fromtag))) { 19507 if (transferer->refer->localtransfer) { 19508 /* We did not find the refered call. Sorry, can't accept then */ 19509 transmit_response(transferer, "202 Accepted", req); 19510 /* Let's fake a response from someone else in order 19511 to follow the standard */ 19512 transmit_notify_with_sipfrag(transferer, seqno, "481 Call leg/transaction does not exist", TRUE); 19513 append_history(transferer, "Xfer", "Refer failed"); 19514 ast_clear_flag(&transferer->flags[0], SIP_GOTREFER); 19515 transferer->refer->status = REFER_FAILED; 19516 return -1; 19517 } 19518 /* Fall through for remote transfers that we did not find locally */ 19519 ast_debug(3, "SIP attended transfer: Not our call - generating INVITE with replaces\n"); 19520 return 0; 19521 } 19522 19523 /* Ok, we can accept this transfer */ 19524 transmit_response(transferer, "202 Accepted", req); 19525 append_history(transferer, "Xfer", "Refer accepted"); 19526 if (!targetcall_pvt->owner) { /* No active channel */ 19527 ast_debug(4, "SIP attended transfer: Error: No owner of target call\n"); 19528 /* Cancel transfer */ 19529 transmit_notify_with_sipfrag(transferer, seqno, "503 Service Unavailable", TRUE); 19530 append_history(transferer, "Xfer", "Refer failed"); 19531 ast_clear_flag(&transferer->flags[0], SIP_GOTREFER); 19532 transferer->refer->status = REFER_FAILED; 19533 sip_pvt_unlock(targetcall_pvt); 19534 if (targetcall_pvt) 19535 ao2_t_ref(targetcall_pvt, -1, "Drop targetcall_pvt pointer"); 19536 return -1; 19537 } 19538 19539 /* We have a channel, find the bridge */ 19540 target.chan1 = targetcall_pvt->owner; /* Transferer to Asterisk */ 19541 target.chan2 = ast_bridged_channel(targetcall_pvt->owner); /* Asterisk to target */ 19542 19543 if (!target.chan2 || !(target.chan2->_state == AST_STATE_UP || target.chan2->_state == AST_STATE_RINGING) ) { 19544 /* Wrong state of new channel */ 19545 if (target.chan2) 19546 ast_debug(4, "SIP attended transfer: Error: Wrong state of target call: %s\n", ast_state2str(target.chan2->_state)); 19547 else if (target.chan1->_state != AST_STATE_RING) 19548 ast_debug(4, "SIP attended transfer: Error: No target channel\n"); 19549 else 19550 ast_debug(4, "SIP attended transfer: Attempting transfer in ringing state\n"); 19551 } 19552 19553 /* Transfer */ 19554 if (sipdebug) { 19555 if (current->chan2) /* We have two bridges */ 19556 ast_debug(4, "SIP attended transfer: trying to bridge %s and %s\n", target.chan1->name, current->chan2->name); 19557 else /* One bridge, propably transfer of IVR/voicemail etc */ 19558 ast_debug(4, "SIP attended transfer: trying to make %s take over (masq) %s\n", target.chan1->name, current->chan1->name); 19559 } 19560 19561 ast_set_flag(&transferer->flags[0], SIP_DEFER_BYE_ON_TRANSFER); /* Delay hangup */ 19562 19563 /* Perform the transfer */ 19564 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", 19565 transferer->owner->name, 19566 transferer->owner->uniqueid, 19567 transferer->callid, 19568 target.chan1->name, 19569 target.chan1->uniqueid); 19570 res = attempt_transfer(current, &target); 19571 sip_pvt_unlock(targetcall_pvt); 19572 if (res) { 19573 /* Failed transfer */ 19574 transmit_notify_with_sipfrag(transferer, seqno, "486 Busy Here", TRUE); 19575 append_history(transferer, "Xfer", "Refer failed"); 19576 if (targetcall_pvt->owner) 19577 ast_channel_unlock(targetcall_pvt->owner); 19578 ast_clear_flag(&transferer->flags[0], SIP_DEFER_BYE_ON_TRANSFER); 19579 } else { 19580 /* Transfer succeeded! */ 19581 19582 /* Tell transferer that we're done. */ 19583 transmit_notify_with_sipfrag(transferer, seqno, "200 OK", TRUE); 19584 append_history(transferer, "Xfer", "Refer succeeded"); 19585 transferer->refer->status = REFER_200OK; 19586 if (targetcall_pvt->owner) { 19587 ast_debug(1, "SIP attended transfer: Unlocking channel %s\n", targetcall_pvt->owner->name); 19588 ast_channel_unlock(targetcall_pvt->owner); 19589 } 19590 } 19591 if (targetcall_pvt) 19592 ao2_t_ref(targetcall_pvt, -1, "drop targetcall_pvt"); 19593 return 1; 19594 }
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 7152 of file chan_sip.c.
Referenced by handle_request_do().
07153 { 07154 int h = 0, t = 0; 07155 int lws = 0; 07156 07157 for (; h < len;) { 07158 /* Eliminate all CRs */ 07159 if (msgbuf[h] == '\r') { 07160 h++; 07161 continue; 07162 } 07163 /* Check for end-of-line */ 07164 if (msgbuf[h] == '\n') { 07165 /* Check for end-of-message */ 07166 if (h + 1 == len) 07167 break; 07168 /* Check for a continuation line */ 07169 if (msgbuf[h + 1] == ' ' || msgbuf[h + 1] == '\t') { 07170 /* Merge continuation line */ 07171 h++; 07172 continue; 07173 } 07174 /* Propagate LF and start new line */ 07175 msgbuf[t++] = msgbuf[h++]; 07176 lws = 0; 07177 continue; 07178 } 07179 if (msgbuf[h] == ' ' || msgbuf[h] == '\t') { 07180 if (lws) { 07181 h++; 07182 continue; 07183 } 07184 msgbuf[t++] = msgbuf[h++]; 07185 lws = 1; 07186 continue; 07187 } 07188 msgbuf[t++] = msgbuf[h++]; 07189 if (lws) 07190 lws = 0; 07191 } 07192 msgbuf[t] = '\0'; 07193 return t; 07194 }
static void make_our_tag | ( | char * | tagbuf, | |
size_t | len | |||
) | [static] |
Make our SIP dialog tag.
Definition at line 6708 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().
06709 { 06710 snprintf(tagbuf, len, "as%08lx", ast_random()); 06711 }
static int manager_show_registry | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Show SIP registrations in the manager API.
Definition at line 13790 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().
13791 { 13792 const char *id = astman_get_header(m, "ActionID"); 13793 char idtext[256] = ""; 13794 int total = 0; 13795 13796 if (!ast_strlen_zero(id)) 13797 snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id); 13798 13799 astman_send_listack(s, m, "Registrations will follow", "start"); 13800 13801 ASTOBJ_CONTAINER_TRAVERSE(®l, 1, do { 13802 ASTOBJ_RDLOCK(iterator); 13803 astman_append(s, 13804 "Event: RegistryEntry\r\n" 13805 "%s" 13806 "Host: %s\r\n" 13807 "Port: %d\r\n" 13808 "Username: %s\r\n" 13809 "Refresh: %d\r\n" 13810 "State: %s\r\n" 13811 "RegistrationTime: %ld\r\n" 13812 "\r\n", idtext, iterator->hostname, iterator->portno ? iterator->portno : STANDARD_SIP_PORT, 13813 iterator->username, iterator->refresh, regstate2str(iterator->regstate), (long) iterator->regtime.tv_sec); 13814 ASTOBJ_UNLOCK(iterator); 13815 total++; 13816 } while(0)); 13817 13818 astman_append(s, 13819 "Event: RegistrationsComplete\r\n" 13820 "EventList: Complete\r\n" 13821 "ListItems: %d\r\n" 13822 "%s" 13823 "\r\n", total, idtext); 13824 13825 return 0; 13826 }
static int manager_sip_qualify_peer | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Qualify SIP peers in the manager API.
Definition at line 14517 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().
14518 { 14519 const char *a[4]; 14520 const char *peer; 14521 14522 peer = astman_get_header(m, "Peer"); 14523 if (ast_strlen_zero(peer)) { 14524 astman_send_error(s, m, "Peer: <name> missing."); 14525 return 0; 14526 } 14527 a[0] = "sip"; 14528 a[1] = "qualify"; 14529 a[2] = "peer"; 14530 a[3] = peer; 14531 14532 _sip_qualify_peer(1, -1, s, m, 4, a); 14533 astman_append(s, "\r\n\r\n" ); 14534 return 0; 14535 }
static int manager_sip_show_peer | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Show SIP peers in the manager API.
Definition at line 14458 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().
14459 { 14460 const char *a[4]; 14461 const char *peer; 14462 14463 peer = astman_get_header(m, "Peer"); 14464 if (ast_strlen_zero(peer)) { 14465 astman_send_error(s, m, "Peer: <name> missing."); 14466 return 0; 14467 } 14468 a[0] = "sip"; 14469 a[1] = "show"; 14470 a[2] = "peer"; 14471 a[3] = peer; 14472 14473 _sip_show_peer(1, -1, s, m, 4, a); 14474 astman_append(s, "\r\n\r\n" ); 14475 return 0; 14476 }
static int manager_sip_show_peers | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Show SIP peers in the manager API.
Definition at line 13837 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().
13838 { 13839 const char *id = astman_get_header(m, "ActionID"); 13840 const char *a[] = {"sip", "show", "peers"}; 13841 char idtext[256] = ""; 13842 int total = 0; 13843 13844 if (!ast_strlen_zero(id)) 13845 snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id); 13846 13847 astman_send_listack(s, m, "Peer status list will follow", "start"); 13848 /* List the peers in separate manager events */ 13849 _sip_show_peers(-1, &total, s, m, 3, a); 13850 /* Send final confirmation */ 13851 astman_append(s, 13852 "Event: PeerlistComplete\r\n" 13853 "EventList: Complete\r\n" 13854 "ListItems: %d\r\n" 13855 "%s" 13856 "\r\n", total, idtext); 13857 return 0; 13858 }
static int manager_sipnotify | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 10594 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().
10595 { 10596 const char *channame = astman_get_header(m, "Channel"); 10597 struct ast_variable *vars = astman_get_variables(m); 10598 struct sip_pvt *p; 10599 10600 if (ast_strlen_zero(channame)) { 10601 astman_send_error(s, m, "SIPNotify requires a channel name"); 10602 return 0; 10603 } 10604 10605 if (!strncasecmp(channame, "sip/", 4)) { 10606 channame += 4; 10607 } 10608 10609 if (!(p = sip_alloc(NULL, NULL, 0, SIP_NOTIFY, NULL))) { 10610 astman_send_error(s, m, "Unable to build sip pvt data for notify (memory/socket error)"); 10611 return 0; 10612 } 10613 10614 if (create_addr(p, channame, NULL, 0)) { 10615 /* Maybe they're not registered, etc. */ 10616 dialog_unlink_all(p, TRUE, TRUE); 10617 dialog_unref(p, "unref dialog inside for loop" ); 10618 /* sip_destroy(p); */ 10619 astman_send_error(s, m, "Could not create address"); 10620 return 0; 10621 } 10622 10623 /* Notify is outgoing call */ 10624 ast_set_flag(&p->flags[0], SIP_OUTGOING); 10625 10626 /* Recalculate our side, and recalculate Call ID */ 10627 ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip, p); 10628 build_via(p); 10629 ao2_t_unlink(dialogs, p, "About to change the callid -- remove the old name"); 10630 build_callid_pvt(p); 10631 ao2_t_link(dialogs, p, "Linking in new name"); 10632 dialog_ref(p, "bump the count of p, which transmit_sip_request will decrement."); 10633 sip_scheddestroy(p, SIP_TRANS_TIMEOUT); 10634 10635 if (!transmit_notify_custom(p, vars)) { 10636 astman_send_ack(s, m, "Notify Sent"); 10637 } else { 10638 astman_send_error(s, m, "Unable to send notify"); 10639 } 10640 ast_variables_destroy(vars); 10641 return 0; 10642 }
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 2390 of file chan_sip.c.
References _map_x_s::s, table, and _map_x_s::x.
Referenced by str2dtmfmode(), str2stmode(), and str2strefresher().
02391 { 02392 const struct _map_x_s *cur; 02393 02394 for (cur = table; cur->s; cur++) 02395 if (!strcasecmp(cur->s, s)) 02396 return cur->x; 02397 return errorvalue; 02398 }
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 2377 of file chan_sip.c.
References _map_x_s::s, table, and _map_x_s::x.
Referenced by dtmfmode2str(), faxec2str(), insecure2str(), nat2str(), referstatus2str(), regstate2str(), stmode2str(), and strefresher2str().
02378 { 02379 const struct _map_x_s *cur; 02380 02381 for (cur = table; cur->s; cur++) 02382 if (cur->x == x) 02383 return cur->s; 02384 return errorstring; 02385 }
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 2988 of file chan_sip.c.
References sip_methods, and text.
Referenced by __sip_autodestruct(), __sip_semi_ack(), and find_sip_method().
02989 { 02990 int len = strlen(sip_methods[id].text); 02991 int l_name = name ? strlen(name) : 0; 02992 /* true if the string is long enough, and ends with whitespace, and matches */ 02993 return (l_name >= len && name[len] < 33 && 02994 !strncasecmp(sip_methods[id].text, name, len)); 02995 }
static void mwi_event_cb | ( | const struct ast_event * | , | |
void * | ||||
) | [static] |
Receive MWI events that we have subscribed to.
Definition at line 11970 of file chan_sip.c.
References ao2_lock(), ao2_unlock(), and sip_send_mwi_to_peer().
11971 { 11972 struct sip_peer *peer = userdata; 11973 11974 ao2_lock(peer); 11975 sip_send_mwi_to_peer(peer, event, 0); 11976 ao2_unlock(peer); 11977 }
static const char * nat2str | ( | int | nat | ) | const [static] |
Convert NAT setting to text string.
Definition at line 13572 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 2963 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().
02964 { 02965 if (peer && peer->outboundproxy) { 02966 if (sipdebug) 02967 ast_debug(1, "OBPROXY: Applying peer OBproxy to this call\n"); 02968 append_history(dialog, "OBproxy", "Using peer obproxy %s", peer->outboundproxy->name); 02969 return peer->outboundproxy; 02970 } 02971 if (global_outboundproxy.name[0]) { 02972 if (sipdebug) 02973 ast_debug(1, "OBPROXY: Applying global OBproxy to this call\n"); 02974 append_history(dialog, "OBproxy", "Using global obproxy %s", global_outboundproxy.name); 02975 return &global_outboundproxy; 02976 } 02977 if (sipdebug) 02978 ast_debug(1, "OBPROXY: Not applying OBproxy to this call\n"); 02979 return NULL; 02980 }
static void parse_copy | ( | struct sip_request * | dst, | |
const struct sip_request * | src | |||
) | [static] |
Copy SIP request, parse it.
Definition at line 3756 of file chan_sip.c.
References copy_request(), and parse_request().
Referenced by send_request(), and send_response().
03757 { 03758 copy_request(dst, src); 03759 parse_request(dst); 03760 }
int parse_minse | ( | const char * | p_hdrval, | |
int *const | p_interval | |||
) | [static] |
Session-Timers: Function for parsing Min-SE header.
Definition at line 21732 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().
21733 { 21734 if (ast_strlen_zero(p_hdrval)) { 21735 ast_log(LOG_WARNING, "Null Min-SE header\n"); 21736 return -1; 21737 } 21738 21739 *p_interval = 0; 21740 p_hdrval = ast_skip_blanks(p_hdrval); 21741 if (!sscanf(p_hdrval, "%30d", p_interval)) { 21742 ast_log(LOG_WARNING, "Parsing of Min-SE header failed %s\n", p_hdrval); 21743 return -1; 21744 } 21745 21746 ast_debug(2, "Received Min-SE: %d\n", *p_interval); 21747 return 0; 21748 }
static void parse_moved_contact | ( | struct sip_pvt * | p, | |
struct sip_request * | req | |||
) | [static] |
Parse 302 Moved temporalily response.
Definition at line 16697 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_pvt::flags, get_header(), get_in_brackets(), get_transport(), sip_pvt::owner, pbx_builtin_setvar_helper(), remove_uri_parameters(), s, set_socket_transport(), SIP_PROMISCREDIR, SIP_TRANSPORT_TCP, SIP_TRANSPORT_TLS, SIP_TRANSPORT_UDP, SIPBUFSIZE, sip_pvt::socket, strcasestr(), and sip_socket::tcptls_session.
Referenced by handle_response().
16698 { 16699 char tmp[SIPBUFSIZE]; 16700 char *s, *e, *t, *trans; 16701 char *domain; 16702 enum sip_transport transport = SIP_TRANSPORT_UDP; 16703 16704 ast_copy_string(tmp, get_header(req, "Contact"), sizeof(tmp)); 16705 if ((t = strchr(tmp, ','))) 16706 *t = '\0'; 16707 16708 s = get_in_brackets(tmp); 16709 if ((trans = strcasestr(s, ";transport="))) do { 16710 trans += 11; 16711 16712 if ((e = strchr(trans, ';'))) 16713 *e = '\0'; 16714 16715 if (!strncasecmp(trans, "tcp", 3)) 16716 transport = SIP_TRANSPORT_TCP; 16717 else if (!strncasecmp(trans, "tls", 3)) 16718 transport = SIP_TRANSPORT_TLS; 16719 else { 16720 if (strncasecmp(trans, "udp", 3)) 16721 ast_debug(1, "received contact with an invalid transport, '%s'\n", s); 16722 transport = SIP_TRANSPORT_UDP; 16723 } 16724 } while(0); 16725 s = remove_uri_parameters(s); 16726 16727 if (p->socket.tcptls_session) { 16728 ao2_ref(p->socket.tcptls_session, -1); 16729 p->socket.tcptls_session = NULL; 16730 } 16731 16732 set_socket_transport(&p->socket, transport); 16733 16734 if (ast_test_flag(&p->flags[0], SIP_PROMISCREDIR)) { 16735 char *host = NULL; 16736 if (!strncasecmp(s, "sip:", 4)) 16737 s += 4; 16738 else if (!strncasecmp(s, "sips:", 5)) 16739 s += 5; 16740 e = strchr(s, '/'); 16741 if (e) 16742 *e = '\0'; 16743 if ((host = strchr(s, '@'))) { 16744 *host++ = '\0'; 16745 ast_debug(2, "Found promiscuous redirection to 'SIP/%s::::%s@%s'\n", s, get_transport(transport), host); 16746 if (p->owner) 16747 ast_string_field_build(p->owner, call_forward, "SIP/%s::::%s@%s", s, get_transport(transport), host); 16748 } else { 16749 ast_debug(2, "Found promiscuous redirection to 'SIP/::::%s@%s'\n", get_transport(transport), s); 16750 if (p->owner) 16751 ast_string_field_build(p->owner, call_forward, "SIP/::::%s@%s", get_transport(transport), s); 16752 } 16753 } else { 16754 e = strchr(tmp, '@'); 16755 if (e) { 16756 *e++ = '\0'; 16757 domain = e; 16758 } else { 16759 /* No username part */ 16760 domain = tmp; 16761 } 16762 e = strchr(tmp, '/'); /* WHEN do we hae a forward slash in the URI? */ 16763 if (e) 16764 *e = '\0'; 16765 16766 if (!strncasecmp(s, "sip:", 4)) 16767 s += 4; 16768 else if (!strncasecmp(s, "sips:", 5)) 16769 s += 5; 16770 e = strchr(s, ';'); /* And username ; parameters? */ 16771 if (e) 16772 *e = '\0'; 16773 ast_debug(2, "Received 302 Redirect to extension '%s' (domain %s)\n", s, domain); 16774 if (p->owner) { 16775 pbx_builtin_setvar_helper(p->owner, "SIPDOMAIN", domain); 16776 ast_string_field_set(p->owner, call_forward, s); 16777 } 16778 } 16779 }
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 11347 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().
11348 { 11349 char contact[SIPBUFSIZE]; 11350 char *c; 11351 11352 /* Look for brackets */ 11353 ast_copy_string(contact, get_header(req, "Contact"), sizeof(contact)); 11354 c = get_in_brackets(contact); 11355 11356 /* Save full contact to call pvt for later bye or re-invite */ 11357 ast_string_field_set(pvt, fullcontact, c); 11358 11359 /* Save URI for later ACKs, BYE or RE-invites */ 11360 ast_string_field_set(pvt, okcontacturi, c); 11361 11362 /* We should return false for URI:s we can't handle, 11363 like tel:, mailto:,ldap: etc */ 11364 return TRUE; 11365 }
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 11426 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_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, sip_peer::default_outbound_transport, 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(), get_transport_str2enum(), global_contact_ha, hp, inaddrcmp(), sip_peer::is_realtime, sip_peer::lastms, LOG_NOTICE, LOG_WARNING, manager_event, sip_peer::name, PARSE_REGISTER_DENIED, PARSE_REGISTER_FAILED, PARSE_REGISTER_QUERY, PARSE_REGISTER_UPDATE, parse_uri(), peers_by_ip, port_str2int(), sip_peer::portinuri, sip_pvt::recv, ref_peer(), register_peer_exten(), sip_peer::rt_fromcontact, s, sched, set_socket_transport(), SIP_NAT_ROUTE, SIP_PAGE2_RTCACHEFRIENDS, sip_poke_peer(), SIP_TRANSPORT_TLS, SIP_TRANSPORT_UDP, SIPBUFSIZE, sip_pvt::sipoptions, sip_peer::sipoptions, sip_peer::socket, sip_request::socket, sip_pvt::socket, STANDARD_SIP_PORT, STANDARD_TLS_PORT, strcasestr(), strsep(), sip_peer::transports, TRUE, sip_socket::type, unref_peer(), sip_peer::useragent, sip_peer::username, VERBOSE_PREFIX_3, and VERBOSITY_ATLEAST.
Referenced by register_verify().
11427 { 11428 char contact[SIPBUFSIZE]; 11429 char data[SIPBUFSIZE]; 11430 const char *expires = get_header(req, "Expires"); 11431 int expire = atoi(expires); 11432 char *curi, *host, *pt, *transport; 11433 int port; 11434 int transport_type; 11435 const char *useragent; 11436 struct hostent *hp; 11437 struct ast_hostent ahp; 11438 struct sockaddr_in oldsin, testsin; 11439 11440 11441 ast_copy_string(contact, get_header(req, "Contact"), sizeof(contact)); 11442 11443 if (ast_strlen_zero(expires)) { /* No expires header, try look in Contact: */ 11444 char *s = strcasestr(contact, ";expires="); 11445 if (s) { 11446 expires = strsep(&s, ";"); /* trim ; and beyond */ 11447 if (sscanf(expires + 9, "%30d", &expire) != 1) 11448 expire = default_expiry; 11449 } else { 11450 /* Nothing has been specified */ 11451 expire = default_expiry; 11452 } 11453 } 11454 11455 copy_socket_data(&pvt->socket, &req->socket); 11456 11457 /* Look for brackets */ 11458 curi = contact; 11459 if (strchr(contact, '<') == NULL) /* No <, check for ; and strip it */ 11460 strsep(&curi, ";"); /* This is Header options, not URI options */ 11461 curi = get_in_brackets(contact); 11462 11463 /* if they did not specify Contact: or Expires:, they are querying 11464 what we currently have stored as their contact address, so return 11465 it 11466 */ 11467 if (ast_strlen_zero(curi) && ast_strlen_zero(expires)) { 11468 /* If we have an active registration, tell them when the registration is going to expire */ 11469 if (peer->expire > -1 && !ast_strlen_zero(peer->fullcontact)) 11470 pvt->expiry = ast_sched_when(sched, peer->expire); 11471 return PARSE_REGISTER_QUERY; 11472 } else if (!strcasecmp(curi, "*") || !expire) { /* Unregister this peer */ 11473 /* This means remove all registrations and return OK */ 11474 memset(&peer->addr, 0, sizeof(peer->addr)); 11475 set_socket_transport(&peer->socket, peer->default_outbound_transport); 11476 11477 AST_SCHED_DEL_UNREF(sched, peer->expire, 11478 unref_peer(peer, "remove register expire ref")); 11479 11480 destroy_association(peer); 11481 11482 register_peer_exten(peer, FALSE); /* Remove extension from regexten= setting in sip.conf */ 11483 peer->fullcontact[0] = '\0'; 11484 peer->useragent[0] = '\0'; 11485 peer->sipoptions = 0; 11486 peer->lastms = 0; 11487 peer->portinuri = 0; 11488 pvt->expiry = 0; 11489 11490 ast_verb(3, "Unregistered SIP '%s'\n", peer->name); 11491 11492 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: SIP\r\nPeer: SIP/%s\r\nPeerStatus: Unregistered\r\n", peer->name); 11493 return PARSE_REGISTER_UPDATE; 11494 } 11495 11496 /* Store whatever we got as a contact from the client */ 11497 ast_copy_string(peer->fullcontact, curi, sizeof(peer->fullcontact)); 11498 11499 /* For the 200 OK, we should use the received contact */ 11500 ast_string_field_build(pvt, our_contact, "<%s>", curi); 11501 11502 /* Make sure it's a SIP URL */ 11503 if (parse_uri(curi, "sip:,sips:", &curi, NULL, &host, &pt, NULL, &transport)) { 11504 ast_log(LOG_NOTICE, "Not a valid SIP contact (missing sip:) trying to use anyway\n"); 11505 } 11506 11507 /* If we have a port number in the given URI, make sure we do remember to not check for NAPTR/SRV records. 11508 The domain part is actually a host. */ 11509 peer->portinuri = !ast_strlen_zero(pt) ? TRUE : FALSE; 11510 11511 /* handle the transport type specified in Contact header. */ 11512 if ((transport_type = get_transport_str2enum(transport))) { 11513 /* if the port is not specified but the transport is, make sure to set the 11514 * default port to match the specified transport. This may or may not be the 11515 * same transport used by the pvt struct for the Register dialog. */ 11516 11517 port = port_str2int(pt, (transport_type == SIP_TRANSPORT_TLS) ? STANDARD_TLS_PORT : STANDARD_SIP_PORT); 11518 } else { 11519 port = port_str2int(pt, STANDARD_SIP_PORT); 11520 transport_type = pvt->socket.type; 11521 } 11522 11523 /* if the peer's socket type is different than the Registration 11524 * transport type, change it. If it got this far, it is a 11525 * supported type, but check just in case */ 11526 if ((peer->socket.type != transport_type) && (peer->transports & transport_type)) { 11527 set_socket_transport(&peer->socket, transport_type); 11528 } 11529 11530 oldsin = peer->addr; 11531 11532 /* If we were already linked into the peers_by_ip container unlink ourselves so nobody can find us */ 11533 if (peer->addr.sin_addr.s_addr) { 11534 ao2_t_unlink(peers_by_ip, peer, "ao2_unlink of peer from peers_by_ip table"); 11535 } 11536 11537 /* Check that they're allowed to register at this IP */ 11538 /* XXX This could block for a long time XXX */ 11539 hp = ast_gethostbyname(host, &ahp); 11540 if (!hp) { 11541 ast_log(LOG_WARNING, "Invalid host '%s'\n", host); 11542 *peer->fullcontact = '\0'; 11543 ast_string_field_set(pvt, our_contact, ""); 11544 return PARSE_REGISTER_FAILED; 11545 } 11546 memcpy(&testsin.sin_addr, hp->h_addr, sizeof(testsin.sin_addr)); 11547 if ( ast_apply_ha(global_contact_ha, &testsin) != AST_SENSE_ALLOW || 11548 ast_apply_ha(peer->contactha, &testsin) != AST_SENSE_ALLOW) { 11549 ast_log(LOG_WARNING, "Host '%s' disallowed by contact ACL (violating IP %s)\n", host, ast_inet_ntoa(testsin.sin_addr)); 11550 *peer->fullcontact = '\0'; 11551 ast_string_field_set(pvt, our_contact, ""); 11552 return PARSE_REGISTER_DENIED; 11553 } 11554 11555 if (!ast_test_flag(&peer->flags[0], SIP_NAT_ROUTE)) { 11556 peer->addr.sin_family = AF_INET; 11557 memcpy(&peer->addr.sin_addr, hp->h_addr, sizeof(peer->addr.sin_addr)); 11558 peer->addr.sin_port = htons(port); 11559 } else { 11560 /* Don't trust the contact field. Just use what they came to us 11561 with */ 11562 peer->addr = pvt->recv; 11563 } 11564 11565 /* if the Contact header information copied into peer->addr matches the 11566 * received address, and the transport types are the same, then copy socket 11567 * data into the peer struct */ 11568 if ((peer->socket.type == pvt->socket.type) && 11569 (peer->addr.sin_addr.s_addr == pvt->recv.sin_addr.s_addr) && 11570 (peer->addr.sin_port == pvt->recv.sin_port)){ 11571 11572 copy_socket_data(&peer->socket, &pvt->socket); 11573 } 11574 11575 /* Now that our address has been updated put ourselves back into the container for lookups */ 11576 ao2_t_link(peers_by_ip, peer, "ao2_link into peers_by_ip table"); 11577 11578 /* Save SIP options profile */ 11579 peer->sipoptions = pvt->sipoptions; 11580 11581 if (!ast_strlen_zero(curi) && ast_strlen_zero(peer->username)) 11582 ast_copy_string(peer->username, curi, sizeof(peer->username)); 11583 11584 AST_SCHED_DEL_UNREF(sched, peer->expire, 11585 unref_peer(peer, "remove register expire ref")); 11586 11587 if (expire > max_expiry) 11588 expire = max_expiry; 11589 if (expire < min_expiry) 11590 expire = min_expiry; 11591 if (peer->is_realtime && !ast_test_flag(&peer->flags[1], SIP_PAGE2_RTCACHEFRIENDS)) { 11592 peer->expire = -1; 11593 } else { 11594 peer->expire = ast_sched_add(sched, (expire + 10) * 1000, expire_register, 11595 ref_peer(peer, "add registration ref")); 11596 if (peer->expire == -1) { 11597 unref_peer(peer, "remote registration ref"); 11598 } 11599 } 11600 pvt->expiry = expire; 11601 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); 11602 /* Saving TCP connections is useless, we won't be able to reconnect 11603 XXX WHY???? XXX 11604 \todo check this 11605 */ 11606 if (!peer->rt_fromcontact && (peer->socket.type & SIP_TRANSPORT_UDP)) 11607 ast_db_put("SIP/Registry", peer->name, data); 11608 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)); 11609 11610 /* Is this a new IP address for us? */ 11611 if (VERBOSITY_ATLEAST(2) && inaddrcmp(&peer->addr, &oldsin)) { 11612 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)); 11613 } 11614 sip_poke_peer(peer, 0); 11615 register_peer_exten(peer, 1); 11616 11617 /* Save User agent */ 11618 useragent = get_header(req, "User-Agent"); 11619 if (strcasecmp(useragent, peer->useragent)) { /* XXX copy if they are different ? */ 11620 ast_copy_string(peer->useragent, useragent, sizeof(peer->useragent)); 11621 ast_verb(4, "Saved useragent \"%s\" for peer %s\n", peer->useragent, peer->name); 11622 } 11623 return PARSE_REGISTER_UPDATE; 11624 }
static int parse_request | ( | struct sip_request * | req | ) | [static] |
Parse a SIP message.
Definition at line 7199 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().
07200 { 07201 char *c = req->data->str; 07202 ptrdiff_t *dst = req->header; 07203 int i = 0, lim = SIP_MAX_HEADERS - 1; 07204 unsigned int skipping_headers = 0; 07205 ptrdiff_t current_header_offset = 0; 07206 char *previous_header = ""; 07207 07208 req->header[0] = 0; 07209 req->headers = -1; /* mark that we are working on the header */ 07210 for (; *c; c++) { 07211 if (*c == '\r') { /* remove \r */ 07212 *c = '\0'; 07213 } else if (*c == '\n') { /* end of this line */ 07214 *c = '\0'; 07215 current_header_offset = (c + 1) - req->data->str; 07216 previous_header = req->data->str + dst[i]; 07217 if (skipping_headers) { 07218 /* check to see if this line is blank; if so, turn off 07219 the skipping flag, so the next line will be processed 07220 as a body line */ 07221 if (ast_strlen_zero(previous_header)) { 07222 skipping_headers = 0; 07223 } 07224 dst[i] = current_header_offset; /* record start of next line */ 07225 continue; 07226 } 07227 if (sipdebug) { 07228 ast_debug(4, "%7s %2d [%3d]: %s\n", 07229 req->headers < 0 ? "Header" : "Body", 07230 i, (int) strlen(previous_header), previous_header); 07231 } 07232 if (ast_strlen_zero(previous_header) && req->headers < 0) { 07233 req->headers = i; /* record number of header lines */ 07234 dst = req->line; /* start working on the body */ 07235 i = 0; 07236 lim = SIP_MAX_LINES - 1; 07237 } else { /* move to next line, check for overflows */ 07238 if (i++ == lim) { 07239 /* if we're processing headers, then skip any remaining 07240 headers and move on to processing the body, otherwise 07241 we're done */ 07242 if (req->headers != -1) { 07243 break; 07244 } else { 07245 req->headers = i; 07246 dst = req->line; 07247 i = 0; 07248 lim = SIP_MAX_LINES - 1; 07249 skipping_headers = 1; 07250 } 07251 } 07252 } 07253 dst[i] = current_header_offset; /* record start of next line */ 07254 } 07255 } 07256 07257 /* Check for last header or body line without CRLF. The RFC for SDP requires CRLF, 07258 but since some devices send without, we'll be generous in what we accept. However, 07259 if we've already reached the maximum number of lines for portion of the message 07260 we were parsing, we can't accept any more, so just ignore it. 07261 */ 07262 previous_header = req->data->str + dst[i]; 07263 if ((i < lim) && !ast_strlen_zero(previous_header)) { 07264 if (sipdebug) { 07265 ast_debug(4, "%7s %2d [%3d]: %s\n", 07266 req->headers < 0 ? "Header" : "Body", 07267 i, (int) strlen(previous_header), previous_header ); 07268 } 07269 i++; 07270 } 07271 07272 /* update count of header or body lines */ 07273 if (req->headers >= 0) { /* we are in the body */ 07274 req->lines = i; 07275 } else { /* no body */ 07276 req->headers = i; 07277 req->lines = 0; 07278 /* req->data->used will be a NULL byte */ 07279 req->line[0] = req->data->used; 07280 } 07281 07282 if (*c) { 07283 ast_log(LOG_WARNING, "Too many lines, skipping <%s>\n", c); 07284 } 07285 07286 /* Split up the first line parts */ 07287 return determine_firstline_parts(req); 07288 }
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 21752 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().
21753 { 21754 char *p_token; 21755 int ref_idx; 21756 char *p_se_hdr; 21757 21758 if (ast_strlen_zero(p_hdrval)) { 21759 ast_log(LOG_WARNING, "Null Session-Expires header\n"); 21760 return -1; 21761 } 21762 21763 *p_ref = SESSION_TIMER_REFRESHER_AUTO; 21764 *p_interval = 0; 21765 21766 p_se_hdr = ast_strdupa(p_hdrval); 21767 p_se_hdr = ast_skip_blanks(p_se_hdr); 21768 21769 while ((p_token = strsep(&p_se_hdr, ";"))) { 21770 p_token = ast_skip_blanks(p_token); 21771 if (!sscanf(p_token, "%30d", p_interval)) { 21772 ast_log(LOG_WARNING, "Parsing of Session-Expires failed\n"); 21773 return -1; 21774 } 21775 21776 ast_debug(2, "Session-Expires: %d\n", *p_interval); 21777 21778 if (!p_se_hdr) 21779 continue; 21780 21781 p_se_hdr = ast_skip_blanks(p_se_hdr); 21782 ref_idx = strlen("refresher="); 21783 if (!strncasecmp(p_se_hdr, "refresher=", ref_idx)) { 21784 p_se_hdr += ref_idx; 21785 p_se_hdr = ast_skip_blanks(p_se_hdr); 21786 21787 if (!strncasecmp(p_se_hdr, "uac", strlen("uac"))) { 21788 *p_ref = SESSION_TIMER_REFRESHER_UAC; 21789 ast_debug(2, "Refresher: UAC\n"); 21790 } else if (!strncasecmp(p_se_hdr, "uas", strlen("uas"))) { 21791 *p_ref = SESSION_TIMER_REFRESHER_UAS; 21792 ast_debug(2, "Refresher: UAS\n"); 21793 } else { 21794 ast_log(LOG_WARNING, "Invalid refresher value %s\n", p_se_hdr); 21795 return -1; 21796 } 21797 break; 21798 } 21799 } 21800 return 0; 21801 }
static unsigned int parse_sip_options | ( | struct sip_pvt * | pvt, | |
const char * | supported | |||
) | [static] |
Parse supported header in incoming packet.
Definition at line 3012 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().
03013 { 03014 char *next, *sep; 03015 char *temp; 03016 unsigned int profile = 0; 03017 int i, found; 03018 03019 if (ast_strlen_zero(supported) ) 03020 return 0; 03021 temp = ast_strdupa(supported); 03022 03023 if (sipdebug) 03024 ast_debug(3, "Begin: parsing SIP \"Supported: %s\"\n", supported); 03025 03026 for (next = temp; next; next = sep) { 03027 found = FALSE; 03028 if ( (sep = strchr(next, ',')) != NULL) 03029 *sep++ = '\0'; 03030 next = ast_skip_blanks(next); 03031 if (sipdebug) 03032 ast_debug(3, "Found SIP option: -%s-\n", next); 03033 for (i = 0; i < ARRAY_LEN(sip_options); i++) { 03034 if (!strcasecmp(next, sip_options[i].text)) { 03035 profile |= sip_options[i].id; 03036 found = TRUE; 03037 if (sipdebug) 03038 ast_debug(3, "Matched SIP option: %s\n", next); 03039 break; 03040 } 03041 } 03042 03043 /* This function is used to parse both Suported: and Require: headers. 03044 Let the caller of this function know that an unknown option tag was 03045 encountered, so that if the UAC requires it then the request can be 03046 rejected with a 420 response. */ 03047 if (!found) 03048 profile |= SIP_OPT_UNKNOWN; 03049 03050 if (!found && sipdebug) { 03051 if (!strncasecmp(next, "x-", 2)) 03052 ast_debug(3, "Found private SIP option, not supported: %s\n", next); 03053 else 03054 ast_debug(3, "Found no match for SIP option: %s (Please file bug report!)\n", next); 03055 } 03056 } 03057 03058 if (pvt) 03059 pvt->sipoptions = profile; 03060 return profile; 03061 }
static int parse_uri | ( | char * | uri, | |
const char * | scheme, | |||
char ** | ret_name, | |||
char ** | pass, | |||
char ** | domain, | |||
char ** | port, | |||
char ** | options, | |||
char ** | transport | |||
) | [static] |
* parses a URI in its components.
* general form we are expecting is sip[s]:username[:password][;parameter]@host[:port][;...] *
Definition at line 4010 of file chan_sip.c.
References ast_debug, ast_strdupa, ast_strlen_zero(), name, and strsep().
Referenced by __set_address_from_contact(), check_user_full(), and parse_register_contact().
04012 { 04013 char *name = NULL; 04014 int error = 0; 04015 04016 /* init field as required */ 04017 if (pass) 04018 *pass = ""; 04019 if (port) 04020 *port = ""; 04021 if (scheme) { 04022 int l; 04023 char *scheme2 = ast_strdupa(scheme); 04024 char *cur = strsep(&scheme2, ","); 04025 for (; !ast_strlen_zero(cur); cur = strsep(&scheme2, ",")) { 04026 l = strlen(cur); 04027 if (!strncasecmp(uri, cur, l)) { 04028 uri += l; 04029 break; 04030 } 04031 } 04032 if (ast_strlen_zero(cur)) { 04033 ast_debug(1, "No supported scheme found in '%s' using the scheme[s] %s\n", uri, scheme); 04034 error = -1; 04035 } 04036 } 04037 if (transport) { 04038 char *t, *type = ""; 04039 *transport = ""; 04040 if ((t = strstr(uri, "transport="))) { 04041 strsep(&t, "="); 04042 if ((type = strsep(&t, ";"))) { 04043 *transport = type; 04044 } 04045 } 04046 } 04047 04048 if (!domain) { 04049 /* if we don't want to split around domain, keep everything as a name, 04050 * so we need to do nothing here, except remember why. 04051 */ 04052 } else { 04053 /* store the result in a temp. variable to avoid it being 04054 * overwritten if arguments point to the same place. 04055 */ 04056 char *c, *dom = ""; 04057 04058 if ((c = strchr(uri, '@')) == NULL) { 04059 /* domain-only URI, according to the SIP RFC. */ 04060 dom = uri; 04061 name = ""; 04062 } else { 04063 *c++ = '\0'; 04064 dom = c; 04065 name = uri; 04066 } 04067 04068 /* Remove options in domain and name */ 04069 dom = strsep(&dom, ";"); 04070 name = strsep(&name, ";"); 04071 04072 if (port && (c = strchr(dom, ':'))) { /* Remove :port */ 04073 *c++ = '\0'; 04074 *port = c; 04075 } 04076 if (pass && (c = strchr(name, ':'))) { /* user:password */ 04077 *c++ = '\0'; 04078 *pass = c; 04079 } 04080 *domain = dom; 04081 } 04082 if (ret_name) /* same as for domain, store the result only at the end */ 04083 *ret_name = name; 04084 if (options) 04085 *options = uri ? uri : ""; 04086 04087 return error; 04088 }
static int peer_cmp_cb | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 1703 of file chan_sip.c.
References CMP_MATCH, CMP_STOP, and sip_peer::name.
01704 { 01705 struct sip_peer *peer = obj, *peer2 = arg; 01706 01707 return !strcasecmp(peer->name, peer2->name) ? CMP_MATCH | CMP_STOP : 0; 01708 }
static int peer_dump_func | ( | void * | userobj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 14061 of file chan_sip.c.
References ao2_t_ref, ast_cli(), and sip_peer::name.
Referenced by sip_show_objects().
14062 { 14063 struct sip_peer *peer = userobj; 14064 int refc = ao2_t_ref(userobj, 0, ""); 14065 int *fd = arg; 14066 14067 ast_cli(*fd, "name: %s\ntype: peer\nobjflags: %d\nrefcount: %d\n\n", 14068 peer->name, 0, refc); 14069 return 0; 14070 }
static int peer_hash_cb | ( | const void * | obj, | |
const int | flags | |||
) | [static] |
Definition at line 1693 of file chan_sip.c.
References ast_str_case_hash(), and sip_peer::name.
01694 { 01695 const struct sip_peer *peer = obj; 01696 01697 return ast_str_case_hash(peer->name); 01698 }
static int peer_ipcmp_cb | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Match Peers by IP and Port number.
This function has two modes.
This callback will be used twice when doing peer matching. There is a first pass for full IP+port matching, and a second pass in case there is a match that meets the insecure=port criteria.
the peer's addr struct provides to fields combined to make a key: the sin_addr.s_addr and sin_port fields.
Definition at line 1741 of file chan_sip.c.
References sip_peer::addr, ast_test_flag, CMP_MATCH, CMP_STOP, sip_peer::flags, SIP_INSECURE_PORT, SIP_TRANSPORT_TCP, SIP_TRANSPORT_TLS, and sip_peer::transports.
Referenced by load_module().
01742 { 01743 struct sip_peer *peer = obj, *peer2 = arg; 01744 01745 if (peer->addr.sin_addr.s_addr != peer2->addr.sin_addr.s_addr) { 01746 /* IP doesn't match */ 01747 return 0; 01748 } 01749 01750 /* We matched the IP, check to see if we need to match by port as well. */ 01751 if ((peer->transports & peer2->transports) & (SIP_TRANSPORT_TLS | SIP_TRANSPORT_TCP)) { 01752 /* peer matching on port is not possible with TCP/TLS */ 01753 return CMP_MATCH | CMP_STOP; 01754 } else if (ast_test_flag(&peer2->flags[0], SIP_INSECURE_PORT)) { 01755 /* We are allowing match without port for peers configured that 01756 * way in this pass through the peers. */ 01757 return ast_test_flag(&peer->flags[0], SIP_INSECURE_PORT) ? 01758 (CMP_MATCH | CMP_STOP) : 0; 01759 } 01760 01761 /* Now only return a match if the port matches, as well. */ 01762 return peer->addr.sin_port == peer2->addr.sin_port ? (CMP_MATCH | CMP_STOP) : 0; 01763 }
static int peer_iphash_cb | ( | const void * | obj, | |
const int | flags | |||
) | [static] |
Definition at line 1713 of file chan_sip.c.
References sip_peer::addr.
Referenced by load_module().
01714 { 01715 const struct sip_peer *peer = obj; 01716 int ret1 = peer->addr.sin_addr.s_addr; 01717 if (ret1 < 0) 01718 ret1 = -ret1; 01719 01720 return ret1; 01721 }
static int peer_is_marked | ( | void * | peerobj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 14251 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 14555 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().
14556 { 14557 struct sip_mailbox *mailbox; 14558 14559 AST_LIST_TRAVERSE(&peer->mailboxes, mailbox, entry) { 14560 ast_str_append(mailbox_str, 0, "%s%s%s%s", 14561 mailbox->mailbox, 14562 ast_strlen_zero(mailbox->context) ? "" : "@", 14563 S_OR(mailbox->context, ""), 14564 AST_LIST_NEXT(mailbox, entry) ? "," : ""); 14565 } 14566 }
static int peer_markall_func | ( | void * | device, | |
void * | arg, | |||
int | flags | |||
) | [static] |
static int peer_status | ( | struct sip_peer * | peer, | |
char * | status, | |||
int | statuslen | |||
) | [static] |
Definition at line 13639 of file chan_sip.c.
References ast_copy_string(), sip_peer::lastms, and sip_peer::maxms.
13640 { 13641 int res = 0; 13642 if (peer->maxms) { 13643 if (peer->lastms < 0) { 13644 ast_copy_string(status, "UNREACHABLE", statuslen); 13645 } else if (peer->lastms > peer->maxms) { 13646 snprintf(status, statuslen, "LAGGED (%d ms)", peer->lastms); 13647 res = 1; 13648 } else if (peer->lastms) { 13649 snprintf(status, statuslen, "OK (%d ms)", peer->lastms); 13650 res = 1; 13651 } else { 13652 ast_copy_string(status, "UNKNOWN", statuslen); 13653 } 13654 } else { 13655 ast_copy_string(status, "Unmonitored", statuslen); 13656 /* Checking if port is 0 */ 13657 res = -1; 13658 } 13659 return res; 13660 }
int peercomparefunc | ( | const void * | a, | |
const void * | b | |||
) |
Definition at line 13880 of file chan_sip.c.
Referenced by _sip_show_peers().
13881 { 13882 struct sip_peer **ap = (struct sip_peer **)a; 13883 struct sip_peer **bp = (struct sip_peer **)b; 13884 return strcmp((*ap)->name, (*bp)->name); 13885 }
static int port_str2int | ( | const char * | pt, | |
unsigned int | standard | |||
) | [static] |
converts ascii port to int representation. If no pt buffer is provided or the pt has errors when being converted to an int value, the port provided as the standard is used.
Definition at line 2933 of file chan_sip.c.
References ast_strlen_zero().
Referenced by __set_address_from_contact(), build_peer(), check_via(), create_addr(), parse_register_contact(), and proxy_allocate().
02934 { 02935 int port = standard; 02936 if (ast_strlen_zero(pt) || (sscanf(pt, "%30d", &port) != 1) || (port < 1) || (port > 65535)) { 02937 port = standard; 02938 } 02939 02940 return port; 02941 }
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 14387 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().
14388 { 14389 int x, codec; 14390 14391 for(x = 0; x < 32 ; x++) { 14392 codec = ast_codec_pref_index(pref, x); 14393 if (!codec) 14394 break; 14395 ast_cli(fd, "%s", ast_getformatname(codec)); 14396 ast_cli(fd, ":%d", pref->framing[x]); 14397 if (x < 31 && ast_codec_pref_index(pref, x + 1)) 14398 ast_cli(fd, ","); 14399 } 14400 if (!x) 14401 ast_cli(fd, "none"); 14402 }
static void print_group | ( | int | fd, | |
ast_group_t | group, | |||
int | crlf | |||
) | [static] |
Print call group and pickup group.
Definition at line 14111 of file chan_sip.c.
References ast_cli(), ast_print_group(), and buf.
Referenced by _sip_show_peer(), and sip_show_user().
14112 { 14113 char buf[256]; 14114 ast_cli(fd, crlf ? "%s\r\n" : "%s\n", ast_print_group(buf, sizeof(buf), group) ); 14115 }
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 21811 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().
21812 { 21813 int rtn; 21814 const char *p_hdrval; 21815 int minse; 21816 21817 p_hdrval = get_header(rsp, "Min-SE"); 21818 if (ast_strlen_zero(p_hdrval)) { 21819 ast_log(LOG_WARNING, "422 response without a Min-SE header %s\n", p_hdrval); 21820 return; 21821 } 21822 rtn = parse_minse(p_hdrval, &minse); 21823 if (rtn != 0) { 21824 ast_log(LOG_WARNING, "Parsing of Min-SE header failed %s\n", p_hdrval); 21825 return; 21826 } 21827 p->stimer->st_interval = minse; 21828 transmit_invite(p, SIP_INVITE, 1, 2); 21829 }
static int proc_session_timer | ( | const void * | vp | ) | [static] |
Session-Timers: Process session refresh timeout event.
Definition at line 21651 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, sip_st_dlg::quit_flag, 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().
21652 { 21653 struct sip_pvt *p = (struct sip_pvt *) vp; 21654 int sendreinv = FALSE; 21655 int res = 0; 21656 21657 if (!p->stimer) { 21658 ast_log(LOG_WARNING, "Null stimer in proc_session_timer - %s\n", p->callid); 21659 goto return_unref; 21660 } 21661 21662 ast_debug(2, "Session timer expired: %d - %s\n", p->stimer->st_schedid, p->callid); 21663 21664 if (!p->owner) { 21665 goto return_unref; 21666 } 21667 21668 if ((p->stimer->st_active != TRUE) || (p->owner->_state != AST_STATE_UP)) { 21669 goto return_unref; 21670 } 21671 21672 switch (p->stimer->st_ref) { 21673 case SESSION_TIMER_REFRESHER_UAC: 21674 if (p->outgoing_call == TRUE) { 21675 sendreinv = TRUE; 21676 } 21677 break; 21678 case SESSION_TIMER_REFRESHER_UAS: 21679 if (p->outgoing_call != TRUE) { 21680 sendreinv = TRUE; 21681 } 21682 break; 21683 default: 21684 ast_log(LOG_ERROR, "Unknown session refresher %d\n", p->stimer->st_ref); 21685 goto return_unref; 21686 } 21687 21688 if (sendreinv == TRUE) { 21689 res = 1; 21690 transmit_reinvite_with_sdp(p, FALSE, TRUE); 21691 } else { 21692 p->stimer->st_expirys++; 21693 if (p->stimer->st_expirys >= 2) { 21694 if (p->stimer->quit_flag) { 21695 goto return_unref; 21696 } 21697 ast_log(LOG_WARNING, "Session-Timer expired - %s\n", p->callid); 21698 sip_pvt_lock(p); 21699 while (p->owner && ast_channel_trylock(p->owner)) { 21700 sip_pvt_unlock(p); 21701 usleep(1); 21702 if (p->stimer && p->stimer->quit_flag) { 21703 goto return_unref; 21704 } 21705 sip_pvt_lock(p); 21706 } 21707 21708 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_DEV); 21709 ast_channel_unlock(p->owner); 21710 sip_pvt_unlock(p); 21711 } 21712 } 21713 21714 return_unref: 21715 if (!res) { 21716 /* An error occurred. Stop session timer processing */ 21717 if (p->stimer) { 21718 p->stimer->st_schedid = -1; 21719 stop_session_timer(p); 21720 } 21721 21722 /* If we are not asking to be rescheduled, then we need to release our 21723 * reference to the dialog. */ 21724 dialog_unref(p, "removing session timer ref"); 21725 } 21726 21727 return res; 21728 }
static void process_request_queue | ( | struct sip_pvt * | p, | |
int * | recount, | |||
int * | nounlock | |||
) | [static] |
Definition at line 20868 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().
20869 { 20870 struct sip_request *req; 20871 20872 while ((req = AST_LIST_REMOVE_HEAD(&p->request_queue, next))) { 20873 if (handle_incoming(p, req, &p->recv, recount, nounlock) == -1) { 20874 /* Request failed */ 20875 if (option_debug) { 20876 ast_log(LOG_DEBUG, "SIP message could not be handled, bad request: %-70.70s\n", p->callid[0] ? p->callid : "<no callid>"); 20877 } 20878 } 20879 ast_free(req); 20880 } 20881 }
static int process_sdp | ( | struct sip_pvt * | p, | |
struct sip_request * | req, | |||
int | t38action | |||
) | [static] |
Process SIP SDP offer, select formats and activate RTP channels If offer is rejected, we will not change any properties of the call Return 0 on success, a negative value on errors. Must be called after find_sdp().
< RTP Audio host IP
< RTP video host IP
< RTP text host IP
< UDPTL host ip
< RTP Audio port number
< RTP Video port number
< RTP Text port number
< UDPTL Image port number
< media socket address
< video socket address
< image socket address
< text socket address
Definition at line 7454 of file chan_sip.c.
References append_history, ast_clear_flag, ast_codec_choose(), AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, ast_copy_string(), ast_debug, AST_FORMAT_AUDIO_MASK, AST_FORMAT_T140RED, ast_getformatname_multiple(), ast_inet_ntoa(), ast_log(), ast_null_frame, ast_queue_control(), ast_queue_control_data(), ast_queue_frame(), ast_rtp_alloc_size(), AST_RTP_DTMF, ast_rtp_get_current_formats(), ast_rtp_get_peer(), ast_rtp_lookup_mime_multiple(), ast_rtp_new_init(), ast_rtp_pt_clear(), ast_rtp_pt_copy(), ast_rtp_set_m_type(), ast_rtp_set_peer(), ast_rtp_setdtmf(), ast_rtp_setdtmfcompensate(), ast_rtp_stop(), ast_set_flag, ast_set_read_format(), ast_set_write_format(), ast_skip_blanks(), ast_strlen_zero(), ast_test_flag, ast_threadstorage_get(), ast_udptl_get_far_max_datagram(), ast_udptl_set_far_max_datagram(), ast_udptl_set_peer(), ast_udptl_stop(), ast_verbose, buf, sip_pvt::callid, sip_pvt::capability, change_t38_state(), sip_request::data, sip_request::debug, EVENT_FLAG_CALL, FALSE, sip_pvt::flags, get_sdp_iterate(), get_sdp_line(), ast_hostent::hp, hp, sip_pvt::jointcapability, sip_pvt::jointnoncodeccapability, sip_pvt::lastinvite, sip_pvt::lastrtprx, sip_pvt::lastrtptx, LOG_DEBUG, LOG_ERROR, LOG_NOTICE, LOG_WARNING, manager_event, sip_pvt::mohsuggest, ast_channel::name, ast_channel::nativeformats, sip_request::next, sip_pvt::noncodeccapability, sip_pvt::notext, sip_pvt::novideo, offered_media::offered, sip_pvt::offered_media, option_debug, sip_pvt::owner, sip_pvt::peercapability, sip_pvt::prefs, process_sdp_a_audio(), process_sdp_a_image(), process_sdp_a_sendonly(), process_sdp_a_text(), process_sdp_a_video(), process_sdp_c(), process_sdp_o(), ast_channel::readformat, sip_pvt::red, sip_pvt::rtp, rtp_red_init(), S_OR, SDP_AUDIO, SDP_IMAGE, sip_request::sdp_start, SDP_T38_ACCEPT, SDP_T38_INITIATE, SDP_TEXT, SDP_VIDEO, sip_pvt::session_modify, sip_debug_test_pvt(), SIP_DTMF, SIP_DTMF_AUTO, SIP_DTMF_INBAND, SIP_DTMF_RFC2833, 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, sip_pvt::t38, T38_DISABLED, T38_ENABLED, T38_LOCAL_REINVITE, T38_PEER_REINVITE, text, t38properties::their_parms, sip_pvt::trtp, TRUE, sip_pvt::udptl, ast_channel::uniqueid, sip_pvt::vrtp, and ast_channel::writeformat.
07455 { 07456 /* Iterators for SDP parsing */ 07457 int start = req->sdp_start; 07458 int next = start; 07459 int iterator = start; 07460 07461 /* Temporary vars for SDP parsing */ 07462 char type = '\0'; 07463 const char *value = NULL; 07464 const char *m = NULL; /* SDP media offer */ 07465 const char *nextm = NULL; 07466 int len = -1; 07467 07468 /* Host information */ 07469 struct ast_hostent sessionhp; 07470 struct ast_hostent audiohp; 07471 struct ast_hostent videohp; 07472 struct ast_hostent texthp; 07473 struct ast_hostent imagehp; 07474 struct hostent *hp = NULL; /*!< RTP Audio host IP */ 07475 struct hostent *vhp = NULL; /*!< RTP video host IP */ 07476 struct hostent *thp = NULL; /*!< RTP text host IP */ 07477 struct hostent *ihp = NULL; /*!< UDPTL host ip */ 07478 int portno = -1; /*!< RTP Audio port number */ 07479 int vportno = -1; /*!< RTP Video port number */ 07480 int tportno = -1; /*!< RTP Text port number */ 07481 int udptlportno = -1; /*!< UDPTL Image port number */ 07482 struct sockaddr_in sin; /*!< media socket address */ 07483 struct sockaddr_in vsin; /*!< video socket address */ 07484 struct sockaddr_in isin; /*!< image socket address */ 07485 struct sockaddr_in tsin; /*!< text socket address */ 07486 07487 /* Peer capability is the capability in the SDP, non codec is RFC2833 DTMF (101) */ 07488 int peercapability = 0, peernoncodeccapability = 0; 07489 int vpeercapability = 0, vpeernoncodeccapability = 0; 07490 int tpeercapability = 0, tpeernoncodeccapability = 0; 07491 07492 struct ast_rtp *newaudiortp, *newvideortp, *newtextrtp; 07493 int newjointcapability; /* Negotiated capability */ 07494 int newpeercapability; 07495 int newnoncodeccapability; 07496 07497 const char *codecs; 07498 int codec; 07499 07500 /* Others */ 07501 int sendonly = -1; 07502 int vsendonly = -1; 07503 int numberofports; 07504 int numberofmediastreams = 0; 07505 int last_rtpmap_codec = 0; 07506 int red_data_pt[10]; /* For T.140 red */ 07507 int red_num_gen = 0; /* For T.140 red */ 07508 char red_fmtp[100] = "empty"; /* For T.140 red */ 07509 int debug = sip_debug_test_pvt(p); 07510 07511 /* START UNKNOWN */ 07512 char buf[SIPBUFSIZE]; 07513 /* END UNKNOWN */ 07514 07515 /* Initial check */ 07516 if (!p->rtp) { 07517 ast_log(LOG_ERROR, "Got SDP but have no RTP session allocated.\n"); 07518 return -1; 07519 } 07520 07521 /* Initialize the temporary RTP structures we use to evaluate the offer from the peer */ 07522 #ifdef LOW_MEMORY 07523 newaudiortp = ast_threadstorage_get(&ts_audio_rtp, ast_rtp_alloc_size()); 07524 #else 07525 newaudiortp = alloca(ast_rtp_alloc_size()); 07526 #endif 07527 memset(newaudiortp, 0, ast_rtp_alloc_size()); 07528 ast_rtp_new_init(newaudiortp); 07529 ast_rtp_pt_clear(newaudiortp); 07530 07531 #ifdef LOW_MEMORY 07532 newvideortp = ast_threadstorage_get(&ts_video_rtp, ast_rtp_alloc_size()); 07533 #else 07534 newvideortp = alloca(ast_rtp_alloc_size()); 07535 #endif 07536 memset(newvideortp, 0, ast_rtp_alloc_size()); 07537 ast_rtp_new_init(newvideortp); 07538 ast_rtp_pt_clear(newvideortp); 07539 07540 #ifdef LOW_MEMORY 07541 newtextrtp = ast_threadstorage_get(&ts_text_rtp, ast_rtp_alloc_size()); 07542 #else 07543 newtextrtp = alloca(ast_rtp_alloc_size()); 07544 #endif 07545 memset(newtextrtp, 0, ast_rtp_alloc_size()); 07546 ast_rtp_new_init(newtextrtp); 07547 ast_rtp_pt_clear(newtextrtp); 07548 07549 /* Update our last rtprx when we receive an SDP, too */ 07550 p->lastrtprx = p->lastrtptx = time(NULL); /* XXX why both ? */ 07551 07552 memset(p->offered_media, 0, sizeof(p->offered_media)); 07553 07554 07555 /* default: novideo and notext set */ 07556 p->novideo = TRUE; 07557 p->notext = TRUE; 07558 07559 if (p->vrtp) 07560 ast_rtp_pt_clear(newvideortp); /* Must be cleared in case no m=video line exists */ 07561 07562 if (p->trtp) 07563 ast_rtp_pt_clear(newtextrtp); /* Must be cleared in case no m=text line exists */ 07564 07565 /* Scan for the first media stream (m=) line to limit scanning of globals */ 07566 nextm = get_sdp_iterate(&next, req, "m"); 07567 if (ast_strlen_zero(nextm)) { 07568 ast_log(LOG_WARNING, "Insufficient information for SDP (m= not found)\n"); 07569 return -1; 07570 } 07571 07572 /* Scan session level SDP parameters (lines before first media stream) */ 07573 while ((type = get_sdp_line(&iterator, next - 1, req, &value)) != '\0') { 07574 int processed = FALSE; 07575 switch (type) { 07576 case 'o': 07577 /* If we end up receiving SDP that doesn't actually modify the session we don't want to treat this as a fatal 07578 * error. We just want to ignore the SDP and let the rest of the packet be handled as normal. 07579 */ 07580 if (!process_sdp_o(value, p)) 07581 return (p->session_modify == FALSE) ? 0 : -1; 07582 break; 07583 case 'c': 07584 if (process_sdp_c(value, &sessionhp)) { 07585 processed = TRUE; 07586 hp = &sessionhp.hp; 07587 vhp = hp; 07588 thp = hp; 07589 ihp = hp; 07590 } 07591 break; 07592 case 'a': 07593 if (process_sdp_a_sendonly(value, &sendonly)) { 07594 processed = TRUE; 07595 vsendonly = sendonly; 07596 } 07597 else if (process_sdp_a_audio(value, p, newaudiortp, &last_rtpmap_codec)) 07598 processed = TRUE; 07599 else if (process_sdp_a_video(value, p, newvideortp, &last_rtpmap_codec)) 07600 processed = TRUE; 07601 else if (process_sdp_a_text(value, p, newtextrtp, red_fmtp, &red_num_gen, red_data_pt, &last_rtpmap_codec)) 07602 processed = TRUE; 07603 else if (process_sdp_a_image(value, p)) 07604 processed = TRUE; 07605 break; 07606 } 07607 07608 if (option_debug > 2) 07609 ast_log(LOG_DEBUG, "Processing session-level SDP %c=%s... %s\n", type, value, (processed == TRUE)? "OK." : "UNSUPPORTED."); 07610 } 07611 07612 07613 07614 /* Scan media stream (m=) specific parameters loop */ 07615 while (!ast_strlen_zero(nextm)) { 07616 int audio = FALSE; 07617 int video = FALSE; 07618 int image = FALSE; 07619 int text = FALSE; 07620 int x; 07621 07622 numberofports = 1; 07623 len = -1; 07624 start = next; 07625 m = nextm; 07626 iterator = next; 07627 nextm = get_sdp_iterate(&next, req, "m"); 07628 07629 /* Search for audio media definition */ 07630 if ((sscanf(m, "audio %30u/%30u RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) || 07631 (sscanf(m, "audio %30u RTP/AVP %n", &x, &len) == 1 && len > 0)) { 07632 audio = TRUE; 07633 p->offered_media[SDP_AUDIO].offered = TRUE; 07634 numberofmediastreams++; 07635 portno = x; 07636 07637 /* Scan through the RTP payload types specified in a "m=" line: */ 07638 codecs = m + len; 07639 ast_copy_string(p->offered_media[SDP_AUDIO].text, codecs, sizeof(p->offered_media[SDP_AUDIO].text)); 07640 for (; !ast_strlen_zero(codecs); codecs = ast_skip_blanks(codecs + len)) { 07641 if (sscanf(codecs, "%30u%n", &codec, &len) != 1) { 07642 ast_log(LOG_WARNING, "Error in codec string '%s'\n", codecs); 07643 return -1; 07644 } 07645 if (debug) 07646 ast_verbose("Found RTP audio format %d\n", codec); 07647 07648 ast_rtp_set_m_type(newaudiortp, codec); 07649 } 07650 /* Search for video media definition */ 07651 } else if ((sscanf(m, "video %30u/%30u RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) || 07652 (sscanf(m, "video %30u RTP/AVP %n", &x, &len) == 1 && len >= 0)) { 07653 video = TRUE; 07654 p->novideo = FALSE; 07655 p->offered_media[SDP_VIDEO].offered = TRUE; 07656 numberofmediastreams++; 07657 vportno = x; 07658 07659 /* Scan through the RTP payload types specified in a "m=" line: */ 07660 codecs = m + len; 07661 ast_copy_string(p->offered_media[SDP_VIDEO].text, codecs, sizeof(p->offered_media[SDP_VIDEO].text)); 07662 for (; !ast_strlen_zero(codecs); codecs = ast_skip_blanks(codecs + len)) { 07663 if (sscanf(codecs, "%30u%n", &codec, &len) != 1) { 07664 ast_log(LOG_WARNING, "Error in codec string '%s'\n", codecs); 07665 return -1; 07666 } 07667 if (debug) 07668 ast_verbose("Found RTP video format %d\n", codec); 07669 ast_rtp_set_m_type(newvideortp, codec); 07670 } 07671 /* Search for text media definition */ 07672 } else if ((sscanf(m, "text %30u/%30u RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) || 07673 (sscanf(m, "text %30u RTP/AVP %n", &x, &len) == 1 && len > 0)) { 07674 text = TRUE; 07675 p->notext = FALSE; 07676 p->offered_media[SDP_TEXT].offered = TRUE; 07677 numberofmediastreams++; 07678 tportno = x; 07679 07680 /* Scan through the RTP payload types specified in a "m=" line: */ 07681 codecs = m + len; 07682 ast_copy_string(p->offered_media[SDP_TEXT].text, codecs, sizeof(p->offered_media[SDP_TEXT].text)); 07683 for (; !ast_strlen_zero(codecs); codecs = ast_skip_blanks(codecs + len)) { 07684 if (sscanf(codecs, "%30u%n", &codec, &len) != 1) { 07685 ast_log(LOG_WARNING, "Error in codec string '%s'\n", codecs); 07686 return -1; 07687 } 07688 if (debug) 07689 ast_verbose("Found RTP text format %d\n", codec); 07690 ast_rtp_set_m_type(newtextrtp, codec); 07691 } 07692 /* Search for image media definition */ 07693 } else if (p->udptl && ((sscanf(m, "image %30u udptl t38%n", &x, &len) == 1 && len > 0) || 07694 (sscanf(m, "image %30u UDPTL t38%n", &x, &len) == 1 && len > 0) )) { 07695 image = TRUE; 07696 if (debug) 07697 ast_verbose("Got T.38 offer in SDP in dialog %s\n", p->callid); 07698 p->offered_media[SDP_IMAGE].offered = TRUE; 07699 udptlportno = x; 07700 numberofmediastreams++; 07701 07702 if (p->t38.state != T38_ENABLED) { 07703 memset(&p->t38.their_parms, 0, sizeof(p->t38.their_parms)); 07704 } 07705 } else { 07706 ast_log(LOG_WARNING, "Unsupported SDP media type in offer: %s\n", m); 07707 continue; 07708 } 07709 07710 /* Check for number of ports */ 07711 if (numberofports > 1) 07712 ast_log(LOG_WARNING, "SDP offered %d ports for media, not supported by Asterisk. Will try anyway...\n", numberofports); 07713 07714 07715 07716 /* Media stream specific parameters */ 07717 while ((type = get_sdp_line(&iterator, next - 1, req, &value)) != '\0') { 07718 int processed = FALSE; 07719 07720 switch (type) { 07721 case 'c': 07722 if (audio) { 07723 if (process_sdp_c(value, &audiohp)) { 07724 processed = TRUE; 07725 hp = &audiohp.hp; 07726 } 07727 } else if (video) { 07728 if (process_sdp_c(value, &videohp)) { 07729 processed = TRUE; 07730 vhp = &videohp.hp; 07731 } 07732 } else if (text) { 07733 if (process_sdp_c(value, &texthp)) { 07734 processed = TRUE; 07735 thp = &texthp.hp; 07736 } 07737 } else if (image) { 07738 if (process_sdp_c(value, &imagehp)) { 07739 processed = TRUE; 07740 ihp = &imagehp.hp; 07741 } 07742 } 07743 break; 07744 case 'a': 07745 /* Audio specific scanning */ 07746 if (audio) { 07747 if (process_sdp_a_sendonly(value, &sendonly)) 07748 processed = TRUE; 07749 else if (process_sdp_a_audio(value, p, newaudiortp, &last_rtpmap_codec)) 07750 processed = TRUE; 07751 } 07752 /* Video specific scanning */ 07753 else if (video) { 07754 if (process_sdp_a_sendonly(value, &vsendonly)) 07755 processed = TRUE; 07756 else if (process_sdp_a_video(value, p, newvideortp, &last_rtpmap_codec)) 07757 processed = TRUE; 07758 } 07759 /* Text (T.140) specific scanning */ 07760 else if (text) { 07761 if (process_sdp_a_text(value, p, newtextrtp, red_fmtp, &red_num_gen, red_data_pt, &last_rtpmap_codec)) 07762 processed = TRUE; 07763 } 07764 /* Image (T.38 FAX) specific scanning */ 07765 else if (image) { 07766 if (process_sdp_a_image(value, p)) 07767 processed = TRUE; 07768 } 07769 break; 07770 } 07771 07772 if (option_debug > 2) 07773 ast_log(LOG_DEBUG, "Processing media-level (%s) SDP %c=%s... %s\n", 07774 (audio == TRUE)? "audio" : (video == TRUE)? "video" : "image", 07775 type, value, 07776 (processed == TRUE)? "OK." : "UNSUPPORTED."); 07777 } 07778 } 07779 07780 07781 /* Sanity checks */ 07782 if (!hp && !vhp && !thp && !ihp) { 07783 ast_log(LOG_WARNING, "Insufficient information in SDP (c=)...\n"); 07784 return -1; 07785 } 07786 07787 if (portno == -1 && vportno == -1 && udptlportno == -1 && tportno == -1) 07788 /* No acceptable offer found in SDP - we have no ports */ 07789 /* Do not change RTP or VRTP if this is a re-invite */ 07790 return -2; 07791 07792 if (numberofmediastreams > 3) 07793 /* We have too many fax, audio and/or video and/or text media streams, fail this offer */ 07794 return -3; 07795 07796 if (udptlportno == -1) { 07797 change_t38_state(p, T38_DISABLED); 07798 } 07799 07800 /* Now gather all of the codecs that we are asked for: */ 07801 ast_rtp_get_current_formats(newaudiortp, &peercapability, &peernoncodeccapability); 07802 ast_rtp_get_current_formats(newvideortp, &vpeercapability, &vpeernoncodeccapability); 07803 ast_rtp_get_current_formats(newtextrtp, &tpeercapability, &tpeernoncodeccapability); 07804 07805 newjointcapability = p->capability & (peercapability | vpeercapability | tpeercapability); 07806 newpeercapability = (peercapability | vpeercapability | tpeercapability); 07807 newnoncodeccapability = p->noncodeccapability & peernoncodeccapability; 07808 07809 07810 if (debug) { 07811 /* shame on whoever coded this.... */ 07812 char s1[SIPBUFSIZE], s2[SIPBUFSIZE], s3[SIPBUFSIZE], s4[SIPBUFSIZE], s5[SIPBUFSIZE]; 07813 07814 ast_verbose("Capabilities: us - %s, peer - audio=%s/video=%s/text=%s, combined - %s\n", 07815 ast_getformatname_multiple(s1, SIPBUFSIZE, p->capability), 07816 ast_getformatname_multiple(s2, SIPBUFSIZE, peercapability), 07817 ast_getformatname_multiple(s3, SIPBUFSIZE, vpeercapability), 07818 ast_getformatname_multiple(s4, SIPBUFSIZE, tpeercapability), 07819 ast_getformatname_multiple(s5, SIPBUFSIZE, newjointcapability)); 07820 07821 ast_verbose("Non-codec capabilities (dtmf): us - %s, peer - %s, combined - %s\n", 07822 ast_rtp_lookup_mime_multiple(s1, SIPBUFSIZE, p->noncodeccapability, 0, 0), 07823 ast_rtp_lookup_mime_multiple(s2, SIPBUFSIZE, peernoncodeccapability, 0, 0), 07824 ast_rtp_lookup_mime_multiple(s3, SIPBUFSIZE, newnoncodeccapability, 0, 0)); 07825 } 07826 if (!newjointcapability && (portno != -1)) { 07827 ast_log(LOG_NOTICE, "No compatible codecs, not accepting this offer!\n"); 07828 /* Do NOT Change current setting */ 07829 return -1; 07830 } 07831 07832 /* Setup audio address and port */ 07833 if (p->rtp) { 07834 if (portno > 0) { 07835 sin.sin_family = AF_INET; 07836 sin.sin_port = htons(portno); 07837 memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr)); 07838 ast_rtp_set_peer(p->rtp, &sin); 07839 if (debug) 07840 ast_verbose("Peer audio RTP is at port %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 07841 /* We are now ready to change the sip session and p->rtp and p->vrtp with the offered codecs, since 07842 they are acceptable */ 07843 p->jointcapability = newjointcapability; /* Our joint codec profile for this call */ 07844 p->peercapability = newpeercapability; /* The other sides capability in latest offer */ 07845 p->jointnoncodeccapability = newnoncodeccapability; /* DTMF capabilities */ 07846 07847 ast_rtp_pt_copy(p->rtp, newaudiortp); 07848 07849 if (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO) { 07850 ast_clear_flag(&p->flags[0], SIP_DTMF); 07851 if (newnoncodeccapability & AST_RTP_DTMF) { 07852 /* XXX Would it be reasonable to drop the DSP at this point? XXX */ 07853 ast_set_flag(&p->flags[0], SIP_DTMF_RFC2833); 07854 /* Since RFC2833 is now negotiated we need to change some properties of the RTP stream */ 07855 ast_rtp_setdtmf(p->rtp, 1); 07856 ast_rtp_setdtmfcompensate(p->rtp, ast_test_flag(&p->flags[1], SIP_PAGE2_RFC2833_COMPENSATE)); 07857 } else { 07858 ast_set_flag(&p->flags[0], SIP_DTMF_INBAND); 07859 } 07860 } 07861 } else if (udptlportno > 0) { 07862 if (debug) 07863 ast_verbose("Got T.38 Re-invite without audio. Keeping RTP active during T.38 session.\n"); 07864 } else { 07865 ast_rtp_stop(p->rtp); 07866 if (debug) 07867 ast_verbose("Peer doesn't provide audio\n"); 07868 } 07869 } 07870 07871 /* Setup video address and port */ 07872 if (p->vrtp) { 07873 if (vportno > 0) { 07874 vsin.sin_family = AF_INET; 07875 vsin.sin_port = htons(vportno); 07876 memcpy(&vsin.sin_addr, vhp->h_addr, sizeof(vsin.sin_addr)); 07877 ast_rtp_set_peer(p->vrtp, &vsin); 07878 if (debug) 07879 ast_verbose("Peer video RTP is at port %s:%d\n", ast_inet_ntoa(vsin.sin_addr), ntohs(vsin.sin_port)); 07880 ast_rtp_pt_copy(p->vrtp, newvideortp); 07881 } else { 07882 ast_rtp_stop(p->vrtp); 07883 if (debug) 07884 ast_verbose("Peer doesn't provide video\n"); 07885 } 07886 } 07887 07888 /* Setup text address and port */ 07889 if (p->trtp) { 07890 if (tportno > 0) { 07891 tsin.sin_family = AF_INET; 07892 tsin.sin_port = htons(tportno); 07893 memcpy(&tsin.sin_addr, thp->h_addr, sizeof(tsin.sin_addr)); 07894 ast_rtp_set_peer(p->trtp, &tsin); 07895 if (debug) 07896 ast_verbose("Peer T.140 RTP is at port %s:%d\n", ast_inet_ntoa(vsin.sin_addr), ntohs(vsin.sin_port)); 07897 if ((p->jointcapability & AST_FORMAT_T140RED)) { 07898 p->red = 1; 07899 rtp_red_init(p->trtp, 300, red_data_pt, 2); 07900 } else { 07901 p->red = 0; 07902 } 07903 ast_rtp_pt_copy(p->trtp, newtextrtp); 07904 } else { 07905 ast_rtp_stop(p->trtp); 07906 if (debug) 07907 ast_verbose("Peer doesn't provide T.140\n"); 07908 } 07909 } 07910 /* Setup image address and port */ 07911 if (p->udptl) { 07912 if (udptlportno > 0) { 07913 isin.sin_family = AF_INET; 07914 isin.sin_port = htons(udptlportno); 07915 if (ast_test_flag(&p->flags[0], SIP_NAT) && ast_test_flag(&p->flags[1], SIP_PAGE2_UDPTL_DESTINATION)) { 07916 struct sockaddr_in remote_address = { 0, }; 07917 ast_rtp_get_peer(p->rtp, &remote_address); 07918 if (remote_address.sin_addr.s_addr) { 07919 memcpy(&isin, &remote_address, sizeof(isin)); 07920 if (debug) { 07921 ast_log(LOG_DEBUG, "Peer T.38 UDPTL is set behind NAT and with destination, destination address now %s\n", ast_inet_ntoa(isin.sin_addr)); 07922 } 07923 } 07924 } else { 07925 memcpy(&isin.sin_addr, ihp->h_addr, sizeof(sin.sin_addr)); 07926 } 07927 ast_udptl_set_peer(p->udptl, &isin); 07928 if (debug) 07929 ast_debug(1,"Peer T.38 UDPTL is at port %s:%d\n", ast_inet_ntoa(isin.sin_addr), ntohs(isin.sin_port)); 07930 07931 /* verify the far max ifp can be calculated. this requires far max datagram to be set. */ 07932 if (!ast_udptl_get_far_max_datagram(p->udptl)) { 07933 /* setting to zero will force a default if none was provided by the SDP */ 07934 ast_udptl_set_far_max_datagram(p->udptl, 0); 07935 } 07936 07937 /* Remote party offers T38, we need to update state */ 07938 if ((t38action == SDP_T38_ACCEPT) && 07939 (p->t38.state == T38_LOCAL_REINVITE)) { 07940 change_t38_state(p, T38_ENABLED); 07941 } else if ((t38action == SDP_T38_INITIATE) && 07942 p->owner && p->lastinvite) { 07943 change_t38_state(p, T38_PEER_REINVITE); /* T38 Offered in re-invite from remote party */ 07944 } 07945 } else { 07946 ast_udptl_stop(p->udptl); 07947 if (debug) 07948 ast_debug(1, "Peer doesn't provide T.38 UDPTL\n"); 07949 } 07950 } 07951 07952 if ((portno == -1) && (p->t38.state != T38_DISABLED)) { 07953 ast_debug(3, "Have T.38 but no audio, accepting offer anyway\n"); 07954 return 0; 07955 } 07956 07957 /* Ok, we're going with this offer */ 07958 ast_debug(2, "We're settling with these formats: %s\n", ast_getformatname_multiple(buf, SIPBUFSIZE, p->jointcapability)); 07959 07960 if (!p->owner) /* There's no open channel owning us so we can return here. For a re-invite or so, we proceed */ 07961 return 0; 07962 07963 ast_debug(4, "We have an owner, now see if we need to change this call\n"); 07964 07965 if (!(p->owner->nativeformats & p->jointcapability) && (p->jointcapability & AST_FORMAT_AUDIO_MASK)) { 07966 if (debug) { 07967 char s1[SIPBUFSIZE], s2[SIPBUFSIZE]; 07968 ast_debug(1, "Oooh, we need to change our audio formats since our peer supports only %s and not %s\n", 07969 ast_getformatname_multiple(s1, SIPBUFSIZE, p->jointcapability), 07970 ast_getformatname_multiple(s2, SIPBUFSIZE, p->owner->nativeformats)); 07971 } 07972 p->owner->nativeformats = ast_codec_choose(&p->prefs, p->jointcapability, 1) | (p->capability & vpeercapability) | (p->capability & tpeercapability); 07973 ast_set_read_format(p->owner, p->owner->readformat); 07974 ast_set_write_format(p->owner, p->owner->writeformat); 07975 } 07976 07977 if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD) && sin.sin_addr.s_addr && (!sendonly || sendonly == -1)) { 07978 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 07979 /* Activate a re-invite */ 07980 ast_queue_frame(p->owner, &ast_null_frame); 07981 /* Queue Manager Unhold event */ 07982 append_history(p, "Unhold", "%s", req->data->str); 07983 if (global_callevents) 07984 manager_event(EVENT_FLAG_CALL, "Hold", 07985 "Status: Off\r\n" 07986 "Channel: %s\r\n" 07987 "Uniqueid: %s\r\n", 07988 p->owner->name, 07989 p->owner->uniqueid); 07990 if (global_notifyhold) 07991 sip_peer_hold(p, FALSE); 07992 ast_clear_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD); /* Clear both flags */ 07993 } else if (!sin.sin_addr.s_addr || (sendonly && sendonly != -1)) { 07994 int already_on_hold = ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD); 07995 ast_queue_control_data(p->owner, AST_CONTROL_HOLD, 07996 S_OR(p->mohsuggest, NULL), 07997 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 07998 if (sendonly) 07999 ast_rtp_stop(p->rtp); 08000 /* RTCP needs to go ahead, even if we're on hold!!! */ 08001 /* Activate a re-invite */ 08002 ast_queue_frame(p->owner, &ast_null_frame); 08003 /* Queue Manager Hold event */ 08004 append_history(p, "Hold", "%s", req->data->str); 08005 if (global_callevents && !ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD)) { 08006 manager_event(EVENT_FLAG_CALL, "Hold", 08007 "Status: On\r\n" 08008 "Channel: %s\r\n" 08009 "Uniqueid: %s\r\n", 08010 p->owner->name, 08011 p->owner->uniqueid); 08012 } 08013 if (sendonly == 1) /* One directional hold (sendonly/recvonly) */ 08014 ast_set_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD_ONEDIR); 08015 else if (sendonly == 2) /* Inactive stream */ 08016 ast_set_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD_INACTIVE); 08017 else 08018 ast_set_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD_ACTIVE); 08019 if (global_notifyhold && !already_on_hold) 08020 sip_peer_hold(p, TRUE); 08021 } 08022 08023 return 0; 08024 }
static int process_sdp_a_audio | ( | const char * | a, | |
struct sip_pvt * | p, | |||
struct ast_rtp * | newaudiortp, | |||
int * | last_rtpmap_codec | |||
) | [static] |
Definition at line 8144 of file chan_sip.c.
References ast_codec_pref_setsize(), ast_debug, ast_log(), ast_rtp_codec_getformat(), ast_rtp_codec_getpref(), ast_rtp_codec_setpref(), AST_RTP_OPT_G726_NONSTANDARD, ast_rtp_set_rtpmap_type(), ast_rtp_unset_m_type(), ast_test_flag, ast_verbose, sip_pvt::autoframing, sip_request::debug, FALSE, sip_pvt::flags, format, LOG_DEBUG, MAX_RTP_PT, option_debug, sip_pvt::rtp, SDP_MAX_RTPMAP_CODECS, sip_debug_test_pvt(), SIP_G726_NONSTANDARD, and TRUE.
Referenced by process_sdp().
08145 { 08146 int found = FALSE; 08147 int codec; 08148 char mimeSubtype[128]; 08149 int debug = sip_debug_test_pvt(p); 08150 08151 if (!strncasecmp(a, "ptime", 5)) { 08152 char *tmp = strrchr(a, ':'); 08153 long int framing = 0; 08154 if (tmp) { 08155 tmp++; 08156 framing = strtol(tmp, NULL, 10); 08157 if (framing == LONG_MIN || framing == LONG_MAX) { 08158 framing = 0; 08159 ast_debug(1, "Can't read framing from SDP: %s\n", a); 08160 } 08161 } 08162 if (framing && p->autoframing) { 08163 struct ast_codec_pref *pref = ast_rtp_codec_getpref(p->rtp); 08164 int codec_n; 08165 int format = 0; 08166 for (codec_n = 0; codec_n < MAX_RTP_PT; codec_n++) { 08167 format = ast_rtp_codec_getformat(codec_n); 08168 if (!format) /* non-codec or not found */ 08169 continue; 08170 if (option_debug) 08171 ast_log(LOG_DEBUG, "Setting framing for %d to %ld\n", format, framing); 08172 ast_codec_pref_setsize(pref, format, framing); 08173 } 08174 ast_rtp_codec_setpref(p->rtp, pref); 08175 } 08176 found = TRUE; 08177 } else if (sscanf(a, "rtpmap: %30u %127[^/]/", &codec, mimeSubtype) == 2) { 08178 /* We have a rtpmap to handle */ 08179 if (*last_rtpmap_codec < SDP_MAX_RTPMAP_CODECS) { 08180 if (ast_rtp_set_rtpmap_type(newaudiortp, codec, "audio", mimeSubtype, 08181 ast_test_flag(&p->flags[0], SIP_G726_NONSTANDARD) ? AST_RTP_OPT_G726_NONSTANDARD : 0) != -1) { 08182 if (debug) 08183 ast_verbose("Found audio description format %s for ID %d\n", mimeSubtype, codec); 08184 //found_rtpmap_codecs[last_rtpmap_codec] = codec; 08185 (*last_rtpmap_codec)++; 08186 found = TRUE; 08187 } else { 08188 ast_rtp_unset_m_type(newaudiortp, codec); 08189 if (debug) 08190 ast_verbose("Found unknown media description format %s for ID %d\n", mimeSubtype, codec); 08191 } 08192 } else { 08193 if (debug) 08194 ast_verbose("Discarded description format %s for ID %d\n", mimeSubtype, codec); 08195 } 08196 } 08197 08198 return found; 08199 }
static int process_sdp_a_image | ( | const char * | a, | |
struct sip_pvt * | p | |||
) | [static] |
Definition at line 8282 of file chan_sip.c.
References ast_debug, AST_T38_RATE_12000, AST_T38_RATE_14400, AST_T38_RATE_2400, AST_T38_RATE_4800, AST_T38_RATE_7200, AST_T38_RATE_9600, AST_T38_RATE_MANAGEMENT_LOCAL_TCF, AST_T38_RATE_MANAGEMENT_TRANSFERRED_TCF, ast_udptl_set_error_correction_scheme(), ast_udptl_set_far_max_datagram(), FALSE, ast_control_t38_parameters::fill_bit_removal, ast_control_t38_parameters::rate, ast_control_t38_parameters::rate_management, s, sip_pvt::t38, sip_pvt::t38_maxdatagram, t38properties::their_parms, ast_control_t38_parameters::transcoding_jbig, ast_control_t38_parameters::transcoding_mmr, TRUE, sip_pvt::udptl, UDPTL_ERROR_CORRECTION_FEC, UDPTL_ERROR_CORRECTION_NONE, UDPTL_ERROR_CORRECTION_REDUNDANCY, and ast_control_t38_parameters::version.
Referenced by process_sdp().
08283 { 08284 int found = FALSE; 08285 char s[256]; 08286 unsigned int x; 08287 08288 if ((sscanf(a, "T38FaxMaxBuffer:%30u", &x) == 1)) { 08289 ast_debug(3, "MaxBufferSize:%d\n", x); 08290 found = TRUE; 08291 } else if ((sscanf(a, "T38MaxBitRate:%30u", &x) == 1) || (sscanf(a, "T38FaxMaxRate:%30u", &x) == 1)) { 08292 ast_debug(3, "T38MaxBitRate: %d\n", x); 08293 switch (x) { 08294 case 14400: 08295 p->t38.their_parms.rate = AST_T38_RATE_14400; 08296 break; 08297 case 12000: 08298 p->t38.their_parms.rate = AST_T38_RATE_12000; 08299 break; 08300 case 9600: 08301 p->t38.their_parms.rate = AST_T38_RATE_9600; 08302 break; 08303 case 7200: 08304 p->t38.their_parms.rate = AST_T38_RATE_7200; 08305 break; 08306 case 4800: 08307 p->t38.their_parms.rate = AST_T38_RATE_4800; 08308 break; 08309 case 2400: 08310 p->t38.their_parms.rate = AST_T38_RATE_2400; 08311 break; 08312 } 08313 found = TRUE; 08314 } else if ((sscanf(a, "T38FaxVersion:%30u", &x) == 1)) { 08315 ast_debug(3, "FaxVersion: %u\n", x); 08316 p->t38.their_parms.version = x; 08317 found = TRUE; 08318 } else if ((sscanf(a, "T38FaxMaxDatagram:%30u", &x) == 1) || (sscanf(a, "T38MaxDatagram:%30u", &x) == 1)) { 08319 /* override the supplied value if the configuration requests it */ 08320 if (((signed int) p->t38_maxdatagram >= 0) && ((unsigned int) p->t38_maxdatagram > x)) { 08321 ast_debug(1, "Overriding T38FaxMaxDatagram '%d' with '%d'\n", x, p->t38_maxdatagram); 08322 x = p->t38_maxdatagram; 08323 } 08324 ast_debug(3, "FaxMaxDatagram: %u\n", x); 08325 ast_udptl_set_far_max_datagram(p->udptl, x); 08326 found = TRUE; 08327 } else if ((strncmp(a, "T38FaxFillBitRemoval", 20) == 0)) { 08328 if (sscanf(a, "T38FaxFillBitRemoval:%30u", &x) == 1) { 08329 ast_debug(3, "FillBitRemoval: %d\n", x); 08330 if (x == 1) { 08331 p->t38.their_parms.fill_bit_removal = TRUE; 08332 } 08333 } else { 08334 ast_debug(3, "FillBitRemoval\n"); 08335 p->t38.their_parms.fill_bit_removal = TRUE; 08336 } 08337 found = TRUE; 08338 } else if ((strncmp(a, "T38FaxTranscodingMMR", 20) == 0)) { 08339 if (sscanf(a, "T38FaxTranscodingMMR:%30u", &x) == 1) { 08340 ast_debug(3, "Transcoding MMR: %d\n", x); 08341 if (x == 1) { 08342 p->t38.their_parms.transcoding_mmr = TRUE; 08343 } 08344 } else { 08345 ast_debug(3, "Transcoding MMR\n"); 08346 p->t38.their_parms.transcoding_mmr = TRUE; 08347 } 08348 found = TRUE; 08349 } else if ((strncmp(a, "T38FaxTranscodingJBIG", 21) == 0)) { 08350 if (sscanf(a, "T38FaxTranscodingJBIG:%30u", &x) == 1) { 08351 ast_debug(3, "Transcoding JBIG: %d\n", x); 08352 if (x == 1) { 08353 p->t38.their_parms.transcoding_jbig = TRUE; 08354 } 08355 } else { 08356 ast_debug(3, "Transcoding JBIG\n"); 08357 p->t38.their_parms.transcoding_jbig = TRUE; 08358 } 08359 found = TRUE; 08360 } else if ((sscanf(a, "T38FaxRateManagement:%255s", s) == 1)) { 08361 ast_debug(3, "RateManagement: %s\n", s); 08362 if (!strcasecmp(s, "localTCF")) 08363 p->t38.their_parms.rate_management = AST_T38_RATE_MANAGEMENT_LOCAL_TCF; 08364 else if (!strcasecmp(s, "transferredTCF")) 08365 p->t38.their_parms.rate_management = AST_T38_RATE_MANAGEMENT_TRANSFERRED_TCF; 08366 found = TRUE; 08367 } else if ((sscanf(a, "T38FaxUdpEC:%255s", s) == 1)) { 08368 ast_debug(3, "UDP EC: %s\n", s); 08369 if (!strcasecmp(s, "t38UDPRedundancy")) { 08370 ast_udptl_set_error_correction_scheme(p->udptl, UDPTL_ERROR_CORRECTION_REDUNDANCY); 08371 } else if (!strcasecmp(s, "t38UDPFEC")) { 08372 ast_udptl_set_error_correction_scheme(p->udptl, UDPTL_ERROR_CORRECTION_FEC); 08373 } else { 08374 ast_udptl_set_error_correction_scheme(p->udptl, UDPTL_ERROR_CORRECTION_NONE); 08375 } 08376 found = TRUE; 08377 } 08378 08379 return found; 08380 }
static int process_sdp_a_sendonly | ( | const char * | a, | |
int * | sendonly | |||
) | [static] |
Definition at line 8124 of file chan_sip.c.
Referenced by process_sdp().
08125 { 08126 int found = FALSE; 08127 08128 if (!strcasecmp(a, "sendonly")) { 08129 if (*sendonly == -1) 08130 *sendonly = 1; 08131 found = TRUE; 08132 } else if (!strcasecmp(a, "inactive")) { 08133 if (*sendonly == -1) 08134 *sendonly = 2; 08135 found = TRUE; 08136 } else if (!strcasecmp(a, "sendrecv")) { 08137 if (*sendonly == -1) 08138 *sendonly = 0; 08139 found = TRUE; 08140 } 08141 return found; 08142 }
static int process_sdp_a_text | ( | const char * | a, | |
struct sip_pvt * | p, | |||
struct ast_rtp * | newtextrtp, | |||
char * | red_fmtp, | |||
int * | red_num_gen, | |||
int * | red_data_pt, | |||
int * | last_rtpmap_codec | |||
) | [static] |
Definition at line 8234 of file chan_sip.c.
References ast_rtp_set_rtpmap_type(), ast_verbose, sip_request::debug, FALSE, RED_MAX_GENERATION, SDP_MAX_RTPMAP_CODECS, sip_debug_test_pvt(), sip_pvt::trtp, and TRUE.
Referenced by process_sdp().
08235 { 08236 int found = FALSE; 08237 int codec; 08238 char mimeSubtype[128]; 08239 char *red_cp; 08240 int debug = sip_debug_test_pvt(p); 08241 08242 if (sscanf(a, "rtpmap: %30u %127[^/]/", &codec, mimeSubtype) == 2) { 08243 /* We have a rtpmap to handle */ 08244 if (*last_rtpmap_codec < SDP_MAX_RTPMAP_CODECS) { 08245 if (!strncasecmp(mimeSubtype, "T140", 4)) { /* Text */ 08246 if (p->trtp) { 08247 /* ast_verbose("Adding t140 mimeSubtype to textrtp struct\n"); */ 08248 ast_rtp_set_rtpmap_type(newtextrtp, codec, "text", mimeSubtype, 0); 08249 found = TRUE; 08250 } 08251 } else if (!strncasecmp(mimeSubtype, "RED", 3)) { /* Text with Redudancy */ 08252 if (p->trtp) { 08253 ast_rtp_set_rtpmap_type(newtextrtp, codec, "text", mimeSubtype, 0); 08254 sprintf(red_fmtp, "fmtp:%d ", codec); 08255 if (debug) 08256 ast_verbose("RED submimetype has payload type: %d\n", codec); 08257 found = TRUE; 08258 } 08259 } 08260 } else { 08261 if (debug) 08262 ast_verbose("Discarded description format %s for ID %d\n", mimeSubtype, codec); 08263 } 08264 } else if (!strncmp(a, red_fmtp, strlen(red_fmtp))) { 08265 /* count numbers of generations in fmtp */ 08266 red_cp = &red_fmtp[strlen(red_fmtp)]; 08267 strncpy(red_fmtp, a, 100); 08268 08269 sscanf(red_cp, "%30u", &red_data_pt[*red_num_gen]); 08270 red_cp = strtok(red_cp, "/"); 08271 while (red_cp && (*red_num_gen)++ < RED_MAX_GENERATION) { 08272 sscanf(red_cp, "%30u", &red_data_pt[*red_num_gen]); 08273 red_cp = strtok(NULL, "/"); 08274 } 08275 red_cp = red_fmtp; 08276 found = TRUE; 08277 } 08278 08279 return found; 08280 }
static int process_sdp_a_video | ( | const char * | a, | |
struct sip_pvt * | p, | |||
struct ast_rtp * | newvideortp, | |||
int * | last_rtpmap_codec | |||
) | [static] |
Definition at line 8201 of file chan_sip.c.
References ast_rtp_set_rtpmap_type(), ast_rtp_unset_m_type(), ast_verbose, sip_request::debug, FALSE, SDP_MAX_RTPMAP_CODECS, sip_debug_test_pvt(), and TRUE.
Referenced by process_sdp().
08202 { 08203 int found = FALSE; 08204 int codec; 08205 char mimeSubtype[128]; 08206 int debug = sip_debug_test_pvt(p); 08207 08208 if (sscanf(a, "rtpmap: %30u %127[^/]/", &codec, mimeSubtype) == 2) { 08209 /* We have a rtpmap to handle */ 08210 if (*last_rtpmap_codec < SDP_MAX_RTPMAP_CODECS) { 08211 /* Note: should really look at the '#chans' params too */ 08212 if (!strncasecmp(mimeSubtype, "H26", 3) || !strncasecmp(mimeSubtype, "MP4", 3)) { 08213 if (ast_rtp_set_rtpmap_type(newvideortp, codec, "video", mimeSubtype, 0) != -1) { 08214 if (debug) 08215 ast_verbose("Found video description format %s for ID %d\n", mimeSubtype, codec); 08216 //found_rtpmap_codecs[last_rtpmap_codec] = codec; 08217 (*last_rtpmap_codec)++; 08218 found = TRUE; 08219 } else { 08220 ast_rtp_unset_m_type(newvideortp, codec); 08221 if (debug) 08222 ast_verbose("Found unknown media description format %s for ID %d\n", mimeSubtype, codec); 08223 } 08224 } 08225 } else { 08226 if (debug) 08227 ast_verbose("Discarded description format %s for ID %d\n", mimeSubtype, codec); 08228 } 08229 } 08230 08231 return found; 08232 }
static int process_sdp_c | ( | const char * | c, | |
struct ast_hostent * | hp | |||
) | [static] |
Definition at line 8105 of file chan_sip.c.
References ast_gethostbyname(), ast_log(), FALSE, hp, LOG_WARNING, and TRUE.
Referenced by process_sdp().
08106 { 08107 char host[258]; 08108 struct hostent *hp; 08109 08110 /* Check for Media-description-level-address */ 08111 if (sscanf(c, "IN IP4 %255s", host) != 1) { 08112 ast_log(LOG_WARNING, "Invalid host in c= line, '%s'\n", c); 08113 return FALSE; 08114 } else { 08115 if (!(hp = ast_gethostbyname(host, ast_hp))) { 08116 ast_log(LOG_WARNING, "Unable to lookup RTP Audio host in c= line, '%s'\n", c); 08117 return FALSE; 08118 } 08119 return TRUE; 08120 } 08121 return FALSE; 08122 }
static int process_sdp_o | ( | const char * | o, | |
struct sip_pvt * | p | |||
) | [static] |
Definition at line 8026 of file chan_sip.c.
References ast_debug, ast_log(), ast_strdupa, ast_strlen_zero(), ast_test_flag, sip_pvt::callid, FALSE, sip_pvt::flags, LOG_WARNING, sip_pvt::session_modify, sip_pvt::sessionversion_remote, SIP_PAGE2_IGNORESDPVERSION, t38properties::state, strsep(), sip_pvt::t38, T38_LOCAL_REINVITE, and TRUE.
Referenced by process_sdp().
08027 { 08028 char *o_copy; 08029 char *token; 08030 int64_t rua_version; 08031 08032 /* Store the SDP version number of remote UA. This will allow us to 08033 distinguish between session modifications and session refreshes. If 08034 the remote UA does not send an incremented SDP version number in a 08035 subsequent RE-INVITE then that means its not changing media session. 08036 The RE-INVITE may have been sent to update connected party, remote 08037 target or to refresh the session (Session-Timers). Asterisk must not 08038 change media session and increment its own version number in answer 08039 SDP in this case. */ 08040 08041 p->session_modify = TRUE; 08042 08043 if (ast_strlen_zero(o)) { 08044 ast_log(LOG_WARNING, "SDP syntax error. SDP without an o= line\n"); 08045 return FALSE; 08046 } 08047 08048 o_copy = ast_strdupa(o); 08049 token = strsep(&o_copy, " "); /* Skip username */ 08050 if (!o_copy) { 08051 ast_log(LOG_WARNING, "SDP syntax error in o= line username\n"); 08052 return FALSE; 08053 } 08054 token = strsep(&o_copy, " "); /* Skip session-id */ 08055 if (!o_copy) { 08056 ast_log(LOG_WARNING, "SDP syntax error in o= line session-id\n"); 08057 return FALSE; 08058 } 08059 token = strsep(&o_copy, " "); /* Version */ 08060 if (!o_copy) { 08061 ast_log(LOG_WARNING, "SDP syntax error in o= line\n"); 08062 return FALSE; 08063 } 08064 if (!sscanf(token, "%30" SCNd64, &rua_version)) { 08065 ast_log(LOG_WARNING, "SDP syntax error in o= line version\n"); 08066 return FALSE; 08067 } 08068 08069 /* we need to check the SDP version number the other end sent us; 08070 * our rules for deciding what to accept are a bit complex. 08071 * 08072 * 1) if 'ignoresdpversion' has been set for this dialog, then 08073 * we will just accept whatever they sent and assume it is 08074 * a modification of the session, even if it is not 08075 * 2) otherwise, if this is the first SDP we've seen from them 08076 * we accept it 08077 * 3) otherwise, if the new SDP version number is higher than the 08078 * old one, we accept it 08079 * 4) otherwise, if this SDP is in response to us requesting a switch 08080 * to T.38, we accept the SDP, but also generate a warning message 08081 * that this peer should have the 'ignoresdpversion' option set, 08082 * because it is not following the SDP offer/answer RFC; if we did 08083 * not request a switch to T.38, then we stop parsing the SDP, as it 08084 * has not changed from the previous version 08085 */ 08086 08087 if (ast_test_flag(&p->flags[1], SIP_PAGE2_IGNORESDPVERSION) || 08088 (p->sessionversion_remote < 0) || 08089 (p->sessionversion_remote < rua_version)) { 08090 p->sessionversion_remote = rua_version; 08091 } else { 08092 if (p->t38.state == T38_LOCAL_REINVITE) { 08093 p->sessionversion_remote = rua_version; 08094 ast_log(LOG_WARNING, "Call %s responded to our T.38 reinvite without changing SDP version; 'ignoresdpversion' should be set for this peer.\n", p->callid); 08095 } else { 08096 p->session_modify = FALSE; 08097 ast_debug(2, "Call %s responded to our reinvite without changing SDP version; ignoring SDP.\n", p->callid); 08098 return FALSE; 08099 } 08100 } 08101 08102 return TRUE; 08103 }
static struct sip_proxy* proxy_allocate | ( | char * | name, | |
char * | port, | |||
int | force | |||
) | [static] |
Allocate and initialize sip proxy.
Definition at line 2944 of file chan_sip.c.
References ao2_alloc, ast_copy_string(), ast_strlen_zero(), port_str2int(), proxy_update(), and STANDARD_SIP_PORT.
Referenced by build_peer().
02945 { 02946 struct sip_proxy *proxy; 02947 02948 if (ast_strlen_zero(name)) { 02949 return NULL; 02950 } 02951 02952 proxy = ao2_alloc(sizeof(*proxy), NULL); 02953 if (!proxy) 02954 return NULL; 02955 proxy->force = force; 02956 ast_copy_string(proxy->name, name, sizeof(proxy->name)); 02957 proxy->ip.sin_port = htons(port_str2int(port, STANDARD_SIP_PORT)); 02958 proxy_update(proxy); 02959 return proxy; 02960 }
static int proxy_update | ( | struct sip_proxy * | proxy | ) | [static] |
Resolve DNS srv name or host name in a sip_proxy structure
Definition at line 2913 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().
02914 { 02915 /* if it's actually an IP address and not a name, 02916 there's no need for a managed lookup */ 02917 if (!inet_aton(proxy->name, &proxy->ip.sin_addr)) { 02918 /* Ok, not an IP address, then let's check if it's a domain or host */ 02919 /* XXX Todo - if we have proxy port, don't do SRV */ 02920 if (ast_get_ip_or_srv(&proxy->ip, proxy->name, global_srvlookup ? "_sip._udp" : NULL) < 0) { 02921 ast_log(LOG_WARNING, "Unable to locate host '%s'\n", proxy->name); 02922 return FALSE; 02923 } 02924 } 02925 proxy->last_dnsupdate = time(NULL); 02926 return TRUE; 02927 }
static int queue_request | ( | struct sip_pvt * | p, | |
const struct sip_request * | req | |||
) | [static] |
Definition at line 20938 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().
20939 { 20940 struct sip_request *newreq; 20941 20942 if (!(newreq = ast_calloc(1, sizeof(*newreq)))) { 20943 return -1; 20944 } 20945 20946 copy_request(newreq, req); 20947 AST_LIST_INSERT_TAIL(&p->request_queue, newreq, next); 20948 if (p->request_queue_sched_id == -1) { 20949 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) { 20950 dialog_unref(p, "Decrement refcount due to sched_add failure"); 20951 } 20952 } 20953 20954 return 0; 20955 }
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 4352 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.
04353 { 04354 struct sip_peer *peer; 04355 struct ast_variable *var = NULL; 04356 struct ast_variable *varregs = NULL; 04357 struct ast_variable *tmp; 04358 struct ast_config *peerlist = NULL; 04359 char ipaddr[INET_ADDRSTRLEN]; 04360 char portstring[6]; /*up to 5 digits plus null terminator*/ 04361 char *cat = NULL; 04362 unsigned short portnum; 04363 int realtimeregs = ast_check_realtime("sipregs"); 04364 04365 /* First check on peer name */ 04366 if (newpeername) { 04367 if (realtimeregs) 04368 varregs = ast_load_realtime("sipregs", "name", newpeername, SENTINEL); 04369 04370 var = ast_load_realtime("sippeers", "name", newpeername, "host", "dynamic", SENTINEL); 04371 if (!var && sin) 04372 var = ast_load_realtime("sippeers", "name", newpeername, "host", ast_inet_ntoa(sin->sin_addr), SENTINEL); 04373 if (!var) { 04374 var = ast_load_realtime("sippeers", "name", newpeername, SENTINEL); 04375 /*!\note 04376 * If this one loaded something, then we need to ensure that the host 04377 * field matched. The only reason why we can't have this as a criteria 04378 * is because we only have the IP address and the host field might be 04379 * set as a name (and the reverse PTR might not match). 04380 */ 04381 if (var && sin) { 04382 for (tmp = var; tmp; tmp = tmp->next) { 04383 if (!strcasecmp(tmp->name, "host")) { 04384 struct hostent *hp; 04385 struct ast_hostent ahp; 04386 if (!(hp = ast_gethostbyname(tmp->value, &ahp)) || (memcmp(hp->h_addr, &sin->sin_addr, sizeof(hp->h_addr)))) { 04387 /* No match */ 04388 ast_variables_destroy(var); 04389 var = NULL; 04390 } 04391 break; 04392 } 04393 } 04394 } 04395 } 04396 } 04397 04398 if (!var && sin) { /* Then check on IP address for dynamic peers */ 04399 ast_copy_string(ipaddr, ast_inet_ntoa(sin->sin_addr), sizeof(ipaddr)); 04400 portnum = ntohs(sin->sin_port); 04401 sprintf(portstring, "%u", portnum); 04402 var = ast_load_realtime("sippeers", "host", ipaddr, "port", portstring, SENTINEL); /* First check for fixed IP hosts */ 04403 if (var) { 04404 if (realtimeregs) { 04405 newpeername = get_name_from_variable(var, newpeername); 04406 varregs = ast_load_realtime("sipregs", "name", newpeername, SENTINEL); 04407 } 04408 } else { 04409 if (realtimeregs) 04410 varregs = ast_load_realtime("sipregs", "ipaddr", ipaddr, "port", portstring, SENTINEL); /* Then check for registered hosts */ 04411 else 04412 var = ast_load_realtime("sippeers", "ipaddr", ipaddr, "port", portstring, SENTINEL); /* Then check for registered hosts */ 04413 if (varregs) { 04414 newpeername = get_name_from_variable(varregs, newpeername); 04415 var = ast_load_realtime("sippeers", "name", newpeername, SENTINEL); 04416 } 04417 } 04418 if (!var) { /*We couldn't match on ipaddress and port, so we need to check if port is insecure*/ 04419 peerlist = ast_load_realtime_multientry("sippeers", "host", ipaddr, SENTINEL); 04420 if (peerlist) { 04421 var = get_insecure_variable_from_config(peerlist); 04422 if(var) { 04423 if (realtimeregs) { 04424 newpeername = get_name_from_variable(var, newpeername); 04425 varregs = ast_load_realtime("sipregs", "name", newpeername, SENTINEL); 04426 } 04427 } else { /*var wasn't found in the list of "hosts", so try "ipaddr"*/ 04428 peerlist = NULL; 04429 cat = NULL; 04430 peerlist = ast_load_realtime_multientry("sippeers", "ipaddr", ipaddr, SENTINEL); 04431 if(peerlist) { 04432 var = get_insecure_variable_from_config(peerlist); 04433 if(var) { 04434 if (realtimeregs) { 04435 newpeername = get_name_from_variable(var, newpeername); 04436 varregs = ast_load_realtime("sipregs", "name", newpeername, SENTINEL); 04437 } 04438 } 04439 } 04440 } 04441 } else { 04442 if (realtimeregs) { 04443 peerlist = ast_load_realtime_multientry("sipregs", "ipaddr", ipaddr, SENTINEL); 04444 if (peerlist) { 04445 varregs = get_insecure_variable_from_config(peerlist); 04446 if (varregs) { 04447 newpeername = get_name_from_variable(varregs, newpeername); 04448 var = ast_load_realtime("sippeers", "name", newpeername, SENTINEL); 04449 } 04450 } 04451 } else { 04452 peerlist = ast_load_realtime_multientry("sippeers", "ipaddr", ipaddr, SENTINEL); 04453 if (peerlist) { 04454 var = get_insecure_variable_from_config(peerlist); 04455 if (var) { 04456 newpeername = get_name_from_variable(var, newpeername); 04457 varregs = ast_load_realtime("sipregs", "name", newpeername, SENTINEL); 04458 } 04459 } 04460 } 04461 } 04462 } 04463 } 04464 04465 if (!var) { 04466 if (peerlist) 04467 ast_config_destroy(peerlist); 04468 return NULL; 04469 } 04470 04471 for (tmp = var; tmp; tmp = tmp->next) { 04472 /* If this is type=user, then skip this object. */ 04473 if (!strcasecmp(tmp->name, "type") && 04474 !strcasecmp(tmp->value, "user")) { 04475 if(peerlist) 04476 ast_config_destroy(peerlist); 04477 else { 04478 ast_variables_destroy(var); 04479 ast_variables_destroy(varregs); 04480 } 04481 return NULL; 04482 } else if (!newpeername && !strcasecmp(tmp->name, "name")) { 04483 newpeername = tmp->value; 04484 } 04485 } 04486 04487 if (!newpeername) { /* Did not find peer in realtime */ 04488 ast_log(LOG_WARNING, "Cannot Determine peer name ip=%s\n", ipaddr); 04489 if(peerlist) 04490 ast_config_destroy(peerlist); 04491 else 04492 ast_variables_destroy(var); 04493 return NULL; 04494 } 04495 04496 04497 /* Peer found in realtime, now build it in memory */ 04498 peer = build_peer(newpeername, var, varregs, TRUE, devstate_only); 04499 if (!peer) { 04500 if(peerlist) 04501 ast_config_destroy(peerlist); 04502 else { 04503 ast_variables_destroy(var); 04504 ast_variables_destroy(varregs); 04505 } 04506 return NULL; 04507 } 04508 04509 ast_debug(3, "-REALTIME- loading peer from database to memory. Name: %s. Peer objects: %d\n", peer->name, rpeerobjs); 04510 04511 if (ast_test_flag(&global_flags[1], SIP_PAGE2_RTCACHEFRIENDS) && !devstate_only) { 04512 /* Cache peer */ 04513 ast_copy_flags(&peer->flags[1], &global_flags[1], SIP_PAGE2_RTAUTOCLEAR|SIP_PAGE2_RTCACHEFRIENDS); 04514 if (ast_test_flag(&global_flags[1], SIP_PAGE2_RTAUTOCLEAR)) { 04515 AST_SCHED_REPLACE_UNREF(peer->expire, sched, global_rtautoclear * 1000, expire_register, peer, 04516 unref_peer(_data, "remove registration ref"), 04517 unref_peer(peer, "remove registration ref"), 04518 ref_peer(peer, "add registration ref")); 04519 } 04520 ao2_t_link(peers, peer, "link peer into peers table"); 04521 if (peer->addr.sin_addr.s_addr) { 04522 ao2_t_link(peers_by_ip, peer, "link peer into peers_by_ip table"); 04523 } 04524 } 04525 peer->is_realtime = 1; 04526 if (peerlist) 04527 ast_config_destroy(peerlist); 04528 else { 04529 ast_variables_destroy(var); 04530 ast_variables_destroy(varregs); 04531 } 04532 04533 return peer; 04534 }
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 4156 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.
04157 { 04158 char port[10]; 04159 char ipaddr[INET_ADDRSTRLEN]; 04160 char regseconds[20]; 04161 char *tablename = NULL; 04162 char str_lastms[20]; 04163 04164 const char *sysname = ast_config_AST_SYSTEM_NAME; 04165 char *syslabel = NULL; 04166 04167 time_t nowtime = time(NULL) + expirey; 04168 const char *fc = fullcontact ? "fullcontact" : NULL; 04169 04170 int realtimeregs = ast_check_realtime("sipregs"); 04171 04172 tablename = realtimeregs ? "sipregs" : "sippeers"; 04173 04174 04175 snprintf(str_lastms, sizeof(str_lastms), "%d", lastms); 04176 snprintf(regseconds, sizeof(regseconds), "%d", (int)nowtime); /* Expiration time */ 04177 ast_copy_string(ipaddr, ast_inet_ntoa(sin->sin_addr), sizeof(ipaddr)); 04178 snprintf(port, sizeof(port), "%d", ntohs(sin->sin_port)); 04179 04180 if (ast_strlen_zero(sysname)) /* No system name, disable this */ 04181 sysname = NULL; 04182 else if (sip_cfg.rtsave_sysname) 04183 syslabel = "regserver"; 04184 04185 if (fc) { 04186 ast_update_realtime(tablename, "name", peername, "ipaddr", ipaddr, 04187 "port", port, "regseconds", regseconds, 04188 deprecated_username ? "username" : "defaultuser", defaultuser, 04189 "useragent", useragent, "lastms", str_lastms, 04190 fc, fullcontact, syslabel, sysname, SENTINEL); /* note fc and syslabel _can_ be NULL */ 04191 } else { 04192 ast_update_realtime(tablename, "name", peername, "ipaddr", ipaddr, 04193 "port", port, "regseconds", regseconds, 04194 "useragent", useragent, "lastms", str_lastms, 04195 deprecated_username ? "username" : "defaultuser", defaultuser, 04196 syslabel, sysname, SENTINEL); /* note syslabel _can_ be NULL */ 04197 } 04198 }
static void receive_message | ( | struct sip_pvt * | p, | |
struct sip_request * | req | |||
) | [static] |
Receive SIP MESSAGE method messages.
Definition at line 13459 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().
13460 { 13461 char buf[1400]; 13462 struct ast_frame f; 13463 const char *content_type = get_header(req, "Content-Type"); 13464 13465 if (strncmp(content_type, "text/plain", strlen("text/plain"))) { /* No text/plain attachment */ 13466 transmit_response(p, "415 Unsupported Media Type", req); /* Good enough, or? */ 13467 if (!p->owner) 13468 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 13469 return; 13470 } 13471 13472 if (get_msg_text(buf, sizeof(buf), req, FALSE)) { 13473 ast_log(LOG_WARNING, "Unable to retrieve text from %s\n", p->callid); 13474 transmit_response(p, "202 Accepted", req); 13475 if (!p->owner) 13476 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 13477 return; 13478 } 13479 13480 if (p->owner) { 13481 if (sip_debug_test_pvt(p)) 13482 ast_verbose("SIP Text message received: '%s'\n", buf); 13483 memset(&f, 0, sizeof(f)); 13484 f.frametype = AST_FRAME_TEXT; 13485 f.subclass = 0; 13486 f.offset = 0; 13487 f.data.ptr = buf; 13488 f.datalen = strlen(buf); 13489 ast_queue_frame(p->owner, &f); 13490 transmit_response(p, "202 Accepted", req); /* We respond 202 accepted, since we relay the message */ 13491 return; 13492 } 13493 13494 /* Message outside of a call, we do not support that */ 13495 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); 13496 transmit_response(p, "405 Method Not Allowed", req); 13497 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 13498 return; 13499 }
Definition at line 2755 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().
02756 { 02757 ao2_t_ref(peer, 1, tag); 02758 return peer; 02759 }
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 2772 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().
02773 { 02774 struct sip_proxy *old_obproxy = pvt->outboundproxy; 02775 /* Cool, now get the refs correct */ 02776 if (proxy && proxy != &global_outboundproxy) { 02777 ao2_ref(proxy, +1); 02778 } 02779 pvt->outboundproxy = proxy; 02780 if (old_obproxy && old_obproxy != &global_outboundproxy) { 02781 ao2_ref(old_obproxy, -1); 02782 } 02783 return proxy; 02784 }
static const char * referstatus2str | ( | enum referstatus | rstatus | ) | [static] |
Convert transfer status to string.
Definition at line 2884 of file chan_sip.c.
References map_x_s(), and referstatusstrings.
Referenced by show_channels_cb().
02885 { 02886 return map_x_s(referstatusstrings, rstatus, ""); 02887 }
static void reg_source_db | ( | struct sip_peer * | peer | ) | [static] |
Get registration details from Asterisk DB.
Definition at line 11285 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(), strsep(), TRUE, unref_peer(), and sip_peer::username.
11286 { 11287 char data[256]; 11288 struct in_addr in; 11289 int expire; 11290 int port; 11291 char *scan, *addr, *port_str, *expiry_str, *username, *contact; 11292 11293 if (peer->rt_fromcontact) 11294 return; 11295 if (ast_db_get("SIP/Registry", peer->name, data, sizeof(data))) 11296 return; 11297 11298 scan = data; 11299 addr = strsep(&scan, ":"); 11300 port_str = strsep(&scan, ":"); 11301 expiry_str = strsep(&scan, ":"); 11302 username = strsep(&scan, ":"); 11303 contact = scan; /* Contact include sip: and has to be the last part of the database entry as long as we use : as a separator */ 11304 11305 if (!inet_aton(addr, &in)) 11306 return; 11307 11308 if (port_str) 11309 port = atoi(port_str); 11310 else 11311 return; 11312 11313 if (expiry_str) 11314 expire = atoi(expiry_str); 11315 else 11316 return; 11317 11318 if (username) 11319 ast_copy_string(peer->username, username, sizeof(peer->username)); 11320 if (contact) 11321 ast_copy_string(peer->fullcontact, contact, sizeof(peer->fullcontact)); 11322 11323 ast_debug(2, "SIP Seeding peer from astdb: '%s' at %s@%s:%d for %d\n", 11324 peer->name, peer->username, ast_inet_ntoa(in), port, expire); 11325 11326 memset(&peer->addr, 0, sizeof(peer->addr)); 11327 peer->addr.sin_family = AF_INET; 11328 peer->addr.sin_addr = in; 11329 peer->addr.sin_port = htons(port); 11330 if (sipsock < 0) { 11331 /* SIP isn't up yet, so schedule a poke only, pretty soon */ 11332 AST_SCHED_REPLACE_UNREF(peer->pokeexpire, sched, ast_random() % 5000 + 1, sip_poke_peer_s, peer, 11333 unref_peer(_data, "removing poke peer ref"), 11334 unref_peer(peer, "removing poke peer ref"), 11335 ref_peer(peer, "adding poke peer ref")); 11336 } else { 11337 sip_poke_peer(peer, 0); 11338 } 11339 AST_SCHED_REPLACE_UNREF(peer->expire, sched, (expire + 10) * 1000, expire_register, peer, 11340 unref_peer(_data, "remove registration ref"), 11341 unref_peer(peer, "remove registration ref"), 11342 ref_peer(peer, "add registration ref")); 11343 register_peer_exten(peer, TRUE); 11344 }
static void register_peer_exten | ( | struct sip_peer * | peer, | |
int | onoff | |||
) | [static] |
Automatically add peer extension to dial plan.
Definition at line 4201 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().
04202 { 04203 char multi[256]; 04204 char *stringp, *ext, *context; 04205 struct pbx_find_info q = { .stacklen = 0 }; 04206 04207 /* XXX note that global_regcontext is both a global 'enable' flag and 04208 * the name of the global regexten context, if not specified 04209 * individually. 04210 */ 04211 if (ast_strlen_zero(global_regcontext)) 04212 return; 04213 04214 ast_copy_string(multi, S_OR(peer->regexten, peer->name), sizeof(multi)); 04215 stringp = multi; 04216 while ((ext = strsep(&stringp, "&"))) { 04217 if ((context = strchr(ext, '@'))) { 04218 *context++ = '\0'; /* split ext@context */ 04219 if (!ast_context_find(context)) { 04220 ast_log(LOG_WARNING, "Context %s must exist in regcontext= in sip.conf!\n", context); 04221 continue; 04222 } 04223 } else { 04224 context = global_regcontext; 04225 } 04226 if (onoff) { 04227 if (!ast_exists_extension(NULL, context, ext, 1, NULL)) { 04228 ast_add_extension(context, 1, ext, 1, NULL, NULL, "Noop", 04229 ast_strdup(peer->name), ast_free_ptr, "SIP"); 04230 } 04231 } else if (pbx_find_extension(NULL, NULL, &q, context, ext, 1, NULL, "", E_MATCH)) { 04232 ast_context_remove_extension(context, ext, 1, NULL); 04233 } 04234 } 04235 }
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 12140 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_strlen_zero(), 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, sip_peer::fullcontact, 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_DENIED, PARSE_REGISTER_FAILED, PARSE_REGISTER_QUERY, PARSE_REGISTER_UPDATE, peers, 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, strcasestr(), temp_peer(), terminate_uri(), transmit_fake_auth_response(), transmit_response(), transmit_response_with_date(), TRUE, unref_peer(), update_peer(), and XMIT_UNRELIABLE.
12142 { 12143 enum check_auth_result res = AUTH_NOT_FOUND; 12144 struct sip_peer *peer; 12145 char tmp[256]; 12146 char *name, *c; 12147 char *domain; 12148 12149 terminate_uri(uri); /* warning, overwrite the string */ 12150 12151 ast_copy_string(tmp, get_header(req, "To"), sizeof(tmp)); 12152 if (pedanticsipchecking) 12153 ast_uri_decode(tmp); 12154 12155 c = get_in_brackets(tmp); 12156 c = remove_uri_parameters(c); 12157 12158 if (!strncasecmp(c, "sip:", 4)) { 12159 name = c + 4; 12160 } else if (!strncasecmp(c, "sips:", 5)) { 12161 name = c + 5; 12162 } else { 12163 name = c; 12164 ast_log(LOG_NOTICE, "Invalid to address: '%s' from %s (missing sip:) trying to use anyway...\n", c, ast_inet_ntoa(sin->sin_addr)); 12165 } 12166 12167 /* XXX here too we interpret a missing @domain as a name-only 12168 * URI, whereas the RFC says this is a domain-only uri. 12169 */ 12170 /* Strip off the domain name */ 12171 if ((c = strchr(name, '@'))) { 12172 *c++ = '\0'; 12173 domain = c; 12174 if ((c = strchr(domain, ':'))) /* Remove :port */ 12175 *c = '\0'; 12176 if (!AST_LIST_EMPTY(&domain_list)) { 12177 if (!check_sip_domain(domain, NULL, 0)) { 12178 transmit_response(p, "404 Not found (unknown domain)", &p->initreq); 12179 return AUTH_UNKNOWN_DOMAIN; 12180 } 12181 } 12182 } 12183 c = strchr(name, ';'); /* Remove any Username parameters */ 12184 if (c) 12185 *c = '\0'; 12186 12187 ast_string_field_set(p, exten, name); 12188 build_contact(p); 12189 if (req->ignore) { 12190 /* Expires is a special case, where we only want to load the peer if this isn't a deregistration attempt */ 12191 const char *expires = get_header(req, "Expires"); 12192 int expire = atoi(expires); 12193 12194 if (ast_strlen_zero(expires)) { /* No expires header; look in Contact */ 12195 if ((expires = strcasestr(get_header(req, "Contact"), ";expires="))) { 12196 expire = atoi(expires + 9); 12197 } 12198 } 12199 if (!ast_strlen_zero(expires) && expire == 0) { 12200 transmit_response_with_date(p, "200 OK", req); 12201 return 0; 12202 } 12203 } 12204 peer = find_peer(name, NULL, TRUE, FINDPEERS, FALSE, 0); 12205 if (!(peer && ast_apply_ha(peer->ha, sin))) { 12206 /* Peer fails ACL check */ 12207 if (peer) { 12208 unref_peer(peer, "register_verify: unref_peer: from find_peer operation"); 12209 peer = NULL; 12210 res = AUTH_ACL_FAILED; 12211 } else 12212 res = AUTH_NOT_FOUND; 12213 } 12214 12215 if (peer) { 12216 /* Set Frame packetization */ 12217 if (p->rtp) { 12218 ast_rtp_codec_setpref(p->rtp, &peer->prefs); 12219 p->autoframing = peer->autoframing; 12220 } 12221 if (!peer->host_dynamic) { 12222 ast_log(LOG_ERROR, "Peer '%s' is trying to register, but not configured as host=dynamic\n", peer->name); 12223 res = AUTH_PEER_NOT_DYNAMIC; 12224 } else { 12225 ast_copy_flags(&p->flags[0], &peer->flags[0], SIP_NAT); 12226 if (ast_test_flag(&p->flags[1], SIP_PAGE2_REGISTERTRYING)) 12227 transmit_response(p, "100 Trying", req); 12228 if (!(res = check_auth(p, req, peer->name, peer->secret, peer->md5secret, SIP_REGISTER, uri, XMIT_UNRELIABLE, req->ignore))) { 12229 if (sip_cancel_destroy(p)) 12230 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 12231 12232 if (check_request_transport(peer, req)) { 12233 ast_set_flag(&p->flags[0], SIP_PENDINGBYE); 12234 transmit_response_with_date(p, "403 Forbidden", req); 12235 res = AUTH_BAD_TRANSPORT; 12236 } else { 12237 12238 /* We have a successful registration attempt with proper authentication, 12239 now, update the peer */ 12240 switch (parse_register_contact(p, peer, req)) { 12241 case PARSE_REGISTER_DENIED: 12242 transmit_response_with_date(p, "603 Denied", req); 12243 peer->lastmsgssent = -1; 12244 res = 0; 12245 break; 12246 case PARSE_REGISTER_FAILED: 12247 ast_log(LOG_WARNING, "Failed to parse contact info\n"); 12248 transmit_response_with_date(p, "400 Bad Request", req); 12249 peer->lastmsgssent = -1; 12250 res = 0; 12251 break; 12252 case PARSE_REGISTER_QUERY: 12253 ast_string_field_set(p, fullcontact, peer->fullcontact); 12254 transmit_response_with_date(p, "200 OK", req); 12255 peer->lastmsgssent = -1; 12256 res = 0; 12257 break; 12258 case PARSE_REGISTER_UPDATE: 12259 ast_string_field_set(p, fullcontact, peer->fullcontact); 12260 update_peer(peer, p->expiry); 12261 /* Say OK and ask subsystem to retransmit msg counter */ 12262 transmit_response_with_date(p, "200 OK", req); 12263 if (!ast_test_flag((&peer->flags[1]), SIP_PAGE2_SUBSCRIBEMWIONLY)) 12264 peer->lastmsgssent = -1; 12265 res = 0; 12266 break; 12267 } 12268 } 12269 12270 } 12271 } 12272 } 12273 if (!peer && autocreatepeer) { 12274 /* Create peer if we have autocreate mode enabled */ 12275 peer = temp_peer(name); 12276 if (peer) { 12277 ao2_t_link(peers, peer, "link peer into peer table"); 12278 if (peer->addr.sin_addr.s_addr) { 12279 ao2_t_link(peers_by_ip, peer, "link peer into peers-by-ip table"); 12280 } 12281 12282 if (sip_cancel_destroy(p)) 12283 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 12284 switch (parse_register_contact(p, peer, req)) { 12285 case PARSE_REGISTER_DENIED: 12286 transmit_response_with_date(p, "403 Forbidden (ACL)", req); 12287 peer->lastmsgssent = -1; 12288 res = 0; 12289 break; 12290 case PARSE_REGISTER_FAILED: 12291 ast_log(LOG_WARNING, "Failed to parse contact info\n"); 12292 transmit_response_with_date(p, "400 Bad Request", req); 12293 peer->lastmsgssent = -1; 12294 res = 0; 12295 break; 12296 case PARSE_REGISTER_QUERY: 12297 ast_string_field_set(p, fullcontact, peer->fullcontact); 12298 transmit_response_with_date(p, "200 OK", req); 12299 peer->lastmsgssent = -1; 12300 res = 0; 12301 break; 12302 case PARSE_REGISTER_UPDATE: 12303 ast_string_field_set(p, fullcontact, peer->fullcontact); 12304 /* Say OK and ask subsystem to retransmit msg counter */ 12305 transmit_response_with_date(p, "200 OK", req); 12306 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)); 12307 peer->lastmsgssent = -1; 12308 res = 0; 12309 break; 12310 } 12311 } 12312 } 12313 if (!peer && global_alwaysauthreject) { 12314 /* If we found a peer, we transmit a 100 Trying. Therefore, if we're 12315 * trying to avoid leaking information, we MUST also transmit the same 12316 * response when we DON'T find a peer. */ 12317 transmit_response(p, "100 Trying", req); 12318 /* Insert a fake delay between the 100 and the subsequent failure. */ 12319 sched_yield(); 12320 } 12321 if (!res) { 12322 ast_devstate_changed(AST_DEVICE_UNKNOWN, "SIP/%s", peer->name); 12323 } 12324 if (res < 0) { 12325 switch (res) { 12326 case AUTH_SECRET_FAILED: 12327 /* Wrong password in authentication. Go away, don't try again until you fixed it */ 12328 transmit_response(p, "403 Forbidden (Bad auth)", &p->initreq); 12329 if (global_authfailureevents) 12330 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", 12331 name, ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port)); 12332 break; 12333 case AUTH_USERNAME_MISMATCH: 12334 /* Username and digest username does not match. 12335 Asterisk uses the From: username for authentication. We need the 12336 devices to use the same authentication user name until we support 12337 proper authentication by digest auth name */ 12338 case AUTH_NOT_FOUND: 12339 case AUTH_PEER_NOT_DYNAMIC: 12340 case AUTH_ACL_FAILED: 12341 if (global_alwaysauthreject) { 12342 transmit_fake_auth_response(p, SIP_REGISTER, &p->initreq, XMIT_UNRELIABLE); 12343 } else { 12344 /* URI not found */ 12345 if (res == AUTH_PEER_NOT_DYNAMIC) { 12346 transmit_response(p, "403 Forbidden", &p->initreq); 12347 if (global_authfailureevents) { 12348 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", 12349 "ChannelType: SIP\r\n" 12350 "Peer: SIP/%s\r\n" 12351 "PeerStatus: Rejected\r\n" 12352 "Cause: AUTH_PEER_NOT_DYNAMIC\r\n" 12353 "Address: %s\r\n" 12354 "Port: %d\r\n", 12355 name, ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port)); 12356 } 12357 } else { 12358 transmit_response(p, "404 Not found", &p->initreq); 12359 if (global_authfailureevents) { 12360 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", 12361 "ChannelType: SIP\r\n" 12362 "Peer: SIP/%s\r\n" 12363 "PeerStatus: Rejected\r\n" 12364 "Cause: %s\r\n" 12365 "Address: %s\r\n" 12366 "Port: %d\r\n", 12367 name, 12368 (res == AUTH_USERNAME_MISMATCH) ? "AUTH_USERNAME_MISMATCH" : "URI_NOT_FOUND", 12369 ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port)); 12370 } 12371 } 12372 } 12373 break; 12374 case AUTH_BAD_TRANSPORT: 12375 default: 12376 break; 12377 } 12378 } 12379 if (peer) 12380 unref_peer(peer, "register_verify: unref_peer: tossing stack peer pointer at end of func"); 12381 12382 return res; 12383 }
static struct sip_registry* registry_addref | ( | struct sip_registry * | reg, | |
char * | tag | |||
) | [static] |
Add object reference to SIP registry.
Definition at line 2866 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().
02867 { 02868 ast_debug(3, "SIP Registry %s: refcount now %d\n", reg->hostname, reg->refcount + 1); 02869 return ASTOBJ_REF(reg); /* Add pointer to registry in packet */ 02870 }
static void * registry_unref | ( | struct sip_registry * | reg, | |
char * | tag | |||
) | [static] |
Definition at line 2858 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(), reload_config(), sip_reg_timeout(), sip_register(), sip_registry_destroy(), sip_reregister(), sip_send_all_registers(), and transmit_register().
02859 { 02860 ast_debug(3, "SIP Registry %s: refcount now %d\n", reg->hostname, reg->refcount - 1); 02861 ASTOBJ_UNREF(reg, sip_registry_destroy); 02862 return NULL; 02863 }
static const char * regstate2str | ( | enum sipregistrystate | regstate | ) | const [static] |
Convert registration state status to string.
Definition at line 10666 of file chan_sip.c.
References map_x_s(), and regstatestrings.
10667 { 10668 return map_x_s(regstatestrings, regstate, "Unknown"); 10669 }
static int reload | ( | void | ) | [static] |
Part of Asterisk module interface.
Definition at line 24647 of file chan_sip.c.
References sip_reload().
24648 { 24649 if (sip_reload(0, 0, NULL)) 24650 return 0; 24651 return 1; 24652 }
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 23313 of file chan_sip.c.
References ast_clear_flag, ast_config_load, ast_debug, ast_free_ha(), ast_log(), AST_MAX_CONTEXT, AST_SCHED_DEL_UNREF, ast_test_flag, ast_unload_realtime(), ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_RDLOCK, 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, global_flags, ast_tcptls_session_args::local_address, LOG_NOTICE, registry_unref(), regl, sched, SIP_PAGE2_RTCACHEFRIENDS, sip_tcp_desc, sip_tls_desc, STANDARD_SIP_PORT, STANDARD_TLS_PORT, and TRUE.
23314 { 23315 struct ast_config *cfg, *ucfg; 23316 struct ast_variable *v; 23317 struct sip_peer *peer; 23318 char *cat, *stringp, *context, *oldregcontext; 23319 char newcontexts[AST_MAX_CONTEXT], oldcontexts[AST_MAX_CONTEXT]; 23320 struct ast_flags dummy[2]; 23321 struct ast_flags config_flags = { reason == CHANNEL_MODULE_LOAD ? 0 : ast_test_flag(&global_flags[1], SIP_PAGE2_RTCACHEFRIENDS) ? 0 : CONFIG_FLAG_FILEUNCHANGED }; 23322 int auto_sip_domains = FALSE; 23323 struct sockaddr_in old_bindaddr = bindaddr; 23324 int registry_count = 0, peer_count = 0; 23325 time_t run_start, run_end; 23326 23327 run_start = time(0); 23328 ast_unload_realtime("sipregs"); 23329 ast_unload_realtime("sippeers"); 23330 cfg = ast_config_load(config, config_flags); 23331 23332 /* We *must* have a config file otherwise stop immediately */ 23333 if (!cfg) { 23334 ast_log(LOG_NOTICE, "Unable to load config %s\n", config); 23335 return -1; 23336 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) { 23337 ucfg = ast_config_load("users.conf", config_flags); 23338 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) 23339 return 1; 23340 /* Must reread both files, because one changed */ 23341 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); 23342 cfg = ast_config_load(config, config_flags); 23343 } else { 23344 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); 23345 ucfg = ast_config_load("users.conf", config_flags); 23346 } 23347 23348 /* Initialize tcp sockets */ 23349 memset(&sip_tcp_desc.local_address, 0, sizeof(sip_tcp_desc.local_address)); 23350 memset(&sip_tls_desc.local_address, 0, sizeof(sip_tls_desc.local_address)); 23351 23352 ast_free_ha(global_contact_ha); 23353 global_contact_ha = NULL; 23354 23355 default_tls_cfg.enabled = FALSE; /* Default: Disable TLS */ 23356 23357 sip_tcp_desc.local_address.sin_port = htons(STANDARD_SIP_PORT); 23358 sip_tls_desc.local_address.sin_port = htons(STANDARD_TLS_PORT); 23359 23360 if (reason != CHANNEL_MODULE_LOAD) { 23361 ast_debug(4, "--------------- SIP reload started\n"); 23362 23363 clear_realm_authentication(authl); 23364 clear_sip_domains(); 23365 authl = NULL; 23366 23367 /* First, destroy all outstanding registry calls */ 23368 /* This is needed, since otherwise active registry entries will not be destroyed */ 23369 ASTOBJ_CONTAINER_TRAVERSE(®l, 1, do { /* regl is locked */ 23370 23371 ASTOBJ_RDLOCK(iterator); /* now regl is locked, and the object is also locked */ 23372 if (iterator->call) { 23373 ast_debug(3, "Destroying active SIP dialog for registry %s@%s\n", iterator->username, iterator->hostname); 23374 /* This will also remove references to the registry */ 23375 dialog_unlink_all(iterator->call, TRUE, TRUE); 23376 iterator->call = dialog_unref(iterator->call, "remove iterator->call from registry traversal"); 23377 } 23378 if (iterator->expire > -1) { 23379 AST_SCHED_DEL_UNREF(sched, iterator->expire, registry_unref(iterator, "reg ptr unref from reload config")); 23380 } 23381 if (iterator->timeout > -1) { 23382 AST_SCHED_DEL_UNREF(sched, iterator->timeout, registry_unref(iterator, "reg ptr unref from reload config")); 23383 } 23384 ASTOBJ_UNLOCK(iterator); 23385 23386 } while(0)); 23387 23388 /* Then, actually destroy users and registry */ 23389 ASTOBJ_CONTAINER_DESTROYALL(®l, sip_registry_destroy); 23390 ast_debug(4, "--------------- Done destroying registry list\n"); 23391 ao2_t_callback(peers, OBJ_NODATA, peer_markall_func, 0, "callback to mark all peers"); 23392 } 23393 23394 /* Reset certificate handling for TLS sessions */ 23395 if (reason != CHANNEL_MODULE_LOAD) { 23396 ast_free(default_tls_cfg.certfile); 23397 ast_free(default_tls_cfg.cipher); 23398 ast_free(default_tls_cfg.cafile); 23399 ast_free(default_tls_cfg.capath); 23400 } 23401 default_tls_cfg.certfile = ast_strdup(AST_CERTFILE); /*XXX Not sure if this is useful */ 23402 default_tls_cfg.cipher = ast_strdup(""); 23403 default_tls_cfg.cafile = ast_strdup(""); 23404 default_tls_cfg.capath = ast_strdup(""); 23405 23406 /* Initialize copy of current global_regcontext for later use in removing stale contexts */ 23407 ast_copy_string(oldcontexts, global_regcontext, sizeof(oldcontexts)); 23408 oldregcontext = oldcontexts; 23409 23410 /* Clear all flags before setting default values */ 23411 /* Preserve debugging settings for console */ 23412 sipdebug &= sip_debug_console; 23413 ast_clear_flag(&global_flags[0], AST_FLAGS_ALL); 23414 ast_clear_flag(&global_flags[1], AST_FLAGS_ALL); 23415 23416 /* Reset IP addresses */ 23417 memset(&bindaddr, 0, sizeof(bindaddr)); 23418 memset(&stunaddr, 0, sizeof(stunaddr)); 23419 memset(&internip, 0, sizeof(internip)); 23420 23421 /* Free memory for local network address mask */ 23422 ast_free_ha(localaddr); 23423 memset(&localaddr, 0, sizeof(localaddr)); 23424 memset(&externip, 0, sizeof(externip)); 23425 memset(&default_prefs, 0 , sizeof(default_prefs)); 23426 memset(&global_outboundproxy, 0, sizeof(struct sip_proxy)); 23427 global_outboundproxy.ip.sin_port = htons(STANDARD_SIP_PORT); 23428 global_outboundproxy.ip.sin_family = AF_INET; /*!< Type of address: IPv4 */ 23429 global_outboundproxy.force = FALSE; /*!< Don't force proxy usage, use route: headers */ 23430 ourport_tcp = STANDARD_SIP_PORT; 23431 ourport_tls = STANDARD_TLS_PORT; 23432 bindaddr.sin_port = htons(STANDARD_SIP_PORT); 23433 global_srvlookup = DEFAULT_SRVLOOKUP; 23434 global_tos_sip = DEFAULT_TOS_SIP; 23435 global_tos_audio = DEFAULT_TOS_AUDIO; 23436 global_tos_video = DEFAULT_TOS_VIDEO; 23437 global_tos_text = DEFAULT_TOS_TEXT; 23438 global_cos_sip = DEFAULT_COS_SIP; 23439 global_cos_audio = DEFAULT_COS_AUDIO; 23440 global_cos_video = DEFAULT_COS_VIDEO; 23441 global_cos_text = DEFAULT_COS_TEXT; 23442 23443 externhost[0] = '\0'; /* External host name (for behind NAT DynDNS support) */ 23444 externexpire = 0; /* Expiration for DNS re-issuing */ 23445 externrefresh = 10; 23446 23447 /* Reset channel settings to default before re-configuring */ 23448 allow_external_domains = DEFAULT_ALLOW_EXT_DOM; /* Allow external invites */ 23449 global_regcontext[0] = '\0'; 23450 global_regextenonqualify = DEFAULT_REGEXTENONQUALIFY; 23451 global_notifyringing = DEFAULT_NOTIFYRINGING; 23452 global_notifyhold = FALSE; /*!< Keep track of hold status for a peer */ 23453 global_directrtpsetup = FALSE; /* Experimental feature, disabled by default */ 23454 global_alwaysauthreject = 0; 23455 global_allowsubscribe = FALSE; 23456 snprintf(global_useragent, sizeof(global_useragent), "%s %s", DEFAULT_USERAGENT, ast_get_version()); 23457 snprintf(global_sdpsession, sizeof(global_sdpsession), "%s %s", DEFAULT_SDPSESSION, ast_get_version()); 23458 snprintf(global_sdpowner, sizeof(global_sdpowner), "%s", DEFAULT_SDPOWNER); 23459 global_prematuremediafilter = FALSE; 23460 ast_copy_string(default_notifymime, DEFAULT_NOTIFYMIME, sizeof(default_notifymime)); 23461 ast_copy_string(global_realm, S_OR(ast_config_AST_SYSTEM_NAME, DEFAULT_REALM), sizeof(global_realm)); 23462 ast_copy_string(default_callerid, DEFAULT_CALLERID, sizeof(default_callerid)); 23463 compactheaders = DEFAULT_COMPACTHEADERS; 23464 global_reg_timeout = DEFAULT_REGISTRATION_TIMEOUT; 23465 global_regattempts_max = 0; 23466 pedanticsipchecking = DEFAULT_PEDANTIC; 23467 autocreatepeer = DEFAULT_AUTOCREATEPEER; 23468 global_autoframing = 0; 23469 global_allowguest = DEFAULT_ALLOWGUEST; 23470 global_callcounter = DEFAULT_CALLCOUNTER; 23471 global_match_auth_username = FALSE; /*!< Match auth username if available instead of From: Default off. */ 23472 global_rtptimeout = 0; 23473 global_rtpholdtimeout = 0; 23474 global_rtpkeepalive = 0; 23475 global_allowtransfer = TRANSFER_OPENFORALL; /* Merrily accept all transfers by default */ 23476 global_rtautoclear = 120; 23477 ast_set_flag(&global_flags[1], SIP_PAGE2_ALLOWSUBSCRIBE); /* Default for all devices: TRUE */ 23478 ast_set_flag(&global_flags[1], SIP_PAGE2_ALLOWOVERLAP); /* Default for all devices: TRUE */ 23479 sip_cfg.peer_rtupdate = TRUE; 23480 global_dynamic_exclude_static = 0; /* Exclude static peers */ 23481 23482 /* Session-Timers */ 23483 global_st_mode = SESSION_TIMER_MODE_ACCEPT; 23484 global_st_refresher = SESSION_TIMER_REFRESHER_UAS; 23485 global_min_se = DEFAULT_MIN_SE; 23486 global_max_se = DEFAULT_MAX_SE; 23487 23488 /* Initialize some reasonable defaults at SIP reload (used both for channel and as default for devices */ 23489 ast_copy_string(default_context, DEFAULT_CONTEXT, sizeof(default_context)); 23490 default_subscribecontext[0] = '\0'; 23491 default_language[0] = '\0'; 23492 default_fromdomain[0] = '\0'; 23493 default_qualify = DEFAULT_QUALIFY; 23494 default_maxcallbitrate = DEFAULT_MAX_CALL_BITRATE; 23495 ast_copy_string(default_mohinterpret, DEFAULT_MOHINTERPRET, sizeof(default_mohinterpret)); 23496 ast_copy_string(default_mohsuggest, DEFAULT_MOHSUGGEST, sizeof(default_mohsuggest)); 23497 ast_copy_string(default_vmexten, DEFAULT_VMEXTEN, sizeof(default_vmexten)); 23498 ast_set_flag(&global_flags[0], SIP_DTMF_RFC2833); /*!< Default DTMF setting: RFC2833 */ 23499 ast_set_flag(&global_flags[0], SIP_NAT_RFC3581); /*!< NAT support if requested by device with rport */ 23500 ast_set_flag(&global_flags[0], SIP_CAN_REINVITE); /*!< Allow re-invites */ 23501 23502 /* Debugging settings, always default to off */ 23503 dumphistory = FALSE; 23504 recordhistory = FALSE; 23505 sipdebug &= ~sip_debug_config; 23506 23507 /* Misc settings for the channel */ 23508 global_relaxdtmf = FALSE; 23509 global_callevents = FALSE; 23510 global_authfailureevents = FALSE; 23511 global_t1 = SIP_TIMER_T1; 23512 global_timer_b = 64 * SIP_TIMER_T1; 23513 global_t1min = DEFAULT_T1MIN; 23514 global_qualifyfreq = DEFAULT_QUALIFYFREQ; 23515 global_t38_maxdatagram = -1; 23516 global_shrinkcallerid = 1; 23517 23518 global_matchexterniplocally = FALSE; 23519 23520 /* Copy the default jb config over global_jbconf */ 23521 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf)); 23522 23523 ast_clear_flag(&global_flags[1], SIP_PAGE2_VIDEOSUPPORT | SIP_PAGE2_VIDEOSUPPORT_ALWAYS); 23524 ast_clear_flag(&global_flags[1], SIP_PAGE2_TEXTSUPPORT); 23525 ast_clear_flag(&global_flags[1], SIP_PAGE2_IGNORESDPVERSION); 23526 ast_clear_flag(&global_flags[1], SIP_PAGE2_FAX_DETECT); 23527 23528 23529 /* Read the [general] config section of sip.conf (or from realtime config) */ 23530 for (v = ast_variable_browse(cfg, "general"); v; v = v->next) { 23531 if (handle_common_options(&global_flags[0], &dummy[0], v)) 23532 continue; 23533 if (handle_t38_options(&global_flags[0], &dummy[0], v, &global_t38_maxdatagram)) { 23534 continue; 23535 } 23536 /* handle jb conf */ 23537 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) 23538 continue; 23539 23540 if (!strcasecmp(v->name, "context")) { 23541 ast_copy_string(default_context, v->value, sizeof(default_context)); 23542 } else if (!strcasecmp(v->name, "subscribecontext")) { 23543 ast_copy_string(default_subscribecontext, v->value, sizeof(default_subscribecontext)); 23544 } else if (!strcasecmp(v->name, "callcounter")) { 23545 global_callcounter = ast_true(v->value) ? 1 : 0; 23546 } else if (!strcasecmp(v->name, "allowguest")) { 23547 global_allowguest = ast_true(v->value) ? 1 : 0; 23548 } else if (!strcasecmp(v->name, "realm")) { 23549 ast_copy_string(global_realm, v->value, sizeof(global_realm)); 23550 } else if (!strcasecmp(v->name, "useragent")) { 23551 ast_copy_string(global_useragent, v->value, sizeof(global_useragent)); 23552 ast_debug(1, "Setting SIP channel User-Agent Name to %s\n", global_useragent); 23553 } else if (!strcasecmp(v->name, "sdpsession")) { 23554 ast_copy_string(global_sdpsession, v->value, sizeof(global_sdpsession)); 23555 } else if (!strcasecmp(v->name, "sdpowner")) { 23556 /* Field cannot contain spaces */ 23557 if (!strstr(v->value, " ")) 23558 ast_copy_string(global_sdpowner, v->value, sizeof(global_sdpowner)); 23559 else 23560 ast_log(LOG_WARNING, "'%s' must not contain spaces at line %d. Using default.\n", v->value, v->lineno); 23561 } else if (!strcasecmp(v->name, "allowtransfer")) { 23562 global_allowtransfer = ast_true(v->value) ? TRANSFER_OPENFORALL : TRANSFER_CLOSED; 23563 } else if (!strcasecmp(v->name, "rtcachefriends")) { 23564 ast_set2_flag(&global_flags[1], ast_true(v->value), SIP_PAGE2_RTCACHEFRIENDS); 23565 } else if (!strcasecmp(v->name, "rtsavesysname")) { 23566 sip_cfg.rtsave_sysname = ast_true(v->value); 23567 } else if (!strcasecmp(v->name, "rtupdate")) { 23568 sip_cfg.peer_rtupdate = ast_true(v->value); 23569 } else if (!strcasecmp(v->name, "ignoreregexpire")) { 23570 sip_cfg.ignore_regexpire = ast_true(v->value); 23571 } else if (!strcasecmp(v->name, "timert1")) { 23572 /* Defaults to 500ms, but RFC 3261 states that it is recommended 23573 * for the value to be set higher, though a lower value is only 23574 * allowed on private networks unconnected to the Internet. */ 23575 global_t1 = atoi(v->value); 23576 /* Note that timer B is dependent on the value of T1 */ 23577 global_timer_b = global_t1 * 64; 23578 } else if (!strcasecmp(v->name, "t1min")) { 23579 global_t1min = atoi(v->value); 23580 } else if (!strcasecmp(v->name, "tcpenable")) { 23581 sip_tcp_desc.local_address.sin_family = ast_false(v->value) ? 0 : AF_INET; 23582 ast_debug(2, "Enabling TCP socket for listening\n"); 23583 } else if (!strcasecmp(v->name, "tcpbindaddr")) { 23584 int family = sip_tcp_desc.local_address.sin_family; 23585 if (ast_parse_arg(v->value, PARSE_INADDR, &sip_tcp_desc.local_address)) 23586 ast_log(LOG_WARNING, "Invalid %s '%s' at line %d of %s\n", v->name, v->value, v->lineno, config); 23587 sip_tcp_desc.local_address.sin_family = family; 23588 ast_debug(2, "Setting TCP socket address to %s\n", v->value); 23589 } else if (!strcasecmp(v->name, "tlsenable")) { 23590 default_tls_cfg.enabled = ast_true(v->value) ? TRUE : FALSE; 23591 sip_tls_desc.local_address.sin_family = AF_INET; 23592 } else if (!strcasecmp(v->name, "tlscertfile")) { 23593 ast_free(default_tls_cfg.certfile); 23594 default_tls_cfg.certfile = ast_strdup(v->value); 23595 } else if (!strcasecmp(v->name, "tlscipher")) { 23596 ast_free(default_tls_cfg.cipher); 23597 default_tls_cfg.cipher = ast_strdup(v->value); 23598 } else if (!strcasecmp(v->name, "tlscafile")) { 23599 ast_free(default_tls_cfg.cafile); 23600 default_tls_cfg.cafile = ast_strdup(v->value); 23601 } else if (!strcasecmp(v->name, "tlscapath")) { 23602 ast_free(default_tls_cfg.capath); 23603 default_tls_cfg.capath = ast_strdup(v->value); 23604 } else if (!strcasecmp(v->name, "tlsverifyclient")) { 23605 ast_set2_flag(&default_tls_cfg.flags, ast_true(v->value), AST_SSL_VERIFY_CLIENT); 23606 } else if (!strcasecmp(v->name, "tlsdontverifyserver")) { 23607 ast_set2_flag(&default_tls_cfg.flags, ast_true(v->value), AST_SSL_DONT_VERIFY_SERVER); 23608 } else if (!strcasecmp(v->name, "tlsbindaddr")) { 23609 if (ast_parse_arg(v->value, PARSE_INADDR, &sip_tls_desc.local_address)) 23610 ast_log(LOG_WARNING, "Invalid %s '%s' at line %d of %s\n", v->name, v->value, v->lineno, config); 23611 } else if (!strcasecmp(v->name, "dynamic_exclude_static") || !strcasecmp(v->name, "dynamic_excludes_static")) { 23612 global_dynamic_exclude_static = ast_true(v->value); 23613 } else if (!strcasecmp(v->name, "contactpermit") || !strcasecmp(v->name, "contactdeny")) { 23614 int ha_error = 0; 23615 global_contact_ha = ast_append_ha(v->name + 7, v->value, global_contact_ha, &ha_error); 23616 if (ha_error) { 23617 ast_log(LOG_ERROR, "Bad ACL entry in configuration line %d : %s\n", v->lineno, v->value); 23618 } 23619 } else if (!strcasecmp(v->name, "rtautoclear")) { 23620 int i = atoi(v->value); 23621 if (i > 0) 23622 global_rtautoclear = i; 23623 else 23624 i = 0; 23625 ast_set2_flag(&global_flags[1], i || ast_true(v->value), SIP_PAGE2_RTAUTOCLEAR); 23626 } else if (!strcasecmp(v->name, "usereqphone")) { 23627 ast_set2_flag(&global_flags[0], ast_true(v->value), SIP_USEREQPHONE); 23628 } else if (!strcasecmp(v->name, "prematuremedia")) { 23629 global_prematuremediafilter = ast_true(v->value); 23630 } else if (!strcasecmp(v->name, "relaxdtmf")) { 23631 global_relaxdtmf = ast_true(v->value); 23632 } else if (!strcasecmp(v->name, "vmexten")) { 23633 ast_copy_string(default_vmexten, v->value, sizeof(default_vmexten)); 23634 } else if (!strcasecmp(v->name, "rtptimeout")) { 23635 if ((sscanf(v->value, "%30d", &global_rtptimeout) != 1) || (global_rtptimeout < 0)) { 23636 ast_log(LOG_WARNING, "'%s' is not a valid RTP hold time at line %d. Using default.\n", v->value, v->lineno); 23637 global_rtptimeout = 0; 23638 } 23639 } else if (!strcasecmp(v->name, "rtpholdtimeout")) { 23640 if ((sscanf(v->value, "%30d", &global_rtpholdtimeout) != 1) || (global_rtpholdtimeout < 0)) { 23641 ast_log(LOG_WARNING, "'%s' is not a valid RTP hold time at line %d. Using default.\n", v->value, v->lineno); 23642 global_rtpholdtimeout = 0; 23643 } 23644 } else if (!strcasecmp(v->name, "rtpkeepalive")) { 23645 if ((sscanf(v->value, "%30d", &global_rtpkeepalive) != 1) || (global_rtpkeepalive < 0)) { 23646 ast_log(LOG_WARNING, "'%s' is not a valid RTP keepalive time at line %d. Using default.\n", v->value, v->lineno); 23647 global_rtpkeepalive = 0; 23648 } 23649 } else if (!strcasecmp(v->name, "compactheaders")) { 23650 compactheaders = ast_true(v->value); 23651 } else if (!strcasecmp(v->name, "notifymimetype")) { 23652 ast_copy_string(default_notifymime, v->value, sizeof(default_notifymime)); 23653 } else if (!strcasecmp(v->name, "directrtpsetup")) { 23654 global_directrtpsetup = ast_true(v->value); 23655 } else if (!strcasecmp(v->name, "notifyringing")) { 23656 global_notifyringing = ast_true(v->value); 23657 } else if (!strcasecmp(v->name, "notifyhold")) { 23658 global_notifyhold = ast_true(v->value); 23659 } else if (!strcasecmp(v->name, "alwaysauthreject")) { 23660 global_alwaysauthreject = ast_true(v->value); 23661 } else if (!strcasecmp(v->name, "mohinterpret")) { 23662 ast_copy_string(default_mohinterpret, v->value, sizeof(default_mohinterpret)); 23663 } else if (!strcasecmp(v->name, "mohsuggest")) { 23664 ast_copy_string(default_mohsuggest, v->value, sizeof(default_mohsuggest)); 23665 } else if (!strcasecmp(v->name, "language")) { 23666 ast_copy_string(default_language, v->value, sizeof(default_language)); 23667 } else if (!strcasecmp(v->name, "regcontext")) { 23668 ast_copy_string(newcontexts, v->value, sizeof(newcontexts)); 23669 stringp = newcontexts; 23670 /* Let's remove any contexts that are no longer defined in regcontext */ 23671 cleanup_stale_contexts(stringp, oldregcontext); 23672 /* Create contexts if they don't exist already */ 23673 while ((context = strsep(&stringp, "&"))) { 23674 ast_copy_string(used_context, context, sizeof(used_context)); 23675 ast_context_find_or_create(NULL, NULL, context, "SIP"); 23676 } 23677 ast_copy_string(global_regcontext, v->value, sizeof(global_regcontext)); 23678 } else if (!strcasecmp(v->name, "regextenonqualify")) { 23679 global_regextenonqualify = ast_true(v->value); 23680 } else if (!strcasecmp(v->name, "callerid")) { 23681 ast_copy_string(default_callerid, v->value, sizeof(default_callerid)); 23682 } else if (!strcasecmp(v->name, "fromdomain")) { 23683 ast_copy_string(default_fromdomain, v->value, sizeof(default_fromdomain)); 23684 } else if (!strcasecmp(v->name, "outboundproxy")) { 23685 int portnum; 23686 char *tok, *proxyname; 23687 23688 if (ast_strlen_zero(v->value)) { 23689 ast_log(LOG_WARNING, "no value given for outbound proxy on line %d of sip.conf.", v->lineno); 23690 continue; 23691 } 23692 23693 tok = ast_skip_blanks(strtok(ast_strdupa(v->value), ",")); 23694 23695 sip_parse_host(tok, v->lineno, &proxyname, &portnum, &global_outboundproxy.transport); 23696 23697 global_outboundproxy.ip.sin_port = htons(portnum); 23698 23699 if ((tok = strtok(NULL, ","))) { 23700 global_outboundproxy.force = !strncasecmp(ast_skip_blanks(tok), "force", 5); 23701 } else { 23702 global_outboundproxy.force = FALSE; 23703 } 23704 23705 if (ast_strlen_zero(proxyname)) { 23706 ast_log(LOG_WARNING, "you must specify a name for the outboundproxy on line %d of sip.conf.", v->lineno); 23707 global_outboundproxy.name[0] = '\0'; 23708 continue; 23709 } 23710 23711 ast_copy_string(global_outboundproxy.name, proxyname, sizeof(global_outboundproxy.name)); 23712 23713 proxy_update(&global_outboundproxy); 23714 } else if (!strcasecmp(v->name, "autocreatepeer")) { 23715 autocreatepeer = ast_true(v->value); 23716 } else if (!strcasecmp(v->name, "match_auth_username")) { 23717 global_match_auth_username = ast_true(v->value); 23718 } else if (!strcasecmp(v->name, "srvlookup")) { 23719 global_srvlookup = ast_true(v->value); 23720 } else if (!strcasecmp(v->name, "pedantic")) { 23721 pedanticsipchecking = ast_true(v->value); 23722 } else if (!strcasecmp(v->name, "maxexpirey") || !strcasecmp(v->name, "maxexpiry")) { 23723 max_expiry = atoi(v->value); 23724 if (max_expiry < 1) 23725 max_expiry = DEFAULT_MAX_EXPIRY; 23726 } else if (!strcasecmp(v->name, "minexpirey") || !strcasecmp(v->name, "minexpiry")) { 23727 min_expiry = atoi(v->value); 23728 if (min_expiry < 1) 23729 min_expiry = DEFAULT_MIN_EXPIRY; 23730 } else if (!strcasecmp(v->name, "defaultexpiry") || !strcasecmp(v->name, "defaultexpirey")) { 23731 default_expiry = atoi(v->value); 23732 if (default_expiry < 1) 23733 default_expiry = DEFAULT_DEFAULT_EXPIRY; 23734 } else if (!strcasecmp(v->name, "sipdebug")) { 23735 if (ast_true(v->value)) 23736 sipdebug |= sip_debug_config; 23737 } else if (!strcasecmp(v->name, "dumphistory")) { 23738 dumphistory = ast_true(v->value); 23739 } else if (!strcasecmp(v->name, "recordhistory")) { 23740 recordhistory = ast_true(v->value); 23741 } else if (!strcasecmp(v->name, "registertimeout")) { 23742 global_reg_timeout = atoi(v->value); 23743 if (global_reg_timeout < 1) 23744 global_reg_timeout = DEFAULT_REGISTRATION_TIMEOUT; 23745 } else if (!strcasecmp(v->name, "registerattempts")) { 23746 global_regattempts_max = atoi(v->value); 23747 } else if (!strcasecmp(v->name, "stunaddr")) { 23748 stunaddr.sin_port = htons(3478); 23749 if (ast_parse_arg(v->value, PARSE_INADDR, &stunaddr)) 23750 ast_log(LOG_WARNING, "Invalid STUN server address: %s\n", v->value); 23751 externexpire = time(NULL); 23752 } else if (!strcasecmp(v->name, "bindaddr") || !strcasecmp(v->name, "udpbindaddr")) { 23753 if (ast_parse_arg(v->value, PARSE_INADDR, &bindaddr)) 23754 ast_log(LOG_WARNING, "Invalid address: %s\n", v->value); 23755 } else if (!strcasecmp(v->name, "localnet")) { 23756 struct ast_ha *na; 23757 int ha_error = 0; 23758 23759 if (!(na = ast_append_ha("d", v->value, localaddr, &ha_error))) 23760 ast_log(LOG_WARNING, "Invalid localnet value: %s\n", v->value); 23761 else 23762 localaddr = na; 23763 if (ha_error) 23764 ast_log(LOG_ERROR, "Bad localnet configuration value line %d : %s\n", v->lineno, v->value); 23765 } else if (!strcasecmp(v->name, "externip")) { 23766 if (ast_parse_arg(v->value, PARSE_INADDR, &externip)) 23767 ast_log(LOG_WARNING, "Invalid address for externip keyword: %s\n", v->value); 23768 externexpire = 0; 23769 /* If no port was specified use the value of bindport */ 23770 if (!externip.sin_port) 23771 externip.sin_port = bindaddr.sin_port; 23772 } else if (!strcasecmp(v->name, "externhost")) { 23773 ast_copy_string(externhost, v->value, sizeof(externhost)); 23774 if (ast_parse_arg(externhost, PARSE_INADDR, &externip)) 23775 ast_log(LOG_WARNING, "Invalid address for externhost keyword: %s\n", externhost); 23776 externexpire = time(NULL); 23777 /* If no port was specified use the value of bindport */ 23778 if (!externip.sin_port) 23779 externip.sin_port = bindaddr.sin_port; 23780 } else if (!strcasecmp(v->name, "externrefresh")) { 23781 if (sscanf(v->value, "%30d", &externrefresh) != 1) { 23782 ast_log(LOG_WARNING, "Invalid externrefresh value '%s', must be an integer >0 at line %d\n", v->value, v->lineno); 23783 externrefresh = 10; 23784 } 23785 } else if (!strcasecmp(v->name, "allow")) { 23786 int error = ast_parse_allow_disallow(&default_prefs, &global_capability, v->value, TRUE); 23787 if (error) 23788 ast_log(LOG_WARNING, "Codec configuration errors found in line %d : %s = %s\n", v->lineno, v->name, v->value); 23789 } else if (!strcasecmp(v->name, "disallow")) { 23790 int error = ast_parse_allow_disallow(&default_prefs, &global_capability, v->value, FALSE); 23791 if (error) 23792 ast_log(LOG_WARNING, "Codec configuration errors found in line %d : %s = %s\n", v->lineno, v->name, v->value); 23793 } else if (!strcasecmp(v->name, "autoframing")) { 23794 global_autoframing = ast_true(v->value); 23795 } else if (!strcasecmp(v->name, "allowexternaldomains")) { 23796 allow_external_domains = ast_true(v->value); 23797 } else if (!strcasecmp(v->name, "autodomain")) { 23798 auto_sip_domains = ast_true(v->value); 23799 } else if (!strcasecmp(v->name, "domain")) { 23800 char *domain = ast_strdupa(v->value); 23801 char *cntx = strchr(domain, ','); 23802 23803 if (cntx) 23804 *cntx++ = '\0'; 23805 23806 if (ast_strlen_zero(cntx)) 23807 ast_debug(1, "No context specified at line %d for domain '%s'\n", v->lineno, domain); 23808 if (ast_strlen_zero(domain)) 23809 ast_log(LOG_WARNING, "Empty domain specified at line %d\n", v->lineno); 23810 else 23811 add_sip_domain(ast_strip(domain), SIP_DOMAIN_CONFIG, cntx ? ast_strip(cntx) : ""); 23812 } else if (!strcasecmp(v->name, "register")) { 23813 if (sip_register(v->value, v->lineno) == 0) 23814 registry_count++; 23815 } else if (!strcasecmp(v->name, "tos_sip")) { 23816 if (ast_str2tos(v->value, &global_tos_sip)) 23817 ast_log(LOG_WARNING, "Invalid tos_sip value at line %d, refer to QoS documentation\n", v->lineno); 23818 } else if (!strcasecmp(v->name, "tos_audio")) { 23819 if (ast_str2tos(v->value, &global_tos_audio)) 23820 ast_log(LOG_WARNING, "Invalid tos_audio value at line %d, refer to QoS documentation\n", v->lineno); 23821 } else if (!strcasecmp(v->name, "tos_video")) { 23822 if (ast_str2tos(v->value, &global_tos_video)) 23823 ast_log(LOG_WARNING, "Invalid tos_video value at line %d, refer to QoS documentation\n", v->lineno); 23824 } else if (!strcasecmp(v->name, "tos_text")) { 23825 if (ast_str2tos(v->value, &global_tos_text)) 23826 ast_log(LOG_WARNING, "Invalid tos_text value at line %d, refer to QoS documentation\n", v->lineno); 23827 } else if (!strcasecmp(v->name, "cos_sip")) { 23828 if (ast_str2cos(v->value, &global_cos_sip)) 23829 ast_log(LOG_WARNING, "Invalid cos_sip value at line %d, refer to QoS documentation\n", v->lineno); 23830 } else if (!strcasecmp(v->name, "cos_audio")) { 23831 if (ast_str2cos(v->value, &global_cos_audio)) 23832 ast_log(LOG_WARNING, "Invalid cos_audio value at line %d, refer to QoS documentation\n", v->lineno); 23833 } else if (!strcasecmp(v->name, "cos_video")) { 23834 if (ast_str2cos(v->value, &global_cos_video)) 23835 ast_log(LOG_WARNING, "Invalid cos_video value at line %d, refer to QoS documentation\n", v->lineno); 23836 } else if (!strcasecmp(v->name, "cos_text")) { 23837 if (ast_str2cos(v->value, &global_cos_text)) 23838 ast_log(LOG_WARNING, "Invalid cos_text value at line %d, refer to QoS documentation\n", v->lineno); 23839 } else if (!strcasecmp(v->name, "bindport")) { 23840 int i; 23841 if (sscanf(v->value, "%5d", &i) == 1) { 23842 bindaddr.sin_port = htons(i); 23843 } else { 23844 ast_log(LOG_WARNING, "Invalid port number '%s' at line %d of %s\n", v->value, v->lineno, config); 23845 } 23846 } else if (!strcasecmp(v->name, "hash_user")) { 23847 int i; 23848 if (sscanf(v->value, "%30d", &i) == 1 && i > 2) { 23849 hash_user_size = i; 23850 } else { 23851 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); 23852 } 23853 } else if (!strcasecmp(v->name, "hash_peer")) { 23854 int i; 23855 if (sscanf(v->value, "%30d", &i) == 1 && i > 2) { 23856 hash_peer_size = i; 23857 } else { 23858 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); 23859 } 23860 } else if (!strcasecmp(v->name, "hash_dialog")) { 23861 int i; 23862 if (sscanf(v->value, "%30d", &i) == 1 && i > 2) { 23863 hash_dialog_size = i; 23864 } else { 23865 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); 23866 } 23867 } else if (!strcasecmp(v->name, "qualify")) { 23868 if (!strcasecmp(v->value, "no")) { 23869 default_qualify = 0; 23870 } else if (!strcasecmp(v->value, "yes")) { 23871 default_qualify = DEFAULT_MAXMS; 23872 } else if (sscanf(v->value, "%30d", &default_qualify) != 1) { 23873 ast_log(LOG_WARNING, "Qualification default should be 'yes', 'no', or a number of milliseconds at line %d of sip.conf\n", v->lineno); 23874 default_qualify = 0; 23875 } 23876 } else if (!strcasecmp(v->name, "qualifyfreq")) { 23877 int i; 23878 if (sscanf(v->value, "%30d", &i) == 1) 23879 global_qualifyfreq = i * 1000; 23880 else { 23881 ast_log(LOG_WARNING, "Invalid qualifyfreq number '%s' at line %d of %s\n", v->value, v->lineno, config); 23882 global_qualifyfreq = DEFAULT_QUALIFYFREQ; 23883 } 23884 } else if (!strcasecmp(v->name, "callevents")) { 23885 global_callevents = ast_true(v->value); 23886 } else if (!strcasecmp(v->name, "authfailureevents")) { 23887 global_authfailureevents = ast_true(v->value); 23888 } else if (!strcasecmp(v->name, "maxcallbitrate")) { 23889 default_maxcallbitrate = atoi(v->value); 23890 if (default_maxcallbitrate < 0) 23891 default_maxcallbitrate = DEFAULT_MAX_CALL_BITRATE; 23892 } else if (!strcasecmp(v->name, "matchexterniplocally")) { 23893 global_matchexterniplocally = ast_true(v->value); 23894 } else if (!strcasecmp(v->name, "session-timers")) { 23895 int i = (int) str2stmode(v->value); 23896 if (i < 0) { 23897 ast_log(LOG_WARNING, "Invalid session-timers '%s' at line %d of %s\n", v->value, v->lineno, config); 23898 global_st_mode = SESSION_TIMER_MODE_ACCEPT; 23899 } else { 23900 global_st_mode = i; 23901 } 23902 } else if (!strcasecmp(v->name, "session-expires")) { 23903 if (sscanf(v->value, "%30d", &global_max_se) != 1) { 23904 ast_log(LOG_WARNING, "Invalid session-expires '%s' at line %d of %s\n", v->value, v->lineno, config); 23905 global_max_se = DEFAULT_MAX_SE; 23906 } 23907 } else if (!strcasecmp(v->name, "session-minse")) { 23908 if (sscanf(v->value, "%30d", &global_min_se) != 1) { 23909 ast_log(LOG_WARNING, "Invalid session-minse '%s' at line %d of %s\n", v->value, v->lineno, config); 23910 global_min_se = DEFAULT_MIN_SE; 23911 } 23912 if (global_min_se < 90) { 23913 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); 23914 global_min_se = DEFAULT_MIN_SE; 23915 } 23916 } else if (!strcasecmp(v->name, "session-refresher")) { 23917 int i = (int) str2strefresher(v->value); 23918 if (i < 0) { 23919 ast_log(LOG_WARNING, "Invalid session-refresher '%s' at line %d of %s\n", v->value, v->lineno, config); 23920 global_st_refresher = SESSION_TIMER_REFRESHER_UAS; 23921 } else { 23922 global_st_refresher = i; 23923 } 23924 } else if (!strcasecmp(v->name, "shrinkcallerid")) { 23925 if (ast_true(v->value)) { 23926 global_shrinkcallerid = 1; 23927 } else if (ast_false(v->value)) { 23928 global_shrinkcallerid = 0; 23929 } else { 23930 ast_log(LOG_WARNING, "shrinkcallerid value %s is not valid at line %d.\n", v->value, v->lineno); 23931 } 23932 } 23933 } 23934 23935 if (!allow_external_domains && AST_LIST_EMPTY(&domain_list)) { 23936 ast_log(LOG_WARNING, "To disallow external domains, you need to configure local SIP domains.\n"); 23937 allow_external_domains = 1; 23938 } 23939 23940 /* Build list of authentication to various SIP realms, i.e. service providers */ 23941 for (v = ast_variable_browse(cfg, "authentication"); v ; v = v->next) { 23942 /* Format for authentication is auth = username:password@realm */ 23943 if (!strcasecmp(v->name, "auth")) 23944 authl = add_realm_authentication(authl, v->value, v->lineno); 23945 } 23946 23947 if (ucfg) { 23948 struct ast_variable *gen; 23949 int genhassip, genregistersip; 23950 const char *hassip, *registersip; 23951 23952 genhassip = ast_true(ast_variable_retrieve(ucfg, "general", "hassip")); 23953 genregistersip = ast_true(ast_variable_retrieve(ucfg, "general", "registersip")); 23954 gen = ast_variable_browse(ucfg, "general"); 23955 cat = ast_category_browse(ucfg, NULL); 23956 while (cat) { 23957 if (strcasecmp(cat, "general")) { 23958 hassip = ast_variable_retrieve(ucfg, cat, "hassip"); 23959 registersip = ast_variable_retrieve(ucfg, cat, "registersip"); 23960 if (ast_true(hassip) || (!hassip && genhassip)) { 23961 peer = build_peer(cat, gen, ast_variable_browse(ucfg, cat), 0, 0); 23962 if (peer) { 23963 /* user.conf entries are always of type friend */ 23964 peer->type = SIP_TYPE_USER | SIP_TYPE_PEER; 23965 ao2_t_link(peers, peer, "link peer into peer table"); 23966 if ((peer->type & SIP_TYPE_PEER) && peer->addr.sin_addr.s_addr) { 23967 ao2_t_link(peers_by_ip, peer, "link peer into peers_by_ip table"); 23968 } 23969 23970 unref_peer(peer, "unref_peer: from reload_config"); 23971 peer_count++; 23972 } 23973 } 23974 if (ast_true(registersip) || (!registersip && genregistersip)) { 23975 char tmp[256]; 23976 const char *host = ast_variable_retrieve(ucfg, cat, "host"); 23977 const char *username = ast_variable_retrieve(ucfg, cat, "username"); 23978 const char *secret = ast_variable_retrieve(ucfg, cat, "secret"); 23979 const char *contact = ast_variable_retrieve(ucfg, cat, "contact"); 23980 const char *authuser = ast_variable_retrieve(ucfg, cat, "authuser"); 23981 if (!host) 23982 host = ast_variable_retrieve(ucfg, "general", "host"); 23983 if (!username) 23984 username = ast_variable_retrieve(ucfg, "general", "username"); 23985 if (!secret) 23986 secret = ast_variable_retrieve(ucfg, "general", "secret"); 23987 if (!contact) 23988 contact = "s"; 23989 if (!ast_strlen_zero(username) && !ast_strlen_zero(host)) { 23990 if (!ast_strlen_zero(secret)) { 23991 if (!ast_strlen_zero(authuser)) { 23992 snprintf(tmp, sizeof(tmp), "%s:%s:%s@%s/%s", username, secret, authuser, host, contact); 23993 } else { 23994 snprintf(tmp, sizeof(tmp), "%s:%s@%s/%s", username, secret, host, contact); 23995 } 23996 } else if (!ast_strlen_zero(authuser)) { 23997 snprintf(tmp, sizeof(tmp), "%s::%s@%s/%s", username, authuser, host, contact); 23998 } else { 23999 snprintf(tmp, sizeof(tmp), "%s@%s/%s", username, host, contact); 24000 } 24001 if (sip_register(tmp, 0) == 0) 24002 registry_count++; 24003 } 24004 } 24005 } 24006 cat = ast_category_browse(ucfg, cat); 24007 } 24008 ast_config_destroy(ucfg); 24009 } 24010 24011 24012 /* Load peers, users and friends */ 24013 cat = NULL; 24014 while ( (cat = ast_category_browse(cfg, cat)) ) { 24015 const char *utype; 24016 if (!strcasecmp(cat, "general") || !strcasecmp(cat, "authentication")) 24017 continue; 24018 utype = ast_variable_retrieve(cfg, cat, "type"); 24019 if (!utype) { 24020 ast_log(LOG_WARNING, "Section '%s' lacks type\n", cat); 24021 continue; 24022 } else { 24023 if (!strcasecmp(utype, "user")) { 24024 ; 24025 } else if (!strcasecmp(utype, "friend")) { 24026 ; 24027 } else if (!strcasecmp(utype, "peer")) { 24028 ; 24029 } else { 24030 ast_log(LOG_WARNING, "Unknown type '%s' for '%s' in %s\n", utype, cat, "sip.conf"); 24031 continue; 24032 } 24033 peer = build_peer(cat, ast_variable_browse(cfg, cat), NULL, 0, 0); 24034 if (peer) { 24035 ao2_t_link(peers, peer, "link peer into peers table"); 24036 if ((peer->type & SIP_TYPE_PEER) && peer->addr.sin_addr.s_addr) { 24037 ao2_t_link(peers_by_ip, peer, "link peer into peers_by_ip table"); 24038 } 24039 unref_peer(peer, "unref the result of the build_peer call. Now, the links from the tables are the only ones left."); 24040 peer_count++; 24041 } 24042 } 24043 } 24044 24045 /* Set UDP address and open socket */ 24046 bindaddr.sin_family = AF_INET; 24047 internip = bindaddr; 24048 if (ast_find_ourip(&internip.sin_addr, bindaddr)) { 24049 ast_log(LOG_WARNING, "Unable to get own IP address, SIP disabled\n"); 24050 ast_config_destroy(cfg); 24051 return 0; 24052 } 24053 ast_mutex_lock(&netlock); 24054 if ((sipsock > -1) && (memcmp(&old_bindaddr, &bindaddr, sizeof(struct sockaddr_in)))) { 24055 close(sipsock); 24056 sipsock = -1; 24057 } 24058 if (sipsock < 0) { 24059 sipsock = socket(AF_INET, SOCK_DGRAM, 0); 24060 if (sipsock < 0) { 24061 ast_log(LOG_WARNING, "Unable to create SIP socket: %s\n", strerror(errno)); 24062 ast_config_destroy(cfg); 24063 return -1; 24064 } else { 24065 /* Allow SIP clients on the same host to access us: */ 24066 const int reuseFlag = 1; 24067 24068 setsockopt(sipsock, SOL_SOCKET, SO_REUSEADDR, 24069 (const char*)&reuseFlag, 24070 sizeof reuseFlag); 24071 24072 ast_enable_packet_fragmentation(sipsock); 24073 24074 if (bind(sipsock, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) < 0) { 24075 ast_log(LOG_WARNING, "Failed to bind to %s:%d: %s\n", 24076 ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port), 24077 strerror(errno)); 24078 close(sipsock); 24079 sipsock = -1; 24080 } else { 24081 ast_verb(2, "SIP Listening on %s:%d\n", 24082 ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port)); 24083 ast_netsock_set_qos(sipsock, global_tos_sip, global_cos_sip, "SIP"); 24084 } 24085 } 24086 } 24087 if (stunaddr.sin_addr.s_addr != 0) { 24088 ast_debug(1, "stun to %s:%d\n", 24089 ast_inet_ntoa(stunaddr.sin_addr) , ntohs(stunaddr.sin_port)); 24090 ast_stun_request(sipsock, &stunaddr, 24091 NULL, &externip); 24092 ast_debug(1, "STUN sees us at %s:%d\n", 24093 ast_inet_ntoa(externip.sin_addr) , ntohs(externip.sin_port)); 24094 } 24095 ast_mutex_unlock(&netlock); 24096 24097 /* Start TCP server */ 24098 ast_tcptls_server_start(&sip_tcp_desc); 24099 24100 /* Start TLS server if needed */ 24101 memcpy(sip_tls_desc.tls_cfg, &default_tls_cfg, sizeof(default_tls_cfg)); 24102 24103 if (ast_ssl_setup(sip_tls_desc.tls_cfg)) 24104 ast_tcptls_server_start(&sip_tls_desc); 24105 else if (sip_tls_desc.tls_cfg->enabled) { 24106 sip_tls_desc.tls_cfg = NULL; 24107 ast_log(LOG_WARNING, "SIP TLS server did not load because of errors.\n"); 24108 } 24109 24110 24111 /* Add default domains - host name, IP address and IP:port 24112 * Only do this if user added any sip domain with "localdomains" 24113 * In order to *not* break backwards compatibility 24114 * Some phones address us at IP only, some with additional port number 24115 */ 24116 if (auto_sip_domains) { 24117 char temp[MAXHOSTNAMELEN]; 24118 24119 /* First our default IP address */ 24120 if (bindaddr.sin_addr.s_addr) { 24121 add_sip_domain(ast_inet_ntoa(bindaddr.sin_addr), SIP_DOMAIN_AUTO, NULL); 24122 } else if (internip.sin_addr.s_addr) { 24123 /* Our internal IP address, if configured */ 24124 add_sip_domain(ast_inet_ntoa(internip.sin_addr), SIP_DOMAIN_AUTO, NULL); 24125 } else { 24126 ast_log(LOG_NOTICE, "Can't add wildcard IP address to domain list, please add IP address to domain manually.\n"); 24127 } 24128 24129 /* If TCP is running on a different IP than UDP, then add it too */ 24130 if (sip_tcp_desc.local_address.sin_addr.s_addr && !inaddrcmp(&bindaddr, &sip_tcp_desc.local_address)) 24131 add_sip_domain(ast_inet_ntoa(sip_tcp_desc.local_address.sin_addr), SIP_DOMAIN_AUTO, NULL); 24132 24133 /* If TLS is running on a differen IP than UDP and TCP, then add that too */ 24134 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)) 24135 add_sip_domain(ast_inet_ntoa(sip_tls_desc.local_address.sin_addr), SIP_DOMAIN_AUTO, NULL); 24136 24137 /* Our extern IP address, if configured */ 24138 if (externip.sin_addr.s_addr) 24139 add_sip_domain(ast_inet_ntoa(externip.sin_addr), SIP_DOMAIN_AUTO, NULL); 24140 24141 /* Extern host name (NAT traversal support) */ 24142 if (!ast_strlen_zero(externhost)) 24143 add_sip_domain(externhost, SIP_DOMAIN_AUTO, NULL); 24144 24145 /* Our host name */ 24146 if (!gethostname(temp, sizeof(temp))) 24147 add_sip_domain(temp, SIP_DOMAIN_AUTO, NULL); 24148 } 24149 24150 /* Release configuration from memory */ 24151 ast_config_destroy(cfg); 24152 24153 /* Load the list of manual NOTIFY types to support */ 24154 if (notify_types) 24155 ast_config_destroy(notify_types); 24156 notify_types = ast_config_load(notify_config, config_flags); 24157 24158 /* Done, tell the manager */ 24159 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); 24160 run_end = time(0); 24161 ast_debug(4, "SIP reload_config done...Runtime= %d sec\n", (int)(run_end-run_start)); 24162 24163 return 0; 24164 }
static char * remove_uri_parameters | ( | char * | uri | ) | [static] |
Definition at line 9898 of file chan_sip.c.
Referenced by extract_uri(), parse_moved_contact(), register_verify(), reqprep(), and transmit_state_notify().
09899 { 09900 char *atsign; 09901 atsign = strchr(uri, '@'); /* First, locate the at sign */ 09902 if (!atsign) 09903 atsign = uri; /* Ok hostname only, let's stick with the rest */ 09904 atsign = strchr(atsign, ';'); /* Locate semi colon */ 09905 if (atsign) 09906 *atsign = '\0'; /* Kill at the semi colon */ 09907 return uri; 09908 }
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 13131 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().
13132 { 13133 /* replace callerid if rpid found, and not restricted */ 13134 if (!ast_strlen_zero(rpid_num) && ast_test_flag(&p->flags[0], SIP_TRUSTRPID)) { 13135 char *tmp = ast_strdupa(rpid_num); /* XXX the copy can be done later */ 13136 if (!ast_strlen_zero(calleridname)) 13137 ast_string_field_set(p, cid_name, calleridname); 13138 if (global_shrinkcallerid && ast_is_shrinkable_phonenumber(tmp)) 13139 ast_shrink_phone_number(tmp); 13140 ast_string_field_set(p, cid_num, tmp); 13141 } 13142 }
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 16261 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().
16262 { 16263 char tmp[512]; 16264 char *c; 16265 char oldnonce[256]; 16266 16267 /* table of recognised keywords, and places where they should be copied */ 16268 const struct x { 16269 const char *key; 16270 const ast_string_field *field; 16271 } *i, keys[] = { 16272 { "realm=", &p->realm }, 16273 { "nonce=", &p->nonce }, 16274 { "opaque=", &p->opaque }, 16275 { "qop=", &p->qop }, 16276 { "domain=", &p->domain }, 16277 { NULL, 0 }, 16278 }; 16279 16280 ast_copy_string(tmp, get_header(req, header), sizeof(tmp)); 16281 if (ast_strlen_zero(tmp)) 16282 return -1; 16283 if (strncasecmp(tmp, "Digest ", strlen("Digest "))) { 16284 ast_log(LOG_WARNING, "missing Digest.\n"); 16285 return -1; 16286 } 16287 c = tmp + strlen("Digest "); 16288 ast_copy_string(oldnonce, p->nonce, sizeof(oldnonce)); 16289 while (c && *(c = ast_skip_blanks(c))) { /* lookup for keys */ 16290 for (i = keys; i->key != NULL; i++) { 16291 char *src, *separator; 16292 if (strncasecmp(c, i->key, strlen(i->key)) != 0) 16293 continue; 16294 /* Found. Skip keyword, take text in quotes or up to the separator. */ 16295 c += strlen(i->key); 16296 if (*c == '"') { 16297 src = ++c; 16298 separator = "\""; 16299 } else { 16300 src = c; 16301 separator = ","; 16302 } 16303 strsep(&c, separator); /* clear separator and move ptr */ 16304 ast_string_field_ptr_set(p, i->field, src); 16305 break; 16306 } 16307 if (i->key == NULL) /* not found, try ',' */ 16308 strsep(&c, ","); 16309 } 16310 /* Reset nonce count */ 16311 if (strcmp(p->nonce, oldnonce)) 16312 p->noncecount = 0; 16313 16314 /* Save auth data for following registrations */ 16315 if (p->registry) { 16316 struct sip_registry *r = p->registry; 16317 16318 if (strcmp(r->nonce, p->nonce)) { 16319 ast_string_field_set(r, realm, p->realm); 16320 ast_string_field_set(r, nonce, p->nonce); 16321 ast_string_field_set(r, domain, p->domain); 16322 ast_string_field_set(r, opaque, p->opaque); 16323 ast_string_field_set(r, qop, p->qop); 16324 r->noncecount = 0; 16325 } 16326 } 16327 return build_reply_digest(p, sipmethod, digest, digest_len); 16328 }
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 8791 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.
08792 { 08793 struct sip_request *orig = &p->initreq; 08794 char stripped[80]; 08795 char tmp[80]; 08796 char newto[256]; 08797 const char *c; 08798 const char *ot, *of; 08799 int is_strict = FALSE; /*!< Strict routing flag */ 08800 int is_outbound = ast_test_flag(&p->flags[0], SIP_OUTGOING); /* Session direction */ 08801 08802 memset(req, 0, sizeof(struct sip_request)); 08803 08804 snprintf(p->lastmsg, sizeof(p->lastmsg), "Tx: %s", sip_methods[sipmethod].text); 08805 08806 if (!seqno) { 08807 p->ocseq++; 08808 seqno = p->ocseq; 08809 } 08810 08811 /* A CANCEL must have the same branch as the INVITE that it is canceling. */ 08812 if (sipmethod == SIP_CANCEL) { 08813 p->branch = p->invite_branch; 08814 build_via(p); 08815 } else if (newbranch && (sipmethod == SIP_INVITE)) { 08816 p->branch ^= ast_random(); 08817 p->invite_branch = p->branch; 08818 build_via(p); 08819 } else if (newbranch) { 08820 p->branch ^= ast_random(); 08821 build_via(p); 08822 } 08823 08824 /* Check for strict or loose router */ 08825 if (p->route && !ast_strlen_zero(p->route->hop) && strstr(p->route->hop, ";lr") == NULL) { 08826 is_strict = TRUE; 08827 if (sipdebug) 08828 ast_debug(1, "Strict routing enforced for session %s\n", p->callid); 08829 } 08830 08831 if (sipmethod == SIP_CANCEL) 08832 c = REQ_OFFSET_TO_STR(&p->initreq, rlPart2); /* Use original URI */ 08833 else if (sipmethod == SIP_ACK) { 08834 /* Use URI from Contact: in 200 OK (if INVITE) 08835 (we only have the contacturi on INVITEs) */ 08836 if (!ast_strlen_zero(p->okcontacturi)) 08837 c = is_strict ? p->route->hop : p->okcontacturi; 08838 else 08839 c = REQ_OFFSET_TO_STR(&p->initreq, rlPart2); 08840 } else if (!ast_strlen_zero(p->okcontacturi)) 08841 c = is_strict ? p->route->hop : p->okcontacturi; /* Use for BYE or REINVITE */ 08842 else if (!ast_strlen_zero(p->uri)) 08843 c = p->uri; 08844 else { 08845 char *n; 08846 /* We have no URI, use To: or From: header as URI (depending on direction) */ 08847 ast_copy_string(stripped, get_header(orig, is_outbound ? "To" : "From"), 08848 sizeof(stripped)); 08849 n = get_in_brackets(stripped); 08850 c = remove_uri_parameters(n); 08851 } 08852 init_req(req, sipmethod, c); 08853 08854 snprintf(tmp, sizeof(tmp), "%d %s", seqno, sip_methods[sipmethod].text); 08855 08856 add_header(req, "Via", p->via); 08857 if (p->route) { 08858 set_destination(p, p->route->hop); 08859 add_route(req, is_strict ? p->route->next : p->route); 08860 } 08861 add_header(req, "Max-Forwards", DEFAULT_MAX_FORWARDS); 08862 08863 ot = get_header(orig, "To"); 08864 of = get_header(orig, "From"); 08865 08866 /* Add tag *unless* this is a CANCEL, in which case we need to send it exactly 08867 as our original request, including tag (or presumably lack thereof) */ 08868 if (!strcasestr(ot, "tag=") && sipmethod != SIP_CANCEL) { 08869 /* Add the proper tag if we don't have it already. If they have specified 08870 their tag, use it. Otherwise, use our own tag */ 08871 if (is_outbound && !ast_strlen_zero(p->theirtag)) 08872 snprintf(newto, sizeof(newto), "%s;tag=%s", ot, p->theirtag); 08873 else if (!is_outbound) 08874 snprintf(newto, sizeof(newto), "%s;tag=%s", ot, p->tag); 08875 else 08876 snprintf(newto, sizeof(newto), "%s", ot); 08877 ot = newto; 08878 } 08879 08880 if (is_outbound) { 08881 add_header(req, "From", of); 08882 add_header(req, "To", ot); 08883 } else { 08884 add_header(req, "From", ot); 08885 add_header(req, "To", of); 08886 } 08887 /* Do not add Contact for MESSAGE, BYE and Cancel requests */ 08888 if (sipmethod != SIP_BYE && sipmethod != SIP_CANCEL && sipmethod != SIP_MESSAGE) 08889 add_header(req, "Contact", p->our_contact); 08890 08891 copy_header(req, orig, "Call-ID"); 08892 add_header(req, "CSeq", tmp); 08893 08894 if (!ast_strlen_zero(global_useragent)) 08895 add_header(req, "User-Agent", global_useragent); 08896 08897 if (!ast_strlen_zero(p->rpid)) 08898 add_header(req, "Remote-Party-ID", p->rpid); 08899 08900 if (!ast_strlen_zero(p->url)) { 08901 add_header(req, "Access-URL", p->url); 08902 ast_string_field_set(p, url, NULL); 08903 } 08904 08905 /* Add Session-Timers related headers if the feature is active for this session. 08906 An exception to this behavior is the ACK request. Since Asterisk never requires 08907 session-timers support from a remote end-point (UAS) in an INVITE, it must 08908 not send 'Require: timer' header in the ACK request. 08909 This should only be added in the INVITE transactions, not MESSAGE or REFER or other 08910 in-dialog messages. 08911 */ 08912 if (p->stimer && p->stimer->st_active == TRUE && p->stimer->st_active_peer_ua == TRUE 08913 && sipmethod == SIP_INVITE) { 08914 char se_hdr[256]; 08915 snprintf(se_hdr, sizeof(se_hdr), "%d;refresher=%s", p->stimer->st_interval, 08916 strefresher2str(p->stimer->st_ref)); 08917 add_header(req, "Require", "timer"); 08918 add_header(req, "Session-Expires", se_hdr); 08919 snprintf(se_hdr, sizeof(se_hdr), "%d", st_get_se(p, FALSE)); 08920 add_header(req, "Min-SE", se_hdr); 08921 } 08922 08923 return 0; 08924 }
static int resp_needs_contact | ( | const char * | msg, | |
enum sipmethod | method | |||
) | [inline, static] |
Test if this response needs a contact header.
Definition at line 8665 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().
08665 { 08666 /* Requirements for Contact header inclusion in responses generated 08667 * from the header tables found in the following RFCs. Where the 08668 * Contact header was marked mandatory (m) or optional (o) this 08669 * function returns 1. 08670 * 08671 * - RFC 3261 (ACK, BYE, CANCEL, INVITE, OPTIONS, REGISTER) 08672 * - RFC 2976 (INFO) 08673 * - RFC 3262 (PRACK) 08674 * - RFC 3265 (SUBSCRIBE, NOTIFY) 08675 * - RFC 3311 (UPDATE) 08676 * - RFC 3428 (MESSAGE) 08677 * - RFC 3515 (REFER) 08678 * - RFC 3903 (PUBLISH) 08679 */ 08680 08681 switch (method) { 08682 /* 1xx, 2xx, 3xx, 485 */ 08683 case SIP_INVITE: 08684 case SIP_UPDATE: 08685 case SIP_SUBSCRIBE: 08686 case SIP_NOTIFY: 08687 if ((msg[0] >= '1' && msg[0] <= '3') || !strncmp(msg, "485", 3)) 08688 return 1; 08689 break; 08690 08691 /* 2xx, 3xx, 485 */ 08692 case SIP_REGISTER: 08693 case SIP_OPTIONS: 08694 if (msg[0] == '2' || msg[0] == '3' || !strncmp(msg, "485", 3)) 08695 return 1; 08696 break; 08697 08698 /* 3xx, 485 */ 08699 case SIP_BYE: 08700 case SIP_PRACK: 08701 case SIP_MESSAGE: 08702 case SIP_PUBLISH: 08703 if (msg[0] == '3' || !strncmp(msg, "485", 3)) 08704 return 1; 08705 break; 08706 08707 /* 2xx, 3xx, 4xx, 5xx, 6xx */ 08708 case SIP_REFER: 08709 if (msg[0] >= '2' && msg[0] <= '6') 08710 return 1; 08711 break; 08712 08713 /* contact will not be included for everything else */ 08714 case SIP_ACK: 08715 case SIP_CANCEL: 08716 case SIP_INFO: 08717 case SIP_PING: 08718 default: 08719 return 0; 08720 } 08721 return 0; 08722 }
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 8725 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, sip_pvt::fullcontact, 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.
08726 { 08727 char newto[256]; 08728 const char *ot; 08729 08730 init_resp(resp, msg); 08731 copy_via_headers(p, resp, req, "Via"); 08732 if (msg[0] == '1' || msg[0] == '2') 08733 copy_all_header(resp, req, "Record-Route"); 08734 copy_header(resp, req, "From"); 08735 ot = get_header(req, "To"); 08736 if (!strcasestr(ot, "tag=") && strncmp(msg, "100", 3)) { 08737 /* Add the proper tag if we don't have it already. If they have specified 08738 their tag, use it. Otherwise, use our own tag */ 08739 if (!ast_strlen_zero(p->theirtag) && ast_test_flag(&p->flags[0], SIP_OUTGOING)) 08740 snprintf(newto, sizeof(newto), "%s;tag=%s", ot, p->theirtag); 08741 else if (p->tag && !ast_test_flag(&p->flags[0], SIP_OUTGOING)) 08742 snprintf(newto, sizeof(newto), "%s;tag=%s", ot, p->tag); 08743 else 08744 ast_copy_string(newto, ot, sizeof(newto)); 08745 ot = newto; 08746 } 08747 add_header(resp, "To", ot); 08748 copy_header(resp, req, "Call-ID"); 08749 copy_header(resp, req, "CSeq"); 08750 if (!ast_strlen_zero(global_useragent)) 08751 add_header(resp, "Server", global_useragent); 08752 add_header(resp, "Allow", ALLOWED_METHODS); 08753 add_header(resp, "Supported", SUPPORTED_EXTENSIONS); 08754 08755 /* If this is an invite, add Session-Timers related headers if the feature is active for this session */ 08756 if (p->method == SIP_INVITE && p->stimer && p->stimer->st_active == TRUE && p->stimer->st_active_peer_ua == TRUE) { 08757 char se_hdr[256]; 08758 snprintf(se_hdr, sizeof(se_hdr), "%d;refresher=%s", p->stimer->st_interval, 08759 strefresher2str(p->stimer->st_ref)); 08760 add_header(resp, "Require", "timer"); 08761 add_header(resp, "Session-Expires", se_hdr); 08762 } 08763 08764 if (msg[0] == '2' && (p->method == SIP_SUBSCRIBE || p->method == SIP_REGISTER)) { 08765 /* For registration responses, we also need expiry and 08766 contact info */ 08767 char tmp[256]; 08768 08769 snprintf(tmp, sizeof(tmp), "%d", p->expiry); 08770 add_header(resp, "Expires", tmp); 08771 if (p->expiry) { /* Only add contact if we have an expiry time */ 08772 char contact[SIPBUFSIZE]; 08773 const char *contact_uri = p->method == SIP_SUBSCRIBE ? p->our_contact : p->fullcontact; 08774 char *brackets = strchr(contact_uri, '<'); 08775 snprintf(contact, sizeof(contact), "%s%s%s;expires=%d", brackets ? "" : "<", contact_uri, brackets ? "" : ">", p->expiry); 08776 add_header(resp, "Contact", contact); /* Not when we unregister */ 08777 } 08778 } else if (!ast_strlen_zero(p->our_contact) && resp_needs_contact(msg, p->method)) { 08779 add_header(resp, "Contact", p->our_contact); 08780 } 08781 08782 if (!ast_strlen_zero(p->url)) { 08783 add_header(resp, "Access-URL", p->url); 08784 ast_string_field_set(p, url, NULL); 08785 } 08786 08787 return 0; 08788 }
static int restart_monitor | ( | void | ) | [static] |
Start the channel monitor thread.
Definition at line 21571 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.
21572 { 21573 /* If we're supposed to be stopped -- stay stopped */ 21574 if (monitor_thread == AST_PTHREADT_STOP) 21575 return 0; 21576 ast_mutex_lock(&monlock); 21577 if (monitor_thread == pthread_self()) { 21578 ast_mutex_unlock(&monlock); 21579 ast_log(LOG_WARNING, "Cannot kill myself\n"); 21580 return -1; 21581 } 21582 if (monitor_thread != AST_PTHREADT_NULL) { 21583 /* Wake up the thread */ 21584 pthread_kill(monitor_thread, SIGURG); 21585 } else { 21586 /* Start a new monitor */ 21587 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) { 21588 ast_mutex_unlock(&monlock); 21589 ast_log(LOG_ERROR, "Unable to start monitor thread.\n"); 21590 return -1; 21591 } 21592 } 21593 ast_mutex_unlock(&monlock); 21594 return 0; 21595 }
static void restart_session_timer | ( | struct sip_pvt * | p | ) | [static] |
Session-Timers: Restart session timer.
Definition at line 21599 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().
21600 { 21601 if (!p->stimer) { 21602 ast_log(LOG_WARNING, "Null stimer in restart_session_timer - %s\n", p->callid); 21603 return; 21604 } 21605 21606 if (p->stimer->st_active == TRUE) { 21607 AST_SCHED_DEL_UNREF(sched, p->stimer->st_schedid, 21608 dialog_unref(p, "Removing session timer ref")); 21609 ast_debug(2, "Session timer stopped: %d - %s\n", p->stimer->st_schedid, p->callid); 21610 start_session_timer(p); 21611 } 21612 }
static int retrans_pkt | ( | const void * | data | ) | [static] |
Retransmit SIP message if no answer (Called from scheduler).
Definition at line 3344 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.
03345 { 03346 struct sip_pkt *pkt = (struct sip_pkt *)data, *prev, *cur = NULL; 03347 int reschedule = DEFAULT_RETRANS; 03348 int xmitres = 0; 03349 03350 /* Lock channel PVT */ 03351 sip_pvt_lock(pkt->owner); 03352 03353 if (pkt->retrans < MAX_RETRANS) { 03354 pkt->retrans++; 03355 if (!pkt->timer_t1) { /* Re-schedule using timer_a and timer_t1 */ 03356 if (sipdebug) 03357 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); 03358 } else { 03359 int siptimer_a; 03360 03361 if (sipdebug) 03362 ast_debug(4, "SIP TIMER: Rescheduling retransmission #%d (%d) %s - %d\n", pkt->retransid, pkt->retrans, sip_methods[pkt->method].text, pkt->method); 03363 if (!pkt->timer_a) 03364 pkt->timer_a = 2 ; 03365 else 03366 pkt->timer_a = 2 * pkt->timer_a; 03367 03368 /* For non-invites, a maximum of 4 secs */ 03369 siptimer_a = pkt->timer_t1 * pkt->timer_a; /* Double each time */ 03370 if (pkt->method != SIP_INVITE && siptimer_a > 4000) 03371 siptimer_a = 4000; 03372 03373 /* Reschedule re-transmit */ 03374 reschedule = siptimer_a; 03375 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); 03376 } 03377 03378 if (sip_debug_test_pvt(pkt->owner)) { 03379 const struct sockaddr_in *dst = sip_real_dst(pkt->owner); 03380 ast_verbose("Retransmitting #%d (%s) to %s:%d:\n%s\n---\n", 03381 pkt->retrans, sip_nat_mode(pkt->owner), 03382 ast_inet_ntoa(dst->sin_addr), 03383 ntohs(dst->sin_port), pkt->data->str); 03384 } 03385 03386 append_history(pkt->owner, "ReTx", "%d %s", reschedule, pkt->data->str); 03387 xmitres = __sip_xmit(pkt->owner, pkt->data, pkt->packetlen); 03388 sip_pvt_unlock(pkt->owner); 03389 if (xmitres == XMIT_ERROR) 03390 ast_log(LOG_WARNING, "Network error on retransmit in dialog %s\n", pkt->owner->callid); 03391 else 03392 return reschedule; 03393 } 03394 /* Too many retries */ 03395 if (pkt->owner && pkt->method != SIP_OPTIONS && xmitres == 0) { 03396 if (pkt->is_fatal || sipdebug) /* Tell us if it's critical or if we're debugging */ 03397 ast_log(LOG_WARNING, "Maximum retries exceeded on transmission %s for seqno %d (%s %s) -- See doc/sip-retransmit.txt.\n", 03398 pkt->owner->callid, pkt->seqno, 03399 pkt->is_fatal ? "Critical" : "Non-critical", pkt->is_resp ? "Response" : "Request"); 03400 } else if (pkt->method == SIP_OPTIONS && sipdebug) { 03401 ast_log(LOG_WARNING, "Cancelling retransmit of OPTIONs (call id %s) -- See doc/sip-retransmit.txt.\n", pkt->owner->callid); 03402 03403 } 03404 if (xmitres == XMIT_ERROR) { 03405 ast_log(LOG_WARNING, "Transmit error :: Cancelling transmission on Call ID %s\n", pkt->owner->callid); 03406 append_history(pkt->owner, "XmitErr", "%s", pkt->is_fatal ? "(Critical)" : "(Non-critical)"); 03407 } else 03408 append_history(pkt->owner, "MaxRetries", "%s", pkt->is_fatal ? "(Critical)" : "(Non-critical)"); 03409 03410 pkt->retransid = -1; 03411 03412 if (pkt->is_fatal) { 03413 while(pkt->owner->owner && ast_channel_trylock(pkt->owner->owner)) { 03414 sip_pvt_unlock(pkt->owner); /* SIP_PVT, not channel */ 03415 usleep(1); 03416 sip_pvt_lock(pkt->owner); 03417 } 03418 03419 if (pkt->owner->owner && !pkt->owner->owner->hangupcause) 03420 pkt->owner->owner->hangupcause = AST_CAUSE_NO_USER_RESPONSE; 03421 03422 if (pkt->owner->owner) { 03423 sip_alreadygone(pkt->owner); 03424 ast_log(LOG_WARNING, "Hanging up call %s - no reply to our critical packet (see doc/sip-retransmit.txt).\n", pkt->owner->callid); 03425 ast_queue_hangup_with_cause(pkt->owner->owner, AST_CAUSE_PROTOCOL_ERROR); 03426 ast_channel_unlock(pkt->owner->owner); 03427 } else { 03428 /* If no channel owner, destroy now */ 03429 03430 /* Let the peerpoke system expire packets when the timer expires for poke_noanswer */ 03431 if (pkt->method != SIP_OPTIONS && pkt->method != SIP_REGISTER) { 03432 pkt->owner->needdestroy = 1; 03433 sip_alreadygone(pkt->owner); 03434 append_history(pkt->owner, "DialogKill", "Killing this failed dialog immediately"); 03435 } 03436 } 03437 } 03438 03439 if (pkt->method == SIP_BYE) { 03440 /* We're not getting answers on SIP BYE's. Tear down the call anyway. */ 03441 if (pkt->owner->owner) 03442 ast_channel_unlock(pkt->owner->owner); 03443 append_history(pkt->owner, "ByeFailure", "Remote peer doesn't respond to bye. Destroying call anyway."); 03444 pkt->owner->needdestroy = 1; 03445 } 03446 03447 /* Remove the packet */ 03448 for (prev = NULL, cur = pkt->owner->packets; cur; prev = cur, cur = cur->next) { 03449 if (cur == pkt) { 03450 UNLINK(cur, pkt->owner->packets, prev); 03451 sip_pvt_unlock(pkt->owner); 03452 if (pkt->owner) 03453 pkt->owner = dialog_unref(pkt->owner,"pkt is being freed, its dialog ref is dead now"); 03454 if (pkt->data) 03455 ast_free(pkt->data); 03456 pkt->data = NULL; 03457 ast_free(pkt); 03458 return 0; 03459 } 03460 } 03461 /* error case */ 03462 ast_log(LOG_WARNING, "Weird, couldn't find packet owner!\n"); 03463 sip_pvt_unlock(pkt->owner); 03464 return 0; 03465 }
static int scheduler_process_request_queue | ( | const void * | data | ) | [static] |
Definition at line 20883 of file chan_sip.c.
References ast_channel_trylock, sip_pvt::owner, sip_pvt_lock, and sip_pvt_unlock.
Referenced by queue_request().
20884 { 20885 struct sip_pvt *p = (struct sip_pvt *) data; 20886 int recount = 0; 20887 int nounlock = 0; 20888 int lockretry; 20889 20890 for (lockretry = 10; lockretry > 0; lockretry--) { 20891 sip_pvt_lock(p); 20892 20893 /* lock the owner if it has one -- we may need it */ 20894 /* because this is deadlock-prone, we need to try and unlock if failed */ 20895 if (!p->owner || !ast_channel_trylock(p->owner)) { 20896 break; /* locking succeeded */ 20897 } 20898 20899 if (lockretry != 1) { 20900 sip_pvt_unlock(p); 20901 /* Sleep for a very short amount of time */ 20902 usleep(1); 20903 } 20904 } 20905 20906 if (!lockretry) { 20907 int retry = !AST_LIST_EMPTY(&p->request_queue); 20908 20909 /* we couldn't get the owner lock, which is needed to process 20910 the queued requests, so return a non-zero value, which will 20911 cause the scheduler to run this request again later if there 20912 still requests to be processed 20913 */ 20914 sip_pvt_unlock(p); 20915 if (!retry) { 20916 dialog_unref(p, "The ref to a dialog passed to this sched callback is going out of scope; unref it."); 20917 } 20918 return retry; 20919 }; 20920 20921 process_request_queue(p, &recount, &nounlock); 20922 p->request_queue_sched_id = -1; 20923 20924 if (p->owner && !nounlock) { 20925 ast_channel_unlock(p->owner); 20926 } 20927 sip_pvt_unlock(p); 20928 20929 if (recount) { 20930 ast_update_use_count(); 20931 } 20932 20933 dialog_unref(p, "The ref to a dialog passed to this sched callback is going out of scope; unref it."); 20934 20935 return 0; 20936 }
static int send_provisional_keepalive | ( | const void * | data | ) | [static] |
Definition at line 3792 of file chan_sip.c.
References send_provisional_keepalive_full().
Referenced by update_provisional_keepalive().
03792 { 03793 struct sip_pvt *pvt = (struct sip_pvt *) data; 03794 03795 return send_provisional_keepalive_full(pvt, 0); 03796 }
static int send_provisional_keepalive_full | ( | struct sip_pvt * | pvt, | |
int | with_sdp | |||
) | [static] |
Definition at line 3772 of file chan_sip.c.
References FALSE, sip_pvt::initreq, INV_COMPLETED, sip_pvt::invitestate, sip_pvt::last_provisional, msg, PROVIS_KEEPALIVE_TIMEOUT, S_OR, transmit_response(), transmit_response_with_sdp(), and XMIT_UNRELIABLE.
Referenced by send_provisional_keepalive(), and send_provisional_keepalive_with_sdp().
03773 { 03774 const char *msg = NULL; 03775 03776 if (!pvt->last_provisional || !strncasecmp(pvt->last_provisional, "100", 3)) { 03777 msg = "183 Session Progress"; 03778 } 03779 03780 if (pvt->invitestate < INV_COMPLETED) { 03781 if (with_sdp) { 03782 transmit_response_with_sdp(pvt, S_OR(msg, pvt->last_provisional), &pvt->initreq, XMIT_UNRELIABLE, FALSE); 03783 } else { 03784 transmit_response(pvt, S_OR(msg, pvt->last_provisional), &pvt->initreq); 03785 } 03786 return PROVIS_KEEPALIVE_TIMEOUT; 03787 } 03788 03789 return 0; 03790 }
static int send_provisional_keepalive_with_sdp | ( | const void * | data | ) | [static] |
Definition at line 3798 of file chan_sip.c.
References send_provisional_keepalive_full().
Referenced by update_provisional_keepalive().
03798 { 03799 struct sip_pvt *pvt = (void *)data; 03800 03801 return send_provisional_keepalive_full(pvt, 1); 03802 }
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 3850 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.
03851 { 03852 int res; 03853 03854 /* If we have an outbound proxy, reset peer address 03855 Only do this once. 03856 */ 03857 if (p->outboundproxy) { 03858 p->sa = p->outboundproxy->ip; 03859 } 03860 03861 add_blank(req); 03862 if (sip_debug_test_pvt(p)) { 03863 if (ast_test_flag(&p->flags[0], SIP_NAT_ROUTE)) 03864 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); 03865 else 03866 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); 03867 } 03868 if (p->do_history) { 03869 struct sip_request tmp = { .rlPart1 = 0, }; 03870 parse_copy(&tmp, req); 03871 append_history(p, reliable ? "TxReqRel" : "TxReq", "%s / %s - %s", tmp.data->str, get_header(&tmp, "CSeq"), sip_methods[tmp.method].text); 03872 ast_free(tmp.data); 03873 } 03874 res = (reliable) ? 03875 __sip_reliable_xmit(p, seqno, 0, req->data, req->len, (reliable == XMIT_CRITICAL), req->method) : 03876 __sip_xmit(p, req->data, req->len); 03877 if (req->data) { 03878 ast_free(req->data); 03879 req->data = NULL; 03880 } 03881 return res; 03882 }
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 3813 of file chan_sip.c.
References __sip_reliable_xmit(), __sip_xmit(), add_blank(), append_history, ast_free, ast_inet_ntoa(), AST_SCHED_DEL_UNREF, ast_verbose, sip_request::data, dialog_unref(), sip_pvt::do_history, get_header(), sip_pvt::initreq, sip_request::len, sip_request::method, parse_copy(), sip_pvt::provisional_keepalive_sched_id, REQ_OFFSET_TO_STR, sip_request::rlPart1, sip_request::rlPart2, sched, sip_debug_test_pvt(), SIP_INVITE, sip_methods, sip_nat_mode(), sip_real_dst(), SIP_RESPONSE, SIP_UNKNOWN, ast_str::str, cfsip_methods::text, and XMIT_CRITICAL.
03814 { 03815 int res; 03816 03817 add_blank(req); 03818 if (sip_debug_test_pvt(p)) { 03819 const struct sockaddr_in *dst = sip_real_dst(p); 03820 03821 ast_verbose("\n<--- %sTransmitting (%s) to %s:%d --->\n%s\n<------------>\n", 03822 reliable ? "Reliably " : "", sip_nat_mode(p), 03823 ast_inet_ntoa(dst->sin_addr), 03824 ntohs(dst->sin_port), req->data->str); 03825 } 03826 if (p->do_history) { 03827 struct sip_request tmp = { .rlPart1 = 0, }; 03828 parse_copy(&tmp, req); 03829 append_history(p, reliable ? "TxRespRel" : "TxResp", "%s / %s - %s", tmp.data->str, get_header(&tmp, "CSeq"), 03830 (tmp.method == SIP_RESPONSE || tmp.method == SIP_UNKNOWN) ? REQ_OFFSET_TO_STR(&tmp, rlPart2) : sip_methods[tmp.method].text); 03831 ast_free(tmp.data); 03832 } 03833 03834 /* If we are sending a final response to an INVITE, stop retransmitting provisional responses */ 03835 if (p->initreq.method == SIP_INVITE && reliable == XMIT_CRITICAL) { 03836 AST_SCHED_DEL_UNREF(sched, p->provisional_keepalive_sched_id, dialog_unref(p, "when you delete the provisional_keepalive_sched_id, you should dec the refcount for the stored dialog ptr")); 03837 } 03838 03839 res = (reliable) ? 03840 __sip_reliable_xmit(p, seqno, 1, req->data, req->len, (reliable == XMIT_CRITICAL), req->method) : 03841 __sip_xmit(p, req->data, req->len); 03842 ast_free(req->data); 03843 req->data = NULL; 03844 if (res > 0) 03845 return 0; 03846 return res; 03847 }
static int set_address_from_contact | ( | struct sip_pvt * | pvt | ) | [static] |
Change the other partys IP address based on given contact.
Definition at line 11413 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().
11414 { 11415 if (ast_test_flag(&pvt->flags[0], SIP_NAT_ROUTE)) { 11416 /* NAT: Don't trust the contact field. Just use what they came to us 11417 with. */ 11418 pvt->sa = pvt->recv; 11419 return 0; 11420 } 11421 11422 return __set_address_from_contact(pvt->fullcontact, &pvt->sa, pvt->socket.type == SIP_TRANSPORT_TLS ? 1 : 0); 11423 }
static void set_destination | ( | struct sip_pvt * | p, | |
char * | uri | |||
) | [static] |
Set destination from SIP URI.
Definition at line 8571 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().
08572 { 08573 char *h, *maddr, hostname[256]; 08574 int port, hn; 08575 struct hostent *hp; 08576 struct ast_hostent ahp; 08577 int debug=sip_debug_test_pvt(p); 08578 08579 /* Parse uri to h (host) and port - uri is already just the part inside the <> */ 08580 /* general form we are expecting is sip[s]:username[:password][;parameter]@host[:port][;...] */ 08581 08582 if (debug) 08583 ast_verbose("set_destination: Parsing <%s> for address/port to send to\n", uri); 08584 08585 /* Find and parse hostname */ 08586 h = strchr(uri, '@'); 08587 if (h) 08588 ++h; 08589 else { 08590 h = uri; 08591 if (!strncasecmp(h, "sip:", 4)) 08592 h += 4; 08593 else if (!strncasecmp(h, "sips:", 5)) 08594 h += 5; 08595 } 08596 hn = strcspn(h, ":;>") + 1; 08597 if (hn > sizeof(hostname)) 08598 hn = sizeof(hostname); 08599 ast_copy_string(hostname, h, hn); 08600 /* XXX bug here if string has been trimmed to sizeof(hostname) */ 08601 h += hn - 1; 08602 08603 /* Is "port" present? if not default to STANDARD_SIP_PORT */ 08604 if (*h == ':') { 08605 /* Parse port */ 08606 ++h; 08607 port = strtol(h, &h, 10); 08608 } 08609 else 08610 port = STANDARD_SIP_PORT; 08611 08612 /* Got the hostname:port - but maybe there's a "maddr=" to override address? */ 08613 maddr = strstr(h, "maddr="); 08614 if (maddr) { 08615 maddr += 6; 08616 hn = strspn(maddr, "0123456789.") + 1; 08617 if (hn > sizeof(hostname)) 08618 hn = sizeof(hostname); 08619 ast_copy_string(hostname, maddr, hn); 08620 } 08621 08622 hp = ast_gethostbyname(hostname, &ahp); 08623 if (hp == NULL) { 08624 ast_log(LOG_WARNING, "Can't find address for host '%s'\n", hostname); 08625 return; 08626 } 08627 p->sa.sin_family = AF_INET; 08628 memcpy(&p->sa.sin_addr, hp->h_addr, sizeof(p->sa.sin_addr)); 08629 p->sa.sin_port = htons(port); 08630 if (debug) 08631 ast_verbose("set_destination: set destination to %s, port %d\n", ast_inet_ntoa(p->sa.sin_addr), port); 08632 }
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 22313 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().
22314 { 22315 if (ast_strlen_zero(value)) 22316 return; 22317 22318 if (!ast_false(value)) { 22319 char buf[64]; 22320 char *word, *next; 22321 22322 ast_copy_string(buf, value, sizeof(buf)); 22323 next = buf; 22324 while ((word = strsep(&next, ","))) { 22325 if (!strcasecmp(word, "port")) 22326 ast_set_flag(&flags[0], SIP_INSECURE_PORT); 22327 else if (!strcasecmp(word, "invite")) 22328 ast_set_flag(&flags[0], SIP_INSECURE_INVITE); 22329 else 22330 ast_log(LOG_WARNING, "Unknown insecure mode '%s' on line %d\n", value, lineno); 22331 } 22332 } 22333 }
static void set_nonce_randdata | ( | struct sip_pvt * | p, | |
int | forceupdate | |||
) | [static] |
builds the sip_pvt's randdata field which is used for the nonce challenge. When forceupdate is not set, the nonce is only updated if the current one is stale. In this case, a stalenonce is one which has already received a response, if a nonce has not received a response it is not always necessary or beneficial to create a new one.
Definition at line 11758 of file chan_sip.c.
References ast_random(), ast_string_field_build, ast_strlen_zero(), sip_pvt::randdata, and sip_pvt::stalenonce.
Referenced by check_auth(), and transmit_fake_auth_response().
11759 { 11760 if (p->stalenonce || forceupdate || ast_strlen_zero(p->randdata)) { 11761 ast_string_field_build(p, randdata, "%08lx", ast_random()); /* Create nonce for challenge */ 11762 p->stalenonce = 0; 11763 } 11764 }
static void set_peer_defaults | ( | struct sip_peer * | peer | ) | [static] |
Set peer defaults before configuring specific configurations.
Definition at line 22665 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_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, set_socket_transport(), 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::t38_maxdatagram, sip_peer::timer_b, sip_peer::timer_t1, sip_peer::type, and sip_peer::vmexten.
Referenced by build_peer(), and temp_peer().
22666 { 22667 if (peer->expire == 0) { 22668 /* Don't reset expire or port time during reload 22669 if we have an active registration 22670 */ 22671 peer->expire = -1; 22672 peer->pokeexpire = -1; 22673 peer->addr.sin_port = htons(STANDARD_SIP_PORT); 22674 set_socket_transport(&peer->socket, SIP_TRANSPORT_UDP); 22675 } 22676 peer->type = SIP_TYPE_PEER; 22677 ast_copy_flags(&peer->flags[0], &global_flags[0], SIP_FLAGS_TO_COPY); 22678 ast_copy_flags(&peer->flags[1], &global_flags[1], SIP_PAGE2_FLAGS_TO_COPY); 22679 strcpy(peer->context, default_context); 22680 strcpy(peer->subscribecontext, default_subscribecontext); 22681 strcpy(peer->language, default_language); 22682 strcpy(peer->mohinterpret, default_mohinterpret); 22683 strcpy(peer->mohsuggest, default_mohsuggest); 22684 peer->addr.sin_family = AF_INET; 22685 peer->defaddr.sin_family = AF_INET; 22686 peer->capability = global_capability; 22687 peer->maxcallbitrate = default_maxcallbitrate; 22688 peer->rtptimeout = global_rtptimeout; 22689 peer->rtpholdtimeout = global_rtpholdtimeout; 22690 peer->rtpkeepalive = global_rtpkeepalive; 22691 peer->allowtransfer = global_allowtransfer; 22692 peer->autoframing = global_autoframing; 22693 peer->t38_maxdatagram = global_t38_maxdatagram; 22694 peer->qualifyfreq = global_qualifyfreq; 22695 if (global_callcounter) 22696 peer->call_limit=999; 22697 strcpy(peer->vmexten, default_vmexten); 22698 peer->secret[0] = '\0'; 22699 peer->md5secret[0] = '\0'; 22700 peer->cid_num[0] = '\0'; 22701 peer->cid_name[0] = '\0'; 22702 peer->fromdomain[0] = '\0'; 22703 peer->fromuser[0] = '\0'; 22704 peer->regexten[0] = '\0'; 22705 peer->callgroup = 0; 22706 peer->pickupgroup = 0; 22707 peer->maxms = default_qualify; 22708 peer->prefs = default_prefs; 22709 peer->stimer.st_mode_oper = global_st_mode; /* Session-Timers */ 22710 peer->stimer.st_ref = global_st_refresher; 22711 peer->stimer.st_min_se = global_min_se; 22712 peer->stimer.st_max_se = global_max_se; 22713 peer->timer_t1 = global_t1; 22714 peer->timer_b = global_timer_b; 22715 clear_peer_mailboxes(peer); 22716 }
static void set_socket_transport | ( | struct sip_socket * | socket, | |
int | transport | |||
) | [static] |
Definition at line 11214 of file chan_sip.c.
References ao2_ref, sip_socket::fd, sip_request::socket, sip_socket::tcptls_session, and sip_socket::type.
Referenced by _sip_tcp_helper_thread(), build_peer(), create_addr(), expire_register(), get_transport_pvt(), parse_moved_contact(), parse_register_contact(), set_peer_defaults(), sip_alloc(), sip_request_call(), sip_send_mwi_to_peer(), sipsock_read(), and transmit_register().
11215 { 11216 /* if the transport type changes, clear all socket data */ 11217 if (socket->type != transport) { 11218 socket->fd = -1; 11219 socket->type = transport; 11220 if (socket->tcptls_session) { 11221 ao2_ref(socket->tcptls_session, -1); 11222 socket->tcptls_session = NULL; 11223 } 11224 } 11225 }
static void set_t38_capabilities | ( | struct sip_pvt * | p | ) | [static] |
Set the global T38 capabilities on a SIP dialog structure.
Definition at line 4693 of file chan_sip.c.
References ast_test_flag, ast_udptl_set_error_correction_scheme(), sip_pvt::flags, SIP_PAGE2_T38SUPPORT, SIP_PAGE2_T38SUPPORT_UDPTL, SIP_PAGE2_T38SUPPORT_UDPTL_FEC, SIP_PAGE2_T38SUPPORT_UDPTL_REDUNDANCY, sip_pvt::udptl, UDPTL_ERROR_CORRECTION_FEC, UDPTL_ERROR_CORRECTION_NONE, and UDPTL_ERROR_CORRECTION_REDUNDANCY.
Referenced by check_peer_ok(), create_addr_from_peer(), handle_request_invite(), and sip_alloc().
04694 { 04695 if (p->udptl) { 04696 if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT) == SIP_PAGE2_T38SUPPORT_UDPTL_REDUNDANCY) { 04697 ast_udptl_set_error_correction_scheme(p->udptl, UDPTL_ERROR_CORRECTION_REDUNDANCY); 04698 } else if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT) == SIP_PAGE2_T38SUPPORT_UDPTL_FEC) { 04699 ast_udptl_set_error_correction_scheme(p->udptl, UDPTL_ERROR_CORRECTION_FEC); 04700 } else if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT) == SIP_PAGE2_T38SUPPORT_UDPTL) { 04701 ast_udptl_set_error_correction_scheme(p->udptl, UDPTL_ERROR_CORRECTION_NONE); 04702 } 04703 } 04704 }
static int show_channels_cb | ( | void * | __cur, | |
void * | __arg, | |||
int | flags | |||
) | [static] |
callback for show channel|subscription
Definition at line 15381 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().
15382 { 15383 struct sip_pvt *cur = __cur; 15384 struct __show_chan_arg *arg = __arg; 15385 const struct sockaddr_in *dst = sip_real_dst(cur); 15386 15387 /* XXX indentation preserved to reduce diff. Will be fixed later */ 15388 if (cur->subscribed == NONE && !arg->subscriptions) { 15389 /* set if SIP transfer in progress */ 15390 const char *referstatus = cur->refer ? referstatus2str(cur->refer->status) : ""; 15391 char formatbuf[SIPBUFSIZE/2]; 15392 15393 ast_cli(arg->fd, FORMAT, ast_inet_ntoa(dst->sin_addr), 15394 S_OR(cur->username, S_OR(cur->cid_num, "(None)")), 15395 cur->callid, 15396 ast_getformatname_multiple(formatbuf, sizeof(formatbuf), cur->owner ? cur->owner->nativeformats : 0), 15397 cli_yesno(ast_test_flag(&cur->flags[1], SIP_PAGE2_CALL_ONHOLD)), 15398 cur->needdestroy ? "(d)" : "", 15399 cur->lastmsg , 15400 referstatus 15401 ); 15402 arg->numchans++; 15403 } 15404 if (cur->subscribed != NONE && arg->subscriptions) { 15405 struct ast_str *mailbox_str = ast_str_alloca(512); 15406 if (cur->subscribed == MWI_NOTIFICATION && cur->relatedpeer) 15407 peer_mailboxes_to_str(&mailbox_str, cur->relatedpeer); 15408 ast_cli(arg->fd, FORMAT4, ast_inet_ntoa(dst->sin_addr), 15409 S_OR(cur->username, S_OR(cur->cid_num, "(None)")), 15410 cur->callid, 15411 /* the 'complete' exten/context is hidden in the refer_to field for subscriptions */ 15412 cur->subscribed == MWI_NOTIFICATION ? "--" : cur->subscribeuri, 15413 cur->subscribed == MWI_NOTIFICATION ? "<none>" : ast_extension_state2str(cur->laststate), 15414 subscription_type2str(cur->subscribed), 15415 cur->subscribed == MWI_NOTIFICATION ? S_OR(mailbox_str->str, "<none>") : "<none>", 15416 cur->expiry 15417 ); 15418 arg->numchans++; 15419 } 15420 return 0; /* don't care, we scan all channels */ 15421 }
static int show_chanstats_cb | ( | void * | __cur, | |
void * | __arg, | |||
int | flags | |||
) | [static] |
Callback for show_chanstats.
Definition at line 15060 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().
15061 { 15062 #define FORMAT2 "%-15.15s %-11.11s %-8.8s %-10.10s %-10.10s ( %%) %-6.6s %-10.10s %-10.10s ( %%) %-6.6s\n" 15063 #define FORMAT "%-15.15s %-11.11s %-8.8s %-10.10u%-1.1s %-10.10u (%5.2f%%) %-6.6u %-10.10u%-1.1s %-10.10u (%5.2f%%) %-6.6u\n" 15064 struct sip_pvt *cur = __cur; 15065 unsigned int rxcount, txcount, rxploss, txploss; 15066 char durbuf[10]; 15067 int duration; 15068 int durh, durm, durs; 15069 struct ast_channel *c = cur->owner; 15070 struct __show_chan_arg *arg = __arg; 15071 int fd = arg->fd; 15072 15073 15074 if (cur->subscribed != NONE) /* Subscriptions */ 15075 return 0; /* don't care, we scan all channels */ 15076 15077 if (!cur->rtp) { 15078 if (sipdebug) 15079 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"); 15080 return 0; /* don't care, we scan all channels */ 15081 } 15082 rxcount = ast_rtp_get_qosvalue(cur->rtp, AST_RTP_RXCOUNT); 15083 txcount = ast_rtp_get_qosvalue(cur->rtp, AST_RTP_TXCOUNT); 15084 rxploss = ast_rtp_get_qosvalue(cur->rtp, AST_RTP_RXPLOSS); 15085 txploss = ast_rtp_get_qosvalue(cur->rtp, AST_RTP_TXPLOSS); 15086 15087 /* Find the duration of this channel */ 15088 if (c && c->cdr && !ast_tvzero(c->cdr->start)) { 15089 duration = (int)(ast_tvdiff_ms(ast_tvnow(), c->cdr->start) / 1000); 15090 durh = duration / 3600; 15091 durm = (duration % 3600) / 60; 15092 durs = duration % 60; 15093 snprintf(durbuf, sizeof(durbuf), "%02d:%02d:%02d", durh, durm, durs); 15094 } else { 15095 durbuf[0] = '\0'; 15096 } 15097 /* Print stats for every call with RTP */ 15098 ast_cli(fd, FORMAT, 15099 ast_inet_ntoa(cur->sa.sin_addr), 15100 cur->callid, 15101 durbuf, 15102 rxcount > (unsigned int) 100000 ? (unsigned int) (rxcount)/(unsigned int) 1000 : rxcount, 15103 rxcount > (unsigned int) 100000 ? "K":" ", 15104 rxploss, 15105 (rxcount + rxploss) > 0 ? (double) rxploss / (rxcount + rxploss) * 100 : 0, 15106 ast_rtp_get_qosvalue(cur->rtp, AST_RTP_RXJITTER), 15107 txcount > (unsigned int) 100000 ? (unsigned int) (txcount)/(unsigned int) 1000 : txcount, 15108 txcount > (unsigned int) 100000 ? "K":" ", 15109 txploss, 15110 txcount > 0 ? (double) txploss / txcount * 100 : 0, 15111 ast_rtp_get_qosvalue(cur->rtp, AST_RTP_TXJITTER) 15112 ); 15113 arg->numchans++; 15114 15115 return 0; /* don't care, we scan all channels */ 15116 }
static int sip_addheader | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Add a SIP header to an outbound INVITE.
Definition at line 24434 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(), LOG_WARNING, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), and TRUE.
Referenced by load_module().
24435 { 24436 int no = 0; 24437 int ok = FALSE; 24438 char varbuf[30]; 24439 char *inbuf = data, *subbuf; 24440 24441 if (ast_strlen_zero(inbuf)) { 24442 ast_log(LOG_WARNING, "This application requires the argument: Header\n"); 24443 return 0; 24444 } 24445 ast_channel_lock(chan); 24446 24447 /* Check for headers */ 24448 while (!ok && no <= 50) { 24449 no++; 24450 snprintf(varbuf, sizeof(varbuf), "__SIPADDHEADER%.2d", no); 24451 24452 /* Compare without the leading underscores */ 24453 if ((pbx_builtin_getvar_helper(chan, (const char *) varbuf + 2) == (const char *) NULL)) { 24454 ok = TRUE; 24455 } 24456 } 24457 if (ok) { 24458 size_t len = strlen(inbuf); 24459 subbuf = alloca(len + 1); 24460 ast_get_encoded_str(inbuf, subbuf, len + 1); 24461 pbx_builtin_setvar_helper(chan, varbuf, subbuf); 24462 if (sipdebug) { 24463 ast_debug(1, "SIP Header added \"%s\" as %s\n", inbuf, varbuf); 24464 } 24465 } else { 24466 ast_log(LOG_WARNING, "Too many SIP headers added, max 50\n"); 24467 } 24468 ast_channel_unlock(chan); 24469 return 0; 24470 }
static struct sip_pvt * sip_alloc | ( | ast_string_field | callid, | |
struct sockaddr_in * | sin, | |||
int | useglobal_nat, | |||
const int | intended_method, | |||
struct sip_request * | req | |||
) | [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 6737 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_socket_transport(), 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, sip_request::socket, cfsip_methods::text, TRUE, and sip_socket::type.
Referenced by find_call(), manager_sipnotify(), sip_cli_notify(), sip_poke_peer(), sip_request_call(), sip_send_mwi_to_peer(), and transmit_register().
06739 { 06740 struct sip_pvt *p; 06741 06742 if (!(p = ao2_t_alloc(sizeof(*p), sip_destroy_fn, "allocate a dialog(pvt) struct"))) 06743 return NULL; 06744 06745 if (ast_string_field_init(p, 512)) { 06746 ao2_t_ref(p, -1, "failed to string_field_init, drop p"); 06747 return NULL; 06748 } 06749 06750 if (req) { 06751 set_socket_transport(&p->socket, req->socket.type); /* Later in ast_sip_ouraddrfor we need this to choose the right ip and port for the specific transport */ 06752 } else { 06753 set_socket_transport(&p->socket, SIP_TRANSPORT_UDP); 06754 } 06755 06756 p->socket.fd = -1; 06757 p->method = intended_method; 06758 p->initid = -1; 06759 p->waitid = -1; 06760 p->autokillid = -1; 06761 p->request_queue_sched_id = -1; 06762 p->provisional_keepalive_sched_id = -1; 06763 p->t38id = -1; 06764 p->subscribed = NONE; 06765 p->stateid = -1; 06766 p->sessionversion_remote = -1; 06767 p->session_modify = TRUE; 06768 p->stimer = NULL; 06769 p->prefs = default_prefs; /* Set default codecs for this call */ 06770 06771 if (intended_method != SIP_OPTIONS) { /* Peerpoke has it's own system */ 06772 p->timer_t1 = global_t1; /* Default SIP retransmission timer T1 (RFC 3261) */ 06773 p->timer_b = global_timer_b; /* Default SIP transaction timer B (RFC 3261) */ 06774 } 06775 06776 if (!sin) 06777 p->ourip = internip; 06778 else { 06779 p->sa = *sin; 06780 ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip, p); 06781 } 06782 06783 /* Copy global flags to this PVT at setup. */ 06784 ast_copy_flags(&p->flags[0], &global_flags[0], SIP_FLAGS_TO_COPY); 06785 ast_copy_flags(&p->flags[1], &global_flags[1], SIP_PAGE2_FLAGS_TO_COPY); 06786 06787 p->do_history = recordhistory; 06788 06789 p->branch = ast_random(); 06790 make_our_tag(p->tag, sizeof(p->tag)); 06791 p->ocseq = INITIAL_CSEQ; 06792 06793 if (sip_methods[intended_method].need_rtp) { 06794 p->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr); 06795 /* If the global videosupport flag is on, we always create a RTP interface for video */ 06796 if (ast_test_flag(&p->flags[1], SIP_PAGE2_VIDEOSUPPORT)) 06797 p->vrtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr); 06798 if (ast_test_flag(&p->flags[1], SIP_PAGE2_TEXTSUPPORT)) 06799 p->trtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr); 06800 if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT)) 06801 p->udptl = ast_udptl_new_with_bindaddr(sched, io, 0, bindaddr.sin_addr); 06802 if (!p->rtp|| (ast_test_flag(&p->flags[1], SIP_PAGE2_VIDEOSUPPORT) && !p->vrtp) 06803 || (ast_test_flag(&p->flags[1], SIP_PAGE2_TEXTSUPPORT) && !p->trtp)) { 06804 ast_log(LOG_WARNING, "Unable to create RTP audio %s%ssession: %s\n", 06805 ast_test_flag(&p->flags[1], SIP_PAGE2_VIDEOSUPPORT) ? "and video " : "", 06806 ast_test_flag(&p->flags[1], SIP_PAGE2_TEXTSUPPORT) ? "and text " : "", strerror(errno)); 06807 if (p->chanvars) { 06808 ast_variables_destroy(p->chanvars); 06809 p->chanvars = NULL; 06810 } 06811 ao2_t_ref(p, -1, "failed to create RTP audio session, drop p"); 06812 return NULL; 06813 p->t38_maxdatagram = global_t38_maxdatagram; 06814 } 06815 ast_rtp_setqos(p->rtp, global_tos_audio, global_cos_audio, "SIP RTP"); 06816 ast_rtp_setdtmf(p->rtp, ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833); 06817 ast_rtp_setdtmfcompensate(p->rtp, ast_test_flag(&p->flags[1], SIP_PAGE2_RFC2833_COMPENSATE)); 06818 ast_rtp_set_rtptimeout(p->rtp, global_rtptimeout); 06819 ast_rtp_set_rtpholdtimeout(p->rtp, global_rtpholdtimeout); 06820 ast_rtp_set_rtpkeepalive(p->rtp, global_rtpkeepalive); 06821 if (p->vrtp) { 06822 ast_rtp_setqos(p->vrtp, global_tos_video, global_cos_video, "SIP VRTP"); 06823 ast_rtp_setdtmf(p->vrtp, 0); 06824 ast_rtp_setdtmfcompensate(p->vrtp, 0); 06825 ast_rtp_set_rtptimeout(p->vrtp, global_rtptimeout); 06826 ast_rtp_set_rtpholdtimeout(p->vrtp, global_rtpholdtimeout); 06827 ast_rtp_set_rtpkeepalive(p->vrtp, global_rtpkeepalive); 06828 } 06829 if (p->trtp) { 06830 ast_rtp_setqos(p->trtp, global_tos_text, global_cos_text, "SIP TRTP"); 06831 ast_rtp_setdtmf(p->trtp, 0); 06832 ast_rtp_setdtmfcompensate(p->trtp, 0); 06833 } 06834 if (p->udptl) 06835 ast_udptl_setqos(p->udptl, global_tos_audio, global_cos_audio); 06836 p->maxcallbitrate = default_maxcallbitrate; 06837 p->autoframing = global_autoframing; 06838 ast_rtp_codec_setpref(p->rtp, &p->prefs); 06839 } 06840 06841 if (useglobal_nat && sin) { 06842 /* Setup NAT structure according to global settings if we have an address */ 06843 ast_copy_flags(&p->flags[0], &global_flags[0], SIP_NAT); 06844 p->recv = *sin; 06845 do_setnat(p, ast_test_flag(&p->flags[0], SIP_NAT) & SIP_NAT_ROUTE); 06846 } 06847 06848 if (p->method != SIP_REGISTER) 06849 ast_string_field_set(p, fromdomain, default_fromdomain); 06850 build_via(p); 06851 if (!callid) 06852 build_callid_pvt(p); 06853 else 06854 ast_string_field_set(p, callid, callid); 06855 /* Assign default music on hold class */ 06856 ast_string_field_set(p, mohinterpret, default_mohinterpret); 06857 ast_string_field_set(p, mohsuggest, default_mohsuggest); 06858 p->capability = global_capability; 06859 p->allowtransfer = global_allowtransfer; 06860 if ((ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833) || 06861 (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO)) 06862 p->noncodeccapability |= AST_RTP_DTMF; 06863 if (p->udptl) { 06864 p->t38_maxdatagram = global_t38_maxdatagram; 06865 set_t38_capabilities(p); 06866 } 06867 ast_string_field_set(p, context, default_context); 06868 ast_string_field_set(p, parkinglot, default_parkinglot); 06869 06870 AST_LIST_HEAD_INIT_NOLOCK(&p->request_queue); 06871 06872 /* Add to active dialog list */ 06873 06874 ao2_t_link(dialogs, p, "link pvt into dialogs table"); 06875 06876 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"); 06877 return p; 06878 }
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 2906 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().
02907 { 02908 ast_debug(3, "Setting SIP_ALREADYGONE on dialog %s\n", dialog->callid); 02909 dialog->alreadygone = 1; 02910 }
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 5779 of file chan_sip.c.
References ast_channel::_state, ast_debug, ast_rtp_new_source(), ast_set_flag, ast_setstate(), AST_STATE_UP, FALSE, ast_channel::name, SIP_PAGE2_DIALOG_ESTABLISHED, sip_pvt_lock, sip_pvt_unlock, ast_channel::tech_pvt, transmit_response_with_sdp(), try_suggested_sip_codec(), and XMIT_CRITICAL.
05780 { 05781 int res = 0; 05782 struct sip_pvt *p = ast->tech_pvt; 05783 05784 sip_pvt_lock(p); 05785 if (ast->_state != AST_STATE_UP) { 05786 try_suggested_sip_codec(p); 05787 05788 ast_setstate(ast, AST_STATE_UP); 05789 ast_debug(1, "SIP answering channel: %s\n", ast->name); 05790 ast_rtp_new_source(p->rtp); 05791 res = transmit_response_with_sdp(p, "200 OK", &p->initreq, XMIT_CRITICAL, FALSE); 05792 ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED); 05793 } 05794 sip_pvt_unlock(p); 05795 return res; 05796 }
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 4989 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, 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, 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, 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.
04990 { 04991 int res; 04992 struct sip_pvt *p = ast->tech_pvt; /* chan is locked, so the reference cannot go away */ 04993 struct varshead *headp; 04994 struct ast_var_t *current; 04995 const char *referer = NULL; /* SIP referrer */ 04996 04997 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) { 04998 ast_log(LOG_WARNING, "sip_call called on %s, neither down nor reserved\n", ast->name); 04999 return -1; 05000 } 05001 05002 /* Check whether there is vxml_url, distinctive ring variables */ 05003 headp=&ast->varshead; 05004 AST_LIST_TRAVERSE(headp, current, entries) { 05005 /* Check whether there is a VXML_URL variable */ 05006 if (!p->options->vxml_url && !strcasecmp(ast_var_name(current), "VXML_URL")) { 05007 p->options->vxml_url = ast_var_value(current); 05008 } else if (!p->options->uri_options && !strcasecmp(ast_var_name(current), "SIP_URI_OPTIONS")) { 05009 p->options->uri_options = ast_var_value(current); 05010 } else if (!p->options->addsipheaders && !strncasecmp(ast_var_name(current), "SIPADDHEADER", strlen("SIPADDHEADER"))) { 05011 /* Check whether there is a variable with a name starting with SIPADDHEADER */ 05012 p->options->addsipheaders = 1; 05013 } else if (!strcasecmp(ast_var_name(current), "SIPTRANSFER")) { 05014 /* This is a transfered call */ 05015 p->options->transfer = 1; 05016 } else if (!strcasecmp(ast_var_name(current), "SIPTRANSFER_REFERER")) { 05017 /* This is the referrer */ 05018 referer = ast_var_value(current); 05019 } else if (!strcasecmp(ast_var_name(current), "SIPTRANSFER_REPLACES")) { 05020 /* We're replacing a call. */ 05021 p->options->replaces = ast_var_value(current); 05022 } 05023 } 05024 05025 res = 0; 05026 ast_set_flag(&p->flags[0], SIP_OUTGOING); 05027 05028 if (p->options->transfer) { 05029 char buf[SIPBUFSIZE/2]; 05030 05031 if (referer) { 05032 if (sipdebug) 05033 ast_debug(3, "Call for %s transfered by %s\n", p->username, referer); 05034 snprintf(buf, sizeof(buf)-1, "-> %s (via %s)", p->cid_name, referer); 05035 } else 05036 snprintf(buf, sizeof(buf)-1, "-> %s", p->cid_name); 05037 ast_string_field_set(p, cid_name, buf); 05038 } 05039 ast_debug(1, "Outgoing Call for %s\n", p->username); 05040 05041 res = update_call_counter(p, INC_CALL_RINGING); 05042 05043 if (res == -1) { 05044 ast->hangupcause = AST_CAUSE_USER_BUSY; 05045 return res; 05046 } 05047 p->callingpres = ast->cid.cid_pres; 05048 p->jointcapability = ast_translate_available_formats(p->capability, p->prefcodec); 05049 p->jointnoncodeccapability = p->noncodeccapability; 05050 05051 /* If there are no audio formats left to offer, punt */ 05052 if (!(p->jointcapability & AST_FORMAT_AUDIO_MASK)) { 05053 ast_log(LOG_WARNING, "No audio format found to offer. Cancelling call to %s\n", p->username); 05054 res = -1; 05055 } else { 05056 int xmitres; 05057 05058 xmitres = transmit_invite(p, SIP_INVITE, 1, 2); 05059 if (xmitres == XMIT_ERROR) 05060 return -1; 05061 p->invitestate = INV_CALLING; 05062 05063 /* Initialize auto-congest time */ 05064 AST_SCHED_REPLACE_UNREF(p->initid, sched, p->timer_b, auto_congest, p, 05065 dialog_unref(_data, "dialog ptr dec when SCHED_REPLACE del op succeeded"), 05066 dialog_unref(p, "dialog ptr dec when SCHED_REPLACE add failed"), 05067 dialog_ref(p, "dialog ptr inc when SCHED_REPLACE add succeeded") ); 05068 } 05069 return res; 05070 }
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 3633 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().
03634 { 03635 int res = 0; 03636 if (p->autokillid > -1) { 03637 int res3; 03638 03639 if (!(res3 = ast_sched_del(sched, p->autokillid))) { 03640 append_history(p, "CancelDestroy", ""); 03641 p->autokillid = -1; 03642 dialog_unref(p, "dialog unrefd because autokillid is de-sched'd"); 03643 } 03644 } 03645 return res; 03646 }
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 16083 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.
16084 { 16085 struct ast_variable *varlist; 16086 int i; 16087 16088 switch (cmd) { 16089 case CLI_INIT: 16090 e->command = "sip notify"; 16091 e->usage = 16092 "Usage: sip notify <type> <peer> [<peer>...]\n" 16093 " Send a NOTIFY message to a SIP peer or peers\n" 16094 " Message types are defined in sip_notify.conf\n"; 16095 return NULL; 16096 case CLI_GENERATE: 16097 return complete_sipnotify(a->line, a->word, a->pos, a->n); 16098 } 16099 16100 if (a->argc < 4) 16101 return CLI_SHOWUSAGE; 16102 16103 if (!notify_types) { 16104 ast_cli(a->fd, "No %s file found, or no types listed there\n", notify_config); 16105 return CLI_FAILURE; 16106 } 16107 16108 varlist = ast_variable_browse(notify_types, a->argv[2]); 16109 16110 if (!varlist) { 16111 ast_cli(a->fd, "Unable to find notify type '%s'\n", a->argv[2]); 16112 return CLI_FAILURE; 16113 } 16114 16115 for (i = 3; i < a->argc; i++) { 16116 struct sip_pvt *p; 16117 16118 if (!(p = sip_alloc(NULL, NULL, 0, SIP_NOTIFY, NULL))) { 16119 ast_log(LOG_WARNING, "Unable to build sip pvt data for notify (memory/socket error)\n"); 16120 return CLI_FAILURE; 16121 } 16122 16123 if (create_addr(p, a->argv[i], NULL, 1)) { 16124 /* Maybe they're not registered, etc. */ 16125 dialog_unlink_all(p, TRUE, TRUE); 16126 dialog_unref(p, "unref dialog inside for loop" ); 16127 /* sip_destroy(p); */ 16128 ast_cli(a->fd, "Could not create address for '%s'\n", a->argv[i]); 16129 continue; 16130 } 16131 16132 /* Notify is outgoing call */ 16133 ast_set_flag(&p->flags[0], SIP_OUTGOING); 16134 16135 /* Recalculate our side, and recalculate Call ID */ 16136 ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip, p); 16137 build_via(p); 16138 ao2_t_unlink(dialogs, p, "About to change the callid -- remove the old name"); 16139 build_callid_pvt(p); 16140 ao2_t_link(dialogs, p, "Linking in new name"); 16141 ast_cli(a->fd, "Sending NOTIFY of type '%s' to '%s'\n", a->argv[2], a->argv[i]); 16142 dialog_ref(p, "bump the count of p, which transmit_sip_request will decrement."); 16143 sip_scheddestroy(p, SIP_TRANS_TIMEOUT); 16144 transmit_notify_custom(p, varlist); 16145 } 16146 16147 return CLI_SUCCESS; 16148 }
static int sip_debug_test_addr | ( | const struct sockaddr_in * | addr | ) | [inline, static] |
See if we pass debug IP filter.
Definition at line 3064 of file chan_sip.c.
Referenced by check_peer_ok(), handle_request_do(), and sip_debug_test_pvt().
03065 { 03066 if (!sipdebug) 03067 return 0; 03068 if (debugaddr.sin_addr.s_addr) { 03069 if (((ntohs(debugaddr.sin_port) != 0) 03070 && (debugaddr.sin_port != addr->sin_port)) 03071 || (debugaddr.sin_addr.s_addr != addr->sin_addr.s_addr)) 03072 return 0; 03073 } 03074 return 1; 03075 }
static int sip_debug_test_pvt | ( | struct sip_pvt * | p | ) | [inline, static] |
Test PVT for debugging output.
Definition at line 3093 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(), process_sdp_a_audio(), process_sdp_a_text(), process_sdp_a_video(), receive_message(), retrans_pkt(), send_request(), send_response(), set_destination(), sip_scheddestroy(), sip_sendhtml(), sip_sendtext(), and transmit_register().
03094 { 03095 if (!sipdebug) 03096 return 0; 03097 return sip_debug_test_addr(sip_real_dst(p)); 03098 }
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 5382 of file chan_sip.c.
References __sip_destroy(), ast_debug, sip_pvt::callid, and TRUE.
Referenced by sip_destroy_fn().
05383 { 05384 ast_debug(3, "Destroying SIP dialog %s\n", p->callid); 05385 __sip_destroy(p, TRUE, TRUE); 05386 return NULL; 05387 }
static void sip_destroy_fn | ( | void * | p | ) | [static] |
Definition at line 5372 of file chan_sip.c.
References sip_destroy().
Referenced by sip_alloc().
05373 { 05374 sip_destroy(p); 05375 }
static void sip_destroy_peer | ( | struct sip_peer * | peer | ) | [static] |
Destroy peer object from memory.
Definition at line 4264 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().
04265 { 04266 ast_debug(3, "Destroying SIP peer %s\n", peer->name); 04267 if (peer->outboundproxy) 04268 ao2_ref(peer->outboundproxy, -1); 04269 peer->outboundproxy = NULL; 04270 04271 /* Delete it, it needs to disappear */ 04272 if (peer->call) { 04273 dialog_unlink_all(peer->call, TRUE, TRUE); 04274 peer->call = dialog_unref(peer->call, "peer->call is being unset"); 04275 } 04276 04277 04278 if (peer->mwipvt) { /* We have an active subscription, delete it */ 04279 dialog_unlink_all(peer->mwipvt, TRUE, TRUE); 04280 peer->mwipvt = dialog_unref(peer->mwipvt, "unreffing peer->mwipvt"); 04281 } 04282 04283 if (peer->chanvars) { 04284 ast_variables_destroy(peer->chanvars); 04285 peer->chanvars = NULL; 04286 } 04287 04288 register_peer_exten(peer, FALSE); 04289 ast_free_ha(peer->ha); 04290 if (peer->selfdestruct) 04291 ast_atomic_fetchadd_int(&apeerobjs, -1); 04292 else if (peer->is_realtime) { 04293 ast_atomic_fetchadd_int(&rpeerobjs, -1); 04294 ast_debug(3, "-REALTIME- peer Destroyed. Name: %s. Realtime Peer objects: %d\n", peer->name, rpeerobjs); 04295 } else 04296 ast_atomic_fetchadd_int(&speerobjs, -1); 04297 clear_realm_authentication(peer->auth); 04298 peer->auth = NULL; 04299 if (peer->dnsmgr) 04300 ast_dnsmgr_release(peer->dnsmgr); 04301 clear_peer_mailboxes(peer); 04302 04303 if (peer->socket.tcptls_session) { 04304 ao2_ref(peer->socket.tcptls_session, -1); 04305 peer->socket.tcptls_session = NULL; 04306 } 04307 }
static void sip_destroy_peer_fn | ( | void * | peer | ) | [static] |
Definition at line 4258 of file chan_sip.c.
References sip_destroy_peer().
Referenced by build_peer(), and temp_peer().
04259 { 04260 sip_destroy_peer(peer); 04261 }
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 22071 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().
22072 { 22073 char *host; 22074 char *tmp; 22075 struct sip_peer *p; 22076 22077 int res = AST_DEVICE_INVALID; 22078 22079 /* make sure data is not null. Maybe unnecessary, but better be safe */ 22080 host = ast_strdupa(data ? data : ""); 22081 if ((tmp = strchr(host, '@'))) 22082 host = tmp + 1; 22083 22084 ast_debug(3, "Checking device state for peer %s\n", host); 22085 22086 /* If find_peer asks for a realtime peer, then this breaks rtautoclear. This 22087 * is because when a peer tries to autoexpire, the last thing it does is to 22088 * queue up an event telling the system that the devicestate has changed 22089 * (presumably to unavailable). If we ask for a realtime peer here, this would 22090 * load it BACK into memory, thus defeating the point of trying to clear dead 22091 * hosts out of memory. 22092 */ 22093 if ((p = find_peer(host, NULL, FALSE, FINDALLDEVICES, TRUE, 0))) { 22094 if (p->addr.sin_addr.s_addr || p->defaddr.sin_addr.s_addr) { 22095 /* we have an address for the peer */ 22096 22097 /* Check status in this order 22098 - Hold 22099 - Ringing 22100 - Busy (enforced only by call limit) 22101 - Inuse (we have a call) 22102 - Unreachable (qualify) 22103 If we don't find any of these state, report AST_DEVICE_NOT_INUSE 22104 for registered devices */ 22105 22106 if (p->onHold) 22107 /* First check for hold or ring states */ 22108 res = AST_DEVICE_ONHOLD; 22109 else if (p->inRinging) { 22110 if (p->inRinging == p->inUse) 22111 res = AST_DEVICE_RINGING; 22112 else 22113 res = AST_DEVICE_RINGINUSE; 22114 } else if (p->call_limit && (p->inUse == p->call_limit)) 22115 /* check call limit */ 22116 res = AST_DEVICE_BUSY; 22117 else if (p->call_limit && p->busy_level && p->inUse >= p->busy_level) 22118 /* We're forcing busy before we've reached the call limit */ 22119 res = AST_DEVICE_BUSY; 22120 else if (p->call_limit && p->inUse) 22121 /* Not busy, but we do have a call */ 22122 res = AST_DEVICE_INUSE; 22123 else if (p->maxms && ((p->lastms > p->maxms) || (p->lastms < 0))) 22124 /* We don't have a call. Are we reachable at all? Requires qualify= */ 22125 res = AST_DEVICE_UNAVAILABLE; 22126 else /* Default reply if we're registered and have no other data */ 22127 res = AST_DEVICE_NOT_INUSE; 22128 } else { 22129 /* there is no address, it's unavailable */ 22130 res = AST_DEVICE_UNAVAILABLE; 22131 } 22132 unref_peer(p, "unref_peer, from sip_devicestate, release ref from find_peer"); 22133 } else { 22134 res = AST_DEVICE_UNKNOWN; 22135 } 22136 22137 return res; 22138 }
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 16040 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.
16041 { 16042 int oldsipdebug = sipdebug & sip_debug_console; 16043 char *what; 16044 16045 if (cmd == CLI_INIT) { 16046 e->command = "sip set debug {on|off|ip|peer}"; 16047 e->usage = 16048 "Usage: sip set debug {off|on|ip addr[:port]|peer peername}\n" 16049 " Globally disables dumping of SIP packets,\n" 16050 " or enables it either globally or for a (single)\n" 16051 " IP address or registered peer.\n"; 16052 return NULL; 16053 } else if (cmd == CLI_GENERATE) { 16054 if (a->pos == 4 && strcasestr(a->line, " peer")) /* XXX should check on argv too */ 16055 return complete_sip_peer(a->word, a->n, 0); 16056 return NULL; 16057 } 16058 16059 what = a->argv[e->args-1]; /* guaranteed to exist */ 16060 if (a->argc == e->args) { /* on/off */ 16061 if (!strcasecmp(what, "on")) { 16062 sipdebug |= sip_debug_console; 16063 sipdebug_text = 1; /*! \note this can be a special debug command - "sip debug text" or something */ 16064 memset(&debugaddr, 0, sizeof(debugaddr)); 16065 ast_cli(a->fd, "SIP Debugging %senabled\n", oldsipdebug ? "re-" : ""); 16066 return CLI_SUCCESS; 16067 } else if (!strcasecmp(what, "off")) { 16068 sipdebug &= ~sip_debug_console; 16069 sipdebug_text = 0; 16070 ast_cli(a->fd, "SIP Debugging Disabled\n"); 16071 return CLI_SUCCESS; 16072 } 16073 } else if (a->argc == e->args +1) {/* ip/peer */ 16074 if (!strcasecmp(what, "ip")) 16075 return sip_do_debug_ip(a->fd, a->argv[e->args]); 16076 else if (!strcasecmp(what, "peer")) 16077 return sip_do_debug_peer(a->fd, a->argv[e->args]); 16078 } 16079 return CLI_SHOWUSAGE; /* default, failure */ 16080 }
static char * sip_do_debug_ip | ( | int | fd, | |
char * | arg | |||
) | [static] |
Enable SIP Debugging for a single IP.
Definition at line 15990 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().
15991 { 15992 struct hostent *hp; 15993 struct ast_hostent ahp; 15994 int port = 0; 15995 char *p; 15996 15997 p = arg; 15998 strsep(&p, ":"); 15999 if (p) 16000 port = atoi(p); 16001 hp = ast_gethostbyname(arg, &ahp); 16002 if (hp == NULL) 16003 return CLI_SHOWUSAGE; 16004 16005 debugaddr.sin_family = AF_INET; 16006 memcpy(&debugaddr.sin_addr, hp->h_addr, sizeof(debugaddr.sin_addr)); 16007 debugaddr.sin_port = htons(port); 16008 if (port == 0) 16009 ast_cli(fd, "SIP Debugging Enabled for IP: %s\n", ast_inet_ntoa(debugaddr.sin_addr)); 16010 else 16011 ast_cli(fd, "SIP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(debugaddr.sin_addr), port); 16012 16013 sipdebug |= sip_debug_console; 16014 16015 return CLI_SUCCESS; 16016 }
static char * sip_do_debug_peer | ( | int | fd, | |
char * | arg | |||
) | [static] |
Turn on SIP debugging for a given peer.
Definition at line 16019 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().
16020 { 16021 struct sip_peer *peer = find_peer(arg, NULL, TRUE, FINDPEERS, FALSE, 0); 16022 if (!peer) 16023 ast_cli(fd, "No such peer '%s'\n", arg); 16024 else if (peer->addr.sin_addr.s_addr == 0) 16025 ast_cli(fd, "Unable to get IP address of peer '%s'\n", arg); 16026 else { 16027 debugaddr.sin_family = AF_INET; 16028 debugaddr.sin_addr = peer->addr.sin_addr; 16029 debugaddr.sin_port = peer->addr.sin_port; 16030 ast_cli(fd, "SIP Debugging Enabled for IP: %s:%d\n", 16031 ast_inet_ntoa(debugaddr.sin_addr), ntohs(debugaddr.sin_port)); 16032 sipdebug |= sip_debug_console; 16033 } 16034 if (peer) 16035 unref_peer(peer, "sip_do_debug_peer: unref_peer, from find_peer call"); 16036 return CLI_SUCCESS; 16037 }
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 16151 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.
16152 { 16153 switch (cmd) { 16154 case CLI_INIT: 16155 e->command = "sip history [off]"; 16156 e->usage = 16157 "Usage: sip history [off]\n" 16158 " Enables/Disables recording of SIP dialog history for debugging purposes.\n" 16159 " Use 'sip show history' to view the history of a call number.\n"; 16160 return NULL; 16161 case CLI_GENERATE: 16162 return NULL; 16163 } 16164 16165 if (a->argc < 2 || a->argc > 3) { 16166 return CLI_SHOWUSAGE; 16167 } 16168 if (a->argc == 2) { 16169 recordhistory = TRUE; 16170 ast_cli(a->fd, "SIP History Recording Enabled (use 'sip show history')\n"); 16171 } else { 16172 if (strncasecmp(a->argv[2], "off", 3)) 16173 return CLI_SHOWUSAGE; 16174 recordhistory = FALSE; 16175 ast_cli(a->fd, "SIP History Recording Disabled\n"); 16176 } 16177 return CLI_SUCCESS; 16178 }
static int sip_do_reload | ( | enum channelreloadreason | reason | ) | [static] |
Reload module.
Definition at line 24590 of file chan_sip.c.
References ao2_t_callback, ast_debug, ast_sched_dump(), OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, peer_is_marked(), peers, reload_config(), sched, sip_poke_all_peers(), and sip_send_all_registers().
Referenced by do_monitor().
24591 { 24592 time_t start_poke, end_poke; 24593 24594 reload_config(reason); 24595 ast_sched_dump(sched); 24596 24597 start_poke = time(0); 24598 /* Prune peers who still are supposed to be deleted */ 24599 ao2_t_callback(peers, OBJ_NODATA | OBJ_UNLINK | OBJ_MULTIPLE, peer_is_marked, 0, 24600 "callback to remove marked peers"); 24601 24602 ast_debug(4, "--------------- Done destroying pruned peers\n"); 24603 24604 /* Send qualify (OPTIONS) to all peers */ 24605 sip_poke_all_peers(); 24606 24607 /* Register with all services */ 24608 sip_send_all_registers(); 24609 end_poke = time(0); 24610 24611 ast_debug(4, "do_reload finished. peer poke/prune reg contact time = %d sec.\n", (int)(end_poke-start_poke)); 24612 24613 ast_debug(4, "--------------- SIP reload done\n"); 24614 24615 return 0; 24616 }
static int sip_dtmfmode | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Set the DTMFmode for an outbound SIP call (application).
Definition at line 24376 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, sip_pvt::dsp, 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, and ast_channel::tech_pvt.
Referenced by load_module().
24377 { 24378 struct sip_pvt *p; 24379 char *mode = data; 24380 24381 if (!data) { 24382 ast_log(LOG_WARNING, "This application requires the argument: info, inband, rfc2833\n"); 24383 return 0; 24384 } 24385 ast_channel_lock(chan); 24386 if (!IS_SIP_TECH(chan->tech)) { 24387 ast_log(LOG_WARNING, "Call this application only on SIP incoming calls\n"); 24388 ast_channel_unlock(chan); 24389 return 0; 24390 } 24391 p = chan->tech_pvt; 24392 if (!p) { 24393 ast_channel_unlock(chan); 24394 return 0; 24395 } 24396 sip_pvt_lock(p); 24397 if (!strcasecmp(mode, "info")) { 24398 ast_clear_flag(&p->flags[0], SIP_DTMF); 24399 ast_set_flag(&p->flags[0], SIP_DTMF_INFO); 24400 p->jointnoncodeccapability &= ~AST_RTP_DTMF; 24401 } else if (!strcasecmp(mode, "shortinfo")) { 24402 ast_clear_flag(&p->flags[0], SIP_DTMF); 24403 ast_set_flag(&p->flags[0], SIP_DTMF_SHORTINFO); 24404 p->jointnoncodeccapability &= ~AST_RTP_DTMF; 24405 } else if (!strcasecmp(mode, "rfc2833")) { 24406 ast_clear_flag(&p->flags[0], SIP_DTMF); 24407 ast_set_flag(&p->flags[0], SIP_DTMF_RFC2833); 24408 p->jointnoncodeccapability |= AST_RTP_DTMF; 24409 } else if (!strcasecmp(mode, "inband")) { 24410 ast_clear_flag(&p->flags[0], SIP_DTMF); 24411 ast_set_flag(&p->flags[0], SIP_DTMF_INBAND); 24412 p->jointnoncodeccapability &= ~AST_RTP_DTMF; 24413 } else 24414 ast_log(LOG_WARNING, "I don't know about this dtmf mode: %s\n", mode); 24415 if (p->rtp) 24416 ast_rtp_setdtmf(p->rtp, ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833); 24417 if (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_INBAND) { 24418 if (!p->dsp) { 24419 p->dsp = ast_dsp_new(); 24420 ast_dsp_set_features(p->dsp, DSP_FEATURE_DIGIT_DETECT); 24421 } 24422 } else { 24423 if (p->dsp) { 24424 ast_dsp_free(p->dsp); 24425 p->dsp = NULL; 24426 } 24427 } 24428 sip_pvt_unlock(p); 24429 ast_channel_unlock(chan); 24430 return 0; 24431 }
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 15775 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().
15776 { 15777 int x = 0; 15778 struct sip_history *hist; 15779 static int errmsg = 0; 15780 15781 if (!dialog) 15782 return; 15783 15784 if (!option_debug && !sipdebug) { 15785 if (!errmsg) { 15786 ast_log(LOG_NOTICE, "You must have debugging enabled (SIP or Asterisk) in order to dump SIP history.\n"); 15787 errmsg = 1; 15788 } 15789 return; 15790 } 15791 15792 ast_debug(1, "\n---------- SIP HISTORY for '%s' \n", dialog->callid); 15793 if (dialog->subscribed) 15794 ast_debug(1, " * Subscription\n"); 15795 else 15796 ast_debug(1, " * SIP Call\n"); 15797 if (dialog->history) 15798 AST_LIST_TRAVERSE(dialog->history, hist, list) 15799 ast_debug(1, " %-3.3d. %s\n", ++x, hist->event); 15800 if (!x) 15801 ast_debug(1, "Call '%s' has no history\n", dialog->callid); 15802 ast_debug(1, "\n---------- END SIP HISTORY for '%s' \n", dialog->callid); 15803 }
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 5909 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.
05910 { 05911 int ret = -1; 05912 struct sip_pvt *p; 05913 05914 if (newchan && ast_test_flag(newchan, AST_FLAG_ZOMBIE)) 05915 ast_debug(1, "New channel is zombie\n"); 05916 if (oldchan && ast_test_flag(oldchan, AST_FLAG_ZOMBIE)) 05917 ast_debug(1, "Old channel is zombie\n"); 05918 05919 if (!newchan || !newchan->tech_pvt) { 05920 if (!newchan) 05921 ast_log(LOG_WARNING, "No new channel! Fixup of %s failed.\n", oldchan->name); 05922 else 05923 ast_log(LOG_WARNING, "No SIP tech_pvt! Fixup of %s failed.\n", oldchan->name); 05924 return -1; 05925 } 05926 p = newchan->tech_pvt; 05927 05928 sip_pvt_lock(p); 05929 append_history(p, "Masq", "Old channel: %s\n", oldchan->name); 05930 append_history(p, "Masq (cont)", "...new owner: %s\n", newchan->name); 05931 if (p->owner != oldchan) 05932 ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, p->owner); 05933 else { 05934 p->owner = newchan; 05935 /* Re-invite RTP back to Asterisk. Needed if channel is masqueraded out of a native 05936 RTP bridge (i.e., RTP not going through Asterisk): RTP bridge code might not be 05937 able to do this if the masquerade happens before the bridge breaks (e.g., AMI 05938 redirect of both channels). Note that a channel can not be masqueraded *into* 05939 a native bridge. So there is no danger that this breaks a native bridge that 05940 should stay up. */ 05941 sip_set_rtp_peer(newchan, NULL, NULL, 0, 0, 0); 05942 ret = 0; 05943 } 05944 ast_debug(3, "SIP Fixup: New owner for dialogue %s: %s (Old parent: %s)\n", p->callid, p->owner->name, oldchan->name); 05945 05946 sip_pvt_unlock(p); 05947 return ret; 05948 }
static const char * sip_get_callid | ( | struct ast_channel * | chan | ) | [static] |
Deliver SIP call ID for the call.
Definition at line 4125 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 24533 of file chan_sip.c.
References sip_pvt::capability, chan, sip_pvt::jointcapability, and ast_channel::tech_pvt.
24534 { 24535 struct sip_pvt *p = chan->tech_pvt; 24536 return p->jointcapability ? p->jointcapability : p->capability; 24537 }
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 24210 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.
24211 { 24212 struct sip_pvt *p = NULL; 24213 enum ast_rtp_get_result res = AST_RTP_TRY_PARTIAL; 24214 24215 if (!(p = chan->tech_pvt)) 24216 return AST_RTP_GET_FAILED; 24217 24218 sip_pvt_lock(p); 24219 if (!(p->rtp)) { 24220 sip_pvt_unlock(p); 24221 return AST_RTP_GET_FAILED; 24222 } 24223 24224 *rtp = p->rtp; 24225 24226 if (ast_rtp_getnat(*rtp) && !ast_test_flag(&p->flags[0], SIP_CAN_REINVITE_NAT)) 24227 res = AST_RTP_TRY_PARTIAL; 24228 else if (ast_test_flag(&p->flags[0], SIP_CAN_REINVITE)) 24229 res = AST_RTP_TRY_NATIVE; 24230 else if (ast_test_flag(&global_jbconf, AST_JB_FORCED)) 24231 res = AST_RTP_GET_FAILED; 24232 24233 sip_pvt_unlock(p); 24234 24235 return res; 24236 }
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 24264 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.
24265 { 24266 struct sip_pvt *p = NULL; 24267 enum ast_rtp_get_result res = AST_RTP_TRY_PARTIAL; 24268 24269 if (!(p = chan->tech_pvt)) 24270 return AST_RTP_GET_FAILED; 24271 24272 sip_pvt_lock(p); 24273 if (!(p->trtp)) { 24274 sip_pvt_unlock(p); 24275 return AST_RTP_GET_FAILED; 24276 } 24277 24278 *rtp = p->trtp; 24279 24280 if (ast_test_flag(&p->flags[0], SIP_CAN_REINVITE)) 24281 res = AST_RTP_TRY_NATIVE; 24282 24283 sip_pvt_unlock(p); 24284 24285 return res; 24286 }
static struct ast_udptl * sip_get_udptl_peer | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 24166 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.
24167 { 24168 struct sip_pvt *p; 24169 struct ast_udptl *udptl = NULL; 24170 24171 p = chan->tech_pvt; 24172 if (!p) 24173 return NULL; 24174 24175 sip_pvt_lock(p); 24176 if (p->udptl && ast_test_flag(&p->flags[0], SIP_CAN_REINVITE)) 24177 udptl = p->udptl; 24178 sip_pvt_unlock(p); 24179 return udptl; 24180 }
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 24239 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.
24240 { 24241 struct sip_pvt *p = NULL; 24242 enum ast_rtp_get_result res = AST_RTP_TRY_PARTIAL; 24243 24244 if (!(p = chan->tech_pvt)) 24245 return AST_RTP_GET_FAILED; 24246 24247 sip_pvt_lock(p); 24248 if (!(p->vrtp)) { 24249 sip_pvt_unlock(p); 24250 return AST_RTP_GET_FAILED; 24251 } 24252 24253 *rtp = p->vrtp; 24254 24255 if (ast_test_flag(&p->flags[0], SIP_CAN_REINVITE)) 24256 res = AST_RTP_TRY_NATIVE; 24257 24258 sip_pvt_unlock(p); 24259 24260 return res; 24261 }
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 5552 of file chan_sip.c.
References __sip_pretend_ack(), __sip_semi_ack(), ast_channel::_state, sip_pvt::alreadygone, sip_pvt::answered_elsewhere, append_history, ast_bridged_channel(), ast_cause2str(), ast_channel_trylock, ast_channel_unlock, 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, CHANNEL_DEADLOCK_AVOIDANCE, sip_pkt::data, DEC_CALL_LIMIT, DEFAULT_TRANS_TIMEOUT, dialog_unref(), sip_pvt::dsp, FALSE, find_sip_method(), sip_pvt::flags, hangup_cause2sip(), ast_channel::hangupcause, sip_pvt::hangupcause, INV_CALLING, INV_CANCELLED, INV_COMPLETED, INV_TERMINATED, sip_pvt::invitestate, sip_pkt::is_resp, IS_SIP_TECH, LOG_WARNING, sip_pkt::method, ast_channel::name, sip_pvt::needdestroy, sip_pkt::next, sip_pvt::owner, pbx_builtin_setvar_helper(), sip_pvt::refer, sip_pvt::rtp, RTPQOS_SUMMARY, sched, sip_pkt::seqno, 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_trylock, sip_pvt_unlock, sip_scheddestroy(), stop_media_flows(), stop_session_timer(), ast_str::str, ast_channel::tech, ast_channel::tech_pvt, transmit_request(), transmit_request_with_auth(), transmit_response_reliable(), TRUE, update_call_counter(), sip_pvt::username, and XMIT_RELIABLE.
05553 { 05554 struct sip_pvt *p = ast->tech_pvt; 05555 int needcancel = FALSE; 05556 int needdestroy = 0; 05557 struct ast_channel *oldowner = ast; 05558 05559 if (!p) { 05560 ast_debug(1, "Asked to hangup channel that was not connected\n"); 05561 return 0; 05562 } 05563 if (ast_test_flag(ast, AST_FLAG_ANSWERED_ELSEWHERE)) { 05564 ast_debug(1, "This call was answered elsewhere"); 05565 append_history(p, "Cancel", "Call answered elsewhere"); 05566 p->answered_elsewhere = TRUE; 05567 } 05568 05569 /* Store hangupcause locally in PVT so we still have it before disconnect */ 05570 if (p->owner) 05571 p->hangupcause = p->owner->hangupcause; 05572 05573 if (ast_test_flag(&p->flags[0], SIP_DEFER_BYE_ON_TRANSFER)) { 05574 if (ast_test_flag(&p->flags[0], SIP_INC_COUNT) || ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD)) { 05575 if (sipdebug) 05576 ast_debug(1, "update_call_counter(%s) - decrement call limit counter on hangup\n", p->username); 05577 update_call_counter(p, DEC_CALL_LIMIT); 05578 } 05579 ast_debug(4, "SIP Transfer: Not hanging up right now... Rescheduling hangup for %s.\n", p->callid); 05580 if (p->autokillid > -1 && sip_cancel_destroy(p)) 05581 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 05582 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 05583 ast_clear_flag(&p->flags[0], SIP_DEFER_BYE_ON_TRANSFER); /* Really hang up next time */ 05584 p->needdestroy = 0; 05585 p->owner->tech_pvt = dialog_unref(p->owner->tech_pvt, "unref p->owner->tech_pvt"); 05586 sip_pvt_lock(p); 05587 p->owner = NULL; /* Owner will be gone after we return, so take it away */ 05588 sip_pvt_unlock(p); 05589 return 0; 05590 } 05591 05592 if (ast_test_flag(ast, AST_FLAG_ZOMBIE)) { 05593 if (p->refer) 05594 ast_debug(1, "SIP Transfer: Hanging up Zombie channel %s after transfer ... Call-ID: %s\n", ast->name, p->callid); 05595 else 05596 ast_debug(1, "Hanging up zombie call. Be scared.\n"); 05597 } else 05598 ast_debug(1, "Hangup call %s, SIP callid %s\n", ast->name, p->callid); 05599 05600 sip_pvt_lock(p); 05601 if (ast_test_flag(&p->flags[0], SIP_INC_COUNT) || ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD)) { 05602 if (sipdebug) 05603 ast_debug(1, "update_call_counter(%s) - decrement call limit counter on hangup\n", p->username); 05604 update_call_counter(p, DEC_CALL_LIMIT); 05605 } 05606 05607 /* Determine how to disconnect */ 05608 if (p->owner != ast) { 05609 ast_log(LOG_WARNING, "Huh? We aren't the owner? Can't hangup call.\n"); 05610 sip_pvt_unlock(p); 05611 return 0; 05612 } 05613 /* If the call is not UP, we need to send CANCEL instead of BYE */ 05614 /* In case of re-invites, the call might be UP even though we have an incomplete invite transaction */ 05615 if (p->invitestate < INV_COMPLETED && p->owner->_state != AST_STATE_UP) { 05616 needcancel = TRUE; 05617 ast_debug(4, "Hanging up channel in state %s (not UP)\n", ast_state2str(ast->_state)); 05618 } 05619 05620 stop_media_flows(p); /* Immediately stop RTP, VRTP and UDPTL as applicable */ 05621 05622 append_history(p, needcancel ? "Cancel" : "Hangup", "Cause %s", p->owner ? ast_cause2str(p->hangupcause) : "Unknown"); 05623 05624 /* Disconnect */ 05625 if (p->dsp) 05626 ast_dsp_free(p->dsp); 05627 05628 p->owner = NULL; 05629 ast->tech_pvt = dialog_unref(ast->tech_pvt, "unref ast->tech_pvt"); 05630 05631 ast_module_unref(ast_module_info->self); 05632 /* Do not destroy this pvt until we have timeout or 05633 get an answer to the BYE or INVITE/CANCEL 05634 If we get no answer during retransmit period, drop the call anyway. 05635 (Sorry, mother-in-law, you can't deny a hangup by sending 05636 603 declined to BYE...) 05637 */ 05638 if (p->alreadygone) 05639 needdestroy = 1; /* Set destroy flag at end of this function */ 05640 else if (p->invitestate != INV_CALLING) 05641 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 05642 05643 /* Start the process if it's not already started */ 05644 if (!p->alreadygone && p->initreq.data && !ast_strlen_zero(p->initreq.data->str)) { 05645 if (needcancel) { /* Outgoing call, not up */ 05646 if (ast_test_flag(&p->flags[0], SIP_OUTGOING)) { 05647 /* stop retransmitting an INVITE that has not received a response */ 05648 /* if we can't send right now, mark it pending */ 05649 if (p->invitestate == INV_CALLING) { 05650 /* We can't send anything in CALLING state */ 05651 ast_set_flag(&p->flags[0], SIP_PENDINGBYE); 05652 __sip_pretend_ack(p); 05653 /* Do we need a timer here if we don't hear from them at all? Yes we do or else we will get hung dialogs and those are no fun. */ 05654 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 05655 append_history(p, "DELAY", "Not sending cancel, waiting for timeout"); 05656 } else { 05657 struct sip_pkt *cur; 05658 05659 for (cur = p->packets; cur; cur = cur->next) { 05660 __sip_semi_ack(p, cur->seqno, cur->is_resp, cur->method ? cur->method : find_sip_method(cur->data->str)); 05661 } 05662 p->invitestate = INV_CANCELLED; 05663 /* Send a new request: CANCEL */ 05664 transmit_request(p, SIP_CANCEL, p->lastinvite, XMIT_RELIABLE, FALSE); 05665 /* Actually don't destroy us yet, wait for the 487 on our original 05666 INVITE, but do set an autodestruct just in case we never get it. */ 05667 needdestroy = 0; 05668 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 05669 } 05670 } else { /* Incoming call, not up */ 05671 const char *res; 05672 AST_SCHED_DEL_UNREF(sched, p->provisional_keepalive_sched_id, dialog_unref(p, "when you delete the provisional_keepalive_sched_id, you should dec the refcount for the stored dialog ptr")); 05673 if (p->hangupcause && (res = hangup_cause2sip(p->hangupcause))) 05674 transmit_response_reliable(p, res, &p->initreq); 05675 else 05676 transmit_response_reliable(p, "603 Declined", &p->initreq); 05677 p->invitestate = INV_TERMINATED; 05678 } 05679 } else { /* Call is in UP state, send BYE */ 05680 if (p->stimer->st_active == TRUE) { 05681 stop_session_timer(p); 05682 } 05683 05684 if (!p->pendinginvite) { 05685 struct ast_channel *bridge = ast_bridged_channel(oldowner); 05686 char *audioqos = ""; 05687 char *videoqos = ""; 05688 char *textqos = ""; 05689 05690 /* We need to get the lock on bridge because ast_rtp_set_vars will attempt 05691 * to lock the bridge. This may get hairy... 05692 */ 05693 while (bridge && ast_channel_trylock(bridge)) { 05694 sip_pvt_unlock(p); 05695 do { 05696 /* Use oldowner since p->owner is already NULL */ 05697 CHANNEL_DEADLOCK_AVOIDANCE(oldowner); 05698 } while (sip_pvt_trylock(p)); 05699 bridge = ast_bridged_channel(oldowner); 05700 } 05701 05702 if (p->rtp) 05703 ast_rtp_set_vars(oldowner, p->rtp); 05704 05705 if (bridge) { 05706 struct sip_pvt *q = bridge->tech_pvt; 05707 05708 if (IS_SIP_TECH(bridge->tech) && q && q->rtp) 05709 ast_rtp_set_vars(bridge, q->rtp); 05710 ast_channel_unlock(bridge); 05711 } 05712 05713 if (p->vrtp) 05714 videoqos = ast_rtp_get_quality(p->vrtp, NULL, RTPQOS_SUMMARY); 05715 if (p->trtp) 05716 textqos = ast_rtp_get_quality(p->trtp, NULL, RTPQOS_SUMMARY); 05717 /* Send a hangup */ 05718 if (oldowner->_state == AST_STATE_UP) { 05719 transmit_request_with_auth(p, SIP_BYE, 0, XMIT_RELIABLE, 1); 05720 } 05721 05722 /* Get RTCP quality before end of call */ 05723 if (p->do_history) { 05724 if (p->rtp) 05725 append_history(p, "RTCPaudio", "Quality:%s", audioqos); 05726 if (p->vrtp) 05727 append_history(p, "RTCPvideo", "Quality:%s", videoqos); 05728 if (p->trtp) 05729 append_history(p, "RTCPtext", "Quality:%s", textqos); 05730 } 05731 if (p->rtp && oldowner) 05732 pbx_builtin_setvar_helper(oldowner, "RTPAUDIOQOS", audioqos); 05733 if (p->vrtp && oldowner) 05734 pbx_builtin_setvar_helper(oldowner, "RTPVIDEOQOS", videoqos); 05735 if (p->trtp && oldowner) 05736 pbx_builtin_setvar_helper(oldowner, "RTPTEXTQOS", textqos); 05737 } else { 05738 /* Note we will need a BYE when this all settles out 05739 but we can't send one while we have "INVITE" outstanding. */ 05740 ast_set_flag(&p->flags[0], SIP_PENDINGBYE); 05741 ast_clear_flag(&p->flags[0], SIP_NEEDREINVITE); 05742 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")); 05743 if (sip_cancel_destroy(p)) 05744 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 05745 } 05746 } 05747 } 05748 if (needdestroy) 05749 p->needdestroy = 1; 05750 sip_pvt_unlock(p); 05751 return 0; 05752 }
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 6083 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_SRCCHANGE, AST_CONTROL_SRCUPDATE, AST_CONTROL_T38_PARAMETERS, AST_CONTROL_UNHOLD, AST_CONTROL_VIDUPDATE, ast_log(), ast_moh_start(), ast_moh_stop(), ast_rtp_change_source(), ast_rtp_new_source(), ast_set_flag, AST_SOFTHANGUP_DEV, ast_softhangup_nolock(), AST_STATE_RING, AST_STATE_UP, ast_test_flag, sip_pvt::flags, sip_pvt::initreq, interpret_t38_parameters(), INV_COMPLETED, INV_EARLY_MEDIA, INV_PROCEEDING, sip_pvt::invitestate, LOG_ERROR, LOG_WARNING, sip_pvt::mohinterpret, sip_pvt::novideo, sip_pvt::rtp, sip_alreadygone(), SIP_OUTGOING, SIP_PROG_INBAND, SIP_PROG_INBAND_NEVER, SIP_PROG_INBAND_YES, SIP_PROGRESS_SENT, sip_pvt_lock, sip_pvt_unlock, SIP_RINGING, ast_channel::tech_pvt, transmit_info_with_vidupdate(), transmit_provisional_response(), transmit_response(), transmit_response_reliable(), TRUE, and sip_pvt::vrtp.
06084 { 06085 struct sip_pvt *p = ast->tech_pvt; 06086 int res = 0; 06087 06088 sip_pvt_lock(p); 06089 switch(condition) { 06090 case AST_CONTROL_RINGING: 06091 if (ast->_state == AST_STATE_RING) { 06092 p->invitestate = INV_EARLY_MEDIA; 06093 if (!ast_test_flag(&p->flags[0], SIP_PROGRESS_SENT) || 06094 (ast_test_flag(&p->flags[0], SIP_PROG_INBAND) == SIP_PROG_INBAND_NEVER)) { 06095 /* Send 180 ringing if out-of-band seems reasonable */ 06096 transmit_provisional_response(p, "180 Ringing", &p->initreq, 0); 06097 ast_set_flag(&p->flags[0], SIP_RINGING); 06098 if (ast_test_flag(&p->flags[0], SIP_PROG_INBAND) != SIP_PROG_INBAND_YES) 06099 break; 06100 } else { 06101 /* Well, if it's not reasonable, just send in-band */ 06102 } 06103 } 06104 res = -1; 06105 break; 06106 case AST_CONTROL_BUSY: 06107 if (ast->_state != AST_STATE_UP) { 06108 transmit_response_reliable(p, "486 Busy Here", &p->initreq); 06109 p->invitestate = INV_COMPLETED; 06110 sip_alreadygone(p); 06111 ast_softhangup_nolock(ast, AST_SOFTHANGUP_DEV); 06112 break; 06113 } 06114 res = -1; 06115 break; 06116 case AST_CONTROL_CONGESTION: 06117 if (ast->_state != AST_STATE_UP) { 06118 transmit_response_reliable(p, "503 Service Unavailable", &p->initreq); 06119 p->invitestate = INV_COMPLETED; 06120 sip_alreadygone(p); 06121 ast_softhangup_nolock(ast, AST_SOFTHANGUP_DEV); 06122 break; 06123 } 06124 res = -1; 06125 break; 06126 case AST_CONTROL_PROCEEDING: 06127 if ((ast->_state != AST_STATE_UP) && 06128 !ast_test_flag(&p->flags[0], SIP_PROGRESS_SENT) && 06129 !ast_test_flag(&p->flags[0], SIP_OUTGOING)) { 06130 transmit_response(p, "100 Trying", &p->initreq); 06131 p->invitestate = INV_PROCEEDING; 06132 break; 06133 } 06134 res = -1; 06135 break; 06136 case AST_CONTROL_PROGRESS: 06137 if ((ast->_state != AST_STATE_UP) && 06138 !ast_test_flag(&p->flags[0], SIP_PROGRESS_SENT) && 06139 !ast_test_flag(&p->flags[0], SIP_OUTGOING)) { 06140 p->invitestate = INV_EARLY_MEDIA; 06141 transmit_provisional_response(p, "183 Session Progress", &p->initreq, TRUE); 06142 ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT); 06143 break; 06144 } 06145 res = -1; 06146 break; 06147 case AST_CONTROL_HOLD: 06148 ast_rtp_new_source(p->rtp); 06149 ast_moh_start(ast, data, p->mohinterpret); 06150 break; 06151 case AST_CONTROL_UNHOLD: 06152 ast_rtp_new_source(p->rtp); 06153 ast_moh_stop(ast); 06154 break; 06155 case AST_CONTROL_VIDUPDATE: /* Request a video frame update */ 06156 if (p->vrtp && !p->novideo) { 06157 transmit_info_with_vidupdate(p); 06158 /* ast_rtcp_send_h261fur(p->vrtp); */ 06159 } else 06160 res = -1; 06161 break; 06162 case AST_CONTROL_T38_PARAMETERS: 06163 if (datalen != sizeof(struct ast_control_t38_parameters)) { 06164 ast_log(LOG_ERROR, "Invalid datalen for AST_CONTROL_T38_PARAMETERS. Expected %d, got %d\n", (int) sizeof(struct ast_control_t38_parameters), (int) datalen); 06165 } else { 06166 const struct ast_control_t38_parameters *parameters = data; 06167 interpret_t38_parameters(p, parameters); 06168 } 06169 break; 06170 case AST_CONTROL_SRCUPDATE: 06171 ast_rtp_new_source(p->rtp); 06172 break; 06173 case AST_CONTROL_SRCCHANGE: 06174 ast_rtp_change_source(p->rtp); 06175 break; 06176 case -1: 06177 res = -1; 06178 break; 06179 default: 06180 ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", condition); 06181 res = -1; 06182 break; 06183 } 06184 sip_pvt_unlock(p); 06185 return res; 06186 }
static const char * sip_nat_mode | ( | const struct sip_pvt * | p | ) | [static] |
Display SIP nat mode.
Definition at line 3087 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().
03088 { 03089 return ast_test_flag(&p->flags[0], SIP_NAT) & SIP_NAT_ROUTE ? "NAT" : "no NAT"; 03090 }
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 6194 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_atomic_fetchadd_int(), 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, sip_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_RELAXDTMF, DSP_FEATURE_DIGIT_DETECT, DSP_FEATURE_FAX_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, parkinglot, sip_pvt::parkinglot, 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_FAX_DETECT, 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, ast_variable::value, sip_pvt::vrtp, and ast_channel::writeformat.
Referenced by handle_request_invite(), and sip_request_call().
06195 { 06196 struct ast_channel *tmp; 06197 struct ast_variable *v = NULL; 06198 int fmt; 06199 int what; 06200 int video; 06201 int text; 06202 int needvideo = 0; 06203 int needtext = 0; 06204 char buf[SIPBUFSIZE]; 06205 char *decoded_exten; 06206 06207 { 06208 const char *my_name; /* pick a good name */ 06209 06210 if (title) 06211 my_name = title; 06212 else if ( (my_name = strchr(i->fromdomain, ':')) ) 06213 my_name++; /* skip ':' */ 06214 else 06215 my_name = i->fromdomain; 06216 06217 sip_pvt_unlock(i); 06218 /* Don't hold a sip pvt lock while we allocate a channel */ 06219 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, ast_atomic_fetchadd_int((int *)&chan_idx, +1)); 06220 06221 } 06222 if (!tmp) { 06223 ast_log(LOG_WARNING, "Unable to allocate AST channel structure for SIP channel\n"); 06224 sip_pvt_lock(i); 06225 return NULL; 06226 } 06227 sip_pvt_lock(i); 06228 06229 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; 06230 06231 /* Select our native format based on codec preference until we receive 06232 something from another device to the contrary. */ 06233 if (i->jointcapability) { /* The joint capabilities of us and peer */ 06234 what = i->jointcapability; 06235 video = i->jointcapability & AST_FORMAT_VIDEO_MASK; 06236 text = i->jointcapability & AST_FORMAT_TEXT_MASK; 06237 } else if (i->capability) { /* Our configured capability for this peer */ 06238 what = i->capability; 06239 video = i->capability & AST_FORMAT_VIDEO_MASK; 06240 text = i->capability & AST_FORMAT_TEXT_MASK; 06241 } else { 06242 what = global_capability; /* Global codec support */ 06243 video = global_capability & AST_FORMAT_VIDEO_MASK; 06244 text = global_capability & AST_FORMAT_TEXT_MASK; 06245 } 06246 06247 /* Set the native formats for audio and merge in video */ 06248 tmp->nativeformats = ast_codec_choose(&i->prefs, what, 1) | video | text; 06249 ast_debug(3, "*** Our native formats are %s \n", ast_getformatname_multiple(buf, SIPBUFSIZE, tmp->nativeformats)); 06250 ast_debug(3, "*** Joint capabilities are %s \n", ast_getformatname_multiple(buf, SIPBUFSIZE, i->jointcapability)); 06251 ast_debug(3, "*** Our capabilities are %s \n", ast_getformatname_multiple(buf, SIPBUFSIZE, i->capability)); 06252 ast_debug(3, "*** AST_CODEC_CHOOSE formats are %s \n", ast_getformatname_multiple(buf, SIPBUFSIZE, ast_codec_choose(&i->prefs, what, 1))); 06253 if (i->prefcodec) 06254 ast_debug(3, "*** Our preferred formats from the incoming channel are %s \n", ast_getformatname_multiple(buf, SIPBUFSIZE, i->prefcodec)); 06255 06256 /* XXX Why are we choosing a codec from the native formats?? */ 06257 fmt = ast_best_codec(tmp->nativeformats); 06258 06259 /* If we have a prefcodec setting, we have an inbound channel that set a 06260 preferred format for this call. Otherwise, we check the jointcapability 06261 We also check for vrtp. If it's not there, we are not allowed do any video anyway. 06262 */ 06263 if (i->vrtp) { 06264 if (ast_test_flag(&i->flags[1], SIP_PAGE2_VIDEOSUPPORT)) 06265 needvideo = AST_FORMAT_VIDEO_MASK; 06266 else if (i->prefcodec) 06267 needvideo = i->prefcodec & AST_FORMAT_VIDEO_MASK; /* Outbound call */ 06268 else 06269 needvideo = i->jointcapability & AST_FORMAT_VIDEO_MASK; /* Inbound call */ 06270 } 06271 06272 if (i->trtp) { 06273 if (i->prefcodec) 06274 needtext = i->prefcodec & AST_FORMAT_TEXT_MASK; /* Outbound call */ 06275 else 06276 needtext = i->jointcapability & AST_FORMAT_TEXT_MASK; /* Inbound call */ 06277 } 06278 06279 if (needvideo) 06280 ast_debug(3, "This channel can handle video! HOLLYWOOD next!\n"); 06281 else 06282 ast_debug(3, "This channel will not be able to handle video.\n"); 06283 06284 if ((ast_test_flag(&i->flags[0], SIP_DTMF) == SIP_DTMF_INBAND) || (ast_test_flag(&i->flags[0], SIP_DTMF) == SIP_DTMF_AUTO) || 06285 (ast_test_flag(&i->flags[1], SIP_PAGE2_FAX_DETECT))) { 06286 int features = DSP_FEATURE_DIGIT_DETECT; 06287 06288 if (ast_test_flag(&i->flags[1], SIP_PAGE2_FAX_DETECT)) { 06289 features |= DSP_FEATURE_FAX_DETECT; 06290 } 06291 06292 i->dsp = ast_dsp_new(); 06293 ast_dsp_set_features(i->dsp, features); 06294 if (global_relaxdtmf) 06295 ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | DSP_DIGITMODE_RELAXDTMF); 06296 } 06297 06298 /* Set file descriptors for audio, video, realtime text and UDPTL as needed */ 06299 if (i->rtp) { 06300 ast_channel_set_fd(tmp, 0, ast_rtp_fd(i->rtp)); 06301 ast_channel_set_fd(tmp, 1, ast_rtcp_fd(i->rtp)); 06302 } 06303 if (needvideo && i->vrtp) { 06304 ast_channel_set_fd(tmp, 2, ast_rtp_fd(i->vrtp)); 06305 ast_channel_set_fd(tmp, 3, ast_rtcp_fd(i->vrtp)); 06306 } 06307 if (needtext && i->trtp) 06308 ast_channel_set_fd(tmp, 4, ast_rtp_fd(i->trtp)); 06309 if (i->udptl) 06310 ast_channel_set_fd(tmp, 5, ast_udptl_fd(i->udptl)); 06311 06312 if (state == AST_STATE_RING) 06313 tmp->rings = 1; 06314 tmp->adsicpe = AST_ADSI_UNAVAILABLE; 06315 tmp->writeformat = fmt; 06316 tmp->rawwriteformat = fmt; 06317 tmp->readformat = fmt; 06318 tmp->rawreadformat = fmt; 06319 tmp->tech_pvt = dialog_ref(i, "sip_new: set chan->tech_pvt to i"); 06320 06321 tmp->callgroup = i->callgroup; 06322 tmp->pickupgroup = i->pickupgroup; 06323 tmp->cid.cid_pres = i->callingpres; 06324 if (!ast_strlen_zero(i->parkinglot)) 06325 ast_string_field_set(tmp, parkinglot, i->parkinglot); 06326 if (!ast_strlen_zero(i->accountcode)) 06327 ast_string_field_set(tmp, accountcode, i->accountcode); 06328 if (i->amaflags) 06329 tmp->amaflags = i->amaflags; 06330 if (!ast_strlen_zero(i->language)) 06331 ast_string_field_set(tmp, language, i->language); 06332 i->owner = tmp; 06333 ast_module_ref(ast_module_info->self); 06334 ast_copy_string(tmp->context, i->context, sizeof(tmp->context)); 06335 /*Since it is valid to have extensions in the dialplan that have unescaped characters in them 06336 * we should decode the uri before storing it in the channel, but leave it encoded in the sip_pvt 06337 * structure so that there aren't issues when forming URI's 06338 */ 06339 decoded_exten = ast_strdupa(i->exten); 06340 ast_uri_decode(decoded_exten); 06341 ast_copy_string(tmp->exten, decoded_exten, sizeof(tmp->exten)); 06342 06343 /* Don't use ast_set_callerid() here because it will 06344 * generate an unnecessary NewCallerID event */ 06345 tmp->cid.cid_ani = ast_strdup(i->cid_num); 06346 if (!ast_strlen_zero(i->rdnis)) 06347 tmp->cid.cid_rdnis = ast_strdup(i->rdnis); 06348 06349 if (!ast_strlen_zero(i->exten) && strcmp(i->exten, "s")) 06350 tmp->cid.cid_dnid = ast_strdup(i->exten); 06351 06352 tmp->priority = 1; 06353 if (!ast_strlen_zero(i->uri)) 06354 pbx_builtin_setvar_helper(tmp, "SIPURI", i->uri); 06355 if (!ast_strlen_zero(i->domain)) 06356 pbx_builtin_setvar_helper(tmp, "SIPDOMAIN", i->domain); 06357 if (!ast_strlen_zero(i->callid)) 06358 pbx_builtin_setvar_helper(tmp, "SIPCALLID", i->callid); 06359 if (i->rtp) 06360 ast_jb_configure(tmp, &global_jbconf); 06361 06362 /* Set channel variables for this call from configuration */ 06363 for (v = i->chanvars ; v ; v = v->next) 06364 pbx_builtin_setvar_helper(tmp, v->name, v->value); 06365 06366 if (state != AST_STATE_DOWN && ast_pbx_start(tmp)) { 06367 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name); 06368 tmp->hangupcause = AST_CAUSE_SWITCH_CONGESTION; 06369 ast_hangup(tmp); 06370 tmp = NULL; 06371 } 06372 06373 if (i->do_history) 06374 append_history(i, "NewChan", "Channel %s - from %s", tmp->name, i->callid); 06375 06376 /* Inform manager user about new channel and their SIP call ID */ 06377 if (global_callevents) 06378 manager_event(EVENT_FLAG_SYSTEM, "ChannelUpdate", 06379 "Channel: %s\r\nUniqueid: %s\r\nChanneltype: %s\r\nSIPcallid: %s\r\nSIPfullcontact: %s\r\n", 06380 tmp->name, tmp->uniqueid, "SIP", i->callid, i->fullcontact); 06381 06382 return tmp; 06383 }
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 17967 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_string_field_set, ast_strlen_zero(), ast_channel::context, copy_request(), ast_channel::exten, ast_channel::hangupcause, LOG_WARNING, ast_channel::name, parkinglot, ast_channel::parkinglot, 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().
17968 { 17969 struct sip_dual *d; 17970 struct ast_channel *transferee, *transferer; 17971 /* Chan2m: The transferer, chan1m: The transferee */ 17972 pthread_t th; 17973 17974 transferee = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan1->accountcode, chan1->exten, chan1->context, chan1->amaflags, "Parking/%s", chan1->name); 17975 transferer = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan2->accountcode, chan2->exten, chan2->context, chan2->amaflags, "SIPPeer/%s", chan2->name); 17976 if ((!transferer) || (!transferee)) { 17977 if (transferee) { 17978 transferee->hangupcause = AST_CAUSE_SWITCH_CONGESTION; 17979 ast_hangup(transferee); 17980 } 17981 if (transferer) { 17982 transferer->hangupcause = AST_CAUSE_SWITCH_CONGESTION; 17983 ast_hangup(transferer); 17984 } 17985 return -1; 17986 } 17987 17988 /* Make formats okay */ 17989 transferee->readformat = chan1->readformat; 17990 transferee->writeformat = chan1->writeformat; 17991 17992 /* Prepare for taking over the channel */ 17993 ast_channel_masquerade(transferee, chan1); 17994 17995 /* Setup the extensions and such */ 17996 ast_copy_string(transferee->context, chan1->context, sizeof(transferee->context)); 17997 ast_copy_string(transferee->exten, chan1->exten, sizeof(transferee->exten)); 17998 transferee->priority = chan1->priority; 17999 18000 /* We make a clone of the peer channel too, so we can play 18001 back the announcement */ 18002 18003 /* Make formats okay */ 18004 transferer->readformat = chan2->readformat; 18005 transferer->writeformat = chan2->writeformat; 18006 if (!ast_strlen_zero(chan2->parkinglot)) 18007 ast_string_field_set(transferer, parkinglot, chan2->parkinglot); 18008 18009 /* Prepare for taking over the channel. Go ahead and grab this channel 18010 * lock here to avoid a deadlock with callbacks into the channel driver 18011 * that hold the channel lock and want the pvt lock. */ 18012 while (ast_channel_trylock(chan2)) { 18013 struct sip_pvt *pvt = chan2->tech_pvt; 18014 sip_pvt_unlock(pvt); 18015 usleep(1); 18016 sip_pvt_lock(pvt); 18017 } 18018 ast_channel_masquerade(transferer, chan2); 18019 ast_channel_unlock(chan2); 18020 18021 /* Setup the extensions and such */ 18022 ast_copy_string(transferer->context, chan2->context, sizeof(transferer->context)); 18023 ast_copy_string(transferer->exten, chan2->exten, sizeof(transferer->exten)); 18024 transferer->priority = chan2->priority; 18025 18026 ast_channel_lock(transferer); 18027 if (ast_do_masquerade(transferer)) { 18028 ast_log(LOG_WARNING, "Masquerade failed :(\n"); 18029 ast_channel_unlock(transferer); 18030 transferer->hangupcause = AST_CAUSE_SWITCH_CONGESTION; 18031 ast_hangup(transferer); 18032 return -1; 18033 } 18034 ast_channel_unlock(transferer); 18035 if (!transferer || !transferee) { 18036 if (!transferer) { 18037 ast_debug(1, "No transferer channel, giving up parking\n"); 18038 } 18039 if (!transferee) { 18040 ast_debug(1, "No transferee channel, giving up parking\n"); 18041 } 18042 return -1; 18043 } 18044 if ((d = ast_calloc(1, sizeof(*d)))) { 18045 18046 /* Save original request for followup */ 18047 copy_request(&d->req, req); 18048 d->chan1 = transferee; /* Transferee */ 18049 d->chan2 = transferer; /* Transferer */ 18050 d->seqno = seqno; 18051 if (ast_pthread_create_detached_background(&th, NULL, sip_park_thread, d) < 0) { 18052 /* Could not start thread */ 18053 if (d->req.data) 18054 ast_free(d->req.data); 18055 ast_free(d); /* We don't need it anymore. If thread is created, d will be free'd 18056 by sip_park_thread() */ 18057 return 0; 18058 } 18059 } 18060 return -1; 18061 }
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 17895 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().
17896 { 17897 struct ast_channel *transferee, *transferer; /* Chan1: The transferee, Chan2: The transferer */ 17898 struct sip_dual *d; 17899 struct sip_request req = {0,}; 17900 int ext; 17901 int res; 17902 17903 d = stuff; 17904 transferee = d->chan1; 17905 transferer = d->chan2; 17906 copy_request(&req, &d->req); 17907 17908 if (!transferee || !transferer) { 17909 ast_log(LOG_ERROR, "Missing channels for parking! Transferer %s Transferee %s\n", transferer ? "<available>" : "<missing>", transferee ? "<available>" : "<missing>" ); 17910 if (d->req.data) 17911 ast_free(d->req.data); 17912 free(d); 17913 return NULL; 17914 } 17915 ast_debug(4, "SIP Park: Transferer channel %s, Transferee %s\n", transferer->name, transferee->name); 17916 17917 ast_channel_lock(transferee); 17918 if (ast_do_masquerade(transferee)) { 17919 ast_log(LOG_WARNING, "Masquerade failed.\n"); 17920 transmit_response(transferer->tech_pvt, "503 Internal error", &req); 17921 ast_channel_unlock(transferee); 17922 if (d->req.data) 17923 ast_free(d->req.data); 17924 free(d); 17925 return NULL; 17926 } 17927 ast_channel_unlock(transferee); 17928 17929 res = ast_park_call(transferee, transferer, 0, &ext); 17930 17931 17932 #ifdef WHEN_WE_KNOW_THAT_THE_CLIENT_SUPPORTS_MESSAGE 17933 if (!res) { 17934 transmit_message_with_text(transferer->tech_pvt, "Unable to park call.\n"); 17935 } else { 17936 /* Then tell the transferer what happened */ 17937 sprintf(buf, "Call parked on extension '%d'", ext); 17938 transmit_message_with_text(transferer->tech_pvt, buf); 17939 } 17940 #endif 17941 17942 /* Any way back to the current call??? */ 17943 /* Transmit response to the REFER request */ 17944 transmit_response(transferer->tech_pvt, "202 Accepted", &req); 17945 if (!res) { 17946 /* Transfer succeeded */ 17947 append_history(transferer->tech_pvt, "SIPpark", "Parked call on %d", ext); 17948 transmit_notify_with_sipfrag(transferer->tech_pvt, d->seqno, "200 OK", TRUE); 17949 transferer->hangupcause = AST_CAUSE_NORMAL_CLEARING; 17950 ast_hangup(transferer); /* This will cause a BYE */ 17951 ast_debug(1, "SIP Call parked on extension '%d'\n", ext); 17952 } else { 17953 transmit_notify_with_sipfrag(transferer->tech_pvt, d->seqno, "503 Service Unavailable", TRUE); 17954 append_history(transferer->tech_pvt, "SIPpark", "Parking failed\n"); 17955 ast_debug(1, "SIP Call parked failed \n"); 17956 /* Do not hangup call */ 17957 } 17958 if (d->req.data) 17959 ast_free(d->req.data); 17960 free(d); 17961 return NULL; 17962 }
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 21292 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().
21293 { 21294 char *port; 21295 21296 if ((*hostname = strstr(line, "://"))) { 21297 *hostname += 3; 21298 21299 if (!strncasecmp(line, "tcp", 3)) 21300 *transport = SIP_TRANSPORT_TCP; 21301 else if (!strncasecmp(line, "tls", 3)) 21302 *transport = SIP_TRANSPORT_TLS; 21303 else if (!strncasecmp(line, "udp", 3)) 21304 *transport = SIP_TRANSPORT_UDP; 21305 else 21306 ast_log(LOG_NOTICE, "'%.3s' is not a valid transport type on line %d of sip.conf. defaulting to udp.\n", line, lineno); 21307 } else { 21308 *hostname = line; 21309 *transport = SIP_TRANSPORT_UDP; 21310 } 21311 21312 if ((line = strrchr(*hostname, '@'))) 21313 line++; 21314 else 21315 line = *hostname; 21316 21317 if ((port = strrchr(line, ':'))) { 21318 *port++ = '\0'; 21319 21320 if (!sscanf(port, "%5u", portnum)) { 21321 ast_log(LOG_NOTICE, "'%s' is not a valid port number on line %d of sip.conf. using default.\n", port, lineno); 21322 port = NULL; 21323 } 21324 } 21325 21326 if (!port) { 21327 if (*transport & SIP_TRANSPORT_TLS) { 21328 *portnum = STANDARD_TLS_PORT; 21329 } else { 21330 *portnum = STANDARD_SIP_PORT; 21331 } 21332 } 21333 21334 return 0; 21335 }
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 11952 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().
11953 { 11954 struct sip_peer *peer = find_peer(p->peername, NULL, 1, FINDALLDEVICES, FALSE, 0); 11955 11956 if (!peer) 11957 return; 11958 11959 /* If they put someone on hold, increment the value... otherwise decrement it */ 11960 ast_atomic_fetchadd_int(&peer->onHold, (hold ? +1 : -1)); 11961 11962 /* Request device state update */ 11963 ast_devstate_changed(AST_DEVICE_UNKNOWN, "SIP/%s", peer->name); 11964 unref_peer(peer, "sip_peer_hold: from find_peer operation"); 11965 11966 return; 11967 }
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 24543 of file chan_sip.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_lock(), ao2_t_iterator_next, ao2_unlock(), AST_SCHED_REPLACE_UNREF, peers, sip_peer::pokeexpire, ref_peer(), sched, sip_poke_peer_s(), and unref_peer().
Referenced by load_module(), and sip_do_reload().
24544 { 24545 int ms = 0; 24546 struct ao2_iterator i; 24547 struct sip_peer *peer; 24548 24549 if (!speerobjs) /* No peers, just give up */ 24550 return; 24551 24552 i = ao2_iterator_init(peers, 0); 24553 while ((peer = ao2_t_iterator_next(&i, "iterate thru peers table"))) { 24554 ao2_lock(peer); 24555 ms += 100; 24556 AST_SCHED_REPLACE_UNREF(peer->pokeexpire, sched, ms, sip_poke_peer_s, peer, 24557 unref_peer(_data, "removing poke peer ref"), 24558 unref_peer(peer, "removing poke peer ref"), 24559 ref_peer(peer, "adding poke peer ref")); 24560 ao2_unlock(peer); 24561 unref_peer(peer, "toss iterator peer ptr"); 24562 } 24563 ao2_iterator_destroy(&i); 24564 }
static int sip_poke_noanswer | ( | const void * | data | ) | [static] |
React to lack of answer to Qualify poke.
Definition at line 21916 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().
21917 { 21918 struct sip_peer *peer = (struct sip_peer *)data; 21919 21920 peer->pokeexpire = -1; 21921 21922 if (peer->lastms > -1) { 21923 ast_log(LOG_NOTICE, "Peer '%s' is now UNREACHABLE! Last qualify: %d\n", peer->name, peer->lastms); 21924 if (sip_cfg.peer_rtupdate) { 21925 ast_update_realtime(ast_check_realtime("sipregs") ? "sipregs" : "sippeers", "name", peer->name, "lastms", "-1", SENTINEL); 21926 } 21927 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: SIP\r\nPeer: SIP/%s\r\nPeerStatus: Unreachable\r\nTime: %d\r\n", peer->name, -1); 21928 if (global_regextenonqualify) { 21929 register_peer_exten(peer, FALSE); 21930 } 21931 } 21932 21933 if (peer->call) { 21934 dialog_unlink_all(peer->call, TRUE, TRUE); 21935 peer->call = dialog_unref(peer->call, "unref dialog peer->call"); 21936 /* peer->call = sip_destroy(peer->call);*/ 21937 } 21938 21939 peer->lastms = -1; 21940 ast_devstate_changed(AST_DEVICE_UNKNOWN, "SIP/%s", peer->name); 21941 21942 /* Try again quickly */ 21943 AST_SCHED_REPLACE_UNREF(peer->pokeexpire, sched, 21944 DEFAULT_FREQ_NOTOK, sip_poke_peer_s, peer, 21945 unref_peer(_data, "removing poke peer ref"), 21946 unref_peer(peer, "removing poke peer ref"), 21947 ref_peer(peer, "adding poke peer ref")); 21948 21949 /* Release the ref held by the running scheduler entry */ 21950 unref_peer(peer, "release peer poke noanswer ref"); 21951 21952 return 0; 21953 }
static int sip_poke_peer | ( | struct sip_peer * | peer, | |
int | force | |||
) | [static] |
Check availability of peer, also keep NAT open.
Definition at line 21960 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().
21961 { 21962 struct sip_pvt *p; 21963 int xmitres = 0; 21964 21965 if ((!peer->maxms && !force) || !peer->addr.sin_addr.s_addr) { 21966 /* IF we have no IP, or this isn't to be monitored, return 21967 immediately after clearing things out */ 21968 AST_SCHED_DEL_UNREF(sched, peer->pokeexpire, 21969 unref_peer(peer, "removing poke peer ref")); 21970 21971 peer->lastms = 0; 21972 if (peer->call) { 21973 peer->call = dialog_unref(peer->call, "unref dialog peer->call"); 21974 } 21975 return 0; 21976 } 21977 if (peer->call) { 21978 if (sipdebug) { 21979 ast_log(LOG_NOTICE, "Still have a QUALIFY dialog active, deleting\n"); 21980 } 21981 dialog_unlink_all(peer->call, TRUE, TRUE); 21982 peer->call = dialog_unref(peer->call, "unref dialog peer->call"); 21983 /* peer->call = sip_destroy(peer->call); */ 21984 } 21985 if (!(p = sip_alloc(NULL, NULL, 0, SIP_OPTIONS, NULL))) { 21986 return -1; 21987 } 21988 peer->call = dialog_ref(p, "copy sip alloc from p to peer->call"); 21989 21990 p->sa = peer->addr; 21991 p->recv = peer->addr; 21992 copy_socket_data(&p->socket, &peer->socket); 21993 ast_copy_flags(&p->flags[0], &peer->flags[0], SIP_FLAGS_TO_COPY); 21994 ast_copy_flags(&p->flags[1], &peer->flags[1], SIP_PAGE2_FLAGS_TO_COPY); 21995 21996 /* Send OPTIONs to peer's fullcontact */ 21997 if (!ast_strlen_zero(peer->fullcontact)) 21998 ast_string_field_set(p, fullcontact, peer->fullcontact); 21999 22000 if (!ast_strlen_zero(peer->tohost)) 22001 ast_string_field_set(p, tohost, peer->tohost); 22002 else 22003 ast_string_field_set(p, tohost, ast_inet_ntoa(peer->addr.sin_addr)); 22004 22005 /* Recalculate our side, and recalculate Call ID */ 22006 ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip, p); 22007 build_via(p); 22008 ao2_t_unlink(dialogs, p, "About to change the callid -- remove the old name"); 22009 build_callid_pvt(p); 22010 ao2_t_link(dialogs, p, "Linking in under new name"); 22011 22012 AST_SCHED_DEL_UNREF(sched, peer->pokeexpire, 22013 unref_peer(peer, "removing poke peer ref")); 22014 22015 if (p->relatedpeer) 22016 p->relatedpeer = unref_peer(p->relatedpeer,"unsetting the relatedpeer field in the dialog, before it is set to something else."); 22017 p->relatedpeer = ref_peer(peer, "setting the relatedpeer field in the dialog"); 22018 ast_set_flag(&p->flags[0], SIP_OUTGOING); 22019 #ifdef VOCAL_DATA_HACK 22020 ast_copy_string(p->username, "__VOCAL_DATA_SHOULD_READ_THE_SIP_SPEC__", sizeof(p->username)); 22021 xmitres = transmit_invite(p, SIP_INVITE, 0, 2); /* sinks the p refcount */ 22022 #else 22023 xmitres = transmit_invite(p, SIP_OPTIONS, 0, 2); /* sinks the p refcount */ 22024 #endif 22025 peer->ps = ast_tvnow(); 22026 if (xmitres == XMIT_ERROR) { 22027 sip_poke_noanswer(peer); /* Immediately unreachable, network problems */ 22028 } else if (!force) { 22029 AST_SCHED_REPLACE_UNREF(peer->pokeexpire, sched, peer->maxms * 2, sip_poke_noanswer, peer, 22030 unref_peer(_data, "removing poke peer ref"), 22031 unref_peer(peer, "removing poke peer ref"), 22032 ref_peer(peer, "adding poke peer ref")); 22033 } 22034 dialog_unref(p, "unref dialog at end of sip_poke_peer, obtained from sip_alloc, just before it goes out of scope"); 22035 return 0; 22036 }
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 11271 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().
11272 { 11273 struct sip_peer *peer = (struct sip_peer *)data; 11274 11275 peer->pokeexpire = -1; 11276 11277 sip_poke_peer(peer, 0); 11278 11279 unref_peer(peer, "removing poke peer ref"); 11280 11281 return 0; 11282 }
static int sip_prepare_socket | ( | struct sip_pvt * | p | ) | [static] |
Definition at line 21161 of file chan_sip.c.
References ao2_alloc, ao2_ref, ao2_t_ref, ao2_t_unlink, ast_calloc, ast_copy_string(), ast_debug, ast_pthread_create_background, ast_strdup, ast_strlen_zero(), ast_tcptls_client_create(), ast_tls_config::cafile, ast_tls_config::capath, ast_tls_config::certfile, ast_tls_config::cipher, default_tls_cfg, ast_tcptls_session_instance::fd, 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_tcptls_client_args_destructor(), sip_threadinfo_create(), SIP_TRANSPORT_TCP, SIP_TRANSPORT_TLS, SIP_TRANSPORT_UDP, sip_pvt::socket, threadt, sip_pvt::tohost, and sip_proxy::transport.
Referenced by __sip_xmit().
21162 { 21163 struct sip_socket *s = &p->socket; 21164 static const char name[] = "SIP socket"; 21165 struct sip_threadinfo *th = NULL; 21166 struct ast_tcptls_session_instance *tcptls_session; 21167 struct ast_tcptls_session_args tmp_ca = { 21168 .name = name, 21169 .accept_fd = -1, 21170 }; 21171 struct ast_tcptls_session_args *ca; 21172 21173 /* check to see if a socket is already active */ 21174 if ((s->fd != -1) && (s->type == SIP_TRANSPORT_UDP)) { 21175 return s->fd; 21176 } 21177 if ((s->type & (SIP_TRANSPORT_TCP | SIP_TRANSPORT_TLS)) && 21178 (s->tcptls_session) && 21179 (s->tcptls_session->fd != -1)) { 21180 return s->tcptls_session->fd; 21181 } 21182 21183 if (p->outboundproxy && p->outboundproxy->transport) { 21184 s->type = p->outboundproxy->transport; 21185 } 21186 21187 if (s->type == SIP_TRANSPORT_UDP) { 21188 s->fd = sipsock; 21189 return s->fd; 21190 } 21191 21192 /* At this point we are dealing with a TCP/TLS connection 21193 * 1. We need to check to see if a connectin thread exists 21194 * for this address, if so use that. 21195 * 2. If a thread does not exist for this address, but the tcptls_session 21196 * exists on the socket, the connection was closed. 21197 * 3. If no tcptls_session thread exists for the address, and no tcptls_session 21198 * already exists on the socket, create a new one and launch a new thread. 21199 */ 21200 21201 /* 1. check for existing threads */ 21202 tmp_ca.remote_address = *(sip_real_dst(p)); 21203 if ((tcptls_session = sip_tcp_locate(&tmp_ca.remote_address))) { 21204 s->fd = tcptls_session->fd; 21205 if (s->tcptls_session) { 21206 ao2_ref(s->tcptls_session, -1); 21207 s->tcptls_session = NULL; 21208 } 21209 s->tcptls_session = tcptls_session; 21210 return s->fd; 21211 /* 2. Thread not found, if tcptls_session already exists, it once had a thread and is now terminated */ 21212 } else if (s->tcptls_session) { 21213 return s->fd; /* XXX whether reconnection is ever necessary here needs to be investigated further */ 21214 } 21215 21216 /* 3. Create a new TCP/TLS client connection */ 21217 /* create new session arguments for the client connection */ 21218 if (!(ca = ao2_alloc(sizeof(*ca), sip_tcptls_client_args_destructor)) || 21219 !(ca->name = ast_strdup(name))) { 21220 goto create_tcptls_session_fail; 21221 } 21222 ca->accept_fd = -1; 21223 ca->remote_address = *(sip_real_dst(p)); 21224 /* if type is TLS, we need to create a tls cfg for this session arg */ 21225 if (s->type == SIP_TRANSPORT_TLS) { 21226 if (!(ca->tls_cfg = ast_calloc(1, sizeof(*ca->tls_cfg)))) { 21227 goto create_tcptls_session_fail; 21228 } 21229 memcpy(ca->tls_cfg, &default_tls_cfg, sizeof(*ca->tls_cfg)); 21230 21231 if (!(ca->tls_cfg->certfile = ast_strdup(default_tls_cfg.certfile)) || 21232 !(ca->tls_cfg->cipher = ast_strdup(default_tls_cfg.cipher)) || 21233 !(ca->tls_cfg->cafile = ast_strdup(default_tls_cfg.cafile)) || 21234 !(ca->tls_cfg->capath = ast_strdup(default_tls_cfg.capath))) { 21235 21236 goto create_tcptls_session_fail; 21237 } 21238 21239 /* this host is used as the common name in ssl/tls */ 21240 if (!ast_strlen_zero(p->tohost)) { 21241 ast_copy_string(ca->hostname, p->tohost, sizeof(ca->hostname)); 21242 } 21243 } 21244 /* Create a client connection for address, this does not start the connection, just sets it up. */ 21245 if (!(s->tcptls_session = ast_tcptls_client_create(ca))) { 21246 goto create_tcptls_session_fail; 21247 } 21248 21249 s->fd = s->tcptls_session->fd; 21250 21251 /* client connections need to have the sip_threadinfo object created before 21252 * the thread is detached. This ensures the alert_pipe is up before it will 21253 * be used. Note that this function links the new threadinfo object into the 21254 * threadt container. */ 21255 if (!(th = sip_threadinfo_create(s->tcptls_session, s->type))) { 21256 goto create_tcptls_session_fail; 21257 21258 } 21259 21260 /* Give the new thread a reference to the tcptls_session */ 21261 ao2_ref(s->tcptls_session, +1); 21262 21263 if (ast_pthread_create_background(&ca->master, NULL, sip_tcp_worker_fn, s->tcptls_session)) { 21264 ast_debug(1, "Unable to launch '%s'.", ca->name); 21265 ao2_ref(s->tcptls_session, -1); /* take away the thread ref we just gave it */ 21266 goto create_tcptls_session_fail; 21267 } 21268 21269 return s->fd; 21270 21271 create_tcptls_session_fail: 21272 if (ca) { 21273 ao2_t_ref(ca, -1, "failed to create client, getting rid of client tcptls_session arguments"); 21274 } 21275 if (s->tcptls_session) { 21276 close(tcptls_session->fd); 21277 s->fd = tcptls_session->fd = -1; 21278 ao2_ref(s->tcptls_session, -1); 21279 s->tcptls_session = NULL; 21280 } 21281 if (th) { 21282 ao2_t_unlink(threadt, th, "Removing tcptls thread info object, thread failed to open"); 21283 } 21284 21285 return -1; 21286 }
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 14259 of file chan_sip.c.
References sip_peer::addr, ao2_iterator_destroy(), 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, 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.
14260 { 14261 struct sip_peer *peer, *pi; 14262 int prunepeer = FALSE; 14263 int multi = FALSE; 14264 char *name = NULL; 14265 regex_t regexbuf; 14266 struct ao2_iterator i; 14267 14268 if (cmd == CLI_INIT) { 14269 e->command = "sip prune realtime [peer|all] [all|like]"; 14270 e->usage = 14271 "Usage: sip prune realtime [peer [<name>|all|like <pattern>]|all]\n" 14272 " Prunes object(s) from the cache.\n" 14273 " Optional regular expression pattern is used to filter the objects.\n"; 14274 return NULL; 14275 } else if (cmd == CLI_GENERATE) { 14276 if (a->pos == 4) { 14277 if (strcasestr(a->line, "realtime peer")) 14278 return complete_sip_peer(a->word, a->n, SIP_PAGE2_RTCACHEFRIENDS); 14279 } 14280 return NULL; 14281 } 14282 switch (a->argc) { 14283 case 4: 14284 name = a->argv[3]; 14285 /* we accept a name in position 3, but keywords are not good. */ 14286 if (!strcasecmp(name, "peer") || !strcasecmp(name, "like")) 14287 return CLI_SHOWUSAGE; 14288 prunepeer = TRUE; 14289 if (!strcasecmp(name, "all")) { 14290 multi = TRUE; 14291 name = NULL; 14292 } 14293 /* else a single name, already set */ 14294 break; 14295 case 5: 14296 /* sip prune realtime {peer|like} name */ 14297 name = a->argv[4]; 14298 if (!strcasecmp(a->argv[3], "peer")) 14299 prunepeer = TRUE; 14300 else if (!strcasecmp(a->argv[3], "like")) { 14301 prunepeer = TRUE; 14302 multi = TRUE; 14303 } else 14304 return CLI_SHOWUSAGE; 14305 if (!strcasecmp(a->argv[4], "like")) 14306 return CLI_SHOWUSAGE; 14307 if (!multi && !strcasecmp(a->argv[4], "all")) { 14308 multi = TRUE; 14309 name = NULL; 14310 } 14311 break; 14312 case 6: 14313 name = a->argv[5]; 14314 multi = TRUE; 14315 /* sip prune realtime {peer} like name */ 14316 if (strcasecmp(a->argv[4], "like")) 14317 return CLI_SHOWUSAGE; 14318 if (!strcasecmp(a->argv[3], "peer")) { 14319 prunepeer = TRUE; 14320 } else 14321 return CLI_SHOWUSAGE; 14322 break; 14323 default: 14324 return CLI_SHOWUSAGE; 14325 } 14326 14327 if (multi && name) { 14328 if (regcomp(®exbuf, name, REG_EXTENDED | REG_NOSUB)) 14329 return CLI_SHOWUSAGE; 14330 } 14331 14332 if (multi) { 14333 if (prunepeer) { 14334 int pruned = 0; 14335 14336 i = ao2_iterator_init(peers, 0); 14337 while ((pi = ao2_t_iterator_next(&i, "iterate thru peers table"))) { 14338 ao2_lock(pi); 14339 if (name && regexec(®exbuf, pi->name, 0, NULL, 0)) { 14340 unref_peer(pi, "toss iterator peer ptr before continue"); 14341 ao2_unlock(pi); 14342 continue; 14343 }; 14344 if (ast_test_flag(&pi->flags[1], SIP_PAGE2_RTCACHEFRIENDS)) { 14345 pi->the_mark = 1; 14346 pruned++; 14347 } 14348 ao2_unlock(pi); 14349 unref_peer(pi, "toss iterator peer ptr"); 14350 } 14351 ao2_iterator_destroy(&i); 14352 if (pruned) { 14353 ao2_t_callback(peers, OBJ_NODATA | OBJ_UNLINK | OBJ_MULTIPLE, peer_is_marked, 0, 14354 "initiating callback to remove marked peers"); 14355 ast_cli(a->fd, "%d peers pruned.\n", pruned); 14356 } else 14357 ast_cli(a->fd, "No peers found to prune.\n"); 14358 } 14359 } else { 14360 if (prunepeer) { 14361 struct sip_peer tmp; 14362 ast_copy_string(tmp.name, name, sizeof(tmp.name)); 14363 if ((peer = ao2_t_find(peers, &tmp, OBJ_POINTER | OBJ_UNLINK, "finding to unlink from peers"))) { 14364 if (peer->addr.sin_addr.s_addr) { 14365 ao2_t_unlink(peers_by_ip, peer, "unlinking peer from peers_by_ip also"); 14366 } 14367 if (!ast_test_flag(&peer->flags[1], SIP_PAGE2_RTCACHEFRIENDS)) { 14368 ast_cli(a->fd, "Peer '%s' is not a Realtime peer, cannot be pruned.\n", name); 14369 /* put it back! */ 14370 ao2_t_link(peers, peer, "link peer into peer table"); 14371 if (peer->addr.sin_addr.s_addr) { 14372 ao2_t_link(peers_by_ip, peer, "link peer into peers_by_ip table"); 14373 } 14374 14375 } else 14376 ast_cli(a->fd, "Peer '%s' pruned.\n", name); 14377 unref_peer(peer, "sip_prune_realtime: unref_peer: tossing temp peer ptr"); 14378 } else 14379 ast_cli(a->fd, "Peer '%s' not found.\n", name); 14380 } 14381 } 14382 14383 return CLI_SUCCESS; 14384 }
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 14538 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.
14539 { 14540 switch (cmd) { 14541 case CLI_INIT: 14542 e->command = "sip qualify peer"; 14543 e->usage = 14544 "Usage: sip qualify peer <name> [load]\n" 14545 " Requests a response from one SIP peer and the current status.\n" 14546 " Option \"load\" forces lookup of peer in realtime storage.\n"; 14547 return NULL; 14548 case CLI_GENERATE: 14549 return complete_sip_show_peer(a->line, a->word, a->pos, a->n); 14550 } 14551 return _sip_qualify_peer(0, a->fd, NULL, NULL, a->argc, (const char **) a->argv); 14552 }
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 3885 of file chan_sip.c.
References ast_log(), AST_OPTION_T38_STATE, ast_test_flag, chan, sip_pvt::flags, LOG_ERROR, SIP_PAGE2_T38SUPPORT, sip_pvt_lock, sip_pvt_unlock, t38properties::state, sip_pvt::t38, T38_ENABLED, T38_LOCAL_REINVITE, T38_PEER_REINVITE, T38_STATE_NEGOTIATED, T38_STATE_NEGOTIATING, T38_STATE_UNAVAILABLE, T38_STATE_UNKNOWN, and ast_channel::tech_pvt.
03886 { 03887 int res = -1; 03888 enum ast_t38_state state = T38_STATE_UNAVAILABLE; 03889 struct sip_pvt *p = (struct sip_pvt *) chan->tech_pvt; 03890 03891 switch (option) { 03892 case AST_OPTION_T38_STATE: 03893 /* Make sure we got an ast_t38_state enum passed in */ 03894 if (*datalen != sizeof(enum ast_t38_state)) { 03895 ast_log(LOG_ERROR, "Invalid datalen for AST_OPTION_T38_STATE option. Expected %d, got %d\n", (int)sizeof(enum ast_t38_state), *datalen); 03896 return -1; 03897 } 03898 03899 sip_pvt_lock(p); 03900 03901 /* 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 */ 03902 if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT)) { 03903 switch (p->t38.state) { 03904 case T38_LOCAL_REINVITE: 03905 case T38_PEER_REINVITE: 03906 state = T38_STATE_NEGOTIATING; 03907 break; 03908 case T38_ENABLED: 03909 state = T38_STATE_NEGOTIATED; 03910 break; 03911 default: 03912 state = T38_STATE_UNKNOWN; 03913 } 03914 } 03915 03916 sip_pvt_unlock(p); 03917 03918 *((enum ast_t38_state *) data) = state; 03919 res = 0; 03920 03921 break; 03922 default: 03923 break; 03924 } 03925 03926 return res; 03927 }
static struct ast_frame * sip_read | ( | struct ast_channel * | ast | ) | [static] |
Read SIP RTP from channel.
Definition at line 6631 of file chan_sip.c.
References ast_channel::_state, ast_async_goto(), ast_channel_lock, ast_channel_unlock, ast_exists_extension(), AST_FRAME_VOICE, ast_log(), ast_null_frame, AST_STATE_UP, ast_test_flag, ast_verbose, FALSE, sip_pvt::flags, ast_frame::frametype, INV_EARLY_MEDIA, sip_pvt::invitestate, sip_pvt::lastrtprx, LOG_NOTICE, pbx_builtin_setvar_helper(), S_OR, SIP_PAGE2_FAX_DETECT, sip_pvt_lock, sip_pvt_unlock, sip_rtp_read(), ast_channel::tech_pvt, and VERBOSE_PREFIX_2.
06632 { 06633 struct ast_frame *fr; 06634 struct sip_pvt *p = ast->tech_pvt; 06635 int faxdetected = FALSE; 06636 06637 sip_pvt_lock(p); 06638 fr = sip_rtp_read(ast, p, &faxdetected); 06639 p->lastrtprx = time(NULL); 06640 06641 /* If we detect a CNG tone and fax detection is enabled then send us off to the fax extension */ 06642 if (faxdetected && ast_test_flag(&p->flags[1], SIP_PAGE2_FAX_DETECT)) { 06643 ast_channel_lock(ast); 06644 if (strcmp(ast->exten, "fax")) { 06645 const char *target_context = S_OR(ast->macrocontext, ast->context); 06646 ast_channel_unlock(ast); 06647 if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) { 06648 ast_verbose(VERBOSE_PREFIX_2 "Redirecting '%s' to fax extension\n", ast->name); 06649 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten); 06650 if (ast_async_goto(ast, target_context, "fax", 1)) { 06651 ast_log(LOG_NOTICE, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context); 06652 } 06653 fr = &ast_null_frame; 06654 } else { 06655 ast_log(LOG_NOTICE, "Fax detected but no fax extension\n"); 06656 } 06657 } else { 06658 ast_channel_unlock(ast); 06659 } 06660 } 06661 06662 /* Only allow audio through if they sent progress with SDP, or if the channel is actually answered */ 06663 if (fr && fr->frametype == AST_FRAME_VOICE && p->invitestate != INV_EARLY_MEDIA && ast->_state != AST_STATE_UP) { 06664 fr = &ast_null_frame; 06665 } 06666 06667 sip_pvt_unlock(p); 06668 06669 return fr; 06670 }
static struct sockaddr_in * sip_real_dst | ( | const struct sip_pvt * | p | ) | [static] |
The real destination address for a write.
Definition at line 3078 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().
03079 { 03080 if (p->outboundproxy) 03081 return &p->outboundproxy->ip; 03082 03083 return ast_test_flag(&p->flags[0], SIP_NAT) & SIP_NAT_ROUTE ? &p->recv : &p->sa; 03084 }
static int sip_refer_allocate | ( | struct sip_pvt * | p | ) | [static] |
Allocate SIP refer structure.
Definition at line 11031 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().
11032 { 11033 p->refer = ast_calloc(1, sizeof(struct sip_refer)); 11034 return p->refer ? 1 : 0; 11035 }
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 10715 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().
10716 { 10717 10718 /* if we are here, our registration timed out, so we'll just do it over */ 10719 struct sip_registry *r = (struct sip_registry *)data; /* the ref count should have been bumped when the sched item was added */ 10720 struct sip_pvt *p; 10721 int res; 10722 10723 /* if we couldn't get a reference to the registry object, punt */ 10724 if (!r) 10725 return 0; 10726 10727 if (r->dnsmgr) { 10728 /* If the registration has timed out, maybe the IP changed. Force a refresh. */ 10729 ast_dnsmgr_refresh(r->dnsmgr); 10730 } 10731 10732 ast_log(LOG_NOTICE, " -- Registration for '%s@%s' timed out, trying again (Attempt #%d)\n", r->username, r->hostname, r->regattempts); 10733 /* If the initial tranmission failed, we may not have an existing dialog, 10734 * so it is possible that r->call == NULL. 10735 * Otherwise destroy it, as we have a timeout so we don't want it. 10736 */ 10737 if (r->call) { 10738 /* Unlink us, destroy old call. Locking is not relevant here because all this happens 10739 in the single SIP manager thread. */ 10740 p = r->call; 10741 sip_pvt_lock(p); 10742 p->needdestroy = 1; 10743 /* Pretend to ACK anything just in case */ 10744 __sip_pretend_ack(p); 10745 sip_pvt_unlock(p); 10746 10747 /* decouple the two objects */ 10748 /* p->registry == r, so r has 2 refs, and the unref won't take the object away */ 10749 if (p->registry) 10750 p->registry = registry_unref(p->registry, "p->registry unreffed"); 10751 r->call = dialog_unref(r->call, "unrefing r->call"); 10752 } 10753 /* If we have a limit, stop registration and give up */ 10754 r->timeout = -1; 10755 if (global_regattempts_max && r->regattempts > global_regattempts_max) { 10756 /* Ok, enough is enough. Don't try any more */ 10757 /* We could add an external notification here... 10758 steal it from app_voicemail :-) */ 10759 ast_log(LOG_NOTICE, " -- Giving up forever trying to register '%s@%s'\n", r->username, r->hostname); 10760 r->regstate = REG_STATE_FAILED; 10761 } else { 10762 r->regstate = REG_STATE_UNREGISTERED; 10763 res=transmit_register(r, SIP_REGISTER, NULL, NULL); 10764 } 10765 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)); 10766 registry_unref(r, "unreffing registry_unref r"); 10767 return 0; 10768 }
static int sip_register | ( | const char * | value, | |
int | lineno | |||
) | [static] |
Parse register=> line in sip.conf and add to registry.
Definition at line 7058 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, sip_registry::peername, registry_unref(), regl, secret, sip_parse_host(), SIP_TRANSPORT_UDP, sip_registry::transport, and sip_registry::username.
Referenced by build_peer().
07059 { 07060 struct sip_registry *reg; 07061 int portnum = 0; 07062 enum sip_transport transport = SIP_TRANSPORT_UDP; 07063 char buf[256] = ""; 07064 char *username = NULL; 07065 char *hostname=NULL, *secret=NULL, *authuser=NULL, *expire=NULL, *tmp=NULL; 07066 char *callback=NULL, *peername=NULL; 07067 07068 if (!value) 07069 return -1; 07070 ast_copy_string(buf, value, sizeof(buf)); 07071 tmp = strrchr(buf, '@'); 07072 07073 /* split [/extension][~expiry] */ 07074 expire = strchr(tmp, '~'); 07075 if (expire) 07076 *expire++ = '\0'; 07077 callback = strrchr(tmp, '/'); 07078 if (callback) 07079 *callback++ = '\0'; 07080 if (ast_strlen_zero(callback)) 07081 callback = "s"; 07082 07083 /* split [peername?][transport://] */ 07084 tmp = strchr(buf, '?'); 07085 if (tmp) { 07086 *tmp++ = '\0'; 07087 peername = buf; 07088 } else { 07089 tmp = buf; 07090 } 07091 /* tmp is set at the beginning of [transport://] */ 07092 sip_parse_host(tmp, lineno, &username, &portnum, &transport); 07093 07094 /* First split around the last '@' then parse the two components. */ 07095 hostname = strrchr(username, '@'); /* allow @ in the first part */ 07096 if (hostname) 07097 *hostname++ = '\0'; 07098 if (ast_strlen_zero(username) || ast_strlen_zero(hostname)) { 07099 ast_log(LOG_WARNING, "Format for registration is [transport://]user[@domain][:secret[:authuser]]@host[:port][/extension][~expiry] at line %d\n", lineno); 07100 return -1; 07101 } 07102 /* split user[:secret[:authuser]] */ 07103 secret = strchr(username, ':'); 07104 if (secret) { 07105 *secret++ = '\0'; 07106 authuser = strchr(secret, ':'); 07107 if (authuser) 07108 *authuser++ = '\0'; 07109 } 07110 07111 if (!(reg = ast_calloc(1, sizeof(*reg)))) { 07112 ast_log(LOG_ERROR, "Out of memory. Can't allocate SIP registry entry\n"); 07113 return -1; 07114 } 07115 07116 if (ast_string_field_init(reg, 256)) { 07117 ast_log(LOG_ERROR, "Out of memory. Can't allocate SIP registry strings\n"); 07118 ast_free(reg); 07119 return -1; 07120 } 07121 07122 ast_atomic_fetchadd_int(®objs, 1); 07123 ASTOBJ_INIT(reg); 07124 ast_string_field_set(reg, callback, callback); 07125 if (!ast_strlen_zero(username)) 07126 ast_string_field_set(reg, username, username); 07127 if (hostname) 07128 ast_string_field_set(reg, hostname, hostname); 07129 if (authuser) 07130 ast_string_field_set(reg, authuser, authuser); 07131 if (secret) 07132 ast_string_field_set(reg, secret, secret); 07133 if (peername) { 07134 ast_string_field_set(reg, peername, peername); 07135 } 07136 reg->transport = transport; 07137 reg->expire = -1; 07138 reg->configured_expiry = (expire ? atoi(expire) : default_expiry); 07139 reg->expiry = reg->configured_expiry; 07140 reg->timeout = -1; 07141 reg->refresh = reg->expiry; 07142 reg->portno = portnum; 07143 reg->callid_valid = FALSE; 07144 reg->ocseq = INITIAL_CSEQ; 07145 ASTOBJ_CONTAINER_LINK(®l, reg); /* Add the new registry entry to the list */ 07146 registry_unref(reg, "unref the reg pointer"); /* release the reference given by ASTOBJ_INIT. The container has another reference */ 07147 return 0; 07148 }
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 5074 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(), and unload_module().
05075 { 05076 /* Really delete */ 05077 ast_debug(3, "Destroying registry entry for %s@%s\n", reg->username, reg->hostname); 05078 05079 if (reg->call) { 05080 /* Clear registry before destroying to ensure 05081 we don't get reentered trying to grab the registry lock */ 05082 reg->call->registry = registry_unref(reg->call->registry, "destroy reg->call->registry"); 05083 ast_debug(3, "Destroying active SIP dialog for registry %s@%s\n", reg->username, reg->hostname); 05084 dialog_unlink_all(reg->call, TRUE, TRUE); 05085 reg->call = dialog_unref(reg->call, "unref reg->call"); 05086 /* reg->call = sip_destroy(reg->call); */ 05087 } 05088 AST_SCHED_DEL(sched, reg->expire); 05089 AST_SCHED_DEL(sched, reg->timeout); 05090 05091 ast_string_field_free_memory(reg); 05092 ast_atomic_fetchadd_int(®objs, -1); 05093 ast_dnsmgr_release(reg->dnsmgr); 05094 ast_free(reg); 05095 }
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 16818 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().
16819 { 16820 struct sip_pvt *p = (struct sip_pvt *) data; 16821 16822 sip_pvt_lock(p); /* called from schedule thread which requires a lock */ 16823 ast_set_flag(&p->flags[0], SIP_NEEDREINVITE); 16824 p->waitid = -1; 16825 check_pendings(p); 16826 sip_pvt_unlock(p); 16827 dialog_unref(p, "unref the dialog ptr from sip_reinvite_retry, because it held a dialog ptr"); 16828 return 0; 16829 }
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 24619 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().
24620 { 24621 24622 switch (cmd) { 24623 case CLI_INIT: 24624 e->command = "sip reload"; 24625 e->usage = 24626 "Usage: sip reload\n" 24627 " Reloads SIP configuration from sip.conf\n"; 24628 return NULL; 24629 case CLI_GENERATE: 24630 return NULL; 24631 } 24632 24633 ast_mutex_lock(&sip_reload_lock); 24634 if (sip_reloading) 24635 ast_verbose("Previous SIP reload not yet done\n"); 24636 else { 24637 sip_reloading = TRUE; 24638 sip_reloadreason = (a && a->fd) ? CHANNEL_CLI_RELOAD : CHANNEL_MODULE_RELOAD; 24639 } 24640 ast_mutex_unlock(&sip_reload_lock); 24641 restart_monitor(); 24642 24643 return CLI_SUCCESS; 24644 }
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 22150 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, LOG_ERROR, LOG_NOTICE, LOG_WARNING, manager_event, sip_pvt::options, sip_pvt::outgoing_call, sip_pvt::peername, restart_monitor(), secret, set_socket_transport(), sip_alloc(), SIP_INVITE, sip_new(), sip_pvt_lock, sip_pvt_unlock, SIP_TRANSPORT_TCP, SIP_TRANSPORT_TLS, SIP_TRANSPORT_UDP, sip_pvt::socket, and TRUE.
22151 { 22152 struct sip_pvt *p; 22153 struct ast_channel *tmpc = NULL; 22154 char *ext = NULL, *host; 22155 char tmp[256]; 22156 char *dest = data; 22157 char *dnid; 22158 char *secret = NULL; 22159 char *md5secret = NULL; 22160 char *authname = NULL; 22161 char *trans = NULL; 22162 enum sip_transport transport = 0; 22163 int oldformat = format; 22164 22165 /* mask request with some set of allowed formats. 22166 * XXX this needs to be fixed. 22167 * The original code uses AST_FORMAT_AUDIO_MASK, but it is 22168 * unclear what to use here. We have global_capabilities, which is 22169 * configured from sip.conf, and sip_tech.capabilities, which is 22170 * hardwired to all audio formats. 22171 */ 22172 format &= AST_FORMAT_AUDIO_MASK; 22173 if (!format) { 22174 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)); 22175 *cause = AST_CAUSE_BEARERCAPABILITY_NOTAVAIL; /* Can't find codec to connect to host */ 22176 return NULL; 22177 } 22178 ast_debug(1, "Asked to create a SIP channel with formats: %s\n", ast_getformatname_multiple(tmp, sizeof(tmp), oldformat)); 22179 22180 if (!(p = sip_alloc(NULL, NULL, 0, SIP_INVITE, NULL))) { 22181 ast_log(LOG_ERROR, "Unable to build sip pvt data for '%s' (Out of memory or socket error)\n", dest); 22182 *cause = AST_CAUSE_SWITCH_CONGESTION; 22183 return NULL; 22184 } 22185 22186 p->outgoing_call = TRUE; 22187 22188 if (!(p->options = ast_calloc(1, sizeof(*p->options)))) { 22189 dialog_unlink_all(p, TRUE, TRUE); 22190 dialog_unref(p, "unref dialog p from mem fail"); 22191 /* sip_destroy(p); */ 22192 ast_log(LOG_ERROR, "Unable to build option SIP data structure - Out of memory\n"); 22193 *cause = AST_CAUSE_SWITCH_CONGESTION; 22194 return NULL; 22195 } 22196 22197 /* Save the destination, the SIP dial string */ 22198 ast_copy_string(tmp, dest, sizeof(tmp)); 22199 22200 22201 /* Find DNID and take it away */ 22202 dnid = strchr(tmp, '!'); 22203 if (dnid != NULL) { 22204 *dnid++ = '\0'; 22205 ast_string_field_set(p, todnid, dnid); 22206 } 22207 22208 /* Find at sign - @ */ 22209 host = strchr(tmp, '@'); 22210 if (host) { 22211 *host++ = '\0'; 22212 ext = tmp; 22213 secret = strchr(ext, ':'); 22214 } 22215 if (secret) { 22216 *secret++ = '\0'; 22217 md5secret = strchr(secret, ':'); 22218 } 22219 if (md5secret) { 22220 *md5secret++ = '\0'; 22221 authname = strchr(md5secret, ':'); 22222 } 22223 if (authname) { 22224 *authname++ = '\0'; 22225 trans = strchr(authname, ':'); 22226 } 22227 if (trans) { 22228 *trans++ = '\0'; 22229 if (!strcasecmp(trans, "tcp")) 22230 transport = SIP_TRANSPORT_TCP; 22231 else if (!strcasecmp(trans, "tls")) 22232 transport = SIP_TRANSPORT_TLS; 22233 else { 22234 if (strcasecmp(trans, "udp")) 22235 ast_log(LOG_WARNING, "'%s' is not a valid transport option to Dial() for SIP calls, using udp by default.\n", trans); 22236 transport = SIP_TRANSPORT_UDP; 22237 } 22238 } else { /* use default */ 22239 transport = SIP_TRANSPORT_UDP; 22240 } 22241 22242 if (!host) { 22243 ext = strchr(tmp, '/'); 22244 if (ext) 22245 *ext++ = '\0'; 22246 host = tmp; 22247 } 22248 22249 set_socket_transport(&p->socket, transport); 22250 22251 /* We now have 22252 host = peer name, DNS host name or DNS domain (for SRV) 22253 ext = extension (user part of URI) 22254 dnid = destination of the call (applies to the To: header) 22255 */ 22256 if (create_addr(p, host, NULL, 1)) { 22257 *cause = AST_CAUSE_UNREGISTERED; 22258 ast_debug(3, "Cant create SIP call - target device not registered\n"); 22259 dialog_unlink_all(p, TRUE, TRUE); 22260 dialog_unref(p, "unref dialog p UNREGISTERED"); 22261 /* sip_destroy(p); */ 22262 return NULL; 22263 } 22264 if (ast_strlen_zero(p->peername) && ext) 22265 ast_string_field_set(p, peername, ext); 22266 /* Recalculate our side, and recalculate Call ID */ 22267 ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip, p); 22268 build_via(p); 22269 ao2_t_unlink(dialogs, p, "About to change the callid -- remove the old name"); 22270 build_callid_pvt(p); 22271 ao2_t_link(dialogs, p, "Linking in under new name"); 22272 22273 /* We have an extension to call, don't use the full contact here */ 22274 /* This to enable dialing registered peers with extension dialling, 22275 like SIP/peername/extension 22276 SIP/peername will still use the full contact 22277 */ 22278 if (ext) { 22279 ast_string_field_set(p, username, ext); 22280 ast_string_field_set(p, fullcontact, NULL); 22281 } 22282 if (secret && !ast_strlen_zero(secret)) 22283 ast_string_field_set(p, peersecret, secret); 22284 22285 if (md5secret && !ast_strlen_zero(md5secret)) 22286 ast_string_field_set(p, peermd5secret, md5secret); 22287 22288 if (authname && !ast_strlen_zero(authname)) 22289 ast_string_field_set(p, authname, authname); 22290 #if 0 22291 printf("Setting up to call extension '%s' at '%s'\n", ext ? ext : "<none>", host); 22292 #endif 22293 p->prefcodec = oldformat; /* Format for this call */ 22294 p->jointcapability = oldformat; 22295 sip_pvt_lock(p); 22296 tmpc = sip_new(p, AST_STATE_DOWN, host); /* Place the call */ 22297 if (global_callevents) 22298 manager_event(EVENT_FLAG_SYSTEM, "ChannelUpdate", 22299 "Channel: %s\r\nChanneltype: %s\r\nSIPcallid: %s\r\nSIPfullcontact: %s\r\nPeername: %s\r\n", 22300 p->owner? p->owner->name : "", "SIP", p->callid, p->fullcontact, p->peername); 22301 sip_pvt_unlock(p); 22302 if (!tmpc) { 22303 dialog_unlink_all(p, TRUE, TRUE); 22304 /* sip_destroy(p); */ 22305 } 22306 dialog_unref(p, "toss pvt ptr at end of sip_request_call"); 22307 ast_update_use_count(); 22308 restart_monitor(); 22309 return tmpc; 22310 }
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 10677 of file chan_sip.c.
References __sip_do_register(), append_history, ast_log(), sip_registry::call, sip_registry::configured_expiry, sip_pvt::do_history, sip_registry::expire, sip_registry::expiry, sip_registry::hostname, LOG_NOTICE, registry_unref(), and sip_registry::username.
Referenced by handle_response_register(), sip_send_all_registers(), and sip_show_sched().
10678 { 10679 /* if we are here, we know that we need to reregister. */ 10680 struct sip_registry *r= (struct sip_registry *) data; 10681 10682 /* if we couldn't get a reference to the registry object, punt */ 10683 if (!r) 10684 return 0; 10685 10686 if (r->call && r->call->do_history) 10687 append_history(r->call, "RegistryRenew", "Account: %s@%s", r->username, r->hostname); 10688 /* Since registry's are only added/removed by the the monitor thread, this 10689 may be overkill to reference/dereference at all here */ 10690 if (sipdebug) 10691 ast_log(LOG_NOTICE, " -- Re-registration for %s@%s\n", r->username, r->hostname); 10692 10693 r->expire = -1; 10694 r->expiry = r->configured_expiry; 10695 __sip_do_register(r); 10696 registry_unref(r, "unref the re-register scheduled event"); 10697 return 0; 10698 }
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 6541 of file chan_sip.c.
References ast_debug, ast_dsp_free(), ast_dsp_process(), ast_dsp_set_features(), AST_FORMAT_AUDIO_MASK, AST_FORMAT_TEXT_MASK, AST_FORMAT_VIDEO_MASK, AST_FRAME_DTMF, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_VOICE, ast_getformatname(), ast_log(), 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, sip_pvt::dsp, DSP_FEATURE_DIGIT_DETECT, f, ast_channel::fdno, sip_pvt::flags, sip_pvt::jointcapability, LOG_DEBUG, ast_channel::name, ast_channel::nativeformats, option_debug, sip_pvt::owner, ast_channel::readformat, sip_pvt::rtp, SIP_DTMF, SIP_DTMF_INBAND, SIP_DTMF_RFC2833, SIP_PAGE2_FAX_DETECT, sip_pvt::trtp, sip_pvt::udptl, sip_pvt::vrtp, and ast_channel::writeformat.
Referenced by sip_read().
06542 { 06543 /* Retrieve audio/etc from channel. Assumes p->lock is already held. */ 06544 struct ast_frame *f; 06545 06546 if (!p->rtp) { 06547 /* We have no RTP allocated for this channel */ 06548 return &ast_null_frame; 06549 } 06550 06551 switch(ast->fdno) { 06552 case 0: 06553 f = ast_rtp_read(p->rtp); /* RTP Audio */ 06554 break; 06555 case 1: 06556 f = ast_rtcp_read(p->rtp); /* RTCP Control Channel */ 06557 break; 06558 case 2: 06559 f = ast_rtp_read(p->vrtp); /* RTP Video */ 06560 break; 06561 case 3: 06562 f = ast_rtcp_read(p->vrtp); /* RTCP Control Channel for video */ 06563 break; 06564 case 4: 06565 f = ast_rtp_read(p->trtp); /* RTP Text */ 06566 if (sipdebug_text) { 06567 int i; 06568 unsigned char* arr = f->data.ptr; 06569 for (i=0; i < f->datalen; i++) 06570 ast_verbose("%c", (arr[i] > ' ' && arr[i] < '}') ? arr[i] : '.'); 06571 ast_verbose(" -> "); 06572 for (i=0; i < f->datalen; i++) 06573 ast_verbose("%02X ", arr[i]); 06574 ast_verbose("\n"); 06575 } 06576 break; 06577 case 5: 06578 f = ast_udptl_read(p->udptl); /* UDPTL for T.38 */ 06579 break; 06580 default: 06581 f = &ast_null_frame; 06582 } 06583 /* Don't forward RFC2833 if we're not supposed to */ 06584 if (f && (f->frametype == AST_FRAME_DTMF_BEGIN || f->frametype == AST_FRAME_DTMF_END) && 06585 (ast_test_flag(&p->flags[0], SIP_DTMF) != SIP_DTMF_RFC2833)) { 06586 ast_debug(1, "Ignoring DTMF (%c) RTP frame because dtmfmode is not RFC2833\n", f->subclass); 06587 return &ast_null_frame; 06588 } 06589 06590 /* We already hold the channel lock */ 06591 if (!p->owner || (f && f->frametype != AST_FRAME_VOICE)) 06592 return f; 06593 06594 if (f && f->subclass != (p->owner->nativeformats & AST_FORMAT_AUDIO_MASK)) { 06595 if (!(f->subclass & p->jointcapability)) { 06596 ast_debug(1, "Bogus frame of format '%s' received from '%s'!\n", 06597 ast_getformatname(f->subclass), p->owner->name); 06598 return &ast_null_frame; 06599 } 06600 ast_debug(1, "Oooh, format changed to %d %s\n", 06601 f->subclass, ast_getformatname(f->subclass)); 06602 p->owner->nativeformats = (p->owner->nativeformats & (AST_FORMAT_VIDEO_MASK | AST_FORMAT_TEXT_MASK)) | f->subclass; 06603 ast_set_read_format(p->owner, p->owner->readformat); 06604 ast_set_write_format(p->owner, p->owner->writeformat); 06605 } 06606 06607 if (f && ((ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_INBAND) || ast_test_flag(&p->flags[1], SIP_PAGE2_FAX_DETECT)) && p->dsp) { 06608 f = ast_dsp_process(p->owner, p->dsp, f); 06609 if (f && f->frametype == AST_FRAME_DTMF) { 06610 if (f->subclass == 'f') { 06611 if (option_debug) 06612 ast_log(LOG_DEBUG, "Fax CNG detected on %s\n", ast->name); 06613 *faxdetect = 1; 06614 /* If we only needed this DSP for fax detection purposes we can just drop it now */ 06615 if (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_INBAND) { 06616 ast_dsp_set_features(p->dsp, DSP_FEATURE_DIGIT_DETECT); 06617 } else { 06618 ast_dsp_free(p->dsp); 06619 p->dsp = NULL; 06620 } 06621 } else { 06622 ast_debug(1, "* Detected inband DTMF '%c'\n", f->subclass); 06623 } 06624 } 06625 } 06626 06627 return f; 06628 }
static void sip_scheddestroy | ( | struct sip_pvt * | p, | |
int | ms | |||
) | [static] |
Schedule destruction of SIP dialog.
Definition at line 3607 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(), auto_congest(), 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().
03608 { 03609 if (ms < 0) { 03610 if (p->timer_t1 == 0) { 03611 p->timer_t1 = global_t1; /* Set timer T1 if not set (RFC 3261) */ 03612 p->timer_b = global_timer_b; /* Set timer B if not set (RFC 3261) */ 03613 } 03614 ms = p->timer_t1 * 64; 03615 } 03616 if (sip_debug_test_pvt(p)) 03617 ast_verbose("Scheduling destruction of SIP dialog '%s' in %d ms (Method: %s)\n", p->callid, ms, sip_methods[p->method].text); 03618 if (sip_cancel_destroy(p)) 03619 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 03620 03621 if (p->do_history) 03622 append_history(p, "SchedDestroy", "%d ms", ms); 03623 p->autokillid = ast_sched_add(sched, ms, __sip_autodestruct, dialog_ref(p, "setting ref as passing into ast_sched_add for __sip_autodestruct")); 03624 03625 if (p->stimer && p->stimer->st_active == TRUE && p->stimer->st_schedid > 0) 03626 stop_session_timer(p); 03627 }
static void sip_send_all_registers | ( | void | ) | [static] |
Send all known registrations.
Definition at line 24567 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().
24568 { 24569 int ms; 24570 int regspacing; 24571 if (!regobjs) 24572 return; 24573 regspacing = default_expiry * 1000/regobjs; 24574 if (regspacing > 100) 24575 regspacing = 100; 24576 ms = regspacing; 24577 ASTOBJ_CONTAINER_TRAVERSE(®l, 1, do { 24578 ASTOBJ_WRLOCK(iterator); 24579 ms += regspacing; 24580 AST_SCHED_REPLACE_UNREF(iterator->expire, sched, ms, sip_reregister, iterator, 24581 registry_unref(_data, "REPLACE sched del decs the refcount"), 24582 registry_unref(iterator, "REPLACE sched add failure decs the refcount"), 24583 registry_addref(iterator, "REPLACE sched add incs the refcount")); 24584 ASTOBJ_UNLOCK(iterator); 24585 } while (0) 24586 ); 24587 }
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 21363 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, set_socket_transport(), sip_alloc(), SIP_NOTIFY, SIP_OUTGOING, SIP_PAGE2_SUBSCRIBEMWIONLY, sip_scheddestroy(), sip_pvt::socket, ast_str::str, transmit_notify_with_mwi(), TRUE, and sip_peer::vmexten.
Referenced by build_peer(), handle_request_subscribe(), and mwi_event_cb().
21364 { 21365 /* Called with peerl lock, but releases it */ 21366 struct sip_pvt *p; 21367 int newmsgs = 0, oldmsgs = 0; 21368 21369 if (ast_test_flag((&peer->flags[1]), SIP_PAGE2_SUBSCRIBEMWIONLY) && !peer->mwipvt) 21370 return 0; 21371 21372 /* Do we have an IP address? If not, skip this peer */ 21373 if (!peer->addr.sin_addr.s_addr && !peer->defaddr.sin_addr.s_addr) 21374 return 0; 21375 21376 if (event) { 21377 newmsgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS); 21378 oldmsgs = ast_event_get_ie_uint(event, AST_EVENT_IE_OLDMSGS); 21379 } else if (!get_cached_mwi(peer, &newmsgs, &oldmsgs)) { 21380 /* got it! Don't keep looking. */ 21381 } else if (cache_only) { 21382 return 0; 21383 } else { /* Fall back to manually checking the mailbox */ 21384 struct ast_str *mailbox_str = ast_str_alloca(512); 21385 peer_mailboxes_to_str(&mailbox_str, peer); 21386 ast_app_inboxcount(mailbox_str->str, &newmsgs, &oldmsgs); 21387 } 21388 21389 if (peer->mwipvt) { 21390 /* Base message on subscription */ 21391 p = dialog_ref(peer->mwipvt, "sip_send_mwi_to_peer: Setting dialog ptr p from peer->mwipvt-- should this be done?"); 21392 } else { 21393 /* Build temporary dialog for this message */ 21394 if (!(p = sip_alloc(NULL, NULL, 0, SIP_NOTIFY, NULL))) 21395 return -1; 21396 /* If we don't set the socket type to 0, then create_addr_from_peer will fail immediately if the peer 21397 * uses any transport other than UDP. We set the type to 0 here and then let create_addr_from_peer copy 21398 * the peer's socket information to the sip_pvt we just allocated 21399 */ 21400 set_socket_transport(&p->socket, 0); 21401 if (create_addr_from_peer(p, peer)) { 21402 /* Maybe they're not registered, etc. */ 21403 dialog_unlink_all(p, TRUE, TRUE); 21404 dialog_unref(p, "unref dialog p just created via sip_alloc"); 21405 /* sip_destroy(p); */ 21406 return 0; 21407 } 21408 /* Recalculate our side, and recalculate Call ID */ 21409 ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip, p); 21410 build_via(p); 21411 ao2_t_unlink(dialogs, p, "About to change the callid -- remove the old name"); 21412 build_callid_pvt(p); 21413 ao2_t_link(dialogs, p, "Linking in under new name"); 21414 /* Destroy this session after 32 secs */ 21415 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 21416 } 21417 21418 /* Send MWI */ 21419 ast_set_flag(&p->flags[0], SIP_OUTGOING); 21420 /* the following will decrement the refcount on p as it finishes */ 21421 transmit_notify_with_mwi(p, newmsgs, oldmsgs, peer->vmexten); 21422 dialog_unref(p, "unref dialog ptr p just before it goes out of scope at the end of sip_send_mwi_to_peer."); 21423 return 0; 21424 }
static int sip_senddigit_begin | ( | struct ast_channel * | ast, | |
char | digit | |||
) | [static] |
Definition at line 5950 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.
05951 { 05952 struct sip_pvt *p = ast->tech_pvt; 05953 int res = 0; 05954 05955 sip_pvt_lock(p); 05956 switch (ast_test_flag(&p->flags[0], SIP_DTMF)) { 05957 case SIP_DTMF_INBAND: 05958 res = -1; /* Tell Asterisk to generate inband indications */ 05959 break; 05960 case SIP_DTMF_RFC2833: 05961 if (p->rtp) 05962 ast_rtp_senddigit_begin(p->rtp, digit); 05963 break; 05964 default: 05965 break; 05966 } 05967 sip_pvt_unlock(p); 05968 05969 return res; 05970 }
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 5974 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().
05975 { 05976 struct sip_pvt *p = ast->tech_pvt; 05977 int res = 0; 05978 05979 sip_pvt_lock(p); 05980 switch (ast_test_flag(&p->flags[0], SIP_DTMF)) { 05981 case SIP_DTMF_INFO: 05982 case SIP_DTMF_SHORTINFO: 05983 transmit_info_with_digit(p, digit, duration); 05984 break; 05985 case SIP_DTMF_RFC2833: 05986 if (p->rtp) 05987 ast_rtp_senddigit_end(p->rtp, digit); 05988 break; 05989 case SIP_DTMF_INBAND: 05990 res = -1; /* Tell Asterisk to stop inband indications */ 05991 break; 05992 } 05993 sip_pvt_unlock(p); 05994 05995 return res; 05996 }
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 4091 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.
04092 { 04093 struct sip_pvt *p = chan->tech_pvt; 04094 04095 if (subclass != AST_HTML_URL) 04096 return -1; 04097 04098 ast_string_field_build(p, url, "<%s>;mode=active", data); 04099 04100 if (sip_debug_test_pvt(p)) 04101 ast_debug(1, "Send URL %s, state = %d!\n", data, chan->_state); 04102 04103 switch (chan->_state) { 04104 case AST_STATE_RING: 04105 transmit_response(p, "100 Trying", &p->initreq); 04106 break; 04107 case AST_STATE_RINGING: 04108 transmit_response(p, "180 Ringing", &p->initreq); 04109 break; 04110 case AST_STATE_UP: 04111 if (!p->pendinginvite) { /* We are up, and have no outstanding invite */ 04112 transmit_reinvite_with_sdp(p, FALSE, FALSE); 04113 } else if (!ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) { 04114 ast_set_flag(&p->flags[0], SIP_NEEDREINVITE); 04115 } 04116 break; 04117 default: 04118 ast_log(LOG_WARNING, "Don't know how to send URI when state is %d!\n", chan->_state); 04119 } 04120 04121 return 0; 04122 }
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 4132 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().
04133 { 04134 struct sip_pvt *p = ast->tech_pvt; 04135 int debug = sip_debug_test_pvt(p); 04136 04137 if (debug) 04138 ast_verbose("Sending text %s on %s\n", text, ast->name); 04139 if (!p) 04140 return -1; 04141 /* NOT ast_strlen_zero, because a zero-length message is specifically 04142 * allowed by RFC 3428 (See section 10, Examples) */ 04143 if (!text) 04144 return 0; 04145 if (debug) 04146 ast_verbose("Really sending text %s on %s\n", text, ast->name); 04147 transmit_message_with_text(p, text); 04148 return 0; 04149 }
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 16181 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.
16182 { 16183 switch (cmd) { 16184 case CLI_INIT: 16185 e->command = "sip set history {on|off}"; 16186 e->usage = 16187 "Usage: sip set history {on|off}\n" 16188 " Enables/Disables recording of SIP dialog history for debugging purposes.\n" 16189 " Use 'sip show history' to view the history of a call number.\n"; 16190 return NULL; 16191 case CLI_GENERATE: 16192 return NULL; 16193 } 16194 16195 if (a->argc != e->args) 16196 return CLI_SHOWUSAGE; 16197 16198 if (!strncasecmp(a->argv[e->args - 1], "on", 2)) { 16199 recordhistory = TRUE; 16200 ast_cli(a->fd, "SIP History Recording Enabled (use 'sip show history')\n"); 16201 } else if (!strncasecmp(a->argv[e->args - 1], "off", 3)) { 16202 recordhistory = FALSE; 16203 ast_cli(a->fd, "SIP History Recording Disabled\n"); 16204 } else { 16205 return CLI_SHOWUSAGE; 16206 } 16207 return CLI_SUCCESS; 16208 }
static void sip_set_redirstr | ( | struct sip_pvt * | p, | |
char * | reason | |||
) | [static] |
Translate referring cause.
Definition at line 12386 of file chan_sip.c.
References ast_string_field_set.
Referenced by get_rdnis().
12386 { 12387 12388 if (!strcmp(reason, "unknown")) { 12389 ast_string_field_set(p, redircause, "UNKNOWN"); 12390 } else if (!strcmp(reason, "user-busy")) { 12391 ast_string_field_set(p, redircause, "BUSY"); 12392 } else if (!strcmp(reason, "no-answer")) { 12393 ast_string_field_set(p, redircause, "NOANSWER"); 12394 } else if (!strcmp(reason, "unavailable")) { 12395 ast_string_field_set(p, redircause, "UNREACHABLE"); 12396 } else if (!strcmp(reason, "unconditional")) { 12397 ast_string_field_set(p, redircause, "UNCONDITIONAL"); 12398 } else if (!strcmp(reason, "time-of-day")) { 12399 ast_string_field_set(p, redircause, "UNKNOWN"); 12400 } else if (!strcmp(reason, "do-not-disturb")) { 12401 ast_string_field_set(p, redircause, "UNKNOWN"); 12402 } else if (!strcmp(reason, "deflection")) { 12403 ast_string_field_set(p, redircause, "UNKNOWN"); 12404 } else if (!strcmp(reason, "follow-me")) { 12405 ast_string_field_set(p, redircause, "UNKNOWN"); 12406 } else if (!strcmp(reason, "out-of-service")) { 12407 ast_string_field_set(p, redircause, "UNREACHABLE"); 12408 } else if (!strcmp(reason, "away")) { 12409 ast_string_field_set(p, redircause, "UNREACHABLE"); 12410 } else { 12411 ast_string_field_set(p, redircause, "UNKNOWN"); 12412 } 12413 }
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 24289 of file chan_sip.c.
References ast_channel::_state, sip_pvt::alreadygone, append_history, ast_bridged_channel(), 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().
24290 { 24291 struct sip_pvt *p; 24292 int changed = 0; 24293 24294 p = chan->tech_pvt; 24295 if (!p) 24296 return -1; 24297 24298 /* Disable early RTP bridge */ 24299 if (!ast_bridged_channel(chan) && !global_directrtpsetup) /* We are in early state */ 24300 return 0; 24301 24302 sip_pvt_lock(p); 24303 if (p->alreadygone) { 24304 /* If we're destroyed, don't bother */ 24305 sip_pvt_unlock(p); 24306 return 0; 24307 } 24308 24309 /* if this peer cannot handle reinvites of the media stream to devices 24310 that are known to be behind a NAT, then stop the process now 24311 */ 24312 if (nat_active && !ast_test_flag(&p->flags[0], SIP_CAN_REINVITE_NAT)) { 24313 sip_pvt_unlock(p); 24314 return 0; 24315 } 24316 24317 if (rtp) { 24318 changed |= ast_rtp_get_peer(rtp, &p->redirip); 24319 } else if (p->redirip.sin_addr.s_addr || ntohs(p->redirip.sin_port) != 0) { 24320 memset(&p->redirip, 0, sizeof(p->redirip)); 24321 changed = 1; 24322 } 24323 if (vrtp) { 24324 changed |= ast_rtp_get_peer(vrtp, &p->vredirip); 24325 } else if (p->vredirip.sin_addr.s_addr || ntohs(p->vredirip.sin_port) != 0) { 24326 memset(&p->vredirip, 0, sizeof(p->vredirip)); 24327 changed = 1; 24328 } 24329 if (trtp) { 24330 changed |= ast_rtp_get_peer(trtp, &p->tredirip); 24331 } else if (p->tredirip.sin_addr.s_addr || ntohs(p->tredirip.sin_port) != 0) { 24332 memset(&p->tredirip, 0, sizeof(p->tredirip)); 24333 changed = 1; 24334 } 24335 if (codecs && (p->redircodecs != codecs)) { 24336 p->redircodecs = codecs; 24337 changed = 1; 24338 } 24339 if (changed && !ast_test_flag(&p->flags[0], SIP_GOTREFER) && !ast_test_flag(&p->flags[0], SIP_DEFER_BYE_ON_TRANSFER)) { 24340 if (chan->_state != AST_STATE_UP) { /* We are in early state */ 24341 if (p->do_history) 24342 append_history(p, "ExtInv", "Initial invite sent with remote bridge proposal."); 24343 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)); 24344 } else if (!p->pendinginvite) { /* We are up, and have no outstanding invite */ 24345 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)); 24346 transmit_reinvite_with_sdp(p, FALSE, FALSE); 24347 } else if (!ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) { 24348 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)); 24349 /* We have a pending Invite. Send re-invite when we're done with the invite */ 24350 ast_set_flag(&p->flags[0], SIP_NEEDREINVITE); 24351 } 24352 } 24353 /* Reset lastrtprx timer */ 24354 p->lastrtprx = p->lastrtptx = time(NULL); 24355 sip_pvt_unlock(p); 24356 return 0; 24357 }
static int sip_set_udptl_peer | ( | struct ast_channel * | chan, | |
struct ast_udptl * | udptl | |||
) | [static] |
Definition at line 24182 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.
24183 { 24184 struct sip_pvt *p; 24185 24186 p = chan->tech_pvt; 24187 if (!p) 24188 return -1; 24189 sip_pvt_lock(p); 24190 if (udptl) 24191 ast_udptl_get_peer(udptl, &p->udptlredirip); 24192 else 24193 memset(&p->udptlredirip, 0, sizeof(p->udptlredirip)); 24194 if (!ast_test_flag(&p->flags[0], SIP_GOTREFER)) { 24195 if (!p->pendinginvite) { 24196 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); 24197 transmit_reinvite_with_sdp(p, TRUE, FALSE); 24198 } else if (!ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) { 24199 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); 24200 ast_set_flag(&p->flags[0], SIP_NEEDREINVITE); 24201 } 24202 } 24203 /* Reset lastrtprx timer */ 24204 p->lastrtprx = p->lastrtptx = time(NULL); 24205 sip_pvt_unlock(p); 24206 return 0; 24207 }
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 15607 of file chan_sip.c.
References sip_pvt::allowtransfer, ao2_iterator_destroy(), 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, 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.
15608 { 15609 struct sip_pvt *cur; 15610 size_t len; 15611 int found = 0; 15612 struct ao2_iterator i; 15613 15614 switch (cmd) { 15615 case CLI_INIT: 15616 e->command = "sip show channel"; 15617 e->usage = 15618 "Usage: sip show channel <call-id>\n" 15619 " Provides detailed status on a given SIP dialog (identified by SIP call-id).\n"; 15620 return NULL; 15621 case CLI_GENERATE: 15622 return complete_sipch(a->line, a->word, a->pos, a->n); 15623 } 15624 15625 if (a->argc != 4) 15626 return CLI_SHOWUSAGE; 15627 len = strlen(a->argv[3]); 15628 15629 i = ao2_iterator_init(dialogs, 0); 15630 while ((cur = ao2_t_iterator_next(&i, "iterate thru dialogs"))) { 15631 sip_pvt_lock(cur); 15632 15633 if (!strncasecmp(cur->callid, a->argv[3], len)) { 15634 char formatbuf[SIPBUFSIZE/2]; 15635 ast_cli(a->fd, "\n"); 15636 if (cur->subscribed != NONE) 15637 ast_cli(a->fd, " * Subscription (type: %s)\n", subscription_type2str(cur->subscribed)); 15638 else 15639 ast_cli(a->fd, " * SIP Call\n"); 15640 ast_cli(a->fd, " Curr. trans. direction: %s\n", ast_test_flag(&cur->flags[0], SIP_OUTGOING) ? "Outgoing" : "Incoming"); 15641 ast_cli(a->fd, " Call-ID: %s\n", cur->callid); 15642 ast_cli(a->fd, " Owner channel ID: %s\n", cur->owner ? cur->owner->name : "<none>"); 15643 ast_cli(a->fd, " Our Codec Capability: %d\n", cur->capability); 15644 ast_cli(a->fd, " Non-Codec Capability (DTMF): %d\n", cur->noncodeccapability); 15645 ast_cli(a->fd, " Their Codec Capability: %d\n", cur->peercapability); 15646 ast_cli(a->fd, " Joint Codec Capability: %d\n", cur->jointcapability); 15647 ast_cli(a->fd, " Format: %s\n", ast_getformatname_multiple(formatbuf, sizeof(formatbuf), cur->owner ? cur->owner->nativeformats : 0) ); 15648 ast_cli(a->fd, " T.38 support %s\n", cli_yesno(cur->udptl != NULL)); 15649 ast_cli(a->fd, " Video support %s\n", cli_yesno(cur->vrtp != NULL)); 15650 ast_cli(a->fd, " MaxCallBR: %d kbps\n", cur->maxcallbitrate); 15651 ast_cli(a->fd, " Theoretical Address: %s:%d\n", ast_inet_ntoa(cur->sa.sin_addr), ntohs(cur->sa.sin_port)); 15652 ast_cli(a->fd, " Received Address: %s:%d\n", ast_inet_ntoa(cur->recv.sin_addr), ntohs(cur->recv.sin_port)); 15653 ast_cli(a->fd, " SIP Transfer mode: %s\n", transfermode2str(cur->allowtransfer)); 15654 ast_cli(a->fd, " NAT Support: %s\n", nat2str(ast_test_flag(&cur->flags[0], SIP_NAT))); 15655 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)" ); 15656 ast_cli(a->fd, " Our Tag: %s\n", cur->tag); 15657 ast_cli(a->fd, " Their Tag: %s\n", cur->theirtag); 15658 ast_cli(a->fd, " SIP User agent: %s\n", cur->useragent); 15659 if (!ast_strlen_zero(cur->username)) 15660 ast_cli(a->fd, " Username: %s\n", cur->username); 15661 if (!ast_strlen_zero(cur->peername)) 15662 ast_cli(a->fd, " Peername: %s\n", cur->peername); 15663 if (!ast_strlen_zero(cur->uri)) 15664 ast_cli(a->fd, " Original uri: %s\n", cur->uri); 15665 if (!ast_strlen_zero(cur->cid_num)) 15666 ast_cli(a->fd, " Caller-ID: %s\n", cur->cid_num); 15667 ast_cli(a->fd, " Need Destroy: %s\n", cli_yesno(cur->needdestroy)); 15668 ast_cli(a->fd, " Last Message: %s\n", cur->lastmsg); 15669 ast_cli(a->fd, " Promiscuous Redir: %s\n", cli_yesno(ast_test_flag(&cur->flags[0], SIP_PROMISCREDIR))); 15670 ast_cli(a->fd, " Route: %s\n", cur->route ? cur->route->hop : "N/A"); 15671 ast_cli(a->fd, " DTMF Mode: %s\n", dtmfmode2str(ast_test_flag(&cur->flags[0], SIP_DTMF))); 15672 ast_cli(a->fd, " SIP Options: "); 15673 if (cur->sipoptions) { 15674 int x; 15675 for (x = 0 ; x < ARRAY_LEN(sip_options); x++) { 15676 if (cur->sipoptions & sip_options[x].id) 15677 ast_cli(a->fd, "%s ", sip_options[x].text); 15678 } 15679 ast_cli(a->fd, "\n"); 15680 } else 15681 ast_cli(a->fd, "(none)\n"); 15682 15683 if (!cur->stimer) 15684 ast_cli(a->fd, " Session-Timer: Uninitiallized\n"); 15685 else { 15686 ast_cli(a->fd, " Session-Timer: %s\n", cur->stimer->st_active ? "Active" : "Inactive"); 15687 if (cur->stimer->st_active == TRUE) { 15688 ast_cli(a->fd, " S-Timer Interval: %d\n", cur->stimer->st_interval); 15689 ast_cli(a->fd, " S-Timer Refresher: %s\n", strefresher2str(cur->stimer->st_ref)); 15690 ast_cli(a->fd, " S-Timer Expirys: %d\n", cur->stimer->st_expirys); 15691 ast_cli(a->fd, " S-Timer Sched Id: %d\n", cur->stimer->st_schedid); 15692 ast_cli(a->fd, " S-Timer Peer Sts: %s\n", cur->stimer->st_active_peer_ua ? "Active" : "Inactive"); 15693 ast_cli(a->fd, " S-Timer Cached Min-SE: %d\n", cur->stimer->st_cached_min_se); 15694 ast_cli(a->fd, " S-Timer Cached SE: %d\n", cur->stimer->st_cached_max_se); 15695 ast_cli(a->fd, " S-Timer Cached Ref: %s\n", strefresher2str(cur->stimer->st_cached_ref)); 15696 ast_cli(a->fd, " S-Timer Cached Mode: %s\n", stmode2str(cur->stimer->st_cached_mode)); 15697 } 15698 } 15699 15700 ast_cli(a->fd, "\n\n"); 15701 15702 found++; 15703 } 15704 15705 sip_pvt_unlock(cur); 15706 15707 ao2_t_ref(cur, -1, "toss dialog ptr set by iterator_next"); 15708 } 15709 ao2_iterator_destroy(&i); 15710 15711 if (!found) 15712 ast_cli(a->fd, "No such SIP Call ID starting with '%s'\n", a->argv[3]); 15713 15714 return CLI_SUCCESS; 15715 }
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 15428 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.
15429 { 15430 struct __show_chan_arg arg = { .fd = a->fd, .numchans = 0 }; 15431 15432 15433 if (cmd == CLI_INIT) { 15434 e->command = "sip show {channels|subscriptions}"; 15435 e->usage = 15436 "Usage: sip show channels\n" 15437 " Lists all currently active SIP calls (dialogs).\n" 15438 "Usage: sip show subscriptions\n" 15439 " Lists active SIP subscriptions.\n"; 15440 return NULL; 15441 } else if (cmd == CLI_GENERATE) 15442 return NULL; 15443 15444 if (a->argc != e->args) 15445 return CLI_SHOWUSAGE; 15446 arg.subscriptions = !strcasecmp(a->argv[e->args - 1], "subscriptions"); 15447 if (!arg.subscriptions) 15448 ast_cli(arg.fd, FORMAT2, "Peer", "User/ANR", "Call ID", "Format", "Hold", "Last Message", "Expiry"); 15449 else 15450 ast_cli(arg.fd, FORMAT3, "Peer", "User", "Call ID", "Extension", "Last state", "Type", "Mailbox", "Expiry"); 15451 15452 /* iterate on the container and invoke the callback on each item */ 15453 ao2_t_callback(dialogs, OBJ_NODATA, show_channels_cb, &arg, "callback to show channels"); 15454 15455 /* print summary information */ 15456 ast_cli(arg.fd, "%d active SIP %s%s\n", arg.numchans, 15457 (arg.subscriptions ? "subscription" : "dialog"), 15458 ESS(arg.numchans)); /* ESS(n) returns an "s" if n>1 */ 15459 return CLI_SUCCESS; 15460 #undef FORMAT 15461 #undef FORMAT2 15462 #undef FORMAT3 15463 }
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 15119 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.
15120 { 15121 struct __show_chan_arg arg = { .fd = a->fd, .numchans = 0 }; 15122 15123 switch (cmd) { 15124 case CLI_INIT: 15125 e->command = "sip show channelstats"; 15126 e->usage = 15127 "Usage: sip show channelstats\n" 15128 " Lists all currently active SIP channel's RTCP statistics.\n" 15129 " Note that calls in the much optimized RTP P2P bridge mode will not show any packets here."; 15130 return NULL; 15131 case CLI_GENERATE: 15132 return NULL; 15133 } 15134 15135 if (a->argc != 3) 15136 return CLI_SHOWUSAGE; 15137 15138 ast_cli(a->fd, FORMAT2, "Peer", "Call ID", "Duration", "Recv: Pack", "Lost", "Jitter", "Send: Pack", "Lost", "Jitter"); 15139 /* iterate on the container and invoke the callback on each item */ 15140 ao2_t_callback(dialogs, OBJ_NODATA, show_chanstats_cb, &arg, "callback to sip show chanstats"); 15141 ast_cli(a->fd, "%d active SIP channel%s\n", arg.numchans, (arg.numchans != 1) ? "s" : ""); 15142 return CLI_SUCCESS; 15143 }
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 14418 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.
14419 { 14420 struct domain *d; 14421 #define FORMAT "%-40.40s %-20.20s %-16.16s\n" 14422 14423 switch (cmd) { 14424 case CLI_INIT: 14425 e->command = "sip show domains"; 14426 e->usage = 14427 "Usage: sip show domains\n" 14428 " Lists all configured SIP local domains.\n" 14429 " Asterisk only responds to SIP messages to local domains.\n"; 14430 return NULL; 14431 case CLI_GENERATE: 14432 return NULL; 14433 } 14434 14435 if (AST_LIST_EMPTY(&domain_list)) { 14436 ast_cli(a->fd, "SIP Domain support not enabled.\n\n"); 14437 return CLI_SUCCESS; 14438 } else { 14439 ast_cli(a->fd, FORMAT, "Our local SIP domains:", "Context", "Set by"); 14440 AST_LIST_LOCK(&domain_list); 14441 AST_LIST_TRAVERSE(&domain_list, d, list) 14442 ast_cli(a->fd, FORMAT, d->domain, S_OR(d->context, "(default)"), 14443 domain_mode_to_text(d->mode)); 14444 AST_LIST_UNLOCK(&domain_list); 14445 ast_cli(a->fd, "\n"); 14446 return CLI_SUCCESS; 14447 } 14448 }
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 15718 of file chan_sip.c.
References ao2_iterator_destroy(), 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, 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.
15719 { 15720 struct sip_pvt *cur; 15721 size_t len; 15722 int found = 0; 15723 struct ao2_iterator i; 15724 15725 switch (cmd) { 15726 case CLI_INIT: 15727 e->command = "sip show history"; 15728 e->usage = 15729 "Usage: sip show history <call-id>\n" 15730 " Provides detailed dialog history on a given SIP call (specified by call-id).\n"; 15731 return NULL; 15732 case CLI_GENERATE: 15733 return complete_sip_show_history(a->line, a->word, a->pos, a->n); 15734 } 15735 15736 if (a->argc != 4) 15737 return CLI_SHOWUSAGE; 15738 15739 if (!recordhistory) 15740 ast_cli(a->fd, "\n***Note: History recording is currently DISABLED. Use 'sip set history on' to ENABLE.\n"); 15741 15742 len = strlen(a->argv[3]); 15743 15744 i = ao2_iterator_init(dialogs, 0); 15745 while ((cur = ao2_t_iterator_next(&i, "iterate thru dialogs"))) { 15746 sip_pvt_lock(cur); 15747 if (!strncasecmp(cur->callid, a->argv[3], len)) { 15748 struct sip_history *hist; 15749 int x = 0; 15750 15751 ast_cli(a->fd, "\n"); 15752 if (cur->subscribed != NONE) 15753 ast_cli(a->fd, " * Subscription\n"); 15754 else 15755 ast_cli(a->fd, " * SIP Call\n"); 15756 if (cur->history) 15757 AST_LIST_TRAVERSE(cur->history, hist, list) 15758 ast_cli(a->fd, "%d. %s\n", ++x, hist->event); 15759 if (x == 0) 15760 ast_cli(a->fd, "Call '%s' has no history\n", cur->callid); 15761 found++; 15762 } 15763 sip_pvt_unlock(cur); 15764 ao2_t_ref(cur, -1, "toss dialog ptr from iterator_next"); 15765 } 15766 ao2_iterator_destroy(&i); 15767 15768 if (!found) 15769 ast_cli(a->fd, "No such SIP Call ID starting with '%s'\n", a->argv[3]); 15770 15771 return CLI_SUCCESS; 15772 }
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 13502 of file chan_sip.c.
References ao2_iterator_destroy(), 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, peers, TRUE, unref_peer(), and ast_cli_entry::usage.
13503 { 13504 #define FORMAT "%-25.25s %-15.15s %-15.15s \n" 13505 #define FORMAT2 "%-25.25s %-15.15s %-15.15s \n" 13506 char ilimits[40]; 13507 char iused[40]; 13508 int showall = FALSE; 13509 struct ao2_iterator i; 13510 struct sip_peer *peer; 13511 13512 switch (cmd) { 13513 case CLI_INIT: 13514 e->command = "sip show inuse"; 13515 e->usage = 13516 "Usage: sip show inuse [all]\n" 13517 " List all SIP devices usage counters and limits.\n" 13518 " Add option \"all\" to show all devices, not only those with a limit.\n"; 13519 return NULL; 13520 case CLI_GENERATE: 13521 return NULL; 13522 } 13523 13524 if (a->argc < 3) 13525 return CLI_SHOWUSAGE; 13526 13527 if (a->argc == 4 && !strcmp(a->argv[3], "all")) 13528 showall = TRUE; 13529 13530 ast_cli(a->fd, FORMAT, "* Peer name", "In use", "Limit"); 13531 13532 i = ao2_iterator_init(peers, 0); 13533 while ((peer = ao2_t_iterator_next(&i, "iterate thru peer table"))) { 13534 ao2_lock(peer); 13535 if (peer->call_limit) 13536 snprintf(ilimits, sizeof(ilimits), "%d", peer->call_limit); 13537 else 13538 ast_copy_string(ilimits, "N/A", sizeof(ilimits)); 13539 snprintf(iused, sizeof(iused), "%d/%d/%d", peer->inUse, peer->inRinging, peer->onHold); 13540 if (showall || peer->call_limit) 13541 ast_cli(a->fd, FORMAT2, peer->name, iused, ilimits); 13542 ao2_unlock(peer); 13543 unref_peer(peer, "toss iterator pointer"); 13544 } 13545 ao2_iterator_destroy(&i); 13546 13547 return CLI_SUCCESS; 13548 #undef FORMAT 13549 #undef FORMAT2 13550 }
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 14085 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(), peers, regl, and ast_cli_entry::usage.
14086 { 14087 char tmp[256]; 14088 14089 switch (cmd) { 14090 case CLI_INIT: 14091 e->command = "sip show objects"; 14092 e->usage = 14093 "Usage: sip show objects\n" 14094 " Lists status of known SIP objects\n"; 14095 return NULL; 14096 case CLI_GENERATE: 14097 return NULL; 14098 } 14099 14100 if (a->argc != 3) 14101 return CLI_SHOWUSAGE; 14102 ast_cli(a->fd, "-= Peer objects: %d static, %d realtime, %d autocreate =-\n\n", speerobjs, rpeerobjs, apeerobjs); 14103 ao2_t_callback(peers, OBJ_NODATA, peer_dump_func, &a->fd, "initiate ao2_callback to dump peers"); 14104 ast_cli(a->fd, "-= Registry objects: %d =-\n\n", regobjs); 14105 ASTOBJ_CONTAINER_DUMP(a->fd, tmp, sizeof(tmp), ®l); 14106 ast_cli(a->fd, "-= Dialog objects:\n\n"); 14107 ao2_t_callback(dialogs, OBJ_NODATA, dialog_dump_func, &a->fd, "initiate ao2_callback to dump dialogs"); 14108 return CLI_SUCCESS; 14109 }
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 14479 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.
14480 { 14481 switch (cmd) { 14482 case CLI_INIT: 14483 e->command = "sip show peer"; 14484 e->usage = 14485 "Usage: sip show peer <name> [load]\n" 14486 " Shows all details on one SIP peer and the current status.\n" 14487 " Option \"load\" forces lookup of peer in realtime storage.\n"; 14488 return NULL; 14489 case CLI_GENERATE: 14490 return complete_sip_show_peer(a->line, a->word, a->pos, a->n); 14491 } 14492 return _sip_show_peer(0, a->fd, NULL, NULL, a->argc, (const char **) a->argv); 14493 }
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 13861 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.
13862 { 13863 switch (cmd) { 13864 case CLI_INIT: 13865 e->command = "sip show peers"; 13866 e->usage = 13867 "Usage: sip show peers [like <pattern>]\n" 13868 " Lists all known SIP peers.\n" 13869 " Optional regular expression pattern is used to filter the peer list.\n"; 13870 return NULL; 13871 case CLI_GENERATE: 13872 return NULL; 13873 } 13874 13875 return _sip_show_peers(a->fd, NULL, NULL, NULL, a->argc, (const char **) a->argv); 13876 }
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 14977 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.
14978 { 14979 #define FORMAT2 "%-30.30s %-6.6s %-12.12s %8.8s %-20.20s %-25.25s\n" 14980 #define FORMAT "%-30.30s %-6.6s %-12.12s %8d %-20.20s %-25.25s\n" 14981 char host[80]; 14982 char tmpdat[256]; 14983 struct ast_tm tm; 14984 int counter = 0; 14985 14986 switch (cmd) { 14987 case CLI_INIT: 14988 e->command = "sip show registry"; 14989 e->usage = 14990 "Usage: sip show registry\n" 14991 " Lists all registration requests and status.\n"; 14992 return NULL; 14993 case CLI_GENERATE: 14994 return NULL; 14995 } 14996 14997 if (a->argc != 3) 14998 return CLI_SHOWUSAGE; 14999 ast_cli(a->fd, FORMAT2, "Host", "dnsmgr", "Username", "Refresh", "State", "Reg.Time"); 15000 15001 ASTOBJ_CONTAINER_TRAVERSE(®l, 1, do { 15002 ASTOBJ_RDLOCK(iterator); 15003 snprintf(host, sizeof(host), "%s:%d", iterator->hostname, iterator->portno ? iterator->portno : STANDARD_SIP_PORT); 15004 if (iterator->regtime.tv_sec) { 15005 ast_localtime(&iterator->regtime, &tm, NULL); 15006 ast_strftime(tmpdat, sizeof(tmpdat), "%a, %d %b %Y %T", &tm); 15007 } else 15008 tmpdat[0] = '\0'; 15009 ast_cli(a->fd, FORMAT, host, (iterator->dnsmgr) ? "Y" : "N", iterator->username, iterator->refresh, regstate2str(iterator->regstate), tmpdat); 15010 ASTOBJ_UNLOCK(iterator); 15011 counter++; 15012 } while(0)); 15013 ast_cli(a->fd, "%d SIP registrations.\n", counter); 15014 return CLI_SUCCESS; 15015 #undef FORMAT 15016 #undef FORMAT2 15017 }
static char * sip_show_sched | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 14934 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.
14935 { 14936 struct ast_str *cbuf; 14937 struct ast_cb_names cbnames = {9, { "retrans_pkt", 14938 "__sip_autodestruct", 14939 "expire_register", 14940 "auto_congest", 14941 "sip_reg_timeout", 14942 "sip_poke_peer_s", 14943 "sip_poke_noanswer", 14944 "sip_reregister", 14945 "sip_reinvite_retry"}, 14946 { retrans_pkt, 14947 __sip_autodestruct, 14948 expire_register, 14949 auto_congest, 14950 sip_reg_timeout, 14951 sip_poke_peer_s, 14952 sip_poke_noanswer, 14953 sip_reregister, 14954 sip_reinvite_retry}}; 14955 14956 switch (cmd) { 14957 case CLI_INIT: 14958 e->command = "sip show sched"; 14959 e->usage = 14960 "Usage: sip show sched\n" 14961 " Shows stats on what's in the sched queue at the moment\n"; 14962 return NULL; 14963 case CLI_GENERATE: 14964 return NULL; 14965 } 14966 14967 cbuf = ast_str_alloca(2048); 14968 14969 ast_cli(a->fd, "\n"); 14970 ast_sched_report(sched, &cbuf, &cbnames); 14971 ast_cli(a->fd, "%s", cbuf->str); 14972 14973 return CLI_SUCCESS; 14974 }
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 15148 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, FALSE, faxec2str(), 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_IGNORESDPVERSION, SIP_PAGE2_RFC2833_COMPENSATE, SIP_PAGE2_RTCACHEFRIENDS, SIP_PAGE2_T38SUPPORT, 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.
15149 { 15150 int realtimepeers; 15151 int realtimeregs; 15152 char codec_buf[SIPBUFSIZE]; 15153 const char *msg; /* temporary msg pointer */ 15154 15155 switch (cmd) { 15156 case CLI_INIT: 15157 e->command = "sip show settings"; 15158 e->usage = 15159 "Usage: sip show settings\n" 15160 " Provides detailed list of the configuration of the SIP channel.\n"; 15161 return NULL; 15162 case CLI_GENERATE: 15163 return NULL; 15164 } 15165 15166 15167 realtimepeers = ast_check_realtime("sippeers"); 15168 realtimeregs = ast_check_realtime("sipregs"); 15169 15170 if (a->argc != 3) 15171 return CLI_SHOWUSAGE; 15172 ast_cli(a->fd, "\n\nGlobal Settings:\n"); 15173 ast_cli(a->fd, "----------------\n"); 15174 ast_cli(a->fd, " UDP SIP Port: %d\n", ntohs(bindaddr.sin_port)); 15175 ast_cli(a->fd, " UDP Bindaddress: %s\n", ast_inet_ntoa(bindaddr.sin_addr)); 15176 ast_cli(a->fd, " TCP SIP Port: "); 15177 if (sip_tcp_desc.local_address.sin_family == AF_INET) { 15178 ast_cli(a->fd, "%d\n", ntohs(sip_tcp_desc.local_address.sin_port)); 15179 ast_cli(a->fd, " TCP Bindaddress: %s\n", ast_inet_ntoa(sip_tcp_desc.local_address.sin_addr)); 15180 } else { 15181 ast_cli(a->fd, "Disabled\n"); 15182 } 15183 ast_cli(a->fd, " TLS SIP Port: "); 15184 if (default_tls_cfg.enabled != FALSE) { 15185 ast_cli(a->fd, "%d\n", ntohs(sip_tls_desc.local_address.sin_port)); 15186 ast_cli(a->fd, " TLS Bindaddress: %s\n", ast_inet_ntoa(sip_tls_desc.local_address.sin_addr)); 15187 } else { 15188 ast_cli(a->fd, "Disabled\n"); 15189 } 15190 ast_cli(a->fd, " Videosupport: %s\n", cli_yesno(ast_test_flag(&global_flags[1], SIP_PAGE2_VIDEOSUPPORT))); 15191 ast_cli(a->fd, " Textsupport: %s\n", cli_yesno(ast_test_flag(&global_flags[1], SIP_PAGE2_TEXTSUPPORT))); 15192 ast_cli(a->fd, " AutoCreate Peer: %s\n", cli_yesno(autocreatepeer)); 15193 ast_cli(a->fd, " Ignore SDP sess. ver.: %s\n", cli_yesno(ast_test_flag(&global_flags[1], SIP_PAGE2_IGNORESDPVERSION))); 15194 ast_cli(a->fd, " Match Auth Username: %s\n", cli_yesno(global_match_auth_username)); 15195 ast_cli(a->fd, " Allow unknown access: %s\n", cli_yesno(global_allowguest)); 15196 ast_cli(a->fd, " Allow subscriptions: %s\n", cli_yesno(ast_test_flag(&global_flags[1], SIP_PAGE2_ALLOWSUBSCRIBE))); 15197 ast_cli(a->fd, " Allow overlap dialing: %s\n", cli_yesno(ast_test_flag(&global_flags[1], SIP_PAGE2_ALLOWOVERLAP))); 15198 ast_cli(a->fd, " Allow promsic. redir: %s\n", cli_yesno(ast_test_flag(&global_flags[0], SIP_PROMISCREDIR))); 15199 ast_cli(a->fd, " Enable call counters: %s\n", cli_yesno(global_callcounter)); 15200 ast_cli(a->fd, " SIP domain support: %s\n", cli_yesno(!AST_LIST_EMPTY(&domain_list))); 15201 ast_cli(a->fd, " Realm. auth: %s\n", cli_yesno(authl != NULL)); 15202 ast_cli(a->fd, " Our auth realm %s\n", global_realm); 15203 ast_cli(a->fd, " Call to non-local dom.: %s\n", cli_yesno(allow_external_domains)); 15204 ast_cli(a->fd, " URI user is phone no: %s\n", cli_yesno(ast_test_flag(&global_flags[0], SIP_USEREQPHONE))); 15205 ast_cli(a->fd, " Always auth rejects: %s\n", cli_yesno(global_alwaysauthreject)); 15206 ast_cli(a->fd, " Direct RTP setup: %s\n", cli_yesno(global_directrtpsetup)); 15207 ast_cli(a->fd, " User Agent: %s\n", global_useragent); 15208 ast_cli(a->fd, " SDP Session Name: %s\n", ast_strlen_zero(global_sdpsession) ? "-" : global_sdpsession); 15209 ast_cli(a->fd, " SDP Owner Name: %s\n", ast_strlen_zero(global_sdpowner) ? "-" : global_sdpowner); 15210 ast_cli(a->fd, " Reg. context: %s\n", S_OR(global_regcontext, "(not set)")); 15211 ast_cli(a->fd, " Regexten on Qualify: %s\n", cli_yesno(global_regextenonqualify)); 15212 ast_cli(a->fd, " Caller ID: %s\n", default_callerid); 15213 ast_cli(a->fd, " From: Domain: %s\n", default_fromdomain); 15214 ast_cli(a->fd, " Record SIP history: %s\n", recordhistory ? "On" : "Off"); 15215 ast_cli(a->fd, " Call Events: %s\n", global_callevents ? "On" : "Off"); 15216 ast_cli(a->fd, " Auth. Failure Events: %s\n", global_authfailureevents ? "On" : "Off"); 15217 15218 ast_cli(a->fd, " T.38 support: %s\n", cli_yesno(ast_test_flag(&global_flags[1], SIP_PAGE2_T38SUPPORT))); 15219 ast_cli(a->fd, " T.38 EC mode: %s\n", faxec2str(ast_test_flag(&global_flags[1], SIP_PAGE2_T38SUPPORT))); 15220 ast_cli(a->fd, " T.38 MaxDtgrm: %d\n", global_t38_maxdatagram); 15221 15222 if (!realtimepeers && !realtimeregs) 15223 ast_cli(a->fd, " SIP realtime: Disabled\n" ); 15224 else 15225 ast_cli(a->fd, " SIP realtime: Enabled\n" ); 15226 ast_cli(a->fd, " Qualify Freq : %d ms\n", global_qualifyfreq); 15227 ast_cli(a->fd, "\nNetwork QoS Settings:\n"); 15228 ast_cli(a->fd, "---------------------------\n"); 15229 ast_cli(a->fd, " IP ToS SIP: %s\n", ast_tos2str(global_tos_sip)); 15230 ast_cli(a->fd, " IP ToS RTP audio: %s\n", ast_tos2str(global_tos_audio)); 15231 ast_cli(a->fd, " IP ToS RTP video: %s\n", ast_tos2str(global_tos_video)); 15232 ast_cli(a->fd, " IP ToS RTP text: %s\n", ast_tos2str(global_tos_text)); 15233 ast_cli(a->fd, " 802.1p CoS SIP: %d\n", global_cos_sip); 15234 ast_cli(a->fd, " 802.1p CoS RTP audio: %d\n", global_cos_audio); 15235 ast_cli(a->fd, " 802.1p CoS RTP video: %d\n", global_cos_video); 15236 ast_cli(a->fd, " 802.1p CoS RTP text: %d\n", global_cos_text); 15237 ast_cli(a->fd, " Jitterbuffer enabled: %s\n", cli_yesno(ast_test_flag(&global_jbconf, AST_JB_ENABLED))); 15238 ast_cli(a->fd, " Jitterbuffer forced: %s\n", cli_yesno(ast_test_flag(&global_jbconf, AST_JB_FORCED))); 15239 ast_cli(a->fd, " Jitterbuffer max size: %ld\n", global_jbconf.max_size); 15240 ast_cli(a->fd, " Jitterbuffer resync: %ld\n", global_jbconf.resync_threshold); 15241 ast_cli(a->fd, " Jitterbuffer impl: %s\n", global_jbconf.impl); 15242 ast_cli(a->fd, " Jitterbuffer log: %s\n", cli_yesno(ast_test_flag(&global_jbconf, AST_JB_LOG))); 15243 15244 ast_cli(a->fd, "\nNetwork Settings:\n"); 15245 ast_cli(a->fd, "---------------------------\n"); 15246 /* determine if/how SIP address can be remapped */ 15247 if (localaddr == NULL) 15248 msg = "Disabled, no localnet list"; 15249 else if (externip.sin_addr.s_addr == 0) 15250 msg = "Disabled, externip is 0.0.0.0"; 15251 else if (stunaddr.sin_addr.s_addr != 0) 15252 msg = "Enabled using STUN"; 15253 else if (!ast_strlen_zero(externhost)) 15254 msg = "Enabled using externhost"; 15255 else 15256 msg = "Enabled using externip"; 15257 ast_cli(a->fd, " SIP address remapping: %s\n", msg); 15258 ast_cli(a->fd, " Externhost: %s\n", S_OR(externhost, "<none>")); 15259 ast_cli(a->fd, " Externip: %s:%d\n", ast_inet_ntoa(externip.sin_addr), ntohs(externip.sin_port)); 15260 ast_cli(a->fd, " Externrefresh: %d\n", externrefresh); 15261 ast_cli(a->fd, " Internal IP: %s:%d\n", ast_inet_ntoa(internip.sin_addr), ntohs(internip.sin_port)); 15262 { 15263 struct ast_ha *d; 15264 const char *prefix = "Localnet:"; 15265 char buf[INET_ADDRSTRLEN]; /* need to print two addresses */ 15266 15267 for (d = localaddr; d ; prefix = "", d = d->next) { 15268 ast_cli(a->fd, " %-24s%s/%s\n", 15269 prefix, ast_inet_ntoa(d->netaddr), 15270 inet_ntop(AF_INET, &d->netmask, buf, sizeof(buf)) ); 15271 } 15272 } 15273 ast_cli(a->fd, " STUN server: %s:%d\n", ast_inet_ntoa(stunaddr.sin_addr), ntohs(stunaddr.sin_port)); 15274 15275 ast_cli(a->fd, "\nGlobal Signalling Settings:\n"); 15276 ast_cli(a->fd, "---------------------------\n"); 15277 ast_cli(a->fd, " Codecs: "); 15278 ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, global_capability); 15279 ast_cli(a->fd, "%s\n", codec_buf); 15280 ast_cli(a->fd, " Codec Order: "); 15281 print_codec_to_cli(a->fd, &default_prefs); 15282 ast_cli(a->fd, "\n"); 15283 ast_cli(a->fd, " Relax DTMF: %s\n", cli_yesno(global_relaxdtmf)); 15284 ast_cli(a->fd, " RFC2833 Compensation: %s\n", cli_yesno(ast_test_flag(&global_flags[1], SIP_PAGE2_RFC2833_COMPENSATE))); 15285 ast_cli(a->fd, " Compact SIP headers: %s\n", cli_yesno(compactheaders)); 15286 ast_cli(a->fd, " RTP Keepalive: %d %s\n", global_rtpkeepalive, global_rtpkeepalive ? "" : "(Disabled)" ); 15287 ast_cli(a->fd, " RTP Timeout: %d %s\n", global_rtptimeout, global_rtptimeout ? "" : "(Disabled)" ); 15288 ast_cli(a->fd, " RTP Hold Timeout: %d %s\n", global_rtpholdtimeout, global_rtpholdtimeout ? "" : "(Disabled)"); 15289 ast_cli(a->fd, " MWI NOTIFY mime type: %s\n", default_notifymime); 15290 ast_cli(a->fd, " DNS SRV lookup: %s\n", cli_yesno(global_srvlookup)); 15291 ast_cli(a->fd, " Pedantic SIP support: %s\n", cli_yesno(pedanticsipchecking)); 15292 ast_cli(a->fd, " Reg. min duration %d secs\n", min_expiry); 15293 ast_cli(a->fd, " Reg. max duration: %d secs\n", max_expiry); 15294 ast_cli(a->fd, " Reg. default duration: %d secs\n", default_expiry); 15295 ast_cli(a->fd, " Outbound reg. timeout: %d secs\n", global_reg_timeout); 15296 ast_cli(a->fd, " Outbound reg. attempts: %d\n", global_regattempts_max); 15297 ast_cli(a->fd, " Notify ringing state: %s\n", cli_yesno(global_notifyringing)); 15298 ast_cli(a->fd, " Notify hold state: %s\n", cli_yesno(global_notifyhold)); 15299 ast_cli(a->fd, " SIP Transfer mode: %s\n", transfermode2str(global_allowtransfer)); 15300 ast_cli(a->fd, " Max Call Bitrate: %d kbps\n", default_maxcallbitrate); 15301 ast_cli(a->fd, " Auto-Framing: %s\n", cli_yesno(global_autoframing)); 15302 ast_cli(a->fd, " Outb. proxy: %s %s\n", ast_strlen_zero(global_outboundproxy.name) ? "<not set>" : global_outboundproxy.name, 15303 global_outboundproxy.force ? "(forced)" : ""); 15304 ast_cli(a->fd, " Session Timers: %s\n", stmode2str(global_st_mode)); 15305 ast_cli(a->fd, " Session Refresher: %s\n", strefresher2str (global_st_refresher)); 15306 ast_cli(a->fd, " Session Expires: %d secs\n", global_max_se); 15307 ast_cli(a->fd, " Session Min-SE: %d secs\n", global_min_se); 15308 ast_cli(a->fd, " Timer T1: %d\n", global_t1); 15309 ast_cli(a->fd, " Timer T1 minimum: %d\n", global_t1min); 15310 ast_cli(a->fd, " Timer B: %d\n", global_timer_b); 15311 ast_cli(a->fd, " No premature media: %s\n", global_prematuremediafilter ? "Yes" : "No"); 15312 15313 ast_cli(a->fd, "\nDefault Settings:\n"); 15314 ast_cli(a->fd, "-----------------\n"); 15315 ast_cli(a->fd, " Context: %s\n", default_context); 15316 ast_cli(a->fd, " Nat: %s\n", nat2str(ast_test_flag(&global_flags[0], SIP_NAT))); 15317 ast_cli(a->fd, " DTMF: %s\n", dtmfmode2str(ast_test_flag(&global_flags[0], SIP_DTMF))); 15318 ast_cli(a->fd, " Qualify: %d\n", default_qualify); 15319 ast_cli(a->fd, " Use ClientCode: %s\n", cli_yesno(ast_test_flag(&global_flags[0], SIP_USECLIENTCODE))); 15320 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" ); 15321 ast_cli(a->fd, " Language: %s\n", default_language); 15322 ast_cli(a->fd, " MOH Interpret: %s\n", default_mohinterpret); 15323 ast_cli(a->fd, " MOH Suggest: %s\n", default_mohsuggest); 15324 ast_cli(a->fd, " Voice Mail Extension: %s\n", default_vmexten); 15325 15326 15327 if (realtimepeers || realtimeregs) { 15328 ast_cli(a->fd, "\nRealtime SIP Settings:\n"); 15329 ast_cli(a->fd, "----------------------\n"); 15330 ast_cli(a->fd, " Realtime Peers: %s\n", cli_yesno(realtimepeers)); 15331 ast_cli(a->fd, " Realtime Regs: %s\n", cli_yesno(realtimeregs)); 15332 ast_cli(a->fd, " Cache Friends: %s\n", cli_yesno(ast_test_flag(&global_flags[1], SIP_PAGE2_RTCACHEFRIENDS))); 15333 ast_cli(a->fd, " Update: %s\n", cli_yesno(sip_cfg.peer_rtupdate)); 15334 ast_cli(a->fd, " Ignore Reg. Expire: %s\n", cli_yesno(sip_cfg.ignore_regexpire)); 15335 ast_cli(a->fd, " Save sys. name: %s\n", cli_yesno(sip_cfg.rtsave_sysname)); 15336 ast_cli(a->fd, " Auto Clear: %d\n", global_rtautoclear); 15337 } 15338 ast_cli(a->fd, "\n----\n"); 15339 return CLI_SUCCESS; 15340 }
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 13673 of file chan_sip.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_t_iterator_next, ao2_t_ref, ast_cli_args::argc, ast_cli(), ast_inet_ntoa(), 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(), ast_tcptls_session_instance::remote_address, sip_threadinfo::tcptls_session, threadt, sip_threadinfo::type, and ast_cli_entry::usage.
13674 { 13675 struct sip_threadinfo *th; 13676 struct ao2_iterator i; 13677 13678 #define FORMAT2 "%-30.30s %3.6s %9.9s %6.6s\n" 13679 #define FORMAT "%-30.30s %-6d %-9.9s %-6.6s\n" 13680 13681 switch (cmd) { 13682 case CLI_INIT: 13683 e->command = "sip show tcp"; 13684 e->usage = 13685 "Usage: sip show tcp\n" 13686 " Lists all active TCP/TLS sessions.\n"; 13687 return NULL; 13688 case CLI_GENERATE: 13689 return NULL; 13690 } 13691 13692 if (a->argc != 3) 13693 return CLI_SHOWUSAGE; 13694 13695 ast_cli(a->fd, FORMAT2, "Host", "Port", "Transport", "Type"); 13696 i = ao2_iterator_init(threadt, 0); 13697 while ((th = ao2_t_iterator_next(&i, "iterate through tcp threads for 'sip show tcp'"))) { 13698 ast_cli(a->fd, FORMAT, ast_inet_ntoa(th->tcptls_session->remote_address.sin_addr), 13699 ntohs(th->tcptls_session->remote_address.sin_port), 13700 get_transport(th->type), 13701 (th->tcptls_session->client ? "Client" : "Server")); 13702 ao2_t_ref(th, -1, "decrement ref from iterator"); 13703 } 13704 ao2_iterator_destroy(&i); 13705 return CLI_SUCCESS; 13706 #undef FORMAT 13707 #undef FORMAT2 13708 }
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 14858 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(), ast_test_flag, 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(), SIP_PAGE2_IGNORESDPVERSION, stmode2str(), strefresher2str(), transfermode2str(), TRUE, unref_peer(), ast_cli_entry::usage, user, ast_variable::value, and ast_cli_args::word.
14859 { 14860 char cbuf[256]; 14861 struct sip_peer *user; 14862 struct ast_variable *v; 14863 int load_realtime; 14864 14865 switch (cmd) { 14866 case CLI_INIT: 14867 e->command = "sip show user"; 14868 e->usage = 14869 "Usage: sip show user <name> [load]\n" 14870 " Shows all details on one SIP user and the current status.\n" 14871 " Option \"load\" forces lookup of peer in realtime storage.\n"; 14872 return NULL; 14873 case CLI_GENERATE: 14874 return complete_sip_show_user(a->line, a->word, a->pos, a->n); 14875 } 14876 14877 if (a->argc < 4) 14878 return CLI_SHOWUSAGE; 14879 14880 /* Load from realtime storage? */ 14881 load_realtime = (a->argc == 5 && !strcmp(a->argv[4], "load")) ? TRUE : FALSE; 14882 14883 if ((user = find_peer(a->argv[3], NULL, load_realtime, FINDUSERS, FALSE, 0))) { 14884 ao2_lock(user); 14885 ast_cli(a->fd, "\n\n"); 14886 ast_cli(a->fd, " * Name : %s\n", user->name); 14887 ast_cli(a->fd, " Secret : %s\n", ast_strlen_zero(user->secret)?"<Not set>":"<Set>"); 14888 ast_cli(a->fd, " MD5Secret : %s\n", ast_strlen_zero(user->md5secret)?"<Not set>":"<Set>"); 14889 ast_cli(a->fd, " Context : %s\n", user->context); 14890 ast_cli(a->fd, " Language : %s\n", user->language); 14891 if (!ast_strlen_zero(user->accountcode)) 14892 ast_cli(a->fd, " Accountcode : %s\n", user->accountcode); 14893 ast_cli(a->fd, " AMA flags : %s\n", ast_cdr_flags2str(user->amaflags)); 14894 ast_cli(a->fd, " Transfer mode: %s\n", transfermode2str(user->allowtransfer)); 14895 ast_cli(a->fd, " MaxCallBR : %d kbps\n", user->maxcallbitrate); 14896 ast_cli(a->fd, " CallingPres : %s\n", ast_describe_caller_presentation(user->callingpres)); 14897 ast_cli(a->fd, " Call limit : %d\n", user->call_limit); 14898 ast_cli(a->fd, " Callgroup : "); 14899 print_group(a->fd, user->callgroup, 0); 14900 ast_cli(a->fd, " Pickupgroup : "); 14901 print_group(a->fd, user->pickupgroup, 0); 14902 ast_cli(a->fd, " Callerid : %s\n", ast_callerid_merge(cbuf, sizeof(cbuf), user->cid_name, user->cid_num, "<unspecified>")); 14903 ast_cli(a->fd, " ACL : %s\n", cli_yesno(user->ha != NULL)); 14904 ast_cli(a->fd, " Sess-Timers : %s\n", stmode2str(user->stimer.st_mode_oper)); 14905 ast_cli(a->fd, " Sess-Refresh : %s\n", strefresher2str(user->stimer.st_ref)); 14906 ast_cli(a->fd, " Sess-Expires : %d secs\n", user->stimer.st_max_se); 14907 ast_cli(a->fd, " Sess-Min-SE : %d secs\n", user->stimer.st_min_se); 14908 ast_cli(a->fd, " Ign SDP ver : %s\n", cli_yesno(ast_test_flag(&user->flags[1], SIP_PAGE2_IGNORESDPVERSION))); 14909 14910 ast_cli(a->fd, " Codec Order : ("); 14911 print_codec_to_cli(a->fd, &user->prefs); 14912 ast_cli(a->fd, ")\n"); 14913 14914 ast_cli(a->fd, " Auto-Framing: %s \n", cli_yesno(user->autoframing)); 14915 if (user->chanvars) { 14916 ast_cli(a->fd, " Variables :\n"); 14917 for (v = user->chanvars ; v ; v = v->next) 14918 ast_cli(a->fd, " %s = %s\n", v->name, v->value); 14919 } 14920 14921 ast_cli(a->fd, "\n"); 14922 14923 ao2_unlock(user); 14924 unref_peer(user, "sip show user"); 14925 } else { 14926 ast_cli(a->fd, "User %s not found.\n", a->argv[3]); 14927 ast_cli(a->fd, "\n"); 14928 } 14929 14930 return CLI_SUCCESS; 14931 }
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 13711 of file chan_sip.c.
References ao2_iterator_destroy(), 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(), peers, SIP_NAT, SIP_TYPE_USER, TRUE, unref_peer(), ast_cli_entry::usage, and user.
13712 { 13713 regex_t regexbuf; 13714 int havepattern = FALSE; 13715 struct ao2_iterator user_iter; 13716 struct sip_peer *user; 13717 13718 #define FORMAT "%-25.25s %-15.15s %-15.15s %-15.15s %-5.5s%-10.10s\n" 13719 13720 switch (cmd) { 13721 case CLI_INIT: 13722 e->command = "sip show users"; 13723 e->usage = 13724 "Usage: sip show users [like <pattern>]\n" 13725 " Lists all known SIP users.\n" 13726 " Optional regular expression pattern is used to filter the user list.\n"; 13727 return NULL; 13728 case CLI_GENERATE: 13729 return NULL; 13730 } 13731 13732 switch (a->argc) { 13733 case 5: 13734 if (!strcasecmp(a->argv[3], "like")) { 13735 if (regcomp(®exbuf, a->argv[4], REG_EXTENDED | REG_NOSUB)) 13736 return CLI_SHOWUSAGE; 13737 havepattern = TRUE; 13738 } else 13739 return CLI_SHOWUSAGE; 13740 case 3: 13741 break; 13742 default: 13743 return CLI_SHOWUSAGE; 13744 } 13745 13746 ast_cli(a->fd, FORMAT, "Username", "Secret", "Accountcode", "Def.Context", "ACL", "NAT"); 13747 13748 user_iter = ao2_iterator_init(peers, 0); 13749 while ((user = ao2_iterator_next(&user_iter))) { 13750 ao2_lock(user); 13751 if (!(user->type & SIP_TYPE_USER)) { 13752 ao2_unlock(user); 13753 unref_peer(user, "sip show users"); 13754 continue; 13755 } 13756 13757 if (havepattern && regexec(®exbuf, user->name, 0, NULL, 0)) { 13758 ao2_unlock(user); 13759 unref_peer(user, "sip show users"); 13760 continue; 13761 } 13762 13763 ast_cli(a->fd, FORMAT, user->name, 13764 user->secret, 13765 user->accountcode, 13766 user->context, 13767 cli_yesno(user->ha != NULL), 13768 nat2str(ast_test_flag(&user->flags[0], SIP_NAT))); 13769 ao2_unlock(user); 13770 unref_peer(user, "sip show users"); 13771 } 13772 ao2_iterator_destroy(&user_iter); 13773 13774 if (havepattern) 13775 regfree(®exbuf); 13776 13777 return CLI_SUCCESS; 13778 #undef FORMAT 13779 }
static int sip_sipredirect | ( | struct sip_pvt * | p, | |
const char * | dest | |||
) | [static] |
Transfer call before connect with a 302 redirect.
Definition at line 24478 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().
24479 { 24480 char *cdest; 24481 char *extension, *host, *port; 24482 char tmp[80]; 24483 24484 cdest = ast_strdupa(dest); 24485 24486 extension = strsep(&cdest, "@"); 24487 host = strsep(&cdest, ":"); 24488 port = strsep(&cdest, ":"); 24489 if (ast_strlen_zero(extension)) { 24490 ast_log(LOG_ERROR, "Missing mandatory argument: extension\n"); 24491 return 0; 24492 } 24493 24494 /* we'll issue the redirect message here */ 24495 if (!host) { 24496 char *localtmp; 24497 24498 ast_copy_string(tmp, get_header(&p->initreq, "To"), sizeof(tmp)); 24499 if (ast_strlen_zero(tmp)) { 24500 ast_log(LOG_ERROR, "Cannot retrieve the 'To' header from the original SIP request!\n"); 24501 return 0; 24502 } 24503 if ( ( (localtmp = strcasestr(tmp, "sip:")) || (localtmp = strcasestr(tmp, "sips:")) ) 24504 && (localtmp = strchr(localtmp, '@'))) { 24505 char lhost[80], lport[80]; 24506 24507 memset(lhost, 0, sizeof(lhost)); 24508 memset(lport, 0, sizeof(lport)); 24509 localtmp++; 24510 /* This is okey because lhost and lport are as big as tmp */ 24511 sscanf(localtmp, "%80[^<>:; ]:%80[^<>:; ]", lhost, lport); 24512 if (ast_strlen_zero(lhost)) { 24513 ast_log(LOG_ERROR, "Can't find the host address\n"); 24514 return 0; 24515 } 24516 host = ast_strdupa(lhost); 24517 if (!ast_strlen_zero(lport)) { 24518 port = ast_strdupa(lport); 24519 } 24520 } 24521 } 24522 24523 ast_string_field_build(p, our_contact, "Transfer <sip:%s@%s%s%s>", extension, host, port ? ":" : "", port ? port : ""); 24524 transmit_response_reliable(p, "302 Moved Temporarily", &p->initreq); 24525 24526 sip_scheddestroy(p, SIP_TRANS_TIMEOUT); /* Make sure we stop send this reply. */ 24527 sip_alreadygone(p); 24528 /* hangup here */ 24529 return 0; 24530 }
static struct sip_st_dlg * sip_st_alloc | ( | struct sip_pvt *const | p | ) | [static] |
Allocate Session-Timers struct w/in dialog.
Definition at line 6714 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().
06715 { 06716 struct sip_st_dlg *stp; 06717 06718 if (p->stimer) { 06719 ast_log(LOG_ERROR, "Session-Timer struct already allocated\n"); 06720 return p->stimer; 06721 } 06722 06723 if (!(stp = ast_calloc(1, sizeof(struct sip_st_dlg)))) 06724 return NULL; 06725 06726 p->stimer = stp; 06727 06728 stp->st_schedid = -1; /* Session-Timers ast_sched scheduler id */ 06729 06730 return p->stimer; 06731 }
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 21123 of file chan_sip.c.
References SIP_TRANSPORT_TLS, STANDARD_SIP_PORT, and STANDARD_TLS_PORT.
Referenced by build_contact(), initreqprep(), and transmit_notify_with_mwi().
21124 { 21125 if (type & SIP_TRANSPORT_TLS) 21126 return port == STANDARD_TLS_PORT; 21127 else 21128 return port == STANDARD_SIP_PORT; 21129 }
static int sip_t38_abort | ( | const void * | data | ) | [static] |
Definition at line 18769 of file chan_sip.c.
References change_t38_state(), dialog_unref(), T38_DISABLED, and transmit_response_reliable().
Referenced by handle_request_invite().
18770 { 18771 struct sip_pvt *p = (struct sip_pvt *) data; 18772 18773 change_t38_state(p, T38_DISABLED); 18774 transmit_response_reliable(p, "488 Not acceptable here", &p->initreq); 18775 p->t38id = -1; 18776 dialog_unref(p, "unref the dialog ptr from sip_t38_abort, because it held a dialog ptr"); 18777 18778 return 0; 18779 }
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 21148 of file chan_sip.c.
References ao2_callback, ao2_ref, ao2_t_ref, sip_threadinfo::tcptls_session, threadinfo_locate_cb(), and threadt.
Referenced by sip_prepare_socket().
21149 { 21150 struct sip_threadinfo *th; 21151 struct ast_tcptls_session_instance *tcptls_instance = NULL; 21152 21153 if ((th = ao2_callback(threadt, 0, threadinfo_locate_cb, s))) { 21154 tcptls_instance = (ao2_ref(th->tcptls_session, +1), th->tcptls_session); 21155 ao2_t_ref(th, -1, "decrement ref from callback"); 21156 } 21157 return tcptls_instance; 21158 }
static void * sip_tcp_worker_fn | ( | void * | ) | [static] |
SIP TCP connection handler.
Definition at line 2536 of file chan_sip.c.
References _sip_tcp_helper_thread().
Referenced by sip_prepare_socket().
02537 { 02538 struct ast_tcptls_session_instance *tcptls_session = data; 02539 02540 return _sip_tcp_helper_thread(NULL, tcptls_session); 02541 }
static void sip_tcptls_client_args_destructor | ( | void * | obj | ) | [static] |
Definition at line 2419 of file chan_sip.c.
References ast_free, ast_tls_config::cafile, ast_tls_config::capath, ast_tls_config::certfile, ast_tls_config::cipher, ast_tcptls_session_args::name, and ast_tcptls_session_args::tls_cfg.
Referenced by sip_prepare_socket().
02420 { 02421 struct ast_tcptls_session_args *args = obj; 02422 if (args->tls_cfg) { 02423 ast_free(args->tls_cfg->certfile); 02424 ast_free(args->tls_cfg->cipher); 02425 ast_free(args->tls_cfg->cafile); 02426 ast_free(args->tls_cfg->capath); 02427 } 02428 ast_free(args->tls_cfg); 02429 ast_free((char *) args->name); 02430 }
static int sip_tcptls_write | ( | struct ast_tcptls_session_instance * | tcptls_session, | |
const void * | buf, | |||
size_t | len | |||
) | [static] |
used to indicate to a tcptls thread that data is ready to be written
Definition at line 2478 of file chan_sip.c.
References sip_threadinfo::alert_pipe, ao2_alloc, ao2_lock(), ao2_t_find, ao2_t_ref, ao2_unlock(), AST_LIST_INSERT_TAIL, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_str_create(), ast_str_set(), errno, ast_tcptls_session_instance::fd, ast_tcptls_session_instance::lock, LOG_ERROR, OBJ_POINTER, sip_threadinfo::packet_q, TCPTLS_ALERT_DATA, tcptls_packet_destructor(), sip_threadinfo::tcptls_session, threadt, and XMIT_ERROR.
Referenced by __sip_xmit().
02479 { 02480 int res = len; 02481 struct sip_threadinfo *th = NULL; 02482 struct tcptls_packet *packet = NULL; 02483 struct sip_threadinfo tmp = { 02484 .tcptls_session = tcptls_session, 02485 }; 02486 enum sip_tcptls_alert alert = TCPTLS_ALERT_DATA; 02487 02488 if (!tcptls_session) { 02489 return XMIT_ERROR; 02490 } 02491 02492 ast_mutex_lock(&tcptls_session->lock); 02493 02494 if ((tcptls_session->fd == -1) || 02495 !(th = ao2_t_find(threadt, &tmp, OBJ_POINTER, "ao2_find, getting sip_threadinfo in tcp helper thread")) || 02496 !(packet = ao2_alloc(sizeof(*packet), tcptls_packet_destructor)) || 02497 !(packet->data = ast_str_create(len))) { 02498 goto tcptls_write_setup_error; 02499 } 02500 02501 /* goto tcptls_write_error should _NOT_ be used beyond this point */ 02502 ast_str_set(&packet->data, 0, "%s", (char *) buf); 02503 packet->len = len; 02504 02505 /* alert tcptls thread handler that there is a packet to be sent. 02506 * must lock the thread info object to guarantee control of the 02507 * packet queue */ 02508 ao2_lock(th); 02509 if (write(th->alert_pipe[1], &alert, sizeof(alert)) == -1) { 02510 ast_log(LOG_ERROR, "write() to alert pipe failed: %s\n", strerror(errno)); 02511 ao2_t_ref(packet, -1, "could not write to alert pipe, remove packet"); 02512 packet = NULL; 02513 res = XMIT_ERROR; 02514 } else { /* it is safe to queue the frame after issuing the alert when we hold the threadinfo lock */ 02515 AST_LIST_INSERT_TAIL(&th->packet_q, packet, entry); 02516 } 02517 ao2_unlock(th); 02518 02519 ast_mutex_unlock(&tcptls_session->lock); 02520 ao2_t_ref(th, -1, "In sip_tcptls_write, unref threadinfo object after finding it"); 02521 return res; 02522 02523 tcptls_write_setup_error: 02524 if (th) { 02525 ao2_t_ref(th, -1, "In sip_tcptls_write, unref threadinfo obj, could not create packet"); 02526 } 02527 if (packet) { 02528 ao2_t_ref(packet, -1, "could not allocate packet's data"); 02529 } 02530 ast_mutex_unlock(&tcptls_session->lock); 02531 02532 return XMIT_ERROR; 02533 }
static struct sip_threadinfo* sip_threadinfo_create | ( | struct ast_tcptls_session_instance * | tcptls_session, | |
int | transport | |||
) | [static] |
creates a sip_threadinfo object and links it into the threadt table.
Definition at line 2454 of file chan_sip.c.
References sip_threadinfo::alert_pipe, ao2_alloc, ao2_t_link, ao2_t_ref, ast_log(), errno, LOG_ERROR, sip_threadinfo_destructor(), SIP_TRANSPORT_TCP, SIP_TRANSPORT_TLS, ast_tcptls_session_instance::ssl, sip_threadinfo::tcptls_session, and threadt.
Referenced by _sip_tcp_helper_thread(), and sip_prepare_socket().
02455 { 02456 struct sip_threadinfo *th; 02457 02458 if (!tcptls_session || !(th = ao2_alloc(sizeof(*th), sip_threadinfo_destructor))) { 02459 return NULL; 02460 } 02461 02462 th->alert_pipe[0] = th->alert_pipe[1] = -1; 02463 02464 if (pipe(th->alert_pipe) == -1) { 02465 ao2_t_ref(th, -1, "Failed to open alert pipe on sip_threadinfo"); 02466 ast_log(LOG_ERROR, "Could not create sip alert pipe in tcptls thread, error %s\n", strerror(errno)); 02467 return NULL; 02468 } 02469 ao2_t_ref(tcptls_session, +1, "tcptls_session ref for sip_threadinfo object"); 02470 th->tcptls_session = tcptls_session; 02471 th->type = transport ? transport : (tcptls_session->ssl ? SIP_TRANSPORT_TLS: SIP_TRANSPORT_TCP); 02472 ao2_t_link(threadt, th, "Adding new tcptls helper thread"); 02473 ao2_t_ref(th, -1, "Decrementing threadinfo ref from alloc, only table ref remains"); 02474 return th; 02475 }
static void sip_threadinfo_destructor | ( | void * | obj | ) | [static] |
Definition at line 2432 of file chan_sip.c.
References sip_threadinfo::alert_pipe, ao2_t_ref, AST_LIST_REMOVE_HEAD, tcptls_packet::entry, sip_threadinfo::packet_q, and sip_threadinfo::tcptls_session.
Referenced by sip_threadinfo_create().
02433 { 02434 struct sip_threadinfo *th = obj; 02435 struct tcptls_packet *packet; 02436 if (th->alert_pipe[1] > -1) { 02437 close(th->alert_pipe[0]); 02438 } 02439 if (th->alert_pipe[1] > -1) { 02440 close(th->alert_pipe[1]); 02441 } 02442 th->alert_pipe[0] = th->alert_pipe[1] = -1; 02443 02444 while ((packet = AST_LIST_REMOVE_HEAD(&th->packet_q, entry))) { 02445 ao2_t_ref(packet, -1, "thread destruction, removing packet from frame queue"); 02446 } 02447 02448 if (th->tcptls_session) { 02449 ao2_t_ref(th->tcptls_session, -1, "remove tcptls_session for sip_threadinfo object"); 02450 } 02451 }
static int sip_transfer | ( | struct ast_channel * | ast, | |
const char * | dest | |||
) | [static] |
Transfer SIP call.
Definition at line 5999 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().
06000 { 06001 struct sip_pvt *p = ast->tech_pvt; 06002 int res; 06003 06004 if (dest == NULL) /* functions below do not take a NULL */ 06005 dest = ""; 06006 sip_pvt_lock(p); 06007 if (ast->_state == AST_STATE_RING) 06008 res = sip_sipredirect(p, dest); 06009 else 06010 res = transmit_refer(p, dest); 06011 sip_pvt_unlock(p); 06012 return res; 06013 }
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 15023 of file chan_sip.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_SCHED_DEL_UNREF, 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(), sched, TRUE, unref_peer(), ast_cli_entry::usage, and ast_cli_args::word.
15024 { 15025 struct sip_peer *peer; 15026 int load_realtime = 0; 15027 15028 switch (cmd) { 15029 case CLI_INIT: 15030 e->command = "sip unregister"; 15031 e->usage = 15032 "Usage: sip unregister <peer>\n" 15033 " Unregister (force expiration) a SIP peer from the registry\n"; 15034 return NULL; 15035 case CLI_GENERATE: 15036 return complete_sip_unregister(a->line, a->word, a->pos, a->n); 15037 } 15038 15039 if (a->argc != 3) 15040 return CLI_SHOWUSAGE; 15041 15042 if ((peer = find_peer(a->argv[2], NULL, load_realtime, FINDPEERS, TRUE, 0))) { 15043 if (peer->expire > 0) { 15044 AST_SCHED_DEL_UNREF(sched, peer->expire, 15045 unref_peer(peer, "remove register expire ref")); 15046 expire_register(ref_peer(peer, "ref for expire_register")); 15047 ast_cli(a->fd, "Unregistered peer \'%s\'\n\n", a->argv[2]); 15048 } else { 15049 ast_cli(a->fd, "Peer %s not registered\n", a->argv[2]); 15050 } 15051 unref_peer(peer, "sip_unregister: unref_peer via sip_unregister: done with peer from find_peer call"); 15052 } else { 15053 ast_cli(a->fd, "Peer unknown: \'%s\'. Not unregistered.\n", a->argv[2]); 15054 } 15055 15056 return CLI_SUCCESS; 15057 }
static int sip_uri_cmp | ( | const char * | input1, | |
const char * | input2 | |||
) | [static] |
Definition at line 18686 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().
18687 { 18688 char *uri1 = ast_strdupa(input1); 18689 char *uri2 = ast_strdupa(input2); 18690 char *host1; 18691 char *host2; 18692 char *params1; 18693 char *params2; 18694 char *headers1; 18695 char *headers2; 18696 18697 /* Strip off "sip:" from the URI. We know this is present 18698 * because it was checked back in parse_request() 18699 */ 18700 strsep(&uri1, ":"); 18701 strsep(&uri2, ":"); 18702 18703 if ((host1 = strchr(uri1, '@'))) { 18704 *host1++ = '\0'; 18705 } 18706 if ((host2 = strchr(uri2, '@'))) { 18707 *host2++ = '\0'; 18708 } 18709 18710 /* Check for mismatched username and passwords. This is the 18711 * only case-sensitive comparison of a SIP URI 18712 */ 18713 if ((host1 && !host2) || 18714 (host2 && !host1) || 18715 (host1 && host2 && strcmp(uri1, uri2))) { 18716 return 1; 18717 } 18718 18719 if (!host1) 18720 host1 = uri1; 18721 if (!host2) 18722 host2 = uri2; 18723 18724 /* Strip off the parameters and headers so we can compare 18725 * host and port 18726 */ 18727 18728 if ((params1 = strchr(host1, ';'))) { 18729 *params1++ = '\0'; 18730 } 18731 if ((params2 = strchr(host2, ';'))) { 18732 *params2++ = '\0'; 18733 } 18734 18735 /* Headers come after parameters, but there may be headers without 18736 * parameters, thus the S_OR 18737 */ 18738 if ((headers1 = strchr(S_OR(params1, host1), '?'))) { 18739 *headers1++ = '\0'; 18740 } 18741 if ((headers2 = strchr(S_OR(params2, host2), '?'))) { 18742 *headers2++ = '\0'; 18743 } 18744 18745 /* Now the host/port are properly isolated. We can get by with a string comparison 18746 * because the SIP URI checking rules have some interesting exceptions that make 18747 * this possible. I will note 2 in particular 18748 * 1. hostnames which resolve to the same IP address as well as a hostname and its 18749 * IP address are not considered a match with SIP URI's. 18750 * 2. If one URI specifies a port and the other does not, then the URIs do not match. 18751 * This includes if one URI explicitly contains port 5060 and the other implies it 18752 * by not having a port specified. 18753 */ 18754 18755 if (strcasecmp(host1, host2)) { 18756 return 1; 18757 } 18758 18759 /* Headers have easier rules to follow, so do those first */ 18760 if (sip_uri_headers_cmp(headers1, headers2)) { 18761 return 1; 18762 } 18763 18764 /* And now the parameters. Ugh */ 18765 return sip_uri_params_cmp(params1, params2); 18766 }
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 18640 of file chan_sip.c.
References ast_strdupa, ast_strlen_zero(), strcasestr(), and strsep().
Referenced by sip_uri_cmp().
18641 { 18642 char *headers1 = NULL; 18643 char *headers2 = NULL; 18644 int zerolength1 = 0; 18645 int zerolength2 = 0; 18646 int different = 0; 18647 char *header1; 18648 18649 if (ast_strlen_zero(input1)) { 18650 zerolength1 = 1; 18651 } else { 18652 headers1 = ast_strdupa(input1); 18653 } 18654 18655 if (ast_strlen_zero(input2)) { 18656 zerolength2 = 1; 18657 } else { 18658 headers2 = ast_strdupa(input2); 18659 } 18660 18661 if ((zerolength1 && !zerolength2) || 18662 (zerolength2 && !zerolength1)) 18663 return 1; 18664 18665 if (zerolength1 && zerolength2) 18666 return 0; 18667 18668 /* At this point, we can definitively state that both inputs are 18669 * not zero-length. First, one more optimization. If the length 18670 * of the headers is not equal, then we definitely have no match 18671 */ 18672 if (strlen(headers1) != strlen(headers2)) { 18673 return 1; 18674 } 18675 18676 for (header1 = strsep(&headers1, "&"); header1; header1 = strsep(&headers1, "&")) { 18677 if (!strcasestr(headers2, header1)) { 18678 different = 1; 18679 break; 18680 } 18681 } 18682 18683 return different; 18684 }
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 18500 of file chan_sip.c.
References ast_strdupa, and ast_strlen_zero().
Referenced by sip_uri_cmp().
18501 { 18502 char *params1 = NULL; 18503 char *params2 = NULL; 18504 char *pos1; 18505 char *pos2; 18506 int zerolength1 = 0; 18507 int zerolength2 = 0; 18508 int maddrmatch = 0; 18509 int ttlmatch = 0; 18510 int usermatch = 0; 18511 int methodmatch = 0; 18512 18513 if (ast_strlen_zero(input1)) { 18514 zerolength1 = 1; 18515 } else { 18516 params1 = ast_strdupa(input1); 18517 } 18518 if (ast_strlen_zero(input2)) { 18519 zerolength2 = 1; 18520 } else { 18521 params2 = ast_strdupa(input2); 18522 } 18523 18524 /*Quick optimization. If both params are zero-length, then 18525 * they match 18526 */ 18527 if (zerolength1 && zerolength2) { 18528 return 0; 18529 } 18530 18531 pos1 = params1; 18532 while (!ast_strlen_zero(pos1)) { 18533 char *name1 = pos1; 18534 char *value1 = strchr(pos1, '='); 18535 char *semicolon1 = strchr(pos1, ';'); 18536 int matched = 0; 18537 if (semicolon1) { 18538 *semicolon1++ = '\0'; 18539 } 18540 if (!value1) { 18541 goto fail; 18542 } 18543 *value1++ = '\0'; 18544 /* Checkpoint reached. We have the name and value parsed for param1 18545 * We have to duplicate params2 each time through the second loop 18546 * or else we can't search and replace the semicolons with \0 each 18547 * time 18548 */ 18549 pos2 = ast_strdupa(params2); 18550 while (!ast_strlen_zero(pos2)) { 18551 char *name2 = pos2; 18552 char *value2 = strchr(pos2, '='); 18553 char *semicolon2 = strchr(pos2, ';'); 18554 if (semicolon2) { 18555 *semicolon2++ = '\0'; 18556 } 18557 if (!value2) { 18558 goto fail; 18559 } 18560 *value2++ = '\0'; 18561 if (!strcasecmp(name1, name2)) { 18562 if (strcasecmp(value1, value2)) { 18563 goto fail; 18564 } else { 18565 matched = 1; 18566 break; 18567 } 18568 } 18569 pos2 = semicolon2; 18570 } 18571 /* Need to see if the parameter we're looking at is one of the 'must-match' parameters */ 18572 if (!strcasecmp(name1, "maddr")) { 18573 if (matched) { 18574 maddrmatch = 1; 18575 } else { 18576 goto fail; 18577 } 18578 } else if (!strcasecmp(name1, "ttl")) { 18579 if (matched) { 18580 ttlmatch = 1; 18581 } else { 18582 goto fail; 18583 } 18584 } else if (!strcasecmp(name1, "user")) { 18585 if (matched) { 18586 usermatch = 1; 18587 } else { 18588 goto fail; 18589 } 18590 } else if (!strcasecmp(name1, "method")) { 18591 if (matched) { 18592 methodmatch = 1; 18593 } else { 18594 goto fail; 18595 } 18596 } 18597 pos1 = semicolon1; 18598 } 18599 18600 /* We've made it out of that horrible O(m*n) construct and there are no 18601 * failures yet. We're not done yet, though, because params2 could have 18602 * an maddr, ttl, user, or method header and params1 did not. 18603 */ 18604 pos2 = params2; 18605 while (!ast_strlen_zero(pos2)) { 18606 char *name2 = pos2; 18607 char *value2 = strchr(pos2, '='); 18608 char *semicolon2 = strchr(pos2, ';'); 18609 if (semicolon2) { 18610 *semicolon2++ = '\0'; 18611 } 18612 if (!value2) { 18613 goto fail; 18614 } 18615 *value2++ = '\0'; 18616 if ((!strcasecmp(name2, "maddr") && !maddrmatch) || 18617 (!strcasecmp(name2, "ttl") && !ttlmatch) || 18618 (!strcasecmp(name2, "user") && !usermatch) || 18619 (!strcasecmp(name2, "method") && !methodmatch)) { 18620 goto fail; 18621 } 18622 } 18623 return 0; 18624 18625 fail: 18626 return 1; 18627 }
static int sip_write | ( | struct ast_channel * | ast, | |
struct ast_frame * | frame | |||
) | [static] |
Send frame to media channel (rtp).
Definition at line 5799 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(), ast_frame::frametype, INV_EARLY_MEDIA, LOG_WARNING, ast_channel::nativeformats, ast_channel::readformat, red_buffer_t140(), SIP_OUTGOING, SIP_PROGRESS_SENT, sip_pvt_lock, sip_pvt_unlock, ast_frame::subclass, T38_ENABLED, ast_channel::tech_pvt, transmit_provisional_response(), TRUE, and ast_channel::writeformat.
05800 { 05801 struct sip_pvt *p = ast->tech_pvt; 05802 int res = 0; 05803 05804 switch (frame->frametype) { 05805 case AST_FRAME_VOICE: 05806 if (!(frame->subclass & ast->nativeformats)) { 05807 char s1[512], s2[512], s3[512]; 05808 ast_log(LOG_WARNING, "Asked to transmit frame type %d, while native formats is %s(%d) read/write = %s(%d)/%s(%d)\n", 05809 frame->subclass, 05810 ast_getformatname_multiple(s1, sizeof(s1) - 1, ast->nativeformats & AST_FORMAT_AUDIO_MASK), 05811 ast->nativeformats & AST_FORMAT_AUDIO_MASK, 05812 ast_getformatname_multiple(s2, sizeof(s2) - 1, ast->readformat), 05813 ast->readformat, 05814 ast_getformatname_multiple(s3, sizeof(s3) - 1, ast->writeformat), 05815 ast->writeformat); 05816 return 0; 05817 } 05818 if (p) { 05819 sip_pvt_lock(p); 05820 if (p->rtp) { 05821 /* If channel is not up, activate early media session */ 05822 if ((ast->_state != AST_STATE_UP) && 05823 !ast_test_flag(&p->flags[0], SIP_PROGRESS_SENT) && 05824 !ast_test_flag(&p->flags[0], SIP_OUTGOING)) { 05825 ast_rtp_new_source(p->rtp); 05826 if (!global_prematuremediafilter) { 05827 p->invitestate = INV_EARLY_MEDIA; 05828 transmit_provisional_response(p, "183 Session Progress", &p->initreq, TRUE); 05829 ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT); 05830 } 05831 } else if (p->t38.state == T38_ENABLED) { 05832 /* drop frame, can't sent VOICE frames while in T.38 mode */ 05833 } else { 05834 p->lastrtptx = time(NULL); 05835 res = ast_rtp_write(p->rtp, frame); 05836 } 05837 } 05838 sip_pvt_unlock(p); 05839 } 05840 break; 05841 case AST_FRAME_VIDEO: 05842 if (p) { 05843 sip_pvt_lock(p); 05844 if (p->vrtp) { 05845 /* Activate video early media */ 05846 if ((ast->_state != AST_STATE_UP) && 05847 !ast_test_flag(&p->flags[0], SIP_PROGRESS_SENT) && 05848 !ast_test_flag(&p->flags[0], SIP_OUTGOING)) { 05849 p->invitestate = INV_EARLY_MEDIA; 05850 transmit_provisional_response(p, "183 Session Progress", &p->initreq, TRUE); 05851 ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT); 05852 } 05853 p->lastrtptx = time(NULL); 05854 res = ast_rtp_write(p->vrtp, frame); 05855 } 05856 sip_pvt_unlock(p); 05857 } 05858 break; 05859 case AST_FRAME_TEXT: 05860 if (p) { 05861 sip_pvt_lock(p); 05862 if (p->red) { 05863 red_buffer_t140(p->trtp, frame); 05864 } else { 05865 if (p->trtp) { 05866 /* Activate text early media */ 05867 if ((ast->_state != AST_STATE_UP) && 05868 !ast_test_flag(&p->flags[0], SIP_PROGRESS_SENT) && 05869 !ast_test_flag(&p->flags[0], SIP_OUTGOING)) { 05870 p->invitestate = INV_EARLY_MEDIA; 05871 transmit_provisional_response(p, "183 Session Progress", &p->initreq, TRUE); 05872 ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT); 05873 } 05874 p->lastrtptx = time(NULL); 05875 res = ast_rtp_write(p->trtp, frame); 05876 } 05877 } 05878 sip_pvt_unlock(p); 05879 } 05880 break; 05881 case AST_FRAME_IMAGE: 05882 return 0; 05883 break; 05884 case AST_FRAME_MODEM: 05885 if (p) { 05886 sip_pvt_lock(p); 05887 /* UDPTL requires two-way communication, so early media is not needed here. 05888 we simply forget the frames if we get modem frames before the bridge is up. 05889 Fax will re-transmit. 05890 */ 05891 if ((ast->_state == AST_STATE_UP) && 05892 p->udptl && 05893 (p->t38.state == T38_ENABLED)) { 05894 res = ast_udptl_write(p->udptl, frame); 05895 } 05896 sip_pvt_unlock(p); 05897 } 05898 break; 05899 default: 05900 ast_log(LOG_WARNING, "Can't send %d type frames with SIP write\n", frame->frametype); 05901 return 0; 05902 } 05903 05904 return res; 05905 }
static int sipsock_read | ( | int * | id, | |
int | fd, | |||
short | events, | |||
void * | ignore | |||
) | [static] |
Read data from SIP socket.
Definition at line 20962 of file chan_sip.c.
References AST_DYNSTR_BUILD_FAILED, ast_free, ast_log(), ast_str_create(), ast_str_set(), errno, handle_request_do(), LOG_NOTICE, LOG_WARNING, set_socket_transport(), SIP_MIN_PACKET, and SIP_TRANSPORT_UDP.
Referenced by do_monitor().
20963 { 20964 struct sip_request req; 20965 struct sockaddr_in sin = { 0, }; 20966 int res; 20967 socklen_t len = sizeof(sin); 20968 static char readbuf[65535]; 20969 20970 memset(&req, 0, sizeof(req)); 20971 res = recvfrom(fd, readbuf, sizeof(readbuf) - 1, 0, (struct sockaddr *)&sin, &len); 20972 if (res < 0) { 20973 #if !defined(__FreeBSD__) 20974 if (errno == EAGAIN) 20975 ast_log(LOG_NOTICE, "SIP: Received packet with bad UDP checksum\n"); 20976 else 20977 #endif 20978 if (errno != ECONNREFUSED) 20979 ast_log(LOG_WARNING, "Recv error: %s\n", strerror(errno)); 20980 return 1; 20981 } 20982 20983 readbuf[res] = '\0'; 20984 20985 if (!(req.data = ast_str_create(SIP_MIN_PACKET))) { 20986 return 1; 20987 } 20988 20989 if (ast_str_set(&req.data, 0, "%s", readbuf) == AST_DYNSTR_BUILD_FAILED) { 20990 return -1; 20991 } 20992 20993 req.len = res; 20994 req.socket.fd = sipsock; 20995 set_socket_transport(&req.socket, SIP_TRANSPORT_UDP); 20996 req.socket.tcptls_session = NULL; 20997 req.socket.port = bindaddr.sin_port; 20998 20999 handle_request_do(&req, &sin); 21000 if (req.data) { 21001 ast_free(req.data); 21002 req.data = NULL; 21003 } 21004 21005 return 1; 21006 }
Get the session-timer mode.
p | pointer to the SIP dialog |
Definition at line 21893 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().
21894 { 21895 if (!p->stimer) 21896 sip_st_alloc(p); 21897 21898 if (p->stimer->st_cached_mode != SESSION_TIMER_MODE_INVALID) 21899 return p->stimer->st_cached_mode; 21900 21901 if (p->peername) { 21902 struct sip_peer *pp = find_peer(p->peername, NULL, TRUE, FINDPEERS, FALSE, 0); 21903 if (pp) { 21904 p->stimer->st_cached_mode = pp->stimer.st_mode_oper; 21905 unref_peer(pp, "unref peer pointer from find_peer call in st_get_mode"); 21906 return pp->stimer.st_mode_oper; 21907 } 21908 } 21909 21910 p->stimer->st_cached_mode = global_st_mode; 21911 return global_st_mode; 21912 }
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 21871 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().
21872 { 21873 if (p->stimer->st_cached_ref != SESSION_TIMER_REFRESHER_AUTO) 21874 return p->stimer->st_cached_ref; 21875 21876 if (p->peername) { 21877 struct sip_peer *pp = find_peer(p->peername, NULL, TRUE, FINDPEERS, FALSE, 0); 21878 if (pp) { 21879 p->stimer->st_cached_ref = pp->stimer.st_ref; 21880 unref_peer(pp, "unref peer pointer from find_peer call in st_get_refresher"); 21881 return pp->stimer.st_ref; 21882 } 21883 } 21884 21885 p->stimer->st_cached_ref = global_st_refresher; 21886 return global_st_refresher; 21887 }
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 21836 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().
21837 { 21838 if (max == TRUE) { 21839 if (p->stimer->st_cached_max_se) { 21840 return p->stimer->st_cached_max_se; 21841 } else if (p->peername) { 21842 struct sip_peer *pp = find_peer(p->peername, NULL, TRUE, FINDPEERS, FALSE, 0); 21843 if (pp) { 21844 p->stimer->st_cached_max_se = pp->stimer.st_max_se; 21845 unref_peer(pp, "unref peer pointer from find_peer call in st_get_se"); 21846 return (p->stimer->st_cached_max_se); 21847 } 21848 } 21849 p->stimer->st_cached_max_se = global_max_se; 21850 return (p->stimer->st_cached_max_se); 21851 } else { 21852 if (p->stimer->st_cached_min_se) { 21853 return p->stimer->st_cached_min_se; 21854 } else if (p->peername) { 21855 struct sip_peer *pp = find_peer(p->peername, NULL, TRUE, FINDPEERS, FALSE, 0); 21856 if (pp) { 21857 p->stimer->st_cached_min_se = pp->stimer.st_min_se; 21858 unref_peer(pp, "unref peer pointer from find_peer call in st_get_se (2)"); 21859 return (p->stimer->st_cached_min_se); 21860 } 21861 } 21862 p->stimer->st_cached_min_se = global_min_se; 21863 return (p->stimer->st_cached_min_se); 21864 } 21865 }
static void start_session_timer | ( | struct sip_pvt * | p | ) | [static] |
Session-Timers: Start session timer.
Definition at line 21633 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().
21634 { 21635 if (!p->stimer) { 21636 ast_log(LOG_WARNING, "Null stimer in start_session_timer - %s\n", p->callid); 21637 return; 21638 } 21639 21640 p->stimer->st_schedid = ast_sched_add(sched, p->stimer->st_interval * 1000 / 2, proc_session_timer, 21641 dialog_ref(p, "adding session timer ref")); 21642 if (p->stimer->st_schedid < 0) { 21643 dialog_unref(p, "removing session timer ref"); 21644 ast_log(LOG_ERROR, "ast_sched_add failed.\n"); 21645 } 21646 ast_debug(2, "Session timer started: %d - %s\n", p->stimer->st_schedid, p->callid); 21647 }
static const char* stmode2str | ( | enum st_mode | m | ) | [static] |
Definition at line 13610 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 17445 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().
17446 { 17447 /* Immediately stop RTP, VRTP and UDPTL as applicable */ 17448 if (p->rtp) 17449 ast_rtp_stop(p->rtp); 17450 if (p->vrtp) 17451 ast_rtp_stop(p->vrtp); 17452 if (p->trtp) 17453 ast_rtp_stop(p->trtp); 17454 if (p->udptl) 17455 ast_udptl_stop(p->udptl); 17456 }
static void stop_session_timer | ( | struct sip_pvt * | p | ) | [static] |
Session-Timers: Stop session timer.
Definition at line 21616 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().
21617 { 21618 if (!p->stimer) { 21619 ast_log(LOG_WARNING, "Null stimer in stop_session_timer - %s\n", p->callid); 21620 return; 21621 } 21622 21623 if (p->stimer->st_active == TRUE) { 21624 p->stimer->st_active = FALSE; 21625 AST_SCHED_DEL_UNREF(sched, p->stimer->st_schedid, 21626 dialog_unref(p, "removing session timer ref")); 21627 ast_debug(2, "Session timer stopped: %d - %s\n", p->stimer->st_schedid, p->callid); 21628 } 21629 }
static int str2dtmfmode | ( | const char * | str | ) | [static] |
static enum st_mode str2stmode | ( | const char * | s | ) | [static] |
Definition at line 13615 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 13633 of file chan_sip.c.
References map_s_x(), and strefreshers.
Referenced by build_peer().
13634 { 13635 return map_s_x(strefreshers, s, -1); 13636 }
static const char * strefresher2str | ( | enum st_refresher | r | ) | [static] |
Definition at line 13628 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().
13629 { 13630 return map_x_s(strefreshers, r, "Unknown"); 13631 }
static const char * subscription_type2str | ( | enum subscriptiontype | subtype | ) | [static] |
Show subscription type in string format.
Definition at line 15343 of file chan_sip.c.
References ARRAY_LEN, subscription_types, and cfsubscription_types::text.
Referenced by show_channels_cb(), and sip_show_channel().
15344 { 15345 int i; 15346 15347 for (i = 1; i < ARRAY_LEN(subscription_types); i++) { 15348 if (subscription_types[i].type == subtype) { 15349 return subscription_types[i].text; 15350 } 15351 } 15352 return subscription_types[0].text; 15353 }
static unsigned int t38_get_rate | ( | enum ast_control_t38_rate | rate | ) | [static] |
Get Max T.38 Transmission rate from T38 capabilities.
Definition at line 9287 of file chan_sip.c.
References AST_T38_RATE_12000, AST_T38_RATE_14400, AST_T38_RATE_2400, AST_T38_RATE_4800, AST_T38_RATE_7200, and AST_T38_RATE_9600.
Referenced by add_sdp().
09288 { 09289 switch (rate) { 09290 case AST_T38_RATE_2400: 09291 return 2400; 09292 case AST_T38_RATE_4800: 09293 return 4800; 09294 case AST_T38_RATE_7200: 09295 return 7200; 09296 case AST_T38_RATE_9600: 09297 return 9600; 09298 case AST_T38_RATE_12000: 09299 return 12000; 09300 case AST_T38_RATE_14400: 09301 return 14400; 09302 default: 09303 return 0; 09304 } 09305 }
static void tcptls_packet_destructor | ( | void * | obj | ) | [static] |
Definition at line 2412 of file chan_sip.c.
References ast_free, and tcptls_packet::data.
Referenced by sip_tcptls_write().
02413 { 02414 struct tcptls_packet *packet = obj; 02415 02416 ast_free(packet->data); 02417 }
static struct sip_peer * temp_peer | ( | const char * | name | ) | [static] |
Create temporary peer (used in autocreatepeer mode).
Definition at line 22719 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().
22720 { 22721 struct sip_peer *peer; 22722 22723 if (!(peer = ao2_t_alloc(sizeof(*peer), sip_destroy_peer_fn, "allocate a peer struct"))) 22724 return NULL; 22725 22726 ast_atomic_fetchadd_int(&apeerobjs, 1); 22727 set_peer_defaults(peer); 22728 22729 ast_copy_string(peer->name, name, sizeof(peer->name)); 22730 22731 peer->selfdestruct = TRUE; 22732 peer->host_dynamic = TRUE; 22733 peer->prefs = default_prefs; 22734 reg_source_db(peer); 22735 22736 return peer; 22737 }
static void temp_pvt_cleanup | ( | void * | ) | [static] |
Definition at line 8958 of file chan_sip.c.
References ast_free, and ast_string_field_free_memory.
08959 { 08960 struct sip_pvt *p = data; 08961 08962 ast_string_field_free_memory(p); 08963 08964 ast_free(data); 08965 }
static int temp_pvt_init | ( | void * | ) | [static] |
Definition at line 8950 of file chan_sip.c.
References ast_string_field_init, and sip_pvt::do_history.
08951 { 08952 struct sip_pvt *p = data; 08953 08954 p->do_history = 0; /* XXX do we need it ? isn't already all 0 ? */ 08955 return ast_string_field_init(p, 512); 08956 }
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 12126 of file chan_sip.c.
Referenced by check_user_full(), and register_verify().
12127 { 12128 char *t = uri; 12129 while (*t && *t > ' ' && *t != ';') 12130 t++; 12131 *t = '\0'; 12132 return uri; 12133 }
static int threadinfo_locate_cb | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 21131 of file chan_sip.c.
References CMP_MATCH, CMP_STOP, inaddrcmp(), ast_tcptls_session_instance::remote_address, s, and sip_threadinfo::tcptls_session.
Referenced by sip_tcp_locate().
21132 { 21133 struct sip_threadinfo *th = obj; 21134 struct sockaddr_in *s = arg; 21135 21136 if (!inaddrcmp(&th->tcptls_session->remote_address, s)) { 21137 return CMP_MATCH | CMP_STOP; 21138 } 21139 21140 return 0; 21141 }
static int threadt_cmp_cb | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 1773 of file chan_sip.c.
References CMP_MATCH, CMP_STOP, and sip_threadinfo::tcptls_session.
Referenced by load_module().
01774 { 01775 struct sip_threadinfo *th = obj, *th2 = arg; 01776 01777 return (th->tcptls_session == th2->tcptls_session) ? CMP_MATCH | CMP_STOP : 0; 01778 }
static int threadt_hash_cb | ( | const void * | obj, | |
const int | flags | |||
) | [static] |
Definition at line 1766 of file chan_sip.c.
References ast_tcptls_session_instance::remote_address, and sip_threadinfo::tcptls_session.
Referenced by load_module().
01767 { 01768 const struct sip_threadinfo *th = obj; 01769 01770 return (int) th->tcptls_session->remote_address.sin_addr.s_addr; 01771 }
static char * transfermode2str | ( | enum transfermodes | mode | ) | const [static] |
Convert transfer mode to text string.
Definition at line 13554 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().
13555 { 13556 if (mode == TRANSFER_OPENFORALL) 13557 return "open"; 13558 else if (mode == TRANSFER_CLOSED) 13559 return "closed"; 13560 return "strict"; 13561 }
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 12023 of file chan_sip.c.
References AST_DYNSTR_BUILD_FAILED, ast_skip_blanks(), ast_str_set(), ast_str_thread_get(), 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, set_nonce_randdata(), 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().
12024 { 12025 /* We have to emulate EXACTLY what we'd get with a good peer 12026 * and a bad password, or else we leak information. */ 12027 const char *response = "407 Proxy Authentication Required"; 12028 const char *reqheader = "Proxy-Authorization"; 12029 const char *respheader = "Proxy-Authenticate"; 12030 const char *authtoken; 12031 struct ast_str *buf; 12032 char *c; 12033 12034 /* table of recognised keywords, and their value in the digest */ 12035 enum keys { K_NONCE, K_LAST }; 12036 struct x { 12037 const char *key; 12038 const char *s; 12039 } *i, keys[] = { 12040 [K_NONCE] = { "nonce=", "" }, 12041 [K_LAST] = { NULL, NULL} 12042 }; 12043 12044 if (sipmethod == SIP_REGISTER || sipmethod == SIP_SUBSCRIBE) { 12045 response = "401 Unauthorized"; 12046 reqheader = "Authorization"; 12047 respheader = "WWW-Authenticate"; 12048 } 12049 authtoken = get_header(req, reqheader); 12050 if (req->ignore && !ast_strlen_zero(p->randdata) && ast_strlen_zero(authtoken)) { 12051 /* This is a retransmitted invite/register/etc, don't reconstruct authentication 12052 * information */ 12053 transmit_response_with_auth(p, response, req, p->randdata, 0, respheader, 0); 12054 /* Schedule auto destroy in 32 seconds (according to RFC 3261) */ 12055 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 12056 return; 12057 } else if (ast_strlen_zero(p->randdata) || ast_strlen_zero(authtoken)) { 12058 /* We have no auth, so issue challenge and request authentication */ 12059 set_nonce_randdata(p, 1); 12060 transmit_response_with_auth(p, response, req, p->randdata, 0, respheader, 0); 12061 /* Schedule auto destroy in 32 seconds */ 12062 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 12063 return; 12064 } 12065 12066 if (!(buf = ast_str_thread_get(&check_auth_buf, CHECK_AUTH_BUF_INITLEN))) { 12067 transmit_response(p, "403 Forbidden (Bad auth)", &p->initreq); 12068 return; 12069 } 12070 12071 /* Make a copy of the response and parse it */ 12072 if (ast_str_set(&buf, 0, "%s", authtoken) == AST_DYNSTR_BUILD_FAILED) { 12073 transmit_response(p, "403 Forbidden (Bad auth)", &p->initreq); 12074 return; 12075 } 12076 12077 c = buf->str; 12078 12079 while (c && *(c = ast_skip_blanks(c))) { /* lookup for keys */ 12080 for (i = keys; i->key != NULL; i++) { 12081 const char *separator = ","; /* default */ 12082 12083 if (strncasecmp(c, i->key, strlen(i->key)) != 0) { 12084 continue; 12085 } 12086 /* Found. Skip keyword, take text in quotes or up to the separator. */ 12087 c += strlen(i->key); 12088 if (*c == '"') { /* in quotes. Skip first and look for last */ 12089 c++; 12090 separator = "\""; 12091 } 12092 i->s = c; 12093 strsep(&c, separator); 12094 break; 12095 } 12096 if (i->key == NULL) { /* not found, jump after space or comma */ 12097 strsep(&c, " ,"); 12098 } 12099 } 12100 12101 /* Verify nonce from request matches our nonce. If not, send 401 with new nonce */ 12102 if (strcasecmp(p->randdata, keys[K_NONCE].s)) { 12103 if (!req->ignore) { 12104 set_nonce_randdata(p, 1); 12105 } 12106 transmit_response_with_auth(p, response, req, p->randdata, reliable, respheader, FALSE); 12107 12108 /* Schedule auto destroy in 32 seconds */ 12109 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 12110 } else { 12111 transmit_response(p, "403 Forbidden (Bad auth)", &p->initreq); 12112 } 12113 }
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 11115 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().
11116 { 11117 struct sip_request req; 11118 11119 reqprep(&req, p, SIP_INFO, 0, 1); 11120 add_digit(&req, digit, duration, (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_SHORTINFO)); 11121 return send_request(p, &req, XMIT_RELIABLE, p->ocseq); 11122 }
static int transmit_info_with_vidupdate | ( | struct sip_pvt * | p | ) | [static] |
Send SIP INFO with video update request.
Definition at line 11125 of file chan_sip.c.
References add_vidupdate(), sip_pvt::ocseq, reqprep(), send_request(), SIP_INFO, and XMIT_RELIABLE.
Referenced by sip_indicate().
11126 { 11127 struct sip_request req; 11128 11129 reqprep(&req, p, SIP_INFO, 0, 1); 11130 add_vidupdate(&req); 11131 return send_request(p, &req, XMIT_RELIABLE, p->ocseq); 11132 }
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 10185 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_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::offered_media, 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(), proc_422_rsp(), sip_call(), and sip_poke_peer().
10186 { 10187 struct sip_request req; 10188 struct ast_variable *var; 10189 10190 req.method = sipmethod; 10191 if (init) {/* Bump branch even on initial requests */ 10192 p->branch ^= ast_random(); 10193 p->invite_branch = p->branch; 10194 build_via(p); 10195 } 10196 if (init > 1) 10197 initreqprep(&req, p, sipmethod); 10198 else 10199 /* If init=1, we should not generate a new branch. If it's 0, we need a new branch. */ 10200 reqprep(&req, p, sipmethod, 0, init ? 0 : 1); 10201 10202 if (p->options && p->options->auth) 10203 add_header(&req, p->options->authheader, p->options->auth); 10204 append_date(&req); 10205 if (sipmethod == SIP_REFER) { /* Call transfer */ 10206 if (p->refer) { 10207 char buf[SIPBUFSIZE]; 10208 if (!ast_strlen_zero(p->refer->refer_to)) 10209 add_header(&req, "Refer-To", p->refer->refer_to); 10210 if (!ast_strlen_zero(p->refer->referred_by)) { 10211 snprintf(buf, sizeof(buf), "%s <%s>", p->refer->referred_by_name, p->refer->referred_by); 10212 add_header(&req, "Referred-By", buf); 10213 } 10214 } 10215 } 10216 /* This new INVITE is part of an attended transfer. Make sure that the 10217 other end knows and replace the current call with this new call */ 10218 if (p->options && !ast_strlen_zero(p->options->replaces)) { 10219 add_header(&req, "Replaces", p->options->replaces); 10220 add_header(&req, "Require", "replaces"); 10221 } 10222 10223 /* Add Session-Timers related headers */ 10224 if (st_get_mode(p) == SESSION_TIMER_MODE_ORIGINATE) { 10225 char i2astr[10]; 10226 10227 if (!p->stimer->st_interval) 10228 p->stimer->st_interval = st_get_se(p, TRUE); 10229 10230 p->stimer->st_active = TRUE; 10231 10232 snprintf(i2astr, sizeof(i2astr), "%d", p->stimer->st_interval); 10233 add_header(&req, "Session-Expires", i2astr); 10234 snprintf(i2astr, sizeof(i2astr), "%d", st_get_se(p, FALSE)); 10235 add_header(&req, "Min-SE", i2astr); 10236 } 10237 10238 add_header(&req, "Allow", ALLOWED_METHODS); 10239 add_header(&req, "Supported", SUPPORTED_EXTENSIONS); 10240 10241 if(p->notify_headers) { 10242 char buf[512]; 10243 for (var = p->notify_headers; var; var = var->next) { 10244 ast_copy_string(buf, var->value, sizeof(buf)); 10245 add_header(&req, var->name, ast_unescape_semicolon(buf)); 10246 } 10247 } 10248 if (p->options && p->options->addsipheaders && p->owner) { 10249 struct ast_channel *chan = p->owner; /* The owner channel */ 10250 struct varshead *headp; 10251 10252 ast_channel_lock(chan); 10253 10254 headp = &chan->varshead; 10255 10256 if (!headp) 10257 ast_log(LOG_WARNING, "No Headp for the channel...ooops!\n"); 10258 else { 10259 const struct ast_var_t *current; 10260 AST_LIST_TRAVERSE(headp, current, entries) { 10261 /* SIPADDHEADER: Add SIP header to outgoing call */ 10262 if (!strncasecmp(ast_var_name(current), "SIPADDHEADER", strlen("SIPADDHEADER"))) { 10263 char *content, *end; 10264 const char *header = ast_var_value(current); 10265 char *headdup = ast_strdupa(header); 10266 10267 /* Strip of the starting " (if it's there) */ 10268 if (*headdup == '"') 10269 headdup++; 10270 if ((content = strchr(headdup, ':'))) { 10271 *content++ = '\0'; 10272 content = ast_skip_blanks(content); /* Skip white space */ 10273 /* Strip the ending " (if it's there) */ 10274 end = content + strlen(content) -1; 10275 if (*end == '"') 10276 *end = '\0'; 10277 10278 add_header(&req, headdup, content); 10279 if (sipdebug) 10280 ast_debug(1, "Adding SIP Header \"%s\" with content :%s: \n", headdup, content); 10281 } 10282 } 10283 } 10284 } 10285 10286 ast_channel_unlock(chan); 10287 } 10288 if (sdp) { 10289 memset(p->offered_media, 0, sizeof(p->offered_media)); 10290 if (p->udptl && p->t38.state == T38_LOCAL_REINVITE) { 10291 ast_debug(1, "T38 is in state %d on channel %s\n", p->t38.state, p->owner ? p->owner->name : "<none>"); 10292 add_sdp(&req, p, FALSE, FALSE, TRUE); 10293 } else if (p->rtp) 10294 add_sdp(&req, p, FALSE, TRUE, FALSE); 10295 } else { 10296 if (!p->notify_headers) { 10297 add_header_contentLength(&req, 0); 10298 } 10299 } 10300 10301 if (!p->initreq.headers || init > 2) 10302 initialize_initreq(p, &req); 10303 p->lastinvite = p->ocseq; 10304 return send_request(p, &req, init ? XMIT_CRITICAL : XMIT_RELIABLE, p->ocseq); 10305 }
static int transmit_message_with_text | ( | struct sip_pvt * | p, | |
const char * | text | |||
) | [static] |
Transmit text with SIP MESSAGE method.
Definition at line 11021 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().
11022 { 11023 struct sip_request req; 11024 11025 reqprep(&req, p, SIP_MESSAGE, 0, 1); 11026 add_text(&req, text); 11027 return send_request(p, &req, XMIT_RELIABLE, p->ocseq); 11028 }
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 10569 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().
10569 { 10570 struct sip_request req; 10571 struct ast_variable *var, *newvar; 10572 10573 initreqprep(&req, p, SIP_NOTIFY); 10574 10575 /* Copy notify vars and add headers */ 10576 p->notify_headers = newvar = ast_variable_new("Subscription-State", "terminated", ""); 10577 add_header(&req, newvar->name, newvar->value); 10578 for (var = vars; var; var = var->next) { 10579 char buf[512]; 10580 ast_debug(2, " Adding pair %s=%s\n", var->name, var->value); 10581 ast_copy_string(buf, var->value, sizeof(buf)); 10582 add_header(&req, var->name, ast_unescape_semicolon(buf)); 10583 newvar->next = ast_variable_new(var->name, var->value, ""); 10584 newvar = newvar->next; 10585 } 10586 10587 if (!p->initreq.headers) { /* Initialize first request before sending */ 10588 initialize_initreq(p, &req); 10589 } 10590 10591 return send_request(p, &req, XMIT_UNRELIABLE, p->ocseq); 10592 }
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 10496 of file chan_sip.c.
References add_header(), add_header_contentLength(), add_line(), ast_inet_ntoa(), ast_str_alloca, ast_str_append(), ast_strlen_zero(), ast_test_flag, sip_pvt::expiry, exten, sip_pvt::flags, sip_pvt::fromdomain, get_transport(), sip_request::headers, initialize_initreq(), sip_pvt::initreq, initreqprep(), sip_pvt::ocseq, sip_pvt::ourip, ourport, S_OR, send_request(), SIP_NOTIFY, SIP_PAGE2_BUGGY_MWI, sip_standard_port(), SIP_TRANSPORT_UDP, sip_pvt::socket, ast_str::str, sip_pvt::subscribed, sip_socket::type, ast_str::used, and XMIT_RELIABLE.
Referenced by sip_send_mwi_to_peer().
10497 { 10498 struct sip_request req; 10499 struct ast_str *out = ast_str_alloca(500); 10500 int ourport = ntohs(p->ourip.sin_port); 10501 const char *exten = S_OR(vmexten, default_vmexten); 10502 10503 initreqprep(&req, p, SIP_NOTIFY); 10504 add_header(&req, "Event", "message-summary"); 10505 add_header(&req, "Content-Type", default_notifymime); 10506 ast_str_append(&out, 0, "Messages-Waiting: %s\r\n", newmsgs ? "yes" : "no"); 10507 10508 if (!ast_strlen_zero(p->fromdomain)) { 10509 ast_str_append(&out, 0, "Message-Account: sip:%s@%s\r\n", exten, p->fromdomain); 10510 } else if (!sip_standard_port(p->socket.type, ourport)) { 10511 if (p->socket.type == SIP_TRANSPORT_UDP) { 10512 ast_str_append(&out, 0, "Message-Account: sip:%s@%s:%d\r\n", exten, ast_inet_ntoa(p->ourip.sin_addr), ourport); 10513 } else { 10514 ast_str_append(&out, 0, "Message-Account: sip:%s@%s:%d;transport=%s\r\n", exten, ast_inet_ntoa(p->ourip.sin_addr), ourport, get_transport(p->socket.type)); 10515 } 10516 } else { 10517 if (p->socket.type == SIP_TRANSPORT_UDP) { 10518 ast_str_append(&out, 0, "Message-Account: sip:%s@%s\r\n", exten, ast_inet_ntoa(p->ourip.sin_addr)); 10519 } else { 10520 ast_str_append(&out, 0, "Message-Account: sip:%s@%s;transport=%s\r\n", exten, ast_inet_ntoa(p->ourip.sin_addr), get_transport(p->socket.type)); 10521 } 10522 } 10523 /* Cisco has a bug in the SIP stack where it can't accept the 10524 (0/0) notification. This can temporarily be disabled in 10525 sip.conf with the "buggymwi" option */ 10526 ast_str_append(&out, 0, "Voice-Message: %d/%d%s\r\n", 10527 newmsgs, oldmsgs, (ast_test_flag(&p->flags[1], SIP_PAGE2_BUGGY_MWI) ? "" : " (0/0)")); 10528 10529 if (p->subscribed) { 10530 if (p->expiry) 10531 add_header(&req, "Subscription-State", "active"); 10532 else /* Expired */ 10533 add_header(&req, "Subscription-State", "terminated;reason=timeout"); 10534 } 10535 10536 add_header_contentLength(&req, out->used); 10537 add_line(&req, out->str); 10538 10539 if (!p->initreq.headers) 10540 initialize_initreq(p, &req); 10541 return send_request(p, &req, XMIT_RELIABLE, p->ocseq); 10542 }
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 10545 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::ocseq, reqprep(), send_request(), SIP_NOTIFY, SIPBUFSIZE, SUPPORTED_EXTENSIONS, and XMIT_RELIABLE.
Referenced by handle_request_refer(), local_attended_transfer(), and sip_park_thread().
10546 { 10547 struct sip_request req; 10548 char tmp[SIPBUFSIZE/2]; 10549 10550 reqprep(&req, p, SIP_NOTIFY, 0, 1); 10551 snprintf(tmp, sizeof(tmp), "refer;id=%d", cseq); 10552 add_header(&req, "Event", tmp); 10553 add_header(&req, "Subscription-state", terminate ? "terminated;reason=noresource" : "active"); 10554 add_header(&req, "Content-Type", "message/sipfrag;version=2.0"); 10555 add_header(&req, "Allow", ALLOWED_METHODS); 10556 add_header(&req, "Supported", SUPPORTED_EXTENSIONS); 10557 10558 snprintf(tmp, sizeof(tmp), "SIP/2.0 %s\r\n", message); 10559 add_header_contentLength(&req, strlen(tmp)); 10560 add_line(&req, tmp); 10561 10562 if (!p->initreq.headers) 10563 initialize_initreq(p, &req); 10564 10565 return send_request(p, &req, XMIT_RELIABLE, p->ocseq); 10566 }
static int transmit_provisional_response | ( | struct sip_pvt * | p, | |
const char * | msg, | |||
const struct sip_request * | req, | |||
int | with_sdp | |||
) | [static] |
Definition at line 9115 of file chan_sip.c.
References FALSE, transmit_response(), transmit_response_with_sdp(), update_provisional_keepalive(), and XMIT_UNRELIABLE.
Referenced by handle_request_invite(), sip_indicate(), and sip_write().
09116 { 09117 int res; 09118 09119 if (!(res = with_sdp ? transmit_response_with_sdp(p, msg, req, XMIT_UNRELIABLE, FALSE) : transmit_response(p, msg, req))) { 09120 p->last_provisional = msg; 09121 update_provisional_keepalive(p, with_sdp); 09122 } 09123 09124 return res; 09125 }
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 11042 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().
11043 { 11044 struct sip_request req = { 11045 .headers = 0, 11046 }; 11047 char from[256]; 11048 const char *of; 11049 char *c; 11050 char referto[256]; 11051 char *ttag, *ftag; 11052 char *theirtag = ast_strdupa(p->theirtag); 11053 11054 if (sipdebug) 11055 ast_debug(1, "SIP transfer of %s to %s\n", p->callid, dest); 11056 11057 /* Are we transfering an inbound or outbound call ? */ 11058 if (ast_test_flag(&p->flags[0], SIP_OUTGOING)) { 11059 of = get_header(&p->initreq, "To"); 11060 ttag = theirtag; 11061 ftag = p->tag; 11062 } else { 11063 of = get_header(&p->initreq, "From"); 11064 ftag = theirtag; 11065 ttag = p->tag; 11066 } 11067 11068 ast_copy_string(from, of, sizeof(from)); 11069 of = get_in_brackets(from); 11070 ast_string_field_set(p, from, of); 11071 if (!strncasecmp(of, "sip:", 4)) 11072 of += 4; 11073 else if (!strncasecmp(of, "sips:", 5)) 11074 of += 5; 11075 else 11076 ast_log(LOG_NOTICE, "From address missing 'sip(s):', using it anyway\n"); 11077 /* Get just the username part */ 11078 if ((c = strchr(dest, '@'))) 11079 c = NULL; 11080 else if ((c = strchr(of, '@'))) 11081 *c++ = '\0'; 11082 if (c) 11083 snprintf(referto, sizeof(referto), "<sip:%s@%s>", dest, c); 11084 else 11085 snprintf(referto, sizeof(referto), "<sip:%s>", dest); 11086 11087 /* save in case we get 407 challenge */ 11088 sip_refer_allocate(p); 11089 ast_copy_string(p->refer->refer_to, referto, sizeof(p->refer->refer_to)); 11090 ast_copy_string(p->refer->referred_by, p->our_contact, sizeof(p->refer->referred_by)); 11091 p->refer->status = REFER_SENT; /* Set refer status */ 11092 11093 reqprep(&req, p, SIP_REFER, 0, 1); 11094 11095 add_header(&req, "Refer-To", referto); 11096 add_header(&req, "Allow", ALLOWED_METHODS); 11097 add_header(&req, "Supported", SUPPORTED_EXTENSIONS); 11098 if (!ast_strlen_zero(p->our_contact)) 11099 add_header(&req, "Referred-By", p->our_contact); 11100 11101 return send_request(p, &req, XMIT_RELIABLE, p->ocseq); 11102 11103 /* We should propably wait for a NOTIFY here until we ack the transfer */ 11104 /* Maybe fork a new thread and wait for a STATUS of REFER_200OK on the refer status before returning to app_transfer */ 11105 11106 /*! \todo In theory, we should hang around and wait for a reply, before 11107 returning to the dial plan here. Don't know really how that would 11108 affect the transfer() app or the pbx, but, well, to make this 11109 useful we should have a STATUS code on transfer(). 11110 */ 11111 }
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 10773 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_peer::auth, 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, FALSE, find_peer(), FINDPEERS, sip_pvt::flags, sip_pvt::fromdomain, sip_peer::fromdomain, sip_peer::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_registry::nonce, sip_registry::noncecount, sip_pvt::noncecount, obproxy_get(), sip_pvt::ocseq, sip_registry::ocseq, sip_registry::opaque, sip_pvt::our_contact, sip_pvt::ourip, sip_pvt::peerauth, sip_registry::peername, sip_socket::port, sip_registry::portno, sip_registry::qop, sip_registry::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(), set_socket_transport(), 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_peer::tohost, sip_registry::transport, TRUE, unref_peer(), sip_registry::us, sip_peer::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().
10774 { 10775 struct sip_request req; 10776 char from[256]; 10777 char to[256]; 10778 char tmp[80]; 10779 char addr[80]; 10780 struct sip_pvt *p; 10781 struct sip_peer *peer = NULL; 10782 int res; 10783 char *fromdomain; 10784 10785 /* exit if we are already in process with this registrar ?*/ 10786 if (r == NULL || ((auth == NULL) && (r->regstate == REG_STATE_REGSENT || r->regstate == REG_STATE_AUTHSENT))) { 10787 if (r) { 10788 ast_log(LOG_NOTICE, "Strange, trying to register %s@%s when registration already pending\n", r->username, r->hostname); 10789 } 10790 return 0; 10791 } 10792 10793 if (r->dnsmgr == NULL) { 10794 char transport[MAXHOSTNAMELEN]; 10795 peer = find_peer(r->hostname, NULL, TRUE, FINDPEERS, FALSE, 0); 10796 snprintf(transport, sizeof(transport), "_sip._%s", get_transport(r->transport)); /* have to use static get_transport function */ 10797 ast_dnsmgr_lookup(peer ? peer->tohost : r->hostname, &r->us, &r->dnsmgr, global_srvlookup ? transport : NULL); 10798 if (peer) { 10799 peer = unref_peer(peer, "removing peer ref for dnsmgr_lookup"); 10800 } 10801 } 10802 10803 if (r->call) { /* We have a registration */ 10804 if (!auth) { 10805 ast_log(LOG_WARNING, "Already have a REGISTER going on to %s@%s?? \n", r->username, r->hostname); 10806 return 0; 10807 } else { 10808 p = dialog_ref(r->call, "getting a copy of the r->call dialog in transmit_register"); 10809 make_our_tag(p->tag, sizeof(p->tag)); /* create a new local tag for every register attempt */ 10810 ast_string_field_set(p, theirtag, NULL); /* forget their old tag, so we don't match tags when getting response */ 10811 } 10812 } else { 10813 /* Build callid for registration if we haven't registered before */ 10814 if (!r->callid_valid) { 10815 build_callid_registry(r, internip.sin_addr, default_fromdomain); 10816 r->callid_valid = TRUE; 10817 } 10818 /* Allocate SIP dialog for registration */ 10819 if (!(p = sip_alloc( r->callid, NULL, 0, SIP_REGISTER, NULL))) { 10820 ast_log(LOG_WARNING, "Unable to allocate registration transaction (memory or socket error)\n"); 10821 return 0; 10822 } 10823 10824 if (p->do_history) 10825 append_history(p, "RegistryInit", "Account: %s@%s", r->username, r->hostname); 10826 10827 if (!ast_strlen_zero(r->peername)) { 10828 if (!(peer = find_peer(r->peername, NULL, 1, FINDPEERS, FALSE, 0))) { 10829 ast_log(LOG_WARNING, "Could not find peer %s in transmit_register\n", r->peername); 10830 } else { 10831 p->peerauth = peer->auth; 10832 } 10833 } 10834 ref_proxy(p, obproxy_get(p, peer)); /* it is ok to pass a NULL peer into obproxy_get() */ 10835 if (peer) { 10836 unref_peer(peer, "transmit_registration: from find_peer operation"); 10837 } 10838 /* Use port number specified if no SRV record was found */ 10839 if (!r->us.sin_port && r->portno) 10840 r->us.sin_port = htons(r->portno); 10841 10842 /* Find address to hostname */ 10843 if (create_addr(p, r->hostname, &r->us, 0)) { 10844 /* we have what we hope is a temporary network error, 10845 * probably DNS. We need to reschedule a registration try */ 10846 dialog_unlink_all(p, TRUE, TRUE); 10847 p = dialog_unref(p, "unref dialog after unlink_all"); 10848 if (r->timeout > -1) { 10849 AST_SCHED_REPLACE_UNREF(r->timeout, sched, global_reg_timeout * 1000, sip_reg_timeout, r, 10850 registry_unref(_data, "del for REPLACE of registry ptr"), 10851 registry_unref(r, "object ptr dec when SCHED_REPLACE add failed"), 10852 registry_addref(r,"add for REPLACE registry ptr")); 10853 ast_log(LOG_WARNING, "Still have a registration timeout for %s@%s (create_addr() error), %d\n", r->username, r->hostname, r->timeout); 10854 } else { 10855 r->timeout = ast_sched_add(sched, global_reg_timeout * 1000, sip_reg_timeout, registry_addref(r, "add for REPLACE registry ptr")); 10856 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); 10857 } 10858 r->regattempts++; 10859 return 0; 10860 } 10861 10862 /* Copy back Call-ID in case create_addr changed it */ 10863 ast_string_field_set(r, callid, p->callid); 10864 if (!r->dnsmgr && r->portno) { 10865 p->sa.sin_port = htons(r->portno); 10866 p->recv.sin_port = htons(r->portno); 10867 } else { /* Set registry port to the port set from the peer definition/srv or default */ 10868 r->portno = ntohs(p->sa.sin_port); 10869 } 10870 ast_set_flag(&p->flags[0], SIP_OUTGOING); /* Registration is outgoing call */ 10871 r->call = dialog_ref(p, "copying dialog into registry r->call"); /* Save pointer to SIP dialog */ 10872 p->registry = registry_addref(r, "transmit_register: addref to p->registry in transmit_register"); /* Add pointer to registry in packet */ 10873 if (!ast_strlen_zero(r->secret)) /* Secret (password) */ 10874 ast_string_field_set(p, peersecret, r->secret); 10875 if (!ast_strlen_zero(r->md5secret)) 10876 ast_string_field_set(p, peermd5secret, r->md5secret); 10877 /* User name in this realm 10878 - if authuser is set, use that, otherwise use username */ 10879 if (!ast_strlen_zero(r->authuser)) { 10880 ast_string_field_set(p, peername, r->authuser); 10881 ast_string_field_set(p, authname, r->authuser); 10882 } else if (!ast_strlen_zero(r->username)) { 10883 ast_string_field_set(p, peername, r->username); 10884 ast_string_field_set(p, authname, r->username); 10885 ast_string_field_set(p, fromuser, r->username); 10886 } 10887 if (!ast_strlen_zero(r->username)) 10888 ast_string_field_set(p, username, r->username); 10889 /* Save extension in packet */ 10890 if (!ast_strlen_zero(r->callback)) 10891 ast_string_field_set(p, exten, r->callback); 10892 10893 /* Set transport and port so the correct contact is built */ 10894 set_socket_transport(&p->socket, r->transport); 10895 if (r->transport == SIP_TRANSPORT_TLS || r->transport == SIP_TRANSPORT_TCP) { 10896 p->socket.port = sip_tcp_desc.local_address.sin_port; 10897 } 10898 10899 /* 10900 check which address we should use in our contact header 10901 based on whether the remote host is on the external or 10902 internal network so we can register through nat 10903 */ 10904 ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip, p); 10905 build_contact(p); 10906 } 10907 10908 /* set up a timeout */ 10909 if (auth == NULL) { 10910 if (r->timeout > -1) 10911 ast_log(LOG_WARNING, "Still have a registration timeout, #%d - deleting it\n", r->timeout); 10912 AST_SCHED_REPLACE_UNREF(r->timeout, sched, global_reg_timeout * 1000, sip_reg_timeout, r, 10913 registry_unref(_data,"reg ptr unrefed from del in SCHED_REPLACE"), 10914 registry_unref(r,"reg ptr unrefed from add failure in SCHED_REPLACE"), 10915 registry_addref(r,"reg ptr reffed from add in SCHED_REPLACE")); 10916 ast_debug(1, "Scheduled a registration timeout for %s id #%d \n", r->hostname, r->timeout); 10917 } 10918 10919 if ((fromdomain = strchr(r->username, '@'))) { 10920 /* the domain name is just behind '@' */ 10921 fromdomain++ ; 10922 /* We have a domain in the username for registration */ 10923 snprintf(from, sizeof(from), "<sip:%s>;tag=%s", r->username, p->tag); 10924 if (!ast_strlen_zero(p->theirtag)) 10925 snprintf(to, sizeof(to), "<sip:%s>;tag=%s", r->username, p->theirtag); 10926 else 10927 snprintf(to, sizeof(to), "<sip:%s>", r->username); 10928 10929 /* If the registration username contains '@', then the domain should be used as 10930 the equivalent of "fromdomain" for the registration */ 10931 if (ast_strlen_zero(p->fromdomain)) { 10932 ast_string_field_set(p, fromdomain, fromdomain); 10933 } 10934 } else { 10935 snprintf(from, sizeof(from), "<sip:%s@%s>;tag=%s", r->username, p->tohost, p->tag); 10936 if (!ast_strlen_zero(p->theirtag)) 10937 snprintf(to, sizeof(to), "<sip:%s@%s>;tag=%s", r->username, p->tohost, p->theirtag); 10938 else 10939 snprintf(to, sizeof(to), "<sip:%s@%s>", r->username, p->tohost); 10940 } 10941 10942 /* Fromdomain is what we are registering to, regardless of actual 10943 host name from SRV */ 10944 if (!ast_strlen_zero(p->fromdomain)) { 10945 if (r->portno && r->portno != STANDARD_SIP_PORT) 10946 snprintf(addr, sizeof(addr), "sip:%s:%d", p->fromdomain, r->portno); 10947 else 10948 snprintf(addr, sizeof(addr), "sip:%s", p->fromdomain); 10949 } else { 10950 if (r->portno && r->portno != STANDARD_SIP_PORT) 10951 snprintf(addr, sizeof(addr), "sip:%s:%d", r->hostname, r->portno); 10952 else 10953 snprintf(addr, sizeof(addr), "sip:%s", r->hostname); 10954 } 10955 ast_string_field_set(p, uri, addr); 10956 10957 p->branch ^= ast_random(); 10958 10959 init_req(&req, sipmethod, addr); 10960 10961 /* Add to CSEQ */ 10962 snprintf(tmp, sizeof(tmp), "%u %s", ++r->ocseq, sip_methods[sipmethod].text); 10963 p->ocseq = r->ocseq; 10964 10965 build_via(p); 10966 add_header(&req, "Via", p->via); 10967 add_header(&req, "Max-Forwards", DEFAULT_MAX_FORWARDS); 10968 add_header(&req, "From", from); 10969 add_header(&req, "To", to); 10970 add_header(&req, "Call-ID", p->callid); 10971 add_header(&req, "CSeq", tmp); 10972 if (!ast_strlen_zero(global_useragent)) 10973 add_header(&req, "User-Agent", global_useragent); 10974 10975 10976 if (auth) /* Add auth header */ 10977 add_header(&req, authheader, auth); 10978 else if (!ast_strlen_zero(r->nonce)) { 10979 char digest[1024]; 10980 10981 /* We have auth data to reuse, build a digest header. 10982 * Note, this is not always useful because some parties do not 10983 * like nonces to be reused (for good reasons!) so they will 10984 * challenge us anyways. 10985 */ 10986 if (sipdebug) 10987 ast_debug(1, " >>> Re-using Auth data for %s@%s\n", r->username, r->hostname); 10988 ast_string_field_set(p, realm, r->realm); 10989 ast_string_field_set(p, nonce, r->nonce); 10990 ast_string_field_set(p, domain, r->domain); 10991 ast_string_field_set(p, opaque, r->opaque); 10992 ast_string_field_set(p, qop, r->qop); 10993 p->noncecount = ++r->noncecount; 10994 10995 memset(digest, 0, sizeof(digest)); 10996 if(!build_reply_digest(p, sipmethod, digest, sizeof(digest))) 10997 add_header(&req, "Authorization", digest); 10998 else 10999 ast_log(LOG_NOTICE, "No authorization available for authentication of registration to %s@%s\n", r->username, r->hostname); 11000 11001 } 11002 11003 snprintf(tmp, sizeof(tmp), "%d", r->expiry); 11004 add_header(&req, "Expires", tmp); 11005 add_header(&req, "Contact", p->our_contact); 11006 add_header_contentLength(&req, 0); 11007 11008 initialize_initreq(p, &req); 11009 if (sip_debug_test_pvt(p)) { 11010 ast_verbose("REGISTER %d headers, %d lines\n", p->initreq.headers, p->initreq.lines); 11011 } 11012 r->regstate = auth ? REG_STATE_AUTHSENT : REG_STATE_REGSENT; 11013 r->regattempts++; /* Another attempt */ 11014 ast_debug(4, "REGISTER attempt %d to %s@%s\n", r->regattempts, r->username, r->hostname); 11015 res = send_request(p, &req, XMIT_CRITICAL, p->ocseq); 11016 dialog_unref(p, "p is finished here at the end of transmit_register"); 11017 return res; 11018 }
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 9865 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, sip_pvt::offered_media, 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(), interpret_t38_parameters(), proc_session_timer(), sip_sendhtml(), sip_set_rtp_peer(), and sip_set_udptl_peer().
09866 { 09867 struct sip_request req; 09868 09869 reqprep(&req, p, ast_test_flag(&p->flags[0], SIP_REINVITE_UPDATE) ? SIP_UPDATE : SIP_INVITE, 0, 1); 09870 09871 add_header(&req, "Allow", ALLOWED_METHODS); 09872 add_header(&req, "Supported", SUPPORTED_EXTENSIONS); 09873 if (sipdebug) { 09874 if (oldsdp == TRUE) 09875 add_header(&req, "X-asterisk-Info", "SIP re-invite (Session-Timers)"); 09876 else 09877 add_header(&req, "X-asterisk-Info", "SIP re-invite (External RTP bridge)"); 09878 } 09879 09880 if (p->do_history) 09881 append_history(p, "ReInv", "Re-invite sent"); 09882 memset(p->offered_media, 0, sizeof(p->offered_media)); 09883 09884 if (t38version) 09885 add_sdp(&req, p, oldsdp, FALSE, TRUE); 09886 else 09887 add_sdp(&req, p, oldsdp, TRUE, FALSE); 09888 09889 /* Use this as the basis */ 09890 initialize_initreq(p, &req); 09891 p->lastinvite = p->ocseq; 09892 ast_set_flag(&p->flags[0], SIP_OUTGOING); /* Change direction of this dialog */ 09893 09894 return send_request(p, &req, XMIT_CRITICAL, p->ocseq); 09895 }
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 11137 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().
11138 { 11139 struct sip_request resp; 11140 11141 if (sipmethod == SIP_ACK) 11142 p->invitestate = INV_CONFIRMED; 11143 11144 reqprep(&resp, p, sipmethod, seqno, newbranch); 11145 if (sipmethod == SIP_CANCEL && p->answered_elsewhere) 11146 add_header(&resp, "Reason", "SIP;cause=200;text=\"Call completed elsewhere\""); 11147 11148 add_header_contentLength(&resp, 0); 11149 return send_request(p, &resp, reliable, seqno ? seqno : p->ocseq); 11150 }
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 11168 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().
11169 { 11170 struct sip_request resp; 11171 11172 reqprep(&resp, p, sipmethod, seqno, newbranch); 11173 if (!ast_strlen_zero(p->realm)) { 11174 char digest[1024]; 11175 11176 memset(digest, 0, sizeof(digest)); 11177 if(!build_reply_digest(p, sipmethod, digest, sizeof(digest))) { 11178 char *dummy, *response; 11179 enum sip_auth_type code = p->options ? p->options->auth_type : PROXY_AUTH; /* XXX force 407 if unknown */ 11180 auth_headers(code, &dummy, &response); 11181 add_header(&resp, response, digest); 11182 } else 11183 ast_log(LOG_WARNING, "No authentication available for call %s\n", p->callid); 11184 } 11185 /* If we are hanging up and know a cause for that, send it in clear text to make 11186 debugging easier. */ 11187 if (sipmethod == SIP_BYE) { 11188 char buf[10]; 11189 11190 add_header(&resp, "X-Asterisk-HangupCause", ast_cause2str(p->hangupcause)); 11191 snprintf(buf, sizeof(buf), "%d", p->hangupcause); 11192 add_header(&resp, "X-Asterisk-HangupCauseCode", buf); 11193 } 11194 11195 add_header_contentLength(&resp, 0); 11196 return send_request(p, &resp, reliable, seqno ? seqno : p->ocseq); 11197 }
static int transmit_response | ( | struct sip_pvt * | p, | |
const char * | msg, | |||
const struct sip_request * | req | |||
) | [static] |
Transmit response, no retransmits.
Definition at line 9020 of file chan_sip.c.
References __transmit_response(), and XMIT_UNRELIABLE.
09021 { 09022 return __transmit_response(p, msg, req, XMIT_UNRELIABLE); 09023 }
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 9056 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(), interpret_t38_parameters(), sip_hangup(), sip_indicate(), sip_sipredirect(), and sip_t38_abort().
09057 { 09058 return __transmit_response(p, msg, req, req->ignore ? XMIT_UNRELIABLE : XMIT_CRITICAL); 09059 }
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 8968 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().
08969 { 08970 struct sip_pvt *p = NULL; 08971 08972 if (!(p = ast_threadstorage_get(&ts_temp_pvt, sizeof(*p)))) { 08973 ast_log(LOG_ERROR, "Failed to get temporary pvt\n"); 08974 return -1; 08975 } 08976 08977 /* XXX the structure may be dirty from previous usage. 08978 * Here we should state clearly how we should reinitialize it 08979 * before using it. 08980 * E.g. certainly the threadstorage should be left alone, 08981 * but other thihngs such as flags etc. maybe need cleanup ? 08982 */ 08983 08984 /* Initialize the bare minimum */ 08985 p->method = intended_method; 08986 08987 if (!sin) 08988 p->ourip = internip; 08989 else { 08990 p->sa = *sin; 08991 ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip, p); 08992 } 08993 08994 p->branch = ast_random(); 08995 make_our_tag(p->tag, sizeof(p->tag)); 08996 p->ocseq = INITIAL_CSEQ; 08997 08998 if (useglobal_nat && sin) { 08999 ast_copy_flags(&p->flags[0], &global_flags[0], SIP_NAT); 09000 p->recv = *sin; 09001 do_setnat(p, ast_test_flag(&p->flags[0], SIP_NAT) & SIP_NAT_ROUTE); 09002 } 09003 09004 ast_string_field_set(p, fromdomain, default_fromdomain); 09005 build_via(p); 09006 ast_string_field_set(p, callid, callid); 09007 09008 copy_socket_data(&p->socket, &req->socket); 09009 09010 /* Use this temporary pvt structure to send the message */ 09011 __transmit_response(p, msg, req, XMIT_UNRELIABLE); 09012 09013 /* Free the string fields, but not the pool space */ 09014 ast_string_field_init(p, 0); 09015 09016 return 0; 09017 }
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 9084 of file chan_sip.c.
References add_header(), add_header_contentLength(), respprep(), and send_response().
Referenced by handle_incoming(), and handle_request_options().
09085 { 09086 struct sip_request resp; 09087 respprep(&resp, p, msg, req); 09088 add_header(&resp, "Accept", "application/sdp"); 09089 add_header_contentLength(&resp, 0); 09090 return send_response(p, &resp, reliable, 0); 09091 }
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 9094 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().
09095 { 09096 struct sip_request resp; 09097 char tmp[512]; 09098 int seqno = 0; 09099 09100 if (reliable && (sscanf(get_header(req, "CSeq"), "%30d ", &seqno) != 1)) { 09101 ast_log(LOG_WARNING, "Unable to determine sequence number from '%s'\n", get_header(req, "CSeq")); 09102 return -1; 09103 } 09104 /* Stale means that they sent us correct authentication, but 09105 based it on an old challenge (nonce) */ 09106 snprintf(tmp, sizeof(tmp), "Digest algorithm=MD5, realm=\"%s\", nonce=\"%s\"%s", global_realm, randdata, stale ? ", stale=true" : ""); 09107 respprep(&resp, p, msg, req); 09108 add_header(&resp, header, tmp); 09109 add_header_contentLength(&resp, 0); 09110 append_history(p, "AuthChal", "Auth challenge sent for %s - nc %d", p->username, p->noncecount); 09111 return send_response(p, &resp, reliable, seqno); 09112 }
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 9074 of file chan_sip.c.
References add_header_contentLength(), append_date(), respprep(), send_response(), and XMIT_UNRELIABLE.
Referenced by register_verify().
09075 { 09076 struct sip_request resp; 09077 respprep(&resp, p, msg, req); 09078 append_date(&resp); 09079 add_header_contentLength(&resp, 0); 09080 return send_response(p, &resp, XMIT_UNRELIABLE, 0); 09081 }
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 9037 of file chan_sip.c.
References add_header(), add_header_contentLength(), append_date(), respprep(), send_response(), and XMIT_UNRELIABLE.
Referenced by handle_request_invite().
09038 { 09039 struct sip_request resp; 09040 char minse_str[20]; 09041 09042 respprep(&resp, p, msg, req); 09043 append_date(&resp); 09044 09045 snprintf(minse_str, sizeof(minse_str), "%d", minse_int); 09046 add_header(&resp, "Min-SE", minse_str); 09047 09048 add_header_contentLength(&resp, 0); 09049 return send_response(p, &resp, XMIT_UNRELIABLE, 0); 09050 }
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 9782 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, TRUE, and try_suggested_sip_codec().
Referenced by handle_invite_replaces(), handle_request_invite(), send_provisional_keepalive_full(), sip_answer(), and transmit_provisional_response().
09783 { 09784 struct sip_request resp; 09785 int seqno; 09786 if (sscanf(get_header(req, "CSeq"), "%30d ", &seqno) != 1) { 09787 ast_log(LOG_WARNING, "Unable to get seqno from '%s'\n", get_header(req, "CSeq")); 09788 return -1; 09789 } 09790 respprep(&resp, p, msg, req); 09791 if (p->rtp) { 09792 if (!p->autoframing && !ast_test_flag(&p->flags[0], SIP_OUTGOING)) { 09793 ast_debug(1, "Setting framing from config on incoming call\n"); 09794 ast_rtp_codec_setpref(p->rtp, &p->prefs); 09795 } 09796 try_suggested_sip_codec(p); 09797 if (p->t38.state == T38_ENABLED) { 09798 add_sdp(&resp, p, oldsdp, TRUE, TRUE); 09799 } else { 09800 add_sdp(&resp, p, oldsdp, TRUE, FALSE); 09801 } 09802 } else 09803 ast_log(LOG_ERROR, "Can't add SDP to response, since we have no RTP session allocated. Call-ID %s\n", p->callid); 09804 if (reliable && !p->pendinginvite) 09805 p->pendinginvite = seqno; /* Buggy clients sends ACK on RINGING too */ 09806 return send_response(p, &resp, reliable, seqno); 09807 }
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 9736 of file chan_sip.c.
References add_sdp(), ast_log(), 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 interpret_t38_parameters().
09737 { 09738 struct sip_request resp; 09739 int seqno; 09740 09741 if (sscanf(get_header(req, "CSeq"), "%30d ", &seqno) != 1) { 09742 ast_log(LOG_WARNING, "Unable to get seqno from '%s'\n", get_header(req, "CSeq")); 09743 return -1; 09744 } 09745 respprep(&resp, p, msg, req); 09746 if (p->udptl) { 09747 add_sdp(&resp, p, 0, 0, 1); 09748 } else 09749 ast_log(LOG_ERROR, "Can't add SDP to response, since we have no UDPTL session allocated. Call-ID %s\n", p->callid); 09750 if (retrans && !p->pendinginvite) 09751 p->pendinginvite = seqno; /* Buggy clients sends ACK on RINGING too */ 09752 return send_response(p, &resp, retrans, seqno); 09753 }
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 9026 of file chan_sip.c.
References add_header(), add_header_contentLength(), append_date(), respprep(), send_response(), and XMIT_UNRELIABLE.
Referenced by handle_request_invite().
09027 { 09028 struct sip_request resp; 09029 respprep(&resp, p, msg, req); 09030 append_date(&resp); 09031 add_header(&resp, "Unsupported", unsupported); 09032 add_header_contentLength(&resp, 0); 09033 return send_response(p, &resp, XMIT_UNRELIABLE, 0); 09034 }
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 10308 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().
10309 { 10310 struct ast_str *tmp = ast_str_alloca(4000); 10311 char from[256], to[256]; 10312 char *c, *mfrom, *mto; 10313 struct sip_request req; 10314 char hint[AST_MAX_EXTENSION]; 10315 char *statestring = "terminated"; 10316 const struct cfsubscription_types *subscriptiontype; 10317 enum state { NOTIFY_OPEN, NOTIFY_INUSE, NOTIFY_CLOSED } local_state = NOTIFY_OPEN; 10318 char *pidfstate = "--"; 10319 char *pidfnote= "Ready"; 10320 10321 memset(from, 0, sizeof(from)); 10322 memset(to, 0, sizeof(to)); 10323 10324 switch (state) { 10325 case (AST_EXTENSION_RINGING | AST_EXTENSION_INUSE): 10326 statestring = (global_notifyringing) ? "early" : "confirmed"; 10327 local_state = NOTIFY_INUSE; 10328 pidfstate = "busy"; 10329 pidfnote = "Ringing"; 10330 break; 10331 case AST_EXTENSION_RINGING: 10332 statestring = "early"; 10333 local_state = NOTIFY_INUSE; 10334 pidfstate = "busy"; 10335 pidfnote = "Ringing"; 10336 break; 10337 case AST_EXTENSION_INUSE: 10338 statestring = "confirmed"; 10339 local_state = NOTIFY_INUSE; 10340 pidfstate = "busy"; 10341 pidfnote = "On the phone"; 10342 break; 10343 case AST_EXTENSION_BUSY: 10344 statestring = "confirmed"; 10345 local_state = NOTIFY_CLOSED; 10346 pidfstate = "busy"; 10347 pidfnote = "On the phone"; 10348 break; 10349 case AST_EXTENSION_UNAVAILABLE: 10350 statestring = "terminated"; 10351 local_state = NOTIFY_CLOSED; 10352 pidfstate = "away"; 10353 pidfnote = "Unavailable"; 10354 break; 10355 case AST_EXTENSION_ONHOLD: 10356 statestring = "confirmed"; 10357 local_state = NOTIFY_CLOSED; 10358 pidfstate = "busy"; 10359 pidfnote = "On hold"; 10360 break; 10361 case AST_EXTENSION_NOT_INUSE: 10362 default: 10363 /* Default setting */ 10364 break; 10365 } 10366 10367 subscriptiontype = find_subscription_type(p->subscribed); 10368 10369 /* Check which device/devices we are watching and if they are registered */ 10370 if (ast_get_hint(hint, sizeof(hint), NULL, 0, NULL, p->context, p->exten)) { 10371 char *hint2 = hint, *individual_hint = NULL; 10372 int hint_count = 0, unavailable_count = 0; 10373 10374 while ((individual_hint = strsep(&hint2, "&"))) { 10375 hint_count++; 10376 10377 if (ast_device_state(individual_hint) == AST_DEVICE_UNAVAILABLE) 10378 unavailable_count++; 10379 } 10380 10381 /* If none of the hinted devices are registered, we will 10382 * override notification and show no availability. 10383 */ 10384 if (hint_count > 0 && hint_count == unavailable_count) { 10385 local_state = NOTIFY_CLOSED; 10386 pidfstate = "away"; 10387 pidfnote = "Not online"; 10388 } 10389 } 10390 10391 ast_copy_string(from, get_header(&p->initreq, "From"), sizeof(from)); 10392 c = get_in_brackets(from); 10393 if (strncasecmp(c, "sip:", 4) && strncasecmp(c, "sips:", 5)) { 10394 ast_log(LOG_WARNING, "Huh? Not a SIP header (%s)?\n", c); 10395 return -1; 10396 } 10397 10398 mfrom = remove_uri_parameters(c); 10399 10400 ast_copy_string(to, get_header(&p->initreq, "To"), sizeof(to)); 10401 c = get_in_brackets(to); 10402 if (strncasecmp(c, "sip:", 4) && strncasecmp(c, "sips:", 5)) { 10403 ast_log(LOG_WARNING, "Huh? Not a SIP header (%s)?\n", c); 10404 return -1; 10405 } 10406 mto = remove_uri_parameters(c); 10407 10408 reqprep(&req, p, SIP_NOTIFY, 0, 1); 10409 10410 10411 add_header(&req, "Event", subscriptiontype->event); 10412 add_header(&req, "Content-Type", subscriptiontype->mediatype); 10413 switch(state) { 10414 case AST_EXTENSION_DEACTIVATED: 10415 if (timeout) 10416 add_header(&req, "Subscription-State", "terminated;reason=timeout"); 10417 else { 10418 add_header(&req, "Subscription-State", "terminated;reason=probation"); 10419 add_header(&req, "Retry-After", "60"); 10420 } 10421 break; 10422 case AST_EXTENSION_REMOVED: 10423 add_header(&req, "Subscription-State", "terminated;reason=noresource"); 10424 break; 10425 default: 10426 if (p->expiry) 10427 add_header(&req, "Subscription-State", "active"); 10428 else /* Expired */ 10429 add_header(&req, "Subscription-State", "terminated;reason=timeout"); 10430 } 10431 switch (p->subscribed) { 10432 case XPIDF_XML: 10433 case CPIM_PIDF_XML: 10434 ast_str_append(&tmp, 0, 10435 "<?xml version=\"1.0\"?>\n" 10436 "<!DOCTYPE presence PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n" 10437 "<presence>\n"); 10438 ast_str_append(&tmp, 0, "<presentity uri=\"%s;method=SUBSCRIBE\" />\n", mfrom); 10439 ast_str_append(&tmp, 0, "<atom id=\"%s\">\n", p->exten); 10440 ast_str_append(&tmp, 0, "<address uri=\"%s;user=ip\" priority=\"0.800000\">\n", mto); 10441 ast_str_append(&tmp, 0, "<status status=\"%s\" />\n", (local_state == NOTIFY_OPEN) ? "open" : (local_state == NOTIFY_INUSE) ? "inuse" : "closed"); 10442 ast_str_append(&tmp, 0, "<msnsubstatus substatus=\"%s\" />\n", (local_state == NOTIFY_OPEN) ? "online" : (local_state == NOTIFY_INUSE) ? "onthephone" : "offline"); 10443 ast_str_append(&tmp, 0, "</address>\n</atom>\n</presence>\n"); 10444 break; 10445 case PIDF_XML: /* Eyebeam supports this format */ 10446 ast_str_append(&tmp, 0, 10447 "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n" 10448 "<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); 10449 ast_str_append(&tmp, 0, "<pp:person><status>\n"); 10450 if (pidfstate[0] != '-') 10451 ast_str_append(&tmp, 0, "<ep:activities><ep:%s/></ep:activities>\n", pidfstate); 10452 ast_str_append(&tmp, 0, "</status></pp:person>\n"); 10453 ast_str_append(&tmp, 0, "<note>%s</note>\n", pidfnote); /* Note */ 10454 ast_str_append(&tmp, 0, "<tuple id=\"%s\">\n", p->exten); /* Tuple start */ 10455 ast_str_append(&tmp, 0, "<contact priority=\"1\">%s</contact>\n", mto); 10456 if (pidfstate[0] == 'b') /* Busy? Still open ... */ 10457 ast_str_append(&tmp, 0, "<status><basic>open</basic></status>\n"); 10458 else 10459 ast_str_append(&tmp, 0, "<status><basic>%s</basic></status>\n", (local_state != NOTIFY_CLOSED) ? "open" : "closed"); 10460 ast_str_append(&tmp, 0, "</tuple>\n</presence>\n"); 10461 break; 10462 case DIALOG_INFO_XML: /* SNOM subscribes in this format */ 10463 ast_str_append(&tmp, 0, "<?xml version=\"1.0\"?>\n"); 10464 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); 10465 if ((state & AST_EXTENSION_RINGING) && global_notifyringing) 10466 ast_str_append(&tmp, 0, "<dialog id=\"%s\" direction=\"recipient\">\n", p->exten); 10467 else 10468 ast_str_append(&tmp, 0, "<dialog id=\"%s\">\n", p->exten); 10469 ast_str_append(&tmp, 0, "<state>%s</state>\n", statestring); 10470 if (state == AST_EXTENSION_ONHOLD) { 10471 ast_str_append(&tmp, 0, "<local>\n<target uri=\"%s\">\n" 10472 "<param pname=\"+sip.rendering\" pvalue=\"no\"/>\n" 10473 "</target>\n</local>\n", mto); 10474 } 10475 ast_str_append(&tmp, 0, "</dialog>\n</dialog-info>\n"); 10476 break; 10477 case NONE: 10478 default: 10479 break; 10480 } 10481 10482 add_header_contentLength(&req, tmp->used); 10483 add_line(&req, tmp->str); 10484 10485 p->pendinginvite = p->ocseq; /* Remember that we have a pending NOTIFY in order not to confuse the NOTIFY subsystem */ 10486 10487 return send_request(p, &req, XMIT_RELIABLE, p->ocseq); 10488 }
static void try_suggested_sip_codec | ( | struct sip_pvt * | p | ) | [static] |
Try setting codec suggested by the SIP_CODEC channel variable.
Definition at line 5755 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().
05756 { 05757 int fmt; 05758 const char *codec; 05759 05760 codec = pbx_builtin_getvar_helper(p->owner, "SIP_CODEC"); 05761 if (!codec) 05762 return; 05763 05764 fmt = ast_getformatbyname(codec); 05765 if (fmt) { 05766 ast_log(LOG_NOTICE, "Changing codec to '%s' for this call because of ${SIP_CODEC} variable\n", codec); 05767 if (p->jointcapability & fmt) { 05768 p->jointcapability &= fmt; 05769 p->capability &= fmt; 05770 } else 05771 ast_log(LOG_NOTICE, "Ignoring ${SIP_CODEC} variable because it is not shared by both ends.\n"); 05772 } else 05773 ast_log(LOG_NOTICE, "Ignoring ${SIP_CODEC} variable because of unrecognized/not configured codec (check allow/disallow in sip.conf): %s\n", codec); 05774 return; 05775 }
static int unload_module | ( | void | ) | [static] |
PBX unload module API.
Definition at line 24777 of file chan_sip.c.
References ao2_iterator_destroy(), 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_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, global_contact_ha, localaddr, ast_tcptls_session_args::master, monlock, sip_pvt::owner, peers, 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, sip_threadinfo::stop, thread, sip_threadinfo::threadid, threadt, and TRUE.
24778 { 24779 struct sip_pvt *p; 24780 struct sip_threadinfo *th; 24781 struct ast_context *con; 24782 struct ao2_iterator i; 24783 24784 ast_sched_dump(sched); 24785 24786 /* First, take us out of the channel type list */ 24787 ast_channel_unregister(&sip_tech); 24788 24789 /* Unregister dial plan functions */ 24790 ast_custom_function_unregister(&sipchaninfo_function); 24791 ast_custom_function_unregister(&sippeer_function); 24792 ast_custom_function_unregister(&sip_header_function); 24793 ast_custom_function_unregister(&checksipdomain_function); 24794 24795 /* Unregister dial plan applications */ 24796 ast_unregister_application(app_dtmfmode); 24797 ast_unregister_application(app_sipaddheader); 24798 24799 /* Unregister CLI commands */ 24800 ast_cli_unregister_multiple(cli_sip, sizeof(cli_sip) / sizeof(struct ast_cli_entry)); 24801 24802 /* Disconnect from the RTP subsystem */ 24803 ast_rtp_proto_unregister(&sip_rtp); 24804 24805 /* Disconnect from UDPTL */ 24806 ast_udptl_proto_unregister(&sip_udptl); 24807 24808 /* Unregister AMI actions */ 24809 ast_manager_unregister("SIPpeers"); 24810 ast_manager_unregister("SIPshowpeer"); 24811 ast_manager_unregister("SIPqualifypeer"); 24812 ast_manager_unregister("SIPshowregistry"); 24813 ast_manager_unregister("SIPnotify"); 24814 24815 /* Kill TCP/TLS server threads */ 24816 if (sip_tcp_desc.master) 24817 ast_tcptls_server_stop(&sip_tcp_desc); 24818 if (sip_tls_desc.master) 24819 ast_tcptls_server_stop(&sip_tls_desc); 24820 24821 /* Kill all existing TCP/TLS threads */ 24822 i = ao2_iterator_init(threadt, 0); 24823 while ((th = ao2_t_iterator_next(&i, "iterate through tcp threads for 'sip show tcp'"))) { 24824 pthread_t thread = th->threadid; 24825 th->stop = 1; 24826 pthread_kill(thread, SIGURG); 24827 pthread_join(thread, NULL); 24828 ao2_t_ref(th, -1, "decrement ref from iterator"); 24829 } 24830 ao2_iterator_destroy(&i); 24831 24832 /* Hangup all dialogs if they have an owner */ 24833 i = ao2_iterator_init(dialogs, 0); 24834 while ((p = ao2_t_iterator_next(&i, "iterate thru dialogs"))) { 24835 if (p->owner) 24836 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD); 24837 ao2_t_ref(p, -1, "toss dialog ptr from iterator_next"); 24838 } 24839 ao2_iterator_destroy(&i); 24840 24841 ast_mutex_lock(&monlock); 24842 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) { 24843 pthread_cancel(monitor_thread); 24844 pthread_kill(monitor_thread, SIGURG); 24845 pthread_join(monitor_thread, NULL); 24846 } 24847 monitor_thread = AST_PTHREADT_STOP; 24848 ast_mutex_unlock(&monlock); 24849 24850 /* Destroy all the dialogs and free their memory */ 24851 i = ao2_iterator_init(dialogs, 0); 24852 while ((p = ao2_t_iterator_next(&i, "iterate thru dialogs"))) { 24853 dialog_unlink_all(p, TRUE, TRUE); 24854 ao2_t_ref(p, -1, "throw away iterator result"); 24855 } 24856 ao2_iterator_destroy(&i); 24857 24858 /* Free memory for local network address mask */ 24859 ast_free_ha(localaddr); 24860 24861 clear_realm_authentication(authl); 24862 24863 24864 if (default_tls_cfg.certfile) 24865 ast_free(default_tls_cfg.certfile); 24866 if (default_tls_cfg.cipher) 24867 ast_free(default_tls_cfg.cipher); 24868 if (default_tls_cfg.cafile) 24869 ast_free(default_tls_cfg.cafile); 24870 if (default_tls_cfg.capath) 24871 ast_free(default_tls_cfg.capath); 24872 24873 ASTOBJ_CONTAINER_DESTROYALL(®l, sip_registry_destroy); 24874 ASTOBJ_CONTAINER_DESTROY(®l); 24875 24876 ao2_t_ref(peers, -1, "unref the peers table"); 24877 ao2_t_ref(peers_by_ip, -1, "unref the peers_by_ip table"); 24878 ao2_t_ref(dialogs, -1, "unref the dialogs table"); 24879 ao2_t_ref(threadt, -1, "unref the thread table"); 24880 24881 clear_sip_domains(); 24882 ast_free_ha(global_contact_ha); 24883 close(sipsock); 24884 sched_context_destroy(sched); 24885 con = ast_context_find(used_context); 24886 if (con) 24887 ast_context_destroy(con, "SIP"); 24888 ast_unload_realtime("sipregs"); 24889 ast_unload_realtime("sippeers"); 24890 24891 return 0; 24892 }
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 2749 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(), transmit_register(), and update_call_counter().
02750 { 02751 ao2_t_ref(peer, -1, tag); 02752 return NULL; 02753 }
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 5230 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().
05231 { 05232 char name[256]; 05233 int *inuse = NULL, *call_limit = NULL, *inringing = NULL; 05234 int outgoing = fup->outgoing_call; 05235 struct sip_peer *p = NULL; 05236 05237 ast_debug(3, "Updating call counter for %s call\n", outgoing ? "outgoing" : "incoming"); 05238 05239 05240 /* Test if we need to check call limits, in order to avoid 05241 realtime lookups if we do not need it */ 05242 if (!ast_test_flag(&fup->flags[0], SIP_CALL_LIMIT) && !ast_test_flag(&fup->flags[1], SIP_PAGE2_CALL_ONHOLD)) 05243 return 0; 05244 05245 ast_copy_string(name, fup->username, sizeof(name)); 05246 05247 /* Check the list of devices */ 05248 if ((p = find_peer(ast_strlen_zero(fup->peername) ? name : fup->peername, NULL, TRUE, FINDALLDEVICES, FALSE, 0))) { /* Try to find peer */ 05249 inuse = &p->inUse; 05250 call_limit = &p->call_limit; 05251 inringing = &p->inRinging; 05252 ast_copy_string(name, fup->peername, sizeof(name)); 05253 } 05254 if (!p) { 05255 ast_debug(2, "%s is not a local device, no call limit\n", name); 05256 return 0; 05257 } 05258 05259 switch(event) { 05260 /* incoming and outgoing affects the inUse counter */ 05261 case DEC_CALL_LIMIT: 05262 /* Decrement inuse count if applicable */ 05263 if (inuse) { 05264 sip_pvt_lock(fup); 05265 ao2_lock(p); 05266 if (*inuse > 0) { 05267 if (ast_test_flag(&fup->flags[0], SIP_INC_COUNT)) { 05268 (*inuse)--; 05269 ast_clear_flag(&fup->flags[0], SIP_INC_COUNT); 05270 } 05271 } else { 05272 *inuse = 0; 05273 } 05274 ao2_unlock(p); 05275 sip_pvt_unlock(fup); 05276 } 05277 05278 /* Decrement ringing count if applicable */ 05279 if (inringing) { 05280 sip_pvt_lock(fup); 05281 ao2_lock(p); 05282 if (*inringing > 0) { 05283 if (ast_test_flag(&fup->flags[0], SIP_INC_RINGING)) { 05284 (*inringing)--; 05285 ast_clear_flag(&fup->flags[0], SIP_INC_RINGING); 05286 } 05287 } else { 05288 *inringing = 0; 05289 } 05290 ao2_unlock(p); 05291 sip_pvt_unlock(fup); 05292 } 05293 05294 /* Decrement onhold count if applicable */ 05295 sip_pvt_lock(fup); 05296 ao2_lock(p); 05297 if (ast_test_flag(&fup->flags[1], SIP_PAGE2_CALL_ONHOLD) && global_notifyhold) { 05298 ast_clear_flag(&fup->flags[1], SIP_PAGE2_CALL_ONHOLD); 05299 ao2_unlock(p); 05300 sip_pvt_unlock(fup); 05301 sip_peer_hold(fup, FALSE); 05302 } else { 05303 ao2_unlock(p); 05304 sip_pvt_unlock(fup); 05305 } 05306 if (sipdebug) 05307 ast_debug(2, "Call %s %s '%s' removed from call limit %d\n", outgoing ? "to" : "from", "peer", name, *call_limit); 05308 break; 05309 05310 case INC_CALL_RINGING: 05311 case INC_CALL_LIMIT: 05312 /* If call limit is active and we have reached the limit, reject the call */ 05313 if (*call_limit > 0 ) { 05314 if (*inuse >= *call_limit) { 05315 ast_log(LOG_ERROR, "Call %s %s '%s' rejected due to usage limit of %d\n", outgoing ? "to" : "from", "peer", name, *call_limit); 05316 unref_peer(p, "update_call_counter: unref peer p, call limit exceeded"); 05317 return -1; 05318 } 05319 } 05320 if (inringing && (event == INC_CALL_RINGING)) { 05321 sip_pvt_lock(fup); 05322 ao2_lock(p); 05323 if (!ast_test_flag(&fup->flags[0], SIP_INC_RINGING)) { 05324 (*inringing)++; 05325 ast_set_flag(&fup->flags[0], SIP_INC_RINGING); 05326 } 05327 ao2_unlock(p); 05328 sip_pvt_unlock(fup); 05329 } 05330 if (inuse) { 05331 sip_pvt_lock(fup); 05332 ao2_lock(p); 05333 if (!ast_test_flag(&fup->flags[0], SIP_INC_COUNT)) { 05334 (*inuse)++; 05335 ast_set_flag(&fup->flags[0], SIP_INC_COUNT); 05336 } 05337 ao2_unlock(p); 05338 sip_pvt_unlock(fup); 05339 } 05340 if (sipdebug) { 05341 ast_debug(2, "Call %s %s '%s' is %d out of %d\n", outgoing ? "to" : "from", "peer", name, *inuse, *call_limit); 05342 } 05343 break; 05344 05345 case DEC_CALL_RINGING: 05346 if (inringing) { 05347 sip_pvt_lock(fup); 05348 ao2_lock(p); 05349 if (ast_test_flag(&fup->flags[0], SIP_INC_RINGING)) { 05350 if (*inringing > 0) { 05351 (*inringing)--; 05352 } 05353 ast_clear_flag(&fup->flags[0], SIP_INC_RINGING); 05354 } 05355 ao2_unlock(p); 05356 sip_pvt_unlock(fup); 05357 } 05358 break; 05359 05360 default: 05361 ast_log(LOG_ERROR, "update_call_counter(%s, %d) called with no event!\n", name, event); 05362 } 05363 05364 if (p) { 05365 ast_devstate_changed(AST_DEVICE_UNKNOWN, "SIP/%s", p->name); 05366 unref_peer(p, "update_call_counter: unref_peer from call counter"); 05367 } 05368 return 0; 05369 }
static void update_peer | ( | struct sip_peer * | p, | |
int | expire | |||
) | [static] |
Update peer data in database (if used).
Definition at line 4310 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().
04311 { 04312 int rtcachefriends = ast_test_flag(&p->flags[1], SIP_PAGE2_RTCACHEFRIENDS); 04313 if (sip_cfg.peer_rtupdate && 04314 (p->is_realtime || rtcachefriends)) { 04315 realtime_update_peer(p->name, &p->addr, p->username, rtcachefriends ? p->fullcontact : NULL, p->useragent, expire, p->deprecated_username, p->lastms); 04316 } 04317 }
static void update_provisional_keepalive | ( | struct sip_pvt * | pvt, | |
int | with_sdp | |||
) | [static] |
Definition at line 3804 of file chan_sip.c.
References ast_sched_add(), AST_SCHED_DEL_UNREF, dialog_ref(), dialog_unref(), PROVIS_KEEPALIVE_TIMEOUT, sip_pvt::provisional_keepalive_sched_id, sched, send_provisional_keepalive(), and send_provisional_keepalive_with_sdp().
Referenced by transmit_provisional_response().
03805 { 03806 AST_SCHED_DEL_UNREF(sched, pvt->provisional_keepalive_sched_id, dialog_unref(pvt, "when you delete the provisional_keepalive_sched_id, you should dec the refcount for the stored dialog ptr")); 03807 03808 pvt->provisional_keepalive_sched_id = ast_sched_add(sched, PROVIS_KEEPALIVE_TIMEOUT, 03809 with_sdp ? send_provisional_keepalive_with_sdp : send_provisional_keepalive, dialog_ref(pvt, "Increment refcount to pass dialog pointer to sched callback")); 03810 }
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 24898 of file chan_sip.c.
int allow_external_domains [static] |
Accept calls to external SIP domains?
Definition at line 795 of file chan_sip.c.
int apeerobjs = 0 [static] |
Autocreated peer objects
Definition at line 828 of file chan_sip.c.
char* app_dtmfmode = "SIPDtmfMode" [static] |
Definition at line 24361 of file chan_sip.c.
char* app_sipaddheader = "SIPAddHeader" [static] |
Definition at line 24363 of file chan_sip.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 24898 of file chan_sip.c.
Authentication list for realm authentication.
Definition at line 1816 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 762 of file chan_sip.c.
struct sockaddr_in bindaddr [static] |
UDP: The address we bind to
Definition at line 1837 of file chan_sip.c.
unsigned int chan_idx [static] |
Definition at line 561 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 11766 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 24656 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 24654 of file chan_sip.c.
int compactheaders [static] |
send compact sip headers
Definition at line 787 of file chan_sip.c.
const char config[] = "sip.conf" [static] |
Main configuration file
Definition at line 286 of file chan_sip.c.
struct sockaddr_in debugaddr [static] |
Definition at line 1882 of file chan_sip.c.
char default_callerid[AST_MAX_EXTENSION] [static] |
Definition at line 728 of file chan_sip.c.
char default_context[AST_MAX_CONTEXT] [static] |
Definition at line 725 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 729 of file chan_sip.c.
struct ast_jb_conf default_jbconf [static] |
Global jitterbuffer configuration - by default, jb is disabled.
Definition at line 276 of file chan_sip.c.
char default_language[MAX_LANGUAGE] [static] |
Definition at line 727 of file chan_sip.c.
int default_maxcallbitrate [static] |
Maximum bitrate for call
Definition at line 737 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 733 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 734 of file chan_sip.c.
char default_notifymime[AST_MAX_EXTENSION] [static] |
Definition at line 730 of file chan_sip.c.
char default_parkinglot[AST_MAX_CONTEXT] [static] |
Parkinglot
Definition at line 736 of file chan_sip.c.
struct ast_codec_pref default_prefs [static] |
Default codec prefs
Definition at line 738 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 731 of file chan_sip.c.
char default_subscribecontext[AST_MAX_CONTEXT] [static] |
Definition at line 726 of file chan_sip.c.
struct ast_tls_config default_tls_cfg [static] |
Default TLS connection configuration.
Definition at line 2347 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 732 of file chan_sip.c.
char* descrip_dtmfmode = " SIPDtmfMode(inband|info|rfc2833): Changes the dtmfmode for a SIP call\n" [static] |
Definition at line 24360 of file chan_sip.c.
char* descrip_sipaddheader [static] |
Definition at line 24366 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 14118 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 789 of file chan_sip.c.
time_t externexpire [static] |
Expiration counter for re-resolving external host name in dynamic DNS
Definition at line 1868 of file chan_sip.c.
char externhost[MAXHOSTNAMELEN] [static] |
External host name
Definition at line 1867 of file chan_sip.c.
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 1865 of file chan_sip.c.
int externrefresh = 10 [static] |
Definition at line 1869 of file chan_sip.c.
struct _map_x_s faxecmodes[] [static] |
int global_allowguest [static] |
allow unauthenticated peers to connect?
Definition at line 773 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 777 of file chan_sip.c.
enum transfermodes global_allowtransfer [static] |
SIP Refer restriction scheme
Definition at line 803 of file chan_sip.c.
int global_alwaysauthreject [static] |
Send 401 Unauthorized for all failing requests
Definition at line 759 of file chan_sip.c.
int global_authfailureevents [static] |
Whether we send authentication failure manager events or not. Default no.
Definition at line 797 of file chan_sip.c.
int global_autoframing [static] |
Turn autoframing on or off.
Definition at line 802 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 774 of file chan_sip.c.
int global_callevents [static] |
Whether we send manager events or not
Definition at line 796 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 821 of file chan_sip.c.
Referenced by build_peer(), parse_register_contact(), reload_config(), and unload_module().
unsigned int global_cos_audio [static] |
802.1p class of service for audio RTP packets
Definition at line 784 of file chan_sip.c.
unsigned int global_cos_sip [static] |
802.1p class of service for SIP packets
Definition at line 783 of file chan_sip.c.
unsigned int global_cos_text [static] |
802.1p class of service for text RTP packets
Definition at line 786 of file chan_sip.c.
unsigned int global_cos_video [static] |
802.1p class of service for video RTP packets
Definition at line 785 of file chan_sip.c.
int global_directrtpsetup [static] |
Enable support for Direct RTP setup (no re-invites)
Definition at line 755 of file chan_sip.c.
int global_dynamic_exclude_static = 0 [static] |
Exclude static peers from contact registrations
Definition at line 817 of file chan_sip.c.
struct ast_flags global_flags[2] = {{0}} [static] |
global SIP_ flags
Definition at line 832 of file chan_sip.c.
Referenced by build_peer(), build_radius_record(), get_destination(), load_module(), load_moh_classes(), local_ast_moh_start(), reload_config(), 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 284 of file chan_sip.c.
int global_match_auth_username [static] |
Match auth username if available instead of From: Default off.
Definition at line 763 of file chan_sip.c.
int global_matchexterniplocally [static] |
Match externip/externhost setting against localnet setting
Definition at line 805 of file chan_sip.c.
int global_max_se [static] |
Highest threshold for session refresh interval
Definition at line 815 of file chan_sip.c.
int global_min_se [static] |
Lowest threshold for session refresh interval
Definition at line 814 of file chan_sip.c.
int global_notifyhold [static] |
Send notifications on hold
Definition at line 758 of file chan_sip.c.
int global_notifyringing [static] |
Send notifications on ringing
Definition at line 757 of file chan_sip.c.
struct sip_proxy global_outboundproxy [static] |
Outbound proxy
Definition at line 804 of file chan_sip.c.
Referenced by obproxy_get(), ref_proxy(), and sip_show_settings().
int global_prematuremediafilter [static] |
Enable/disable premature frames in a call (causing 183 early media)
Definition at line 765 of file chan_sip.c.
int global_qualifyfreq [static] |
Qualify frequency
Definition at line 806 of file chan_sip.c.
char global_realm[MAXHOSTNAMELEN] [static] |
Default realm
Definition at line 790 of file chan_sip.c.
int global_reg_timeout [static] |
Definition at line 770 of file chan_sip.c.
int global_regattempts_max [static] |
Registration attempts before giving up
Definition at line 771 of file chan_sip.c.
char global_regcontext[AST_MAX_CONTEXT] [static] |
Context for auto-extensions
Definition at line 791 of file chan_sip.c.
int global_regextenonqualify [static] |
Whether to add/remove regexten when qualifying peers
Definition at line 801 of file chan_sip.c.
int global_relaxdtmf [static] |
Relax DTMF
Definition at line 766 of file chan_sip.c.
int global_relaxdtmf [static] |
Relax DTMF
Definition at line 764 of file chan_sip.c.
int global_rtautoclear [static] |
Realtime ??
Definition at line 756 of file chan_sip.c.
int global_rtpholdtimeout [static] |
Time out call if no RTP during hold
Definition at line 768 of file chan_sip.c.
int global_rtpkeepalive [static] |
Send RTP keepalives
Definition at line 769 of file chan_sip.c.
int global_rtptimeout [static] |
Time out call if no RTP
Definition at line 767 of file chan_sip.c.
char global_sdpowner[AST_MAX_EXTENSION] [static] |
SDP owner name for the SIP channel
Definition at line 794 of file chan_sip.c.
char global_sdpsession[AST_MAX_EXTENSION] [static] |
SDP session name for the SIP channel
Definition at line 793 of file chan_sip.c.
int global_shrinkcallerid [static] |
enable or disable shrinking of caller id
Definition at line 772 of file chan_sip.c.
int global_srvlookup [static] |
SRV Lookup on or off. Default is on
Definition at line 760 of file chan_sip.c.
enum st_mode global_st_mode [static] |
Mode of operation for Session-Timers
Definition at line 812 of file chan_sip.c.
enum st_refresher global_st_refresher [static] |
Session-Timer refresher
Definition at line 813 of file chan_sip.c.
int global_t1 [static] |
T1 time
Definition at line 798 of file chan_sip.c.
int global_t1min [static] |
T1 roundtrip time minimum
Definition at line 799 of file chan_sip.c.
int global_t38_maxdatagram [static] |
global T.38 FaxMaxDatagram override
Definition at line 833 of file chan_sip.c.
int global_timer_b [static] |
Timer B - RFC 3261 Section 17.1.1.2
Definition at line 800 of file chan_sip.c.
unsigned int global_tos_audio [static] |
IP type of service for audio RTP packets
Definition at line 780 of file chan_sip.c.
unsigned int global_tos_sip [static] |
IP type of service for SIP packets
Definition at line 779 of file chan_sip.c.
unsigned int global_tos_text [static] |
IP type of service for text RTP packets
Definition at line 782 of file chan_sip.c.
unsigned int global_tos_video [static] |
IP type of service for video RTP packets
Definition at line 781 of file chan_sip.c.
char global_useragent[AST_MAX_EXTENSION] [static] |
Useragent for the SIP channel
Definition at line 792 of file chan_sip.c.
int hash_dialog_size = 563 [static] |
Definition at line 1673 of file chan_sip.c.
int hash_peer_size = 563 [static] |
Size of peer hash table, prime number preferred!
Definition at line 1672 of file chan_sip.c.
int hash_user_size = 563 [static] |
Definition at line 1674 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 1845 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 854 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 1878 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 14451 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 13782 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 848 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 842 of file chan_sip.c.
ast_mutex_t netlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
Definition at line 838 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 287 of file chan_sip.c.
struct ast_config* notify_types = NULL [static] |
The list of manual NOTIFY types we know how to send
Definition at line 1884 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 1880 of file chan_sip.c.
int ourport_tls [static] |
The port used for TCP/TLS connections
Definition at line 1881 of file chan_sip.c.
int pedanticsipchecking [static] |
Extra checking ? Default off
Definition at line 761 of file chan_sip.c.
struct ao2_container* peers |
struct ao2_container* peers_by_ip |
Definition at line 1682 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 788 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 829 of file chan_sip.c.
struct _map_x_s regstatestrings[] [static] |
int rpeerobjs = 0 [static] |
Realtime peers
Definition at line 827 of file chan_sip.c.
struct sched_context* sched [static] |
The scheduling context
Definition at line 853 of file chan_sip.c.
struct sip_settings sip_cfg [static] |
Definition at line 747 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 850 of file chan_sip.c.
enum channelreloadreason sip_reloadreason [static] |
Reason for last reload/load of configuration
Definition at line 851 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 2402 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 2350 of file chan_sip.c.
Referenced by ast_sip_ouraddrfor(), 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 2306 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 2340 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 2361 of file chan_sip.c.
Referenced by ast_sip_ouraddrfor(), 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 2873 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 16681 of file chan_sip.c.
Referenced by load_module(), and unload_module().
enum sip_debug_e sipdebug [static] |
Definition at line 1117 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 1123 of file chan_sip.c.
Structure to declare a dialplan function: SIPPEER.
Definition at line 16589 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 1835 of file chan_sip.c.
int* sipsock_read_id [static] |
ID of IO entry for sipsock FD
Definition at line 855 of file chan_sip.c.
int speerobjs = 0 [static] |
Static peers
Definition at line 826 of file chan_sip.c.
Report Peer status in character string.
Definition at line 13603 of file chan_sip.c.
Referenced by stmode2str(), and str2stmode().
struct _map_x_s strefreshers[] [static] |
Definition at line 13621 of file chan_sip.c.
Referenced by str2strefresher(), and strefresher2str().
struct sockaddr_in stunaddr [static] |
stun server address
Definition at line 1870 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 24359 of file chan_sip.c.
char* synopsis_sipaddheader = "Add a SIP header to the outbound call" [static] |
Definition at line 24364 of file chan_sip.c.
struct ao2_container* threadt [static] |
The table of TCP threads.
Definition at line 1678 of file chan_sip.c.
Referenced by _sip_tcp_helper_thread(), load_module(), sip_prepare_socket(), sip_show_tcp(), sip_tcp_locate(), sip_tcptls_write(), sip_threadinfo_create(), and unload_module().
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 835 of file chan_sip.c.