Implementation of Session Initiation Protocol. More...
#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 | request_queue |
| 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_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 |
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 | 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 64 |
| #define | SIP_MAX_PACKET 4096 |
| #define | SIP_MIN_PACKET 1024 |
| #define | SIP_OPT_100REL (1 << 1) |
| #define | SIP_OPT_EARLY_SESSION (1 << 3) |
| #define | SIP_OPT_EVENTLIST (1 << 11) |
| #define | SIP_OPT_FROMCHANGE (1 << 17) |
| #define | SIP_OPT_GRUU (1 << 12) |
| #define | SIP_OPT_HISTINFO (1 << 15) |
| #define | SIP_OPT_JOIN (1 << 4) |
| #define | SIP_OPT_NOREFERSUB (1 << 14) |
| #define | SIP_OPT_PATH (1 << 5) |
| #define | SIP_OPT_PRECONDITION (1 << 7) |
| #define | SIP_OPT_PREF (1 << 6) |
| #define | SIP_OPT_PRIVACY (1 << 8) |
| #define | SIP_OPT_RECLISTINV (1 << 18) |
| #define | SIP_OPT_RECLISTSUB (1 << 19) |
| #define | SIP_OPT_REPLACES (1 << 0) |
| #define | SIP_OPT_RESPRIORITY (1 << 16) |
| #define | SIP_OPT_SDP_ANAT (1 << 9) |
| #define | SIP_OPT_SEC_AGREE (1 << 10) |
| #define | SIP_OPT_TARGET_DIALOG (1 << 13) |
| #define | SIP_OPT_TIMER (1 << 2) |
| #define | SIP_OPT_UNKNOWN (1 << 20) |
| #define | sip_pvt_lock(x) ao2_lock(x) |
| #define | sip_pvt_trylock(x) ao2_trylock(x) |
| #define | sip_pvt_unlock(x) ao2_unlock(x) |
| #define | SIP_RESERVED ";/?:@&=+$,# " |
| #define | SIP_TIMER_T1 500 |
| #define | SIP_TRANS_TIMEOUT 64 * SIP_TIMER_T1 |
| #define | SIPBUFSIZE 512 |
| #define | STANDARD_SIP_PORT 5060 |
| Standard SIP unsecure port for UDP and TCP from RFC 3261. DO NOT CHANGE THIS. | |
| #define | STANDARD_TLS_PORT 5061 |
| Standard SIP TLS port for sips: from RFC 3261. DO NOT CHANGE THIS. | |
| #define | SUPPORTED 1 |
| #define | SUPPORTED_EXTENSIONS "replaces, timer" |
| SIP Extensions we support. | |
| #define | UNLINK(element, head, prev) |
| #define | XMIT_ERROR -2 |
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 | |
| #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 | |
| #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_CONSTANT_SSRC (1 << 8) |
| #define | SIP_PAGE2_DIALOG_ESTABLISHED (1 << 27) |
| #define | SIP_PAGE2_FAX_DETECT (1 << 28) |
| #define | SIP_PAGE2_FLAGS_TO_COPY |
| #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) |
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 = AST_CLI_DEFINE(sip_do_history_deprecated, "Enable/Disable SIP history") |
| 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 |
| struct ao2_container * | dialogs |
| Here we implement the container for dialogs (sip_pvt), defining generic wrapper functions to ease the transition from the current implementation (a single linked list) to a different container. In addition to a reference to the container, we need functions to lock/unlock the container and individual items, and functions to add/remove references to the individual items. | |
| static struct _map_x_s | dtmfstr [] |
| mapping between dtmf flags and strings | |
| static 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 |
| struct ao2_container * | peers |
| The peer list: Users, Peers and Friends. | |
| struct 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. | |
| struct 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 , } |
GlobalSettings | |
| 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_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 | |
| 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 |
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] |
Implementation of Session Initiation Protocol.
See Also:
Implementation of RFC 3261 - without S/MIME, and experimental TCP and TLS support Configuration file sip.conf
********** IMPORTANT *
TODO:s
Better support of forking
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
In the SIP channel, there's a list of active SIP dialogs, which includes all of these when they are active. "sip show channels" in the CLI will show most of these, excluding subscriptions which are shown by "sip show subscriptions"
sipsock_read sends the packet to handle_incoming(), that parses a bit more. If it is a response to an outbound request, the packet is sent to handle_response(). If it is a request, handle_incoming() sends it to one of a list of functions depending on the request type - INVITE, OPTIONS, REFER, BYE, CANCEL etc sipsock_read locks the ast_channel if it exists (an active call) and unlocks it after we have processed the SIP message.
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 2147 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" |
Definition at line 246 of file chan_sip.c.
Referenced by initreqprep().
| #define CHECK_AUTH_BUF_INITLEN 256 |
Definition at line 11769 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 2054 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 |
| #define DEFAULT_ALLOWGUEST TRUE |
Definition at line 692 of file chan_sip.c.
Referenced by reload_config().
| #define DEFAULT_AUTOCREATEPEER FALSE |
Definition at line 708 of file chan_sip.c.
Referenced by reload_config().
| #define DEFAULT_CALLCOUNTER FALSE |
Definition at line 693 of file chan_sip.c.
Referenced by reload_config().
| #define DEFAULT_CALLERID "asterisk" |
Definition at line 690 of file chan_sip.c.
Referenced by reload_config().
| #define DEFAULT_COMPACTHEADERS FALSE |
Definition at line 695 of file chan_sip.c.
Referenced by reload_config().
| #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.
Referenced by reload_config().
| #define DEFAULT_COS_SIP 4 |
Level 2 class of service for SIP signalling
Definition at line 700 of file chan_sip.c.
Referenced by reload_config().
| #define DEFAULT_COS_TEXT 5 |
Level 2 class of service for text media (T.140)
Definition at line 703 of file chan_sip.c.
Referenced by reload_config().
| #define DEFAULT_COS_VIDEO 6 |
Level 2 class of service for video media
Definition at line 702 of file chan_sip.c.
Referenced by reload_config().
| #define DEFAULT_DEFAULT_EXPIRY 120 |
Definition at line 223 of file chan_sip.c.
Referenced by reload_config().
| #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) |
| #define DEFAULT_MAX_EXPIRY 3600 |
Definition at line 225 of file chan_sip.c.
Referenced by reload_config().
| #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.
Referenced by reload_config().
| #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.
Referenced by reload_config().
| #define DEFAULT_MIN_SE 90 |
Session-Timer Default Min-SE period (RFC 4028)
Definition at line 271 of file chan_sip.c.
Referenced by reload_config().
| #define DEFAULT_MOHINTERPRET "default" |
Definition at line 687 of file chan_sip.c.
Referenced by reload_config().
| #define DEFAULT_MOHSUGGEST "" |
Definition at line 688 of file chan_sip.c.
Referenced by reload_config().
| #define DEFAULT_NOTIFYMIME "application/simple-message-summary" |
Definition at line 691 of file chan_sip.c.
Referenced by reload_config().
| #define DEFAULT_NOTIFYRINGING TRUE |
Definition at line 706 of file chan_sip.c.
Referenced by reload_config().
| #define DEFAULT_PEDANTIC FALSE |
Definition at line 707 of file chan_sip.c.
Referenced by reload_config().
| #define DEFAULT_QUALIFY FALSE |
Definition at line 709 of file chan_sip.c.
Referenced by reload_config().
| #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.
Referenced by reload_config().
| #define DEFAULT_REALM "asterisk" |
Realm for HTTP digest authentication
Definition at line 705 of file chan_sip.c.
Referenced by reload_config().
| #define DEFAULT_REGEXTENONQUALIFY FALSE |
Definition at line 710 of file chan_sip.c.
Referenced by reload_config().
| #define DEFAULT_REGISTRATION_TIMEOUT 20 |
Definition at line 226 of file chan_sip.c.
Referenced by reload_config().
| #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.
Referenced by reload_config().
| #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.
Referenced by reload_config().
| #define DEFAULT_SRVLOOKUP TRUE |
| #define DEFAULT_T1MIN 100 |
100 MS for minimal roundtrip time
Definition at line 711 of file chan_sip.c.
Referenced by reload_config().
| #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.
Referenced by reload_config().
| #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.
Referenced by reload_config().
| #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.
Referenced by reload_config().
| #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.
Referenced by reload_config().
| #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.
Referenced by reload_config().
| #define DEFAULT_VMEXTEN "asterisk" |
Definition at line 689 of file chan_sip.c.
Referenced by reload_config().
| #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 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 15348 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 15348 of file chan_sip.c.
| #define FORMAT "%-30.30s %-6.6s %-12.12s %8d %-20.20s %-25.25s\n" |
Definition at line 15348 of file chan_sip.c.
| #define FORMAT "%-40.40s %-20.20s %-16.16s\n" |
Definition at line 15348 of file chan_sip.c.
| #define FORMAT "%-25.25s %-15.15s %-3.3s %-3.3s %-3.3s %-8d %-10s %s\n" |
Definition at line 15348 of file chan_sip.c.
| #define FORMAT "%-25.25s %-15.15s %-15.15s %-15.15s %-5.5s%-10.10s\n" |
Definition at line 15348 of file chan_sip.c.
| #define FORMAT "%-30.30s %-6d %-9.9s %-6.6s\n" |
Definition at line 15348 of file chan_sip.c.
| #define FORMAT "%-25.25s %-15.15s %-15.15s \n" |
Definition at line 15348 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 15347 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 15347 of file chan_sip.c.
| #define FORMAT2 "%-30.30s %-6.6s %-12.12s %8.8s %-20.20s %-25.25s\n" |
Definition at line 15347 of file chan_sip.c.
| #define FORMAT2 "%-25.25s %-15.15s %-3.3s %-3.3s %-3.3s %-8s %-10s %s\n" |
Definition at line 15347 of file chan_sip.c.
| #define FORMAT2 "%-30.30s %3.6s %9.9s %6.6s\n" |
Definition at line 15347 of file chan_sip.c.
| #define FORMAT2 "%-25.25s %-15.15s %-15.15s \n" |
Definition at line 15347 of file chan_sip.c.
| #define FORMAT3 "%-15.15s %-15.15s %-15.15s %-15.15s %-13.13s %-15.15s %-10.10s %-6.6s\n" |
Definition at line 15346 of file chan_sip.c.
Referenced by sip_show_channels().
| #define FORMAT4 "%-15.15s %-15.15s %-15.15s %-15.15s %-13.13s %-15.15s %-10.10s %-6.6d\n" |
Definition at line 15345 of file chan_sip.c.
Referenced by show_channels_cb().
| #define FROMDOMAIN_INVALID "anonymous.invalid" |
Definition at line 247 of file chan_sip.c.
Referenced by initreqprep().
| #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 |
Definition at line 860 of file chan_sip.c.
Referenced by sip_call(), and update_call_counter().
| #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 2371 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 1408 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 9370 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(), reload_config(), 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(), reload_config(), 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 |
(SIP_PROMISCREDIR | SIP_TRUSTRPID | SIP_SENDRPID | SIP_DTMF | SIP_REINVITE | \ SIP_PROG_INBAND | SIP_USECLIENTCODE | SIP_NAT | SIP_G726_NONSTANDARD | \ SIP_USEREQPHONE | SIP_INSECURE)
Flags to copy from peer/user to dialog.
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 64 |
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(), handle_common_options(), and reload_config().
| #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) |
Definition at line 577 of file chan_sip.c.
Referenced by handle_request_invite().
| #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) |
Definition at line 579 of file chan_sip.c.
Referenced by handle_request_invite().
| #define SIP_OPT_UNKNOWN (1 << 20) |
Definition at line 597 of file chan_sip.c.
Referenced by parse_sip_options().
| #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(), reload_config(), 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(), reload_config(), 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_CONSTANT_SSRC (1 << 8) |
GDP: Don't change SSRC on reinvite
Definition at line 1067 of file chan_sip.c.
Referenced by create_addr_from_peer(), handle_common_options(), handle_request_invite(), and reload_config().
| #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(), reload_config(), sip_new(), sip_read(), and sip_rtp_read().
| #define SIP_PAGE2_FLAGS_TO_COPY |
(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_CONSTANT_SSRC | SIP_PAGE2_FAX_DETECT)
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_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(), reload_config(), 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(), realtime_peer(), and reload_config().
| #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(), realtime_peer(), 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(), reload_config(), 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(), reload_config(), 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(), handle_common_options(), and reload_config().
| #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) |
Definition at line 1046 of file chan_sip.c.
Referenced by sip_indicate(), and sip_show_settings().
| #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 1420 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 1421 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 1422 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.
Referenced by reload_config().
| #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(), reload_config(), 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 UNLINK | ( | element, | |||
| head, | |||||
| prev | ) |
some list management macros.
Definition at line 1887 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.
| INV_NONE |
No state at all, maybe not an INVITE dialog |
| INV_CALLING |
Invite sent, no answer |
| INV_PROCEEDING |
We got/sent 1xx message |
| INV_EARLY_MEDIA |
We got 18x message with to-tag back |
| INV_COMPLETED |
Got final response with error. Wait for ACK, then CONFIRMED |
| INV_CONFIRMED |
Confirmed response - we've got an ack (Incoming calls only) |
| INV_TERMINATED |
Transaction done - either successful (AST_STATE_UP) or failed, but done The only way out of this is a BYE from one side |
| INV_CANCELLED |
Transaction cancelled by client or server in non-terminated state |
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.
| REFER_IDLE |
No REFER is in progress |
| REFER_SENT |
Sent REFER to transferee |
| REFER_RECEIVED |
Received REFER from transferrer |
| REFER_CONFIRMED |
Refer confirmed with a 100 TRYING (unused) |
| REFER_ACCEPTED |
Accepted by transferee |
| REFER_RINGING |
Target Ringing |
| REFER_200OK |
Answered by transfer target |
| REFER_FAILED |
REFER declined - go on |
| REFER_NOAUTH |
We had no auth for REFER |
Definition at line 1140 of file chan_sip.c.
01140 { 01141 REFER_IDLE, /*!< No REFER is in progress */ 01142 REFER_SENT, /*!< Sent REFER to transferee */ 01143 REFER_RECEIVED, /*!< Received REFER from transferrer */ 01144 REFER_CONFIRMED, /*!< Refer confirmed with a 100 TRYING (unused) */ 01145 REFER_ACCEPTED, /*!< Accepted by transferee */ 01146 REFER_RINGING, /*!< Target Ringing */ 01147 REFER_200OK, /*!< Answered by transfer target */ 01148 REFER_FAILED, /*!< REFER declined - go on */ 01149 REFER_NOAUTH /*!< We had no auth for REFER */ 01150 };
| 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 1110 of file chan_sip.c.
01110 { 01111 sip_debug_none = 0, 01112 sip_debug_config = 1, 01113 sip_debug_console = 2, 01114 };
| enum sip_peer_type |
Definition at line 1502 of file chan_sip.c.
01502 { 01503 SIP_TYPE_PEER = (1 << 0), 01504 SIP_TYPE_USER = (1 << 1), 01505 };
| enum sip_result |
The result of a lot of functions.
Definition at line 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 1642 of file chan_sip.c.
01642 { 01643 /*! \brief There is new data to be sent out */ 01644 TCPTLS_ALERT_DATA, 01645 /*! \brief A request to stop the tcp_handler thread */ 01646 TCPTLS_ALERT_STOP, 01647 };
| 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.
| REG_STATE_UNREGISTERED |
We are not registered
|
| REG_STATE_REGSENT |
Registration request sent
|
| REG_STATE_AUTHSENT |
We have tried to authenticate
|
| REG_STATE_REGISTERED |
Registered and done |
| REG_STATE_REJECTED |
Registration rejected *
|
| REG_STATE_TIMEOUT |
Registration timed out *
|
| REG_STATE_NOAUTH |
We have no accepted credentials
|
| REG_STATE_FAILED |
Registration failed after several tries
|
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.
| SESSION_TIMER_MODE_INVALID |
Invalid value |
| SESSION_TIMER_MODE_ACCEPT |
Honor inbound Session-Timer requests |
| SESSION_TIMER_MODE_ORIGINATE |
Originate outbound and honor inbound requests |
| SESSION_TIMER_MODE_REFUSE |
Ignore inbound Session-Timers requests |
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 1894 of file chan_sip.c.
01894 { 01895 SDP_T38_NONE = 0, /*!< Do not modify T38 information at all */ 01896 SDP_T38_INITIATE, /*!< Remote side has requested T38 with us */ 01897 SDP_T38_ACCEPT, /*!< Remote side accepted our T38 request */ 01898 };
| 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 1125 of file chan_sip.c.
01125 { 01126 T38_DISABLED = 0, /*!< Not enabled */ 01127 T38_LOCAL_REINVITE, /*!< Offered from local - REINVITE */ 01128 T38_PEER_REINVITE, /*!< Offered from peer - REINVITE */ 01129 T38_ENABLED /*!< Negotiated (enabled) */ 01130 };
| 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.
| XMIT_CRITICAL |
Transmit critical SIP message reliably, with re-transmits. If it fails, it's critical and will cause a teardown of the session |
| XMIT_RELIABLE |
Transmit SIP message reliably, with re-transmits |
| XMIT_UNRELIABLE |
Transmit SIP message without bothering with re-transmits |
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 6497 of file chan_sip.c.
References ast_skip_blanks(), find_alias(), sip_request::header, sip_request::headers, pass, and REQ_OFFSET_TO_STR.
Referenced by build_route(), copy_all_header(), copy_via_headers(), func_header_read(), get_header(), and handle_response_register().
06498 { 06499 int pass; 06500 06501 /* 06502 * Technically you can place arbitrary whitespace both before and after the ':' in 06503 * a header, although RFC3261 clearly says you shouldn't before, and place just 06504 * one afterwards. If you shouldn't do it, what absolute idiot decided it was 06505 * a good idea to say you can do it, and if you can do it, why in the hell would. 06506 * you say you shouldn't. 06507 * Anyways, pedanticsipchecking controls whether we allow spaces before ':', 06508 * and we always allow spaces after that for compatibility. 06509 */ 06510 for (pass = 0; name && pass < 2;pass++) { 06511 int x, len = strlen(name); 06512 for (x = *start; x < req->headers; x++) { 06513 char *header = REQ_OFFSET_TO_STR(req, header[x]); 06514 if (!strncasecmp(header, name, len)) { 06515 char *r = header + len; /* skip name */ 06516 if (pedanticsipchecking) 06517 r = ast_skip_blanks(r); 06518 06519 if (*r == ':') { 06520 *start = x+1; 06521 return ast_skip_blanks(r+1); 06522 } 06523 } 06524 } 06525 if (pass == 0) /* Try aliases */ 06526 name = find_alias(name, NULL); 06527 } 06528 06529 /* Don't return NULL, so get_header is always a valid pointer */ 06530 return ""; 06531 }
| static void __init_check_auth_buf | ( | void | ) | [static] |
Definition at line 11768 of file chan_sip.c.
| static void __init_ts_temp_pvt | ( | void | ) | [static] |
A per-thread temporary pvt structure.
Definition at line 1803 of file chan_sip.c.
| static void __reg_module | ( | void | ) | [static] |
Definition at line 24869 of file chan_sip.c.
| static int __set_address_from_contact | ( | const char * | fullcontact, | |
| struct sockaddr_in * | sin, | |||
| int | tcp | |||
| ) | [static] |
Definition at line 11369 of file chan_sip.c.
References 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().
11370 { 11371 struct hostent *hp; 11372 struct ast_hostent ahp; 11373 int port = STANDARD_SIP_PORT; 11374 char *host, *pt, *transport; 11375 char contact_buf[256]; 11376 char *contact; 11377 11378 /* Work on a copy */ 11379 ast_copy_string(contact_buf, fullcontact, sizeof(contact_buf)); 11380 contact = contact_buf; 11381 11382 /* 11383 * We have only the part in <brackets> here so we just need to parse a SIP URI. 11384 * 11385 * Note: The outbound proxy could be using UDP between the proxy and Asterisk. 11386 * We still need to be able to send to the remote agent through the proxy. 11387 */ 11388 11389 if (parse_uri(contact, "sip:,sips:", &contact, NULL, &host, &pt, NULL, &transport)) { 11390 ast_log(LOG_WARNING, "Invalid contact uri %s (missing sip: or sips:), attempting to use anyway\n", fullcontact); 11391 } 11392 11393 /* set port */ 11394 if (((get_transport_str2enum(transport) == SIP_TRANSPORT_TLS)) || !(strncasecmp(fullcontact, "sips", 4))) { 11395 port = port_str2int(pt, STANDARD_TLS_PORT); 11396 } else { 11397 port = port_str2int(pt, STANDARD_SIP_PORT); 11398 } 11399 11400 /* XXX This could block for a long time XXX */ 11401 /* We should only do this if it's a name, not an IP */ 11402 hp = ast_gethostbyname(host, &ahp); 11403 if (!hp) { 11404 ast_log(LOG_WARNING, "Invalid host name in Contact: (can't resolve in DNS) : '%s'\n", host); 11405 return -1; 11406 } 11407 sin->sin_family = AF_INET; 11408 memcpy(&sin->sin_addr, hp->h_addr, sizeof(sin->sin_addr)); 11409 sin->sin_port = htons(port); 11410 11411 return 0; 11412 }
| 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 3649 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, 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().
03650 { 03651 struct sip_pkt *cur, *prev = NULL; 03652 const char *msg = "Not Found"; /* used only for debugging */ 03653 int res = FALSE; 03654 03655 /* If we have an outbound proxy for this dialog, then delete it now since 03656 the rest of the requests in this dialog needs to follow the routing. 03657 If obforcing is set, we will keep the outbound proxy during the whole 03658 dialog, regardless of what the SIP rfc says 03659 */ 03660 if (p->outboundproxy && !p->outboundproxy->force){ 03661 ref_proxy(p, NULL); 03662 } 03663 03664 for (cur = p->packets; cur; prev = cur, cur = cur->next) { 03665 if (cur->seqno != seqno || cur->is_resp != resp) 03666 continue; 03667 if (cur->is_resp || cur->method == sipmethod) { 03668 res = TRUE; 03669 msg = "Found"; 03670 if (!resp && (seqno == p->pendinginvite)) { 03671 ast_debug(1, "Acked pending invite %d\n", p->pendinginvite); 03672 p->pendinginvite = 0; 03673 } 03674 if (cur->retransid > -1) { 03675 if (sipdebug) 03676 ast_debug(4, "** SIP TIMER: Cancelling retransmit of packet (reply received) Retransid #%d\n", cur->retransid); 03677 } 03678 /* This odd section is designed to thwart a 03679 * race condition in the packet scheduler. There are 03680 * two conditions under which deleting the packet from the 03681 * scheduler can fail. 03682 * 03683 * 1. The packet has been removed from the scheduler because retransmission 03684 * is being attempted. The problem is that if the packet is currently attempting 03685 * retransmission and we are at this point in the code, then that MUST mean 03686 * that retrans_pkt is waiting on p's lock. Therefore we will relinquish the 03687 * lock temporarily to allow retransmission. 03688 * 03689 * 2. The packet has reached its maximum number of retransmissions and has 03690 * been permanently removed from the packet scheduler. If this is the case, then 03691 * the packet's retransid will be set to -1. The atomicity of the setting and checking 03692 * of the retransid to -1 is ensured since in both cases p's lock is held. 03693 */ 03694 while (cur->retransid > -1 && ast_sched_del(sched, cur->retransid)) { 03695 sip_pvt_unlock(p); 03696 usleep(1); 03697 sip_pvt_lock(p); 03698 } 03699 UNLINK(cur, p->packets, prev); 03700 dialog_unref(cur->owner, "unref pkt cur->owner dialog from sip ack before freeing pkt"); 03701 if (cur->data) 03702 ast_free(cur->data); 03703 ast_free(cur); 03704 break; 03705 } 03706 } 03707 ast_debug(1, "Stopping retransmission on '%s' of %s %d: Match %s\n", 03708 p->callid, resp ? "Response" : "Request", seqno, msg); 03709 return res; 03710 }
| 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 3547 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(), MWI_NOTIFICATION, 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, cfsip_methods::text, transmit_request_with_auth(), transmit_state_notify(), TRUE, unref_peer(), and XMIT_RELIABLE.
Referenced by sip_scheddestroy(), and sip_show_sched().
03548 { 03549 struct sip_pvt *p = (struct sip_pvt *)data; 03550 03551 /* If this is a subscription, tell the phone that we got a timeout */ 03552 if (p->subscribed) { 03553 transmit_state_notify(p, AST_EXTENSION_DEACTIVATED, 1, TRUE); /* Send last notification */ 03554 p->subscribed = NONE; 03555 append_history(p, "Subscribestatus", "timeout"); 03556 ast_debug(3, "Re-scheduled destruction of SIP subscription %s\n", p->callid ? p->callid : "<unknown>"); 03557 return 10000; /* Reschedule this destruction so that we know that it's gone */ 03558 } 03559 03560 /* If there are packets still waiting for delivery, delay the destruction */ 03561 if (p->packets) { 03562 if (!p->needdestroy) { 03563 char method_str[31]; 03564 ast_debug(3, "Re-scheduled destruction of SIP call %s\n", p->callid ? p->callid : "<unknown>"); 03565 append_history(p, "ReliableXmit", "timeout"); 03566 if (sscanf(p->lastmsg, "Tx: %30s", method_str) == 1 || sscanf(p->lastmsg, "Rx: %30s", method_str) == 1) { 03567 if (method_match(SIP_CANCEL, method_str) || method_match(SIP_BYE, method_str)) { 03568 p->needdestroy = 1; 03569 } 03570 } 03571 return 10000; 03572 } else { 03573 /* They've had their chance to respond. Time to bail */ 03574 __sip_pretend_ack(p); 03575 } 03576 } 03577 03578 if (p->subscribed == MWI_NOTIFICATION) 03579 if (p->relatedpeer) 03580 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) */ 03581 03582 /* Reset schedule ID */ 03583 p->autokillid = -1; 03584 03585 if (p->owner) { 03586 ast_log(LOG_WARNING, "Autodestruct on dialog '%s' with owner in place (Method: %s)\n", p->callid, sip_methods[p->method].text); 03587 ast_queue_hangup_with_cause(p->owner, AST_CAUSE_PROTOCOL_ERROR); 03588 } else if (p->refer && !p->alreadygone) { 03589 ast_debug(3, "Finally hanging up channel after transfer: %s\n", p->callid); 03590 transmit_request_with_auth(p, SIP_BYE, 0, XMIT_RELIABLE, 1); 03591 append_history(p, "ReferBYE", "Sending BYE on transferer call leg %s", p->callid); 03592 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 03593 } else { 03594 append_history(p, "AutoDestroy", "%s", p->callid); 03595 ast_debug(3, "Auto destroying SIP dialog '%s'\n", p->callid); 03596 dialog_unlink_all(p, TRUE, TRUE); /* once it's unlinked and unrefd everywhere, it'll be freed automagically */ 03597 /* dialog_unref(p, "unref dialog-- no other matching conditions"); -- unlink all now should finish off the dialog's references and free it. */ 03598 /* sip_destroy(p); */ /* Go ahead and destroy dialog. All attempts to recover is done */ 03599 /* sip_destroy also absorbs the reference */ 03600 } 03601 dialog_unref(p, "The ref to a dialog passed to this sched callback is going out of scope; unref it."); 03602 return 0; 03603 }
| static void __sip_destroy | ( | struct sip_pvt * | p, | |
| int | lockowner, | |||
| int | lockdialoglist | |||
| ) | [static] |
Execute destruction of SIP dialog structure, release memory.
Definition at line 5103 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, sip_pvt::chanvars, sip_request::data, DEC_CALL_LIMIT, dialog_unref(), sip_pvt::flags, free_old_route(), sip_pvt::history, sip_pvt::history_entries, sip_pvt::initreq, LOG_DEBUG, sip_pvt::method, sip_peer::mwipvt, sip_pvt::notify_headers, option_debug, sip_pvt::options, sip_pvt::owner, sip_st_dlg::quit_flag, sip_pvt::refer, sip_pvt::registry, registry_unref(), sip_pvt::relatedpeer, sip_pvt::request_queue, sip_pvt::route, sip_pvt::rtp, sip_debug_test_pvt(), sip_dump_history(), SIP_INC_COUNT, sip_methods, SIP_PAGE2_CALL_ONHOLD, sip_pvt::socket, sip_st_dlg::st_active, sip_st_dlg::st_schedid, sip_pvt::stimer, sip_socket::tcptls_session, ast_channel::tech_pvt, cfsip_methods::text, sip_pvt::trtp, TRUE, sip_pvt::udptl, unref_peer(), update_call_counter(), and sip_pvt::vrtp.
Referenced by sip_destroy().
05104 { 05105 struct sip_request *req; 05106 05107 if (p->stimer) { 05108 ast_free(p->stimer); 05109 p->stimer = NULL; 05110 } 05111 05112 if (sip_debug_test_pvt(p)) 05113 ast_verbose("Really destroying SIP dialog '%s' Method: %s\n", p->callid, sip_methods[p->method].text); 05114 05115 if (ast_test_flag(&p->flags[0], SIP_INC_COUNT) || ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD)) { 05116 update_call_counter(p, DEC_CALL_LIMIT); 05117 ast_debug(2, "This call did not properly clean up call limits. Call ID %s\n", p->callid); 05118 } 05119 05120 /* Unlink us from the owner if we have one */ 05121 if (p->owner) { 05122 if (lockowner) 05123 ast_channel_lock(p->owner); 05124 if (option_debug) 05125 ast_log(LOG_DEBUG, "Detaching from %s\n", p->owner->name); 05126 p->owner->tech_pvt = NULL; 05127 /* Make sure that the channel knows its backend is going away */ 05128 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 05129 if (lockowner) 05130 ast_channel_unlock(p->owner); 05131 /* Give the channel a chance to react before deallocation */ 05132 usleep(1); 05133 } 05134 05135 /* Remove link from peer to subscription of MWI */ 05136 if (p->relatedpeer && p->relatedpeer->mwipvt) 05137 p->relatedpeer->mwipvt = dialog_unref(p->relatedpeer->mwipvt, "delete ->relatedpeer->mwipvt"); 05138 if (p->relatedpeer && p->relatedpeer->call == p) 05139 p->relatedpeer->call = dialog_unref(p->relatedpeer->call, "unset the relatedpeer->call field in tandem with relatedpeer field itself"); 05140 05141 if (p->relatedpeer) 05142 p->relatedpeer = unref_peer(p->relatedpeer,"unsetting a dialog relatedpeer field in sip_destroy"); 05143 05144 if (p->registry) { 05145 if (p->registry->call == p) 05146 p->registry->call = dialog_unref(p->registry->call, "nulling out the registry's call dialog field in unlink_all"); 05147 p->registry = registry_unref(p->registry, "delete p->registry"); 05148 } 05149 05150 if (dumphistory) 05151 sip_dump_history(p); 05152 05153 if (p->options) 05154 ast_free(p->options); 05155 05156 if (p->notify_headers) { 05157 ast_variables_destroy(p->notify_headers); 05158 p->notify_headers = NULL; 05159 } 05160 if (p->rtp) { 05161 ast_rtp_destroy(p->rtp); 05162 } 05163 if (p->vrtp) { 05164 ast_rtp_destroy(p->vrtp); 05165 } 05166 if (p->trtp) { 05167 while (ast_rtp_get_bridged(p->trtp)) 05168 usleep(1); 05169 ast_rtp_destroy(p->trtp); 05170 } 05171 if (p->udptl) 05172 ast_udptl_destroy(p->udptl); 05173 if (p->refer) 05174 ast_free(p->refer); 05175 if (p->route) { 05176 free_old_route(p->route); 05177 p->route = NULL; 05178 } 05179 if (p->initreq.data) 05180 ast_free(p->initreq.data); 05181 05182 /* Destroy Session-Timers if allocated */ 05183 if (p->stimer) { 05184 p->stimer->quit_flag = 1; 05185 if (p->stimer->st_active == TRUE && p->stimer->st_schedid > -1) { 05186 AST_SCHED_DEL_UNREF(sched, p->stimer->st_schedid, 05187 dialog_unref(p, "removing session timer ref")); 05188 } 05189 ast_free(p->stimer); 05190 p->stimer = NULL; 05191 } 05192 05193 /* Clear history */ 05194 if (p->history) { 05195 struct sip_history *hist; 05196 while ( (hist = AST_LIST_REMOVE_HEAD(p->history, list)) ) { 05197 ast_free(hist); 05198 p->history_entries--; 05199 } 05200 ast_free(p->history); 05201 p->history = NULL; 05202 } 05203 05204 while ((req = AST_LIST_REMOVE_HEAD(&p->request_queue, next))) { 05205 ast_free(req); 05206 } 05207 05208 if (p->chanvars) { 05209 ast_variables_destroy(p->chanvars); 05210 p->chanvars = NULL; 05211 } 05212 05213 ast_string_field_free_memory(p); 05214 05215 if (p->socket.tcptls_session) { 05216 ao2_ref(p->socket.tcptls_session, -1); 05217 p->socket.tcptls_session = NULL; 05218 } 05219 }
| static int __sip_do_register | ( | struct sip_registry * | r | ) | [static] |
Register with SIP proxy.
Definition at line 10703 of file chan_sip.c.
References SIP_REGISTER, and transmit_register().
Referenced by sip_reregister().
10704 { 10705 int res; 10706 10707 res = transmit_register(r, SIP_REGISTER, NULL, NULL); 10708 return res; 10709 }
| static void __sip_pretend_ack | ( | struct sip_pvt * | p | ) | [static] |
Pretend to ack all packets called with p locked.
Definition at line 3714 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, ast_str::str, and cfsip_methods::text.
Referenced by __sip_autodestruct(), handle_request_bye(), handle_request_cancel(), sip_hangup(), and sip_reg_timeout().
03715 { 03716 struct sip_pkt *cur = NULL; 03717 03718 while (p->packets) { 03719 int method; 03720 if (cur == p->packets) { 03721 ast_log(LOG_WARNING, "Have a packet that doesn't want to give up! %s\n", sip_methods[cur->method].text); 03722 return; 03723 } 03724 cur = p->packets; 03725 method = (cur->method) ? cur->method : find_sip_method(cur->data->str); 03726 __sip_ack(p, cur->seqno, cur->is_resp, method); 03727 } 03728 }
| 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 3469 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_pkt::data, DEFAULT_RETRANS, dialog_ref(), dialog_unref(), sip_pkt::is_fatal, sip_pkt::is_resp, LOG_ERROR, sip_pkt::method, sip_pkt::next, sip_pkt::owner, sip_pkt::packetlen, sip_pvt::packets, sip_pvt::pendinginvite, sip_pkt::response_code, retrans_pkt(), sip_pkt::retransid, sip_pkt::seqno, SIP_INVITE, SIP_TRANSPORT_UDP, sip_pvt::socket, ast_str::str, sip_pvt::timer_t1, sip_pkt::timer_t1, sip_socket::type, and XMIT_ERROR.
Referenced by send_request(), and send_response().
03470 { 03471 struct sip_pkt *pkt = NULL; 03472 int siptimer_a = DEFAULT_RETRANS; 03473 int xmitres = 0; 03474 int respid; 03475 03476 if (sipmethod == SIP_INVITE) { 03477 /* Note this is a pending invite */ 03478 p->pendinginvite = seqno; 03479 } 03480 03481 /* If the transport is something reliable (TCP or TLS) then don't really send this reliably */ 03482 /* I removed the code from retrans_pkt that does the same thing so it doesn't get loaded into the scheduler */ 03483 /* According to the RFC some packets need to be retransmitted even if its TCP, so this needs to get revisited */ 03484 if (!(p->socket.type & SIP_TRANSPORT_UDP)) { 03485 xmitres = __sip_xmit(p, data, len); /* Send packet */ 03486 if (xmitres == XMIT_ERROR) { /* Serious network trouble, no need to try again */ 03487 append_history(p, "XmitErr", "%s", fatal ? "(Critical)" : "(Non-critical)"); 03488 return AST_FAILURE; 03489 } else 03490 return AST_SUCCESS; 03491 } 03492 03493 if (!(pkt = ast_calloc(1, sizeof(*pkt) + len + 1))) 03494 return AST_FAILURE; 03495 /* copy data, add a terminator and save length */ 03496 if (!(pkt->data = ast_str_create(len))) { 03497 ast_free(pkt); 03498 return AST_FAILURE; 03499 } 03500 ast_str_set(&pkt->data, 0, "%s%s", data->str, "\0"); 03501 pkt->packetlen = len; 03502 /* copy other parameters from the caller */ 03503 pkt->method = sipmethod; 03504 pkt->seqno = seqno; 03505 pkt->is_resp = resp; 03506 pkt->is_fatal = fatal; 03507 pkt->owner = dialog_ref(p, "__sip_reliable_xmit: setting pkt->owner"); 03508 pkt->next = p->packets; 03509 p->packets = pkt; /* Add it to the queue */ 03510 if (resp) { 03511 /* Parse out the response code */ 03512 if (sscanf(ast_str_buffer(pkt->data), "SIP/2.0 %30u", &respid) == 1) { 03513 pkt->response_code = respid; 03514 } 03515 } 03516 pkt->timer_t1 = p->timer_t1; /* Set SIP timer T1 */ 03517 pkt->retransid = -1; 03518 if (pkt->timer_t1) 03519 siptimer_a = pkt->timer_t1 * 2; 03520 03521 /* Schedule retransmission */ 03522 AST_SCHED_REPLACE_VARIABLE(pkt->retransid, sched, siptimer_a, retrans_pkt, pkt, 1); 03523 if (sipdebug) 03524 ast_debug(4, "*** SIP TIMER: Initializing retransmit timer on packet: Id #%d\n", pkt->retransid); 03525 03526 xmitres = __sip_xmit(pkt->owner, pkt->data, pkt->packetlen); /* Send packet */ 03527 03528 if (xmitres == XMIT_ERROR) { /* Serious network trouble, no need to try again */ 03529 append_history(pkt->owner, "XmitErr", "%s", pkt->is_fatal ? "(Critical)" : "(Non-critical)"); 03530 ast_log(LOG_ERROR, "Serious Network Trouble; __sip_xmit returns error for pkt data\n"); 03531 AST_SCHED_DEL(sched, pkt->retransid); 03532 p->packets = pkt->next; 03533 pkt->owner = dialog_unref(pkt->owner,"pkt is being freed, its dialog ref is dead now"); 03534 ast_free(pkt->data); 03535 ast_free(pkt); 03536 return AST_FAILURE; 03537 } else { 03538 return AST_SUCCESS; 03539 } 03540 }
| 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 3731 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, sip_pkt::seqno, sip_methods, ast_str::str, cfsip_methods::text, and TRUE.
Referenced by handle_response(), and sip_hangup().
03732 { 03733 struct sip_pkt *cur; 03734 int res = FALSE; 03735 03736 for (cur = p->packets; cur; cur = cur->next) { 03737 if (cur->seqno == seqno && cur->is_resp == resp && 03738 (cur->is_resp || method_match(sipmethod, cur->data->str))) { 03739 /* this is our baby */ 03740 if (cur->retransid > -1) { 03741 if (sipdebug) 03742 ast_debug(4, "*** SIP TIMER: Cancelling retransmission #%d - %s (got response)\n", cur->retransid, sip_methods[sipmethod].text); 03743 } 03744 AST_SCHED_DEL(sched, cur->retransid); 03745 res = TRUE; 03746 break; 03747 } 03748 } 03749 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"); 03750 return res; 03751 }
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 3168 of file chan_sip.c.
References ast_debug, ast_inet_ntoa(), ast_log(), 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().
03169 { 03170 int res = 0; 03171 const struct sockaddr_in *dst = sip_real_dst(p); 03172 03173 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)); 03174 03175 if (sip_prepare_socket(p) < 0) 03176 return XMIT_ERROR; 03177 03178 if (p->socket.type == SIP_TRANSPORT_UDP) { 03179 res = sendto(p->socket.fd, data->str, len, 0, (const struct sockaddr *)dst, sizeof(struct sockaddr_in)); 03180 } else if (p->socket.tcptls_session) { 03181 res = sip_tcptls_write(p->socket.tcptls_session, data->str, len); 03182 } else { 03183 ast_debug(2, "Socket type is TCP but no tcptls_session is present to write to\n"); 03184 return XMIT_ERROR; 03185 } 03186 03187 if (res == -1) { 03188 switch (errno) { 03189 case EBADF: /* Bad file descriptor - seems like this is generated when the host exist, but doesn't accept the UDP packet */ 03190 case EHOSTUNREACH: /* Host can't be reached */ 03191 case ENETDOWN: /* Inteface down */ 03192 case ENETUNREACH: /* Network failure */ 03193 case ECONNREFUSED: /* ICMP port unreachable */ 03194 res = XMIT_ERROR; /* Don't bother with trying to transmit again */ 03195 } 03196 } 03197 if (res != len) 03198 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)); 03199 03200 return res; 03201 }
| 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 8929 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().
08930 { 08931 struct sip_request resp; 08932 int seqno = 0; 08933 08934 if (reliable && (sscanf(get_header(req, "CSeq"), "%30d ", &seqno) != 1)) { 08935 ast_log(LOG_WARNING, "Unable to determine sequence number from '%s'\n", get_header(req, "CSeq")); 08936 return -1; 08937 } 08938 respprep(&resp, p, msg, req); 08939 add_header_contentLength(&resp, 0); 08940 /* If we are cancelling an incoming invite for some reason, add information 08941 about the reason why we are doing this in clear text */ 08942 if (p->method == SIP_INVITE && msg[0] != '1' && p->owner && p->owner->hangupcause) { 08943 char buf[10]; 08944 08945 add_header(&resp, "X-Asterisk-HangupCause", ast_cause2str(p->owner->hangupcause)); 08946 snprintf(buf, sizeof(buf), "%d", p->owner->hangupcause); 08947 add_header(&resp, "X-Asterisk-HangupCauseCode", buf); 08948 } 08949 return send_response(p, &resp, reliable, seqno); 08950 }
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 24869 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 14466 of file chan_sip.c.
References ast_cli(), astman_send_error(), CLI_SHOWUSAGE, CLI_SUCCESS, FALSE, find_peer(), FINDPEERS, sip_poke_peer(), TRUE, and unref_peer().
Referenced by manager_sip_qualify_peer(), and sip_qualify_peer().
14467 { 14468 struct sip_peer *peer; 14469 int load_realtime; 14470 14471 if (argc < 4) 14472 return CLI_SHOWUSAGE; 14473 14474 load_realtime = (argc == 5 && !strcmp(argv[4], "load")) ? TRUE : FALSE; 14475 if ((peer = find_peer(argv[3], NULL, load_realtime, FINDPEERS, FALSE, 0))) { 14476 sip_poke_peer(peer, 1); 14477 unref_peer(peer, "qualify: done with peer"); 14478 } else if (type == 0) { 14479 ast_cli(fd, "Peer '%s' not found\n", argv[3]); 14480 } else { 14481 astman_send_error(s, m, "Peer not found"); 14482 } 14483 return CLI_SUCCESS; 14484 }
| 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 14551 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_OR, 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().
14552 { 14553 char status[30] = ""; 14554 char cbuf[256]; 14555 struct sip_peer *peer; 14556 char codec_buf[512]; 14557 struct ast_codec_pref *pref; 14558 struct ast_variable *v; 14559 struct sip_auth *auth; 14560 int x = 0, codec = 0, load_realtime; 14561 int realtimepeers; 14562 14563 realtimepeers = ast_check_realtime("sippeers"); 14564 14565 if (argc < 4) 14566 return CLI_SHOWUSAGE; 14567 14568 load_realtime = (argc == 5 && !strcmp(argv[4], "load")) ? TRUE : FALSE; 14569 peer = find_peer(argv[3], NULL, load_realtime, FINDPEERS, FALSE, 0); 14570 14571 if (s) { /* Manager */ 14572 if (peer) { 14573 const char *id = astman_get_header(m, "ActionID"); 14574 14575 astman_append(s, "Response: Success\r\n"); 14576 if (!ast_strlen_zero(id)) 14577 astman_append(s, "ActionID: %s\r\n", id); 14578 } else { 14579 snprintf (cbuf, sizeof(cbuf), "Peer %s not found.", argv[3]); 14580 astman_send_error(s, m, cbuf); 14581 return CLI_SUCCESS; 14582 } 14583 } 14584 if (peer && type==0 ) { /* Normal listing */ 14585 struct ast_str *mailbox_str = ast_str_alloca(512); 14586 ast_cli(fd, "\n\n"); 14587 ast_cli(fd, " * Name : %s\n", peer->name); 14588 if (realtimepeers) { /* Realtime is enabled */ 14589 ast_cli(fd, " Realtime peer: %s\n", peer->is_realtime ? "Yes, cached" : "No"); 14590 } 14591 ast_cli(fd, " Secret : %s\n", ast_strlen_zero(peer->secret)?"<Not set>":"<Set>"); 14592 ast_cli(fd, " MD5Secret : %s\n", ast_strlen_zero(peer->md5secret)?"<Not set>":"<Set>"); 14593 for (auth = peer->auth; auth; auth = auth->next) { 14594 ast_cli(fd, " Realm-auth : Realm %-15.15s User %-10.20s ", auth->realm, auth->username); 14595 ast_cli(fd, "%s\n", !ast_strlen_zero(auth->secret)?"<Secret set>":(!ast_strlen_zero(auth->md5secret)?"<MD5secret set>" : "<Not set>")); 14596 } 14597 ast_cli(fd, " Context : %s\n", peer->context); 14598 ast_cli(fd, " Subscr.Cont. : %s\n", S_OR(peer->subscribecontext, "<Not set>") ); 14599 ast_cli(fd, " Language : %s\n", peer->language); 14600 if (!ast_strlen_zero(peer->accountcode)) 14601 ast_cli(fd, " Accountcode : %s\n", peer->accountcode); 14602 ast_cli(fd, " AMA flags : %s\n", ast_cdr_flags2str(peer->amaflags)); 14603 ast_cli(fd, " Transfer mode: %s\n", transfermode2str(peer->allowtransfer)); 14604 ast_cli(fd, " CallingPres : %s\n", ast_describe_caller_presentation(peer->callingpres)); 14605 if (!ast_strlen_zero(peer->fromuser)) 14606 ast_cli(fd, " FromUser : %s\n", peer->fromuser); 14607 if (!ast_strlen_zero(peer->fromdomain)) 14608 ast_cli(fd, " FromDomain : %s\n", peer->fromdomain); 14609 ast_cli(fd, " Callgroup : "); 14610 print_group(fd, peer->callgroup, 0); 14611 ast_cli(fd, " Pickupgroup : "); 14612 print_group(fd, peer->pickupgroup, 0); 14613 peer_mailboxes_to_str(&mailbox_str, peer); 14614 ast_cli(fd, " Mailbox : %s\n", mailbox_str->str); 14615 ast_cli(fd, " VM Extension : %s\n", peer->vmexten); 14616 ast_cli(fd, " LastMsgsSent : %d/%d\n", (peer->lastmsgssent & 0x7fff0000) >> 16, peer->lastmsgssent & 0xffff); 14617 ast_cli(fd, " Call limit : %d\n", peer->call_limit); 14618 if (peer->busy_level) 14619 ast_cli(fd, " Busy level : %d\n", peer->busy_level); 14620 ast_cli(fd, " Dynamic : %s\n", cli_yesno(peer->host_dynamic)); 14621 ast_cli(fd, " Callerid : %s\n", ast_callerid_merge(cbuf, sizeof(cbuf), peer->cid_name, peer->cid_num, "<unspecified>")); 14622 ast_cli(fd, " MaxCallBR : %d kbps\n", peer->maxcallbitrate); 14623 ast_cli(fd, " Expire : %ld\n", ast_sched_when(sched, peer->expire)); 14624 ast_cli(fd, " Insecure : %s\n", insecure2str(ast_test_flag(&peer->flags[0], SIP_INSECURE))); 14625 ast_cli(fd, " Nat : %s\n", nat2str(ast_test_flag(&peer->flags[0], SIP_NAT))); 14626 ast_cli(fd, " ACL : %s\n", cli_yesno(peer->ha != NULL)); 14627 ast_cli(fd, " T.38 support : %s\n", cli_yesno(ast_test_flag(&peer->flags[1], SIP_PAGE2_T38SUPPORT))); 14628 ast_cli(fd, " T.38 EC mode : %s\n", faxec2str(ast_test_flag(&peer->flags[1], SIP_PAGE2_T38SUPPORT))); 14629 ast_cli(fd, " T.38 MaxDtgrm: %d\n", peer->t38_maxdatagram); 14630 ast_cli(fd, " CanReinvite : %s\n", cli_yesno(ast_test_flag(&peer->flags[0], SIP_CAN_REINVITE))); 14631 ast_cli(fd, " PromiscRedir : %s\n", cli_yesno(ast_test_flag(&peer->flags[0], SIP_PROMISCREDIR))); 14632 ast_cli(fd, " User=Phone : %s\n", cli_yesno(ast_test_flag(&peer->flags[0], SIP_USEREQPHONE))); 14633 ast_cli(fd, " Video Support: %s\n", cli_yesno(ast_test_flag(&peer->flags[1], SIP_PAGE2_VIDEOSUPPORT))); 14634 ast_cli(fd, " Text Support : %s\n", cli_yesno(ast_test_flag(&peer->flags[1], SIP_PAGE2_TEXTSUPPORT))); 14635 ast_cli(fd, " Ign SDP ver : %s\n", cli_yesno(ast_test_flag(&peer->flags[1], SIP_PAGE2_IGNORESDPVERSION))); 14636 ast_cli(fd, " Trust RPID : %s\n", cli_yesno(ast_test_flag(&peer->flags[0], SIP_TRUSTRPID))); 14637 ast_cli(fd, " Send RPID : %s\n", cli_yesno(ast_test_flag(&peer->flags[0], SIP_SENDRPID))); 14638 ast_cli(fd, " Subscriptions: %s\n", cli_yesno(ast_test_flag(&peer->flags[1], SIP_PAGE2_ALLOWSUBSCRIBE))); 14639 ast_cli(fd, " Overlap dial : %s\n", cli_yesno(ast_test_flag(&peer->flags[1], SIP_PAGE2_ALLOWOVERLAP))); 14640 if (peer->outboundproxy) 14641 ast_cli(fd, " Outb. proxy : %s %s\n", ast_strlen_zero(peer->outboundproxy->name) ? "<not set>" : peer->outboundproxy->name, 14642 peer->outboundproxy->force ? "(forced)" : ""); 14643 14644 /* - is enumerated */ 14645 ast_cli(fd, " DTMFmode : %s\n", dtmfmode2str(ast_test_flag(&peer->flags[0], SIP_DTMF))); 14646 ast_cli(fd, " Timer T1 : %d\n", peer->timer_t1); 14647 ast_cli(fd, " Timer B : %d\n", peer->timer_b); 14648 ast_cli(fd, " ToHost : %s\n", peer->tohost); 14649 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)); 14650 ast_cli(fd, " Defaddr->IP : %s Port %d\n", ast_inet_ntoa(peer->defaddr.sin_addr), ntohs(peer->defaddr.sin_port)); 14651 ast_cli(fd, " Transport : %s\n", get_transport(peer->socket.type)); 14652 if (!ast_strlen_zero(global_regcontext)) 14653 ast_cli(fd, " Reg. exten : %s\n", peer->regexten); 14654 ast_cli(fd, " Def. Username: %s\n", peer->username); 14655 ast_cli(fd, " SIP Options : "); 14656 if (peer->sipoptions) { 14657 int lastoption = -1; 14658 for (x = 0 ; x < ARRAY_LEN(sip_options); x++) { 14659 if (sip_options[x].id != lastoption) { 14660 if (peer->sipoptions & sip_options[x].id) 14661 ast_cli(fd, "%s ", sip_options[x].text); 14662 lastoption = x; 14663 } 14664 } 14665 } else 14666 ast_cli(fd, "(none)"); 14667 14668 ast_cli(fd, "\n"); 14669 ast_cli(fd, " Codecs : "); 14670 ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, peer->capability); 14671 ast_cli(fd, "%s\n", codec_buf); 14672 ast_cli(fd, " Codec Order : ("); 14673 print_codec_to_cli(fd, &peer->prefs); 14674 ast_cli(fd, ")\n"); 14675 14676 ast_cli(fd, " Auto-Framing : %s \n", cli_yesno(peer->autoframing)); 14677 ast_cli(fd, " 100 on REG : %s\n", ast_test_flag(&peer->flags[1], SIP_PAGE2_REGISTERTRYING) ? "Yes" : "No"); 14678 ast_cli(fd, " Status : "); 14679 peer_status(peer, status, sizeof(status)); 14680 ast_cli(fd, "%s\n", status); 14681 ast_cli(fd, " Useragent : %s\n", peer->useragent); 14682 ast_cli(fd, " Reg. Contact : %s\n", peer->fullcontact); 14683 ast_cli(fd, " Qualify Freq : %d ms\n", peer->qualifyfreq); 14684 if (peer->chanvars) { 14685 ast_cli(fd, " Variables :\n"); 14686 for (v = peer->chanvars ; v ; v = v->next) 14687 ast_cli(fd, " %s = %s\n", v->name, v->value); 14688 } 14689 14690 ast_cli(fd, " Sess-Timers : %s\n", stmode2str(peer->stimer.st_mode_oper)); 14691 ast_cli(fd, " Sess-Refresh : %s\n", strefresher2str(peer->stimer.st_ref)); 14692 ast_cli(fd, " Sess-Expires : %d secs\n", peer->stimer.st_max_se); 14693 ast_cli(fd, " Min-Sess : %d secs\n", peer->stimer.st_min_se); 14694 ast_cli(fd, " Parkinglot : %s\n", peer->parkinglot); 14695 ast_cli(fd, "\n"); 14696 peer = unref_peer(peer, "sip_show_peer: unref_peer: done with peer ptr"); 14697 } else if (peer && type == 1) { /* manager listing */ 14698 char buffer[256]; 14699 struct ast_str *mailbox_str = ast_str_alloca(512); 14700 astman_append(s, "Channeltype: SIP\r\n"); 14701 astman_append(s, "ObjectName: %s\r\n", peer->name); 14702 astman_append(s, "ChanObjectType: peer\r\n"); 14703 astman_append(s, "SecretExist: %s\r\n", ast_strlen_zero(peer->secret)?"N":"Y"); 14704 astman_append(s, "MD5SecretExist: %s\r\n", ast_strlen_zero(peer->md5secret)?"N":"Y"); 14705 astman_append(s, "Context: %s\r\n", peer->context); 14706 astman_append(s, "Language: %s\r\n", peer->language); 14707 if (!ast_strlen_zero(peer->accountcode)) 14708 astman_append(s, "Accountcode: %s\r\n", peer->accountcode); 14709 astman_append(s, "AMAflags: %s\r\n", ast_cdr_flags2str(peer->amaflags)); 14710 astman_append(s, "CID-CallingPres: %s\r\n", ast_describe_caller_presentation(peer->callingpres)); 14711 if (!ast_strlen_zero(peer->fromuser)) 14712 astman_append(s, "SIP-FromUser: %s\r\n", peer->fromuser); 14713 if (!ast_strlen_zero(peer->fromdomain)) 14714 astman_append(s, "SIP-FromDomain: %s\r\n", peer->fromdomain); 14715 astman_append(s, "Callgroup: "); 14716 astman_append(s, "%s\r\n", ast_print_group(buffer, sizeof(buffer), peer->callgroup)); 14717 astman_append(s, "Pickupgroup: "); 14718 astman_append(s, "%s\r\n", ast_print_group(buffer, sizeof(buffer), peer->pickupgroup)); 14719 peer_mailboxes_to_str(&mailbox_str, peer); 14720 astman_append(s, "VoiceMailbox: %s\r\n", mailbox_str->str); 14721 astman_append(s, "TransferMode: %s\r\n", transfermode2str(peer->allowtransfer)); 14722 astman_append(s, "LastMsgsSent: %d\r\n", peer->lastmsgssent); 14723 astman_append(s, "Call-limit: %d\r\n", peer->call_limit); 14724 astman_append(s, "Busy-level: %d\r\n", peer->busy_level); 14725 astman_append(s, "MaxCallBR: %d kbps\r\n", peer->maxcallbitrate); 14726 astman_append(s, "Dynamic: %s\r\n", peer->host_dynamic?"Y":"N"); 14727 astman_append(s, "Callerid: %s\r\n", ast_callerid_merge(cbuf, sizeof(cbuf), peer->cid_name, peer->cid_num, "")); 14728 astman_append(s, "RegExpire: %ld seconds\r\n", ast_sched_when(sched, peer->expire)); 14729 astman_append(s, "SIP-AuthInsecure: %s\r\n", insecure2str(ast_test_flag(&peer->flags[0], SIP_INSECURE))); 14730 astman_append(s, "SIP-NatSupport: %s\r\n", nat2str(ast_test_flag(&peer->flags[0], SIP_NAT))); 14731 astman_append(s, "ACL: %s\r\n", (peer->ha?"Y":"N")); 14732 astman_append(s, "SIP-CanReinvite: %s\r\n", (ast_test_flag(&peer->flags[0], SIP_CAN_REINVITE)?"Y":"N")); 14733 astman_append(s, "SIP-PromiscRedir: %s\r\n", (ast_test_flag(&peer->flags[0], SIP_PROMISCREDIR)?"Y":"N")); 14734 astman_append(s, "SIP-UserPhone: %s\r\n", (ast_test_flag(&peer->flags[0], SIP_USEREQPHONE)?"Y":"N")); 14735 astman_append(s, "SIP-VideoSupport: %s\r\n", (ast_test_flag(&peer->flags[1], SIP_PAGE2_VIDEOSUPPORT)?"Y":"N")); 14736 astman_append(s, "SIP-TextSupport: %s\r\n", (ast_test_flag(&peer->flags[1], SIP_PAGE2_TEXTSUPPORT)?"Y":"N")); 14737 astman_append(s, "SIP-T.38Support: %s\r\n", (ast_test_flag(&peer->flags[1], SIP_PAGE2_T38SUPPORT)?"Y":"N")); 14738 astman_append(s, "SIP-T.38EC: %s\r\n", faxec2str(ast_test_flag(&peer->flags[1], SIP_PAGE2_T38SUPPORT))); 14739 astman_append(s, "SIP-T.38MaxDtgrm: %d\r\n", peer->t38_maxdatagram); 14740 astman_append(s, "SIP-Sess-Timers: %s\r\n", stmode2str(peer->stimer.st_mode_oper)); 14741 astman_append(s, "SIP-Sess-Refresh: %s\r\n", strefresher2str(peer->stimer.st_ref)); 14742 astman_append(s, "SIP-Sess-Expires: %d\r\n", peer->stimer.st_max_se); 14743 astman_append(s, "SIP-Sess-Min: %d\r\n", peer->stimer.st_min_se); 14744 14745 /* - is enumerated */ 14746 astman_append(s, "SIP-DTMFmode: %s\r\n", dtmfmode2str(ast_test_flag(&peer->flags[0], SIP_DTMF))); 14747 astman_append(s, "ToHost: %s\r\n", peer->tohost); 14748 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)); 14749 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)); 14750 astman_append(s, "Default-Username: %s\r\n", peer->username); 14751 if (!ast_strlen_zero(global_regcontext)) 14752 astman_append(s, "RegExtension: %s\r\n", peer->regexten); 14753 astman_append(s, "Codecs: "); 14754 ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, peer->capability); 14755 astman_append(s, "%s\r\n", codec_buf); 14756 astman_append(s, "CodecOrder: "); 14757 pref = &peer->prefs; 14758 for(x = 0; x < 32 ; x++) { 14759 codec = ast_codec_pref_index(pref, x); 14760 if (!codec) 14761 break; 14762 astman_append(s, "%s", ast_getformatname(codec)); 14763 if (x < 31 && ast_codec_pref_index(pref, x+1)) 14764 astman_append(s, ","); 14765 } 14766 14767 astman_append(s, "\r\n"); 14768 astman_append(s, "Status: "); 14769 peer_status(peer, status, sizeof(status)); 14770 astman_append(s, "%s\r\n", status); 14771 astman_append(s, "SIP-Useragent: %s\r\n", peer->useragent); 14772 astman_append(s, "Reg-Contact: %s\r\n", peer->fullcontact); 14773 astman_append(s, "QualifyFreq: %d ms\r\n", peer->qualifyfreq); 14774 astman_append(s, "Parkinglot: %s\r\n", peer->parkinglot); 14775 if (peer->chanvars) { 14776 for (v = peer->chanvars ; v ; v = v->next) { 14777 astman_append(s, "ChanVariable: %s=%s\r\n", v->name, v->value); 14778 } 14779 } 14780 14781 peer = unref_peer(peer, "sip_show_peer: unref_peer: done with peer"); 14782 14783 } else { 14784 ast_cli(fd, "Peer %s not found.\n", argv[3]); 14785 ast_cli(fd, "\n"); 14786 } 14787 14788 return CLI_SUCCESS; 14789 }
| 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 13859 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(), 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().
13860 { 13861 regex_t regexbuf; 13862 int havepattern = FALSE; 13863 struct sip_peer *peer; 13864 struct ao2_iterator i; 13865 13866 /* the last argument is left-aligned, so we don't need a size anyways */ 13867 #define FORMAT2 "%-25.25s %-15.15s %-3.3s %-3.3s %-3.3s %-8s %-10s %s\n" 13868 #define FORMAT "%-25.25s %-15.15s %-3.3s %-3.3s %-3.3s %-8d %-10s %s\n" 13869 13870 char name[256]; 13871 int total_peers = 0; 13872 int peers_mon_online = 0; 13873 int peers_mon_offline = 0; 13874 int peers_unmon_offline = 0; 13875 int peers_unmon_online = 0; 13876 const char *id; 13877 char idtext[256] = ""; 13878 int realtimepeers; 13879 int objcount = ao2_container_count(peers); 13880 struct sip_peer **peerarray; 13881 int k; 13882 13883 13884 realtimepeers = ast_check_realtime("sippeers"); 13885 peerarray = ast_calloc(sizeof(struct sip_peer *), objcount); 13886 13887 if (s) { /* Manager - get ActionID */ 13888 id = astman_get_header(m, "ActionID"); 13889 if (!ast_strlen_zero(id)) 13890 snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id); 13891 } 13892 13893 switch (argc) { 13894 case 5: 13895 if (!strcasecmp(argv[3], "like")) { 13896 if (regcomp(®exbuf, argv[4], REG_EXTENDED | REG_NOSUB)) 13897 return CLI_SHOWUSAGE; 13898 havepattern = TRUE; 13899 } else 13900 return CLI_SHOWUSAGE; 13901 case 3: 13902 break; 13903 default: 13904 return CLI_SHOWUSAGE; 13905 } 13906 13907 if (!s) /* Normal list */ 13908 ast_cli(fd, FORMAT2, "Name/username", "Host", "Dyn", "Nat", "ACL", "Port", "Status", (realtimepeers ? "Realtime" : "")); 13909 13910 13911 i = ao2_iterator_init(peers, 0); 13912 while ((peer = ao2_t_iterator_next(&i, "iterate thru peers table"))) { 13913 ao2_lock(peer); 13914 13915 if (!(peer->type & SIP_TYPE_PEER)) { 13916 ao2_unlock(peer); 13917 unref_peer(peer, "unref peer because it's actually a user"); 13918 continue; 13919 } 13920 13921 if (havepattern && regexec(®exbuf, peer->name, 0, NULL, 0)) { 13922 objcount--; 13923 ao2_unlock(peer); 13924 unref_peer(peer, "toss iterator peer ptr before continue"); 13925 continue; 13926 } 13927 13928 peerarray[total_peers++] = peer; 13929 ao2_unlock(peer); 13930 } 13931 ao2_iterator_destroy(&i); 13932 13933 qsort(peerarray, total_peers, sizeof(struct sip_peer *), peercomparefunc); 13934 13935 for(k=0; k < total_peers; k++) { 13936 char status[20] = ""; 13937 char srch[2000]; 13938 char pstatus; 13939 peer = peerarray[k]; 13940 13941 ao2_lock(peer); 13942 if (havepattern && regexec(®exbuf, peer->name, 0, NULL, 0)) { 13943 ao2_unlock(peer); 13944 unref_peer(peer, "toss iterator peer ptr before continue"); 13945 continue; 13946 } 13947 13948 if (!ast_strlen_zero(peer->username) && !s) 13949 snprintf(name, sizeof(name), "%s/%s", peer->name, peer->username); 13950 else 13951 ast_copy_string(name, peer->name, sizeof(name)); 13952 13953 pstatus = peer_status(peer, status, sizeof(status)); 13954 if (pstatus == 1) 13955 peers_mon_online++; 13956 else if (pstatus == 0) 13957 peers_mon_offline++; 13958 else { 13959 if (peer->addr.sin_port == 0) 13960 peers_unmon_offline++; 13961 else 13962 peers_unmon_online++; 13963 } 13964 13965 snprintf(srch, sizeof(srch), FORMAT, name, 13966 peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)", 13967 peer->host_dynamic ? " D " : " ", /* Dynamic or not? */ 13968 ast_test_flag(&peer->flags[0], SIP_NAT_ROUTE) ? " N " : " ", /* NAT=yes? */ 13969 peer->ha ? " A " : " ", /* permit/deny */ 13970 ntohs(peer->addr.sin_port), status, 13971 realtimepeers ? (peer->is_realtime ? "Cached RT":"") : ""); 13972 13973 if (!s) {/* Normal CLI list */ 13974 ast_cli(fd, FORMAT, name, 13975 peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "(Unspecified)", 13976 peer->host_dynamic ? " D " : " ", /* Dynamic or not? */ 13977 ast_test_flag(&peer->flags[0], SIP_NAT_ROUTE) ? " N " : " ", /* NAT=yes? */ 13978 peer->ha ? " A " : " ", /* permit/deny */ 13979 13980 ntohs(peer->addr.sin_port), status, 13981 realtimepeers ? (peer->is_realtime ? "Cached RT":"") : ""); 13982 } else { /* Manager format */ 13983 /* The names here need to be the same as other channels */ 13984 astman_append(s, 13985 "Event: PeerEntry\r\n%s" 13986 "Channeltype: SIP\r\n" 13987 "ObjectName: %s\r\n" 13988 "ChanObjectType: peer\r\n" /* "peer" or "user" */ 13989 "IPaddress: %s\r\n" 13990 "IPport: %d\r\n" 13991 "Dynamic: %s\r\n" 13992 "Natsupport: %s\r\n" 13993 "VideoSupport: %s\r\n" 13994 "TextSupport: %s\r\n" 13995 "ACL: %s\r\n" 13996 "Status: %s\r\n" 13997 "RealtimeDevice: %s\r\n\r\n", 13998 idtext, 13999 peer->name, 14000 peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "-none-", 14001 ntohs(peer->addr.sin_port), 14002 peer->host_dynamic ? "yes" : "no", /* Dynamic or not? */ 14003 ast_test_flag(&peer->flags[0], SIP_NAT_ROUTE) ? "yes" : "no", /* NAT=yes? */ 14004 ast_test_flag(&peer->flags[1], SIP_PAGE2_VIDEOSUPPORT) ? "yes" : "no", /* VIDEOSUPPORT=yes? */ 14005 ast_test_flag(&peer->flags[1], SIP_PAGE2_TEXTSUPPORT) ? "yes" : "no", /* TEXTSUPPORT=yes? */ 14006 peer->ha ? "yes" : "no", /* permit/deny */ 14007 status, 14008 realtimepeers ? (peer->is_realtime ? "yes":"no") : "no"); 14009 } 14010 ao2_unlock(peer); 14011 unref_peer(peer, "toss iterator peer ptr"); 14012 } 14013 14014 if (!s) 14015 ast_cli(fd, "%d sip peers [Monitored: %d online, %d offline Unmonitored: %d online, %d offline]\n", 14016 total_peers, peers_mon_online, peers_mon_offline, peers_unmon_online, peers_unmon_offline); 14017 14018 if (havepattern) 14019 regfree(®exbuf); 14020 14021 if (total) 14022 *total = total_peers; 14023 14024 ast_free(peerarray); 14025 14026 return CLI_SUCCESS; 14027 #undef FORMAT 14028 #undef FORMAT2 14029 }
| 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 2543 of file chan_sip.c.
References sip_threadinfo::alert_pipe, 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, errno, ast_tcptls_session_instance::f, sip_socket::fd, ast_tcptls_session_instance::fd, get_header(), handle_request_do(), tcptls_packet::len, sip_request::len, ast_tcptls_session_instance::lock, LOG_ERROR, LOG_WARNING, me, MIN, OBJ_POINTER, sip_threadinfo::packet_q, ast_tcptls_session_instance::parent, parse_request(), sip_socket::port, 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, sip_request::socket, ast_tcptls_session_instance::ssl, sip_threadinfo::stop, TCPTLS_ALERT_DATA, TCPTLS_ALERT_STOP, sip_socket::tcptls_session, sip_threadinfo::tcptls_session, sip_threadinfo::threadid, and ast_str::used.
Referenced by sip_tcp_worker_fn().
02544 { 02545 int res, cl; 02546 struct sip_request req = { 0, } , reqcpy = { 0, }; 02547 struct sip_threadinfo *me = NULL; 02548 char buf[1024] = ""; 02549 struct pollfd fds[2] = { { 0 }, { 0 }, }; 02550 struct ast_tcptls_session_args *ca = NULL; 02551 02552 /* If this is a server session, then the connection has already been setup, 02553 * simply create the threadinfo object so we can access this thread for writing. 02554 * 02555 * if this is a client connection more work must be done. 02556 * 1. We own the parent session args for a client connection. This pointer needs 02557 * to be held on to so we can decrement it's ref count on thread destruction. 02558 * 2. The threadinfo object was created before this thread was launched, however 02559 * it must be found within the threadt table. 02560 * 3. Last, the tcptls_session must be started. 02561 */ 02562 if (!tcptls_session->client) { 02563 if (!(me = sip_threadinfo_create(tcptls_session, tcptls_session->ssl ? SIP_TRANSPORT_TLS : SIP_TRANSPORT_TCP))) { 02564 goto cleanup; 02565 } 02566 ao2_t_ref(me, +1, "Adding threadinfo ref for tcp_helper_thread"); 02567 } else { 02568 struct sip_threadinfo tmp = { 02569 .tcptls_session = tcptls_session, 02570 }; 02571 02572 if ((!(ca = tcptls_session->parent)) || 02573 (!(me = ao2_t_find(threadt, &tmp, OBJ_POINTER, "ao2_find, getting sip_threadinfo in tcp helper thread"))) || 02574 (!(tcptls_session = ast_tcptls_client_start(tcptls_session)))) { 02575 goto cleanup; 02576 } 02577 } 02578 02579 me->threadid = pthread_self(); 02580 ast_debug(2, "Starting thread for %s server\n", tcptls_session->ssl ? "SSL" : "TCP"); 02581 02582 /* set up pollfd to watch for reads on both the socket and the alert_pipe */ 02583 fds[0].fd = tcptls_session->fd; 02584 fds[1].fd = me->alert_pipe[0]; 02585 fds[0].events = fds[1].events = POLLIN | POLLPRI; 02586 02587 if (!(req.data = ast_str_create(SIP_MIN_PACKET))) 02588 goto cleanup; 02589 if (!(reqcpy.data = ast_str_create(SIP_MIN_PACKET))) 02590 goto cleanup; 02591 02592 for (;;) { 02593 struct ast_str *str_save; 02594 02595 res = ast_poll(fds, 2, -1); /* polls for both socket and alert_pipe */ 02596 if (res < 0) { 02597 ast_debug(2, "SIP %s server :: ast_wait_for_input returned %d\n", tcptls_session->ssl ? "SSL": "TCP", res); 02598 goto cleanup; 02599 } 02600 02601 /* handle the socket event, check for both reads from the socket fd, 02602 * and writes from alert_pipe fd */ 02603 if (fds[0].revents) { /* there is data on the socket to be read */ 02604 02605 fds[0].revents = 0; 02606 02607 /* clear request structure */ 02608 str_save = req.data; 02609 memset(&req, 0, sizeof(req)); 02610 req.data = str_save; 02611 ast_str_reset(req.data); 02612 02613 str_save = reqcpy.data; 02614 memset(&reqcpy, 0, sizeof(reqcpy)); 02615 reqcpy.data = str_save; 02616 ast_str_reset(reqcpy.data); 02617 02618 memset(buf, 0, sizeof(buf)); 02619 02620 if (tcptls_session->ssl) { 02621 set_socket_transport(&req.socket, SIP_TRANSPORT_TLS); 02622 req.socket.port = htons(ourport_tls); 02623 } else { 02624 set_socket_transport(&req.socket, SIP_TRANSPORT_TCP); 02625 req.socket.port = htons(ourport_tcp); 02626 } 02627 req.socket.fd = tcptls_session->fd; 02628 02629 /* Read in headers one line at a time */ 02630 while (req.len < 4 || strncmp(REQ_OFFSET_TO_STR(&req, len - 4), "\r\n\r\n", 4)) { 02631 ast_mutex_lock(&tcptls_session->lock); 02632 if (!fgets(buf, sizeof(buf), tcptls_session->f)) { 02633 ast_mutex_unlock(&tcptls_session->lock); 02634 goto cleanup; 02635 } 02636 ast_mutex_unlock(&tcptls_session->lock); 02637 if (me->stop) 02638 goto cleanup; 02639 ast_str_append(&req.data, 0, "%s", buf); 02640 req.len = req.data->used; 02641 } 02642 copy_request(&reqcpy, &req); 02643 parse_request(&reqcpy); 02644 /* In order to know how much to read, we need the content-length header */ 02645 if (sscanf(get_header(&reqcpy, "Content-Length"), "%30d", &cl)) { 02646 while (cl > 0) { 02647 size_t bytes_read; 02648 ast_mutex_lock(&tcptls_session->lock); 02649 if (!(bytes_read = fread(buf, 1, MIN(sizeof(buf) - 1, cl), tcptls_session->f))) { 02650 ast_mutex_unlock(&tcptls_session->lock); 02651 goto cleanup; 02652 } 02653 buf[bytes_read] = '\0'; 02654 ast_mutex_unlock(&tcptls_session->lock); 02655 if (me->stop) 02656 goto cleanup; 02657 cl -= strlen(buf); 02658 ast_str_append(&req.data, 0, "%s", buf); 02659 req.len = req.data->used; 02660 } 02661 } 02662 /*! \todo XXX If there's no Content-Length or if the content-length and what 02663 we receive is not the same - we should generate an error */ 02664 02665 req.socket.tcptls_session = tcptls_session; 02666 handle_request_do(&req, &tcptls_session->remote_address); 02667 } 02668 if (fds[1].revents) { /* alert_pipe indicates there is data in the send queue to be sent */ 02669 enum sip_tcptls_alert alert; 02670 struct tcptls_packet *packet; 02671 02672 fds[1].revents = 0; 02673 02674 if (read(me->alert_pipe[0], &alert, sizeof(alert)) == -1) { 02675 ast_log(LOG_ERROR, "read() failed: %s\n", strerror(errno)); 02676 continue; 02677 } 02678 02679 switch (alert) { 02680 case TCPTLS_ALERT_STOP: 02681 goto cleanup; 02682 case TCPTLS_ALERT_DATA: 02683 ao2_lock(me); 02684 if (!(packet = AST_LIST_REMOVE_HEAD(&me->packet_q, entry))) { 02685 ast_log(LOG_WARNING, "TCPTLS thread alert_pipe indicated packet should be sent, but frame_q is empty"); 02686 } else if (ast_tcptls_server_write(tcptls_session, ast_str_buffer(packet->data), packet->len) == -1) { 02687 ast_log(LOG_WARNING, "Failure to write to tcp/tls socket\n"); 02688 } 02689 02690 if (packet) { 02691 ao2_t_ref(packet, -1, "tcptls packet sent, this is no longer needed"); 02692 } 02693 ao2_unlock(me); 02694 break; 02695 default: 02696 ast_log(LOG_ERROR, "Unknown tcptls thread alert '%d'\n", alert); 02697 } 02698 } 02699 } 02700 02701 ast_debug(2, "Shutting down thread for %s server\n", tcptls_session->ssl ? "SSL" : "TCP"); 02702 02703 cleanup: 02704 if (me) { 02705 ao2_t_unlink(threadt, me, "Removing tcptls helper thread, thread is closing"); 02706 ao2_t_ref(me, -1, "Removing tcp_helper_threads threadinfo ref"); 02707 } 02708 if (reqcpy.data) { 02709 ast_free(reqcpy.data); 02710 } 02711 02712 if (req.data) { 02713 ast_free(req.data); 02714 req.data = NULL; 02715 } 02716 02717 /* if client, we own the parent session arguments and must decrement ref */ 02718 if (ca) { 02719 ao2_t_ref(ca, -1, "closing tcptls thread, getting rid of client tcptls_session arguments"); 02720 } 02721 02722 if (tcptls_session) { 02723 ast_mutex_lock(&tcptls_session->lock); 02724 if (tcptls_session->f) { 02725 fclose(tcptls_session->f); 02726 tcptls_session->f = NULL; 02727 } 02728 if (tcptls_session->fd != -1) { 02729 close(tcptls_session->fd); 02730 tcptls_session->fd = -1; 02731 } 02732 tcptls_session->parent = NULL; 02733 ast_mutex_unlock(&tcptls_session->lock); 02734 02735 ao2_ref(tcptls_session, -1); 02736 tcptls_session = NULL; 02737 } 02738 02739 return NULL; 02740 }
| static int acf_channel_read | ( | struct ast_channel * | chan, | |
| const char * | funcname, | |||
| char * | preparse, | |||
| char * | buf, | |||
| size_t | buflen | |||
| ) | [static] |
Definition at line 19982 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(), sip_pvt::from, IS_SIP_TECH, ast_rtp_quality::local_count, ast_rtp_quality::local_jitter, ast_rtp_quality::local_lostpackets, ast_rtp_quality::local_ssrc, LOG_ERROR, LOG_WARNING, parse(), sip_pvt::peername, sip_pvt::recv, ast_rtp_quality::remote_count, ast_rtp_quality::remote_jitter, ast_rtp_quality::remote_lostpackets, ast_rtp_quality::remote_ssrc, sip_pvt::rtp, RTPQOS_SUMMARY, ast_rtp_quality::rtt, 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.
19983 { 19984 struct sip_pvt *p = chan->tech_pvt; 19985 char *all = "", *parse = ast_strdupa(preparse); 19986 int res = 0; 19987 AST_DECLARE_APP_ARGS(args, 19988 AST_APP_ARG(param); 19989 AST_APP_ARG(type); 19990 AST_APP_ARG(field); 19991 ); 19992 AST_STANDARD_APP_ARGS(args, parse); 19993 19994 /* Sanity check */ 19995 if (!IS_SIP_TECH(chan->tech)) { 19996 ast_log(LOG_ERROR, "Cannot call %s on a non-SIP channel\n", funcname); 19997 return 0; 19998 } 19999 20000 memset(buf, 0, buflen); 20001 20002 if (p == NULL) { 20003 return -1; 20004 } 20005 20006 if (!strcasecmp(args.param, "peerip")) { 20007 ast_copy_string(buf, p->sa.sin_addr.s_addr ? ast_inet_ntoa(p->sa.sin_addr) : "", buflen); 20008 } else if (!strcasecmp(args.param, "recvip")) { 20009 ast_copy_string(buf, p->recv.sin_addr.s_addr ? ast_inet_ntoa(p->recv.sin_addr) : "", buflen); 20010 } else if (!strcasecmp(args.param, "from")) { 20011 ast_copy_string(buf, p->from, buflen); 20012 } else if (!strcasecmp(args.param, "uri")) { 20013 ast_copy_string(buf, p->uri, buflen); 20014 } else if (!strcasecmp(args.param, "useragent")) { 20015 ast_copy_string(buf, p->useragent, buflen); 20016 } else if (!strcasecmp(args.param, "peername")) { 20017 ast_copy_string(buf, p->peername, buflen); 20018 } else if (!strcasecmp(args.param, "t38passthrough")) { 20019 ast_copy_string(buf, (p->t38.state == T38_DISABLED) ? "0" : "1", buflen); 20020 } else if (!strcasecmp(args.param, "rtpdest")) { 20021 struct sockaddr_in sin; 20022 20023 if (ast_strlen_zero(args.type)) 20024 args.type = "audio"; 20025 20026 if (!strcasecmp(args.type, "audio")) 20027 ast_rtp_get_peer(p->rtp, &sin); 20028 else if (!strcasecmp(args.type, "video")) 20029 ast_rtp_get_peer(p->vrtp, &sin); 20030 else if (!strcasecmp(args.type, "text")) 20031 ast_rtp_get_peer(p->trtp, &sin); 20032 else 20033 return -1; 20034 20035 snprintf(buf, buflen, "%s:%d", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 20036 } else if (!strcasecmp(args.param, "rtpqos")) { 20037 struct ast_rtp_quality qos; 20038 struct ast_rtp *rtp = p->rtp; 20039 20040 memset(&qos, 0, sizeof(qos)); 20041 20042 if (ast_strlen_zero(args.type)) 20043 args.type = "audio"; 20044 if (ast_strlen_zero(args.field)) 20045 args.field = "all"; 20046 20047 if (!strcasecmp(args.type, "AUDIO")) { 20048 all = ast_rtp_get_quality(rtp = p->rtp, &qos, RTPQOS_SUMMARY); 20049 } else if (!strcasecmp(args.type, "VIDEO")) { 20050 all = ast_rtp_get_quality(rtp = p->vrtp, &qos, RTPQOS_SUMMARY); 20051 } else if (!strcasecmp(args.type, "TEXT")) { 20052 all = ast_rtp_get_quality(rtp = p->trtp, &qos, RTPQOS_SUMMARY); 20053 } else { 20054 return -1; 20055 } 20056 20057 if (!strcasecmp(args.field, "local_ssrc")) 20058 snprintf(buf, buflen, "%u", qos.local_ssrc); 20059 else if (!strcasecmp(args.field, "local_lostpackets")) 20060 snprintf(buf, buflen, "%u", qos.local_lostpackets); 20061 else if (!strcasecmp(args.field, "local_jitter")) 20062 snprintf(buf, buflen, "%.0f", qos.local_jitter * 1000.0); 20063 else if (!strcasecmp(args.field, "local_count")) 20064 snprintf(buf, buflen, "%u", qos.local_count); 20065 else if (!strcasecmp(args.field, "remote_ssrc")) 20066 snprintf(buf, buflen, "%u", qos.remote_ssrc); 20067 else if (!strcasecmp(args.field, "remote_lostpackets")) 20068 snprintf(buf, buflen, "%u", qos.remote_lostpackets); 20069 else if (!strcasecmp(args.field, "remote_jitter")) 20070 snprintf(buf, buflen, "%.0f", qos.remote_jitter * 1000.0); 20071 else if (!strcasecmp(args.field, "remote_count")) 20072 snprintf(buf, buflen, "%u", qos.remote_count); 20073 else if (!strcasecmp(args.field, "rtt")) 20074 snprintf(buf, buflen, "%.0f", qos.rtt * 1000.0); 20075 else if (!strcasecmp(args.field, "all")) 20076 ast_copy_string(buf, all, buflen); 20077 else if (!ast_rtp_get_qos(rtp, args.field, buf, buflen)) 20078 ; 20079 else { 20080 ast_log(LOG_WARNING, "Unrecognized argument '%s' to %s\n", preparse, funcname); 20081 return -1; 20082 } 20083 } else { 20084 res = -1; 20085 } 20086 return res; 20087 }
| static void add_blank | ( | struct sip_request * | req | ) | [static] |
add a blank line if no body
Definition at line 3762 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().
| 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 9192 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().
09195 { 09196 int rtp_code; 09197 struct ast_format_list fmt; 09198 09199 09200 if (debug) 09201 ast_verbose("Adding codec 0x%x (%s) to SDP\n", codec, ast_getformatname(codec)); 09202 if ((rtp_code = ast_rtp_lookup_code(p->rtp, 1, codec)) == -1) 09203 return; 09204 09205 if (p->rtp) { 09206 struct ast_codec_pref *pref = ast_rtp_codec_getpref(p->rtp); 09207 fmt = ast_codec_pref_getsize(pref, codec); 09208 } 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 */ 09209 return; 09210 ast_str_append(m_buf, 0, " %d", rtp_code); 09211 ast_str_append(a_buf, 0, "a=rtpmap:%d %s/%d\r\n", rtp_code, 09212 ast_rtp_lookup_mime_subtype(1, codec, 09213 ast_test_flag(&p->flags[0], SIP_G726_NONSTANDARD) ? AST_RTP_OPT_G726_NONSTANDARD : 0), 09214 sample_rate); 09215 if (codec == AST_FORMAT_G729A) { 09216 /* Indicate that we don't support VAD (G.729 annex B) */ 09217 ast_str_append(a_buf, 0, "a=fmtp:%d annexb=no\r\n", rtp_code); 09218 } else if (codec == AST_FORMAT_G723_1) { 09219 /* Indicate that we don't support VAD (G.723.1 annex A) */ 09220 ast_str_append(a_buf, 0, "a=fmtp:%d annexa=no\r\n", rtp_code); 09221 } else if (codec == AST_FORMAT_ILBC) { 09222 /* Add information about us using only 20/30 ms packetization */ 09223 ast_str_append(a_buf, 0, "a=fmtp:%d mode=%d\r\n", rtp_code, fmt.cur_ms); 09224 } 09225 09226 if (fmt.cur_ms && (fmt.cur_ms < *min_packet_size)) 09227 *min_packet_size = fmt.cur_ms; 09228 09229 /* Our first codec packetization processed cannot be zero */ 09230 if ((*min_packet_size)==0 && fmt.cur_ms) 09231 *min_packet_size = fmt.cur_ms; 09232 }
| 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 9143 of file chan_sip.c.
References add_header(), add_header_contentLength(), and add_line().
Referenced by transmit_info_with_digit().
09144 { 09145 char tmp[256]; 09146 int event; 09147 if (mode) { 09148 /* Application/dtmf short version used by some implementations */ 09149 if (digit == '*') 09150 event = 10; 09151 else if (digit == '#') 09152 event = 11; 09153 else if ((digit >= 'A') && (digit <= 'D')) 09154 event = 12 + digit - 'A'; 09155 else 09156 event = atoi(&digit); 09157 snprintf(tmp, sizeof(tmp), "%d\r\n", event); 09158 add_header(req, "Content-Type", "application/dtmf"); 09159 add_header_contentLength(req, strlen(tmp)); 09160 add_line(req, tmp); 09161 } else { 09162 /* Application/dtmf-relay as documented by Cisco */ 09163 snprintf(tmp, sizeof(tmp), "Signal=%c\r\nDuration=%u\r\n", digit, duration); 09164 add_header(req, "Content-Type", "application/dtmf-relay"); 09165 add_header_contentLength(req, strlen(tmp)); 09166 add_line(req, tmp); 09167 } 09168 return 0; 09169 }
| static int add_header | ( | struct sip_request * | req, | |
| const char * | var, | |||
| const char * | value | |||
| ) | [static] |
Add header to SIP message.
Definition at line 8394 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.
Referenced by __transmit_response(), add_digit(), add_header_contentLength(), add_route(), add_sdp(), add_text(), add_vidupdate(), append_date(), copy_all_header(), copy_header(), copy_via_headers(), initreqprep(), reqprep(), respprep(), transmit_invite(), transmit_notify_custom(), transmit_notify_with_mwi(), transmit_notify_with_sipfrag(), transmit_refer(), transmit_register(), transmit_reinvite_with_sdp(), transmit_request(), transmit_request_with_auth(), transmit_response_with_allow(), transmit_response_with_auth(), transmit_response_with_minse(), transmit_response_with_unsupported(), and transmit_state_notify().
08395 { 08396 if (req->headers == SIP_MAX_HEADERS) { 08397 ast_log(LOG_WARNING, "Out of SIP header space\n"); 08398 return -1; 08399 } 08400 08401 if (req->lines) { 08402 ast_log(LOG_WARNING, "Can't add more headers when lines have been added\n"); 08403 return -1; 08404 } 08405 08406 if (compactheaders) 08407 var = find_alias(var, var); 08408 08409 ast_str_append(&req->data, 0, "%s: %s\r\n", var, value); 08410 req->header[req->headers] = req->len; 08411 08412 req->len = req->data->used; 08413 req->headers++; 08414 08415 return 0; 08416 }
| static int add_header_contentLength | ( | struct sip_request * | req, | |
| int | len | |||
| ) | [static] |
Add 'Content-Length' header to SIP message.
Definition at line 8419 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().
08420 { 08421 char clen[10]; 08422 08423 snprintf(clen, sizeof(clen), "%d", len); 08424 return add_header(req, "Content-Length", clen); 08425 }
| static int add_line | ( | struct sip_request * | req, | |
| const char * | line | |||
| ) | [static] |
Add content (not header) to SIP message.
Definition at line 8428 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.
Referenced by add_digit(), add_sdp(), add_text(), add_vidupdate(), transmit_notify_with_mwi(), transmit_notify_with_sipfrag(), and transmit_state_notify().
08429 { 08430 if (req->lines == SIP_MAX_LINES) { 08431 ast_log(LOG_WARNING, "Out of SIP line space\n"); 08432 return -1; 08433 } 08434 if (!req->lines) 08435 /* Add extra empty return */ 08436 req->len += ast_str_append(&req->data, 0, "\r\n"); 08437 req->line[req->lines] = req->len; 08438 ast_str_append(&req->data, 0, "%s", line); 08439 req->len = req->data->used; 08440 req->lines++; 08441 return 0; 08442 }
| 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 9310 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().
09313 { 09314 int rtp_code; 09315 09316 if (debug) 09317 ast_verbose("Adding non-codec 0x%x (%s) to SDP\n", format, ast_rtp_lookup_mime_subtype(0, format, 0)); 09318 if ((rtp_code = ast_rtp_lookup_code(p->rtp, 0, format)) == -1) 09319 return; 09320 09321 ast_str_append(m_buf, 0, " %d", rtp_code); 09322 ast_str_append(a_buf, 0, "a=rtpmap:%d %s/%d\r\n", rtp_code, 09323 ast_rtp_lookup_mime_subtype(0, format, 0), 09324 sample_rate); 09325 if (format == AST_RTP_DTMF) /* Indicate we support DTMF and FLASH... */ 09326 ast_str_append(a_buf, 0, "a=fmtp:%d 0-16\r\n", rtp_code); 09327 }
| static void add_peer_mailboxes | ( | struct sip_peer * | peer, | |
| const char * | value | |||
| ) | [static] |
Definition at line 22714 of file chan_sip.c.
References ast_calloc, ast_free, AST_LIST_INSERT_TAIL, ast_strdup, ast_strdupa, ast_strlen_zero(), sip_mailbox::context, context, sip_mailbox::mailbox, mailbox, sip_peer::mailboxes, mbox(), and strsep().
Referenced by build_peer().
22715 { 22716 char *next, *mbox, *context; 22717 22718 next = ast_strdupa(value); 22719 22720 while ((mbox = context = strsep(&next, ","))) { 22721 struct sip_mailbox *mailbox; 22722 22723 if (!(mailbox = ast_calloc(1, sizeof(*mailbox)))) 22724 continue; 22725 22726 strsep(&context, "@"); 22727 if (ast_strlen_zero(mbox)) { 22728 ast_free(mailbox); 22729 continue; 22730 } 22731 mailbox->mailbox = ast_strdup(mbox); 22732 mailbox->context = ast_strdup(context); 22733 22734 AST_LIST_INSERT_TAIL(&peer->mailboxes, mailbox, entry); 22735 } 22736 }
| static void add_peer_mwi_subs | ( | struct sip_peer * | peer | ) | [static] |
Definition at line 20228 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::context, sip_mailbox::event_sub, sip_mailbox::mailbox, mailbox, sip_peer::mailboxes, mwi_event_cb(), and S_OR.
Referenced by build_peer(), and handle_request_subscribe().
20229 { 20230 struct sip_mailbox *mailbox; 20231 20232 AST_LIST_TRAVERSE(&peer->mailboxes, mailbox, entry) { 20233 mailbox->event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, peer, 20234 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox->mailbox, 20235 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, S_OR(mailbox->context, "default"), 20236 AST_EVENT_IE_END); 20237 } 20238 }
| static struct sip_auth * add_realm_authentication | ( | struct sip_auth * | authlist, | |
| const char * | configuration, | |||
| int | lineno | |||
| ) | [static, read] |
Add realm authentication in list.
Definition at line 22538 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, sip_auth::secret, secret, and sip_auth::username.
Referenced by build_peer(), and reload_config().
22539 { 22540 char authcopy[256]; 22541 char *username=NULL, *realm=NULL, *secret=NULL, *md5secret=NULL; 22542 struct sip_auth *a, *b, *auth; 22543 22544 if (ast_strlen_zero(configuration)) 22545 return authlist; 22546 22547 ast_debug(1, "Auth config :: %s\n", configuration); 22548 22549 ast_copy_string(authcopy, configuration, sizeof(authcopy)); 22550 username = authcopy; 22551 22552 /* split user[:secret] and relm */ 22553 realm = strrchr(username, '@'); 22554 if (realm) 22555 *realm++ = '\0'; 22556 if (ast_strlen_zero(username) || ast_strlen_zero(realm)) { 22557 ast_log(LOG_WARNING, "Format for authentication entry is user[:secret]@realm at line %d\n", lineno); 22558 return authlist; 22559 } 22560 22561 /* parse username at ':' for secret, or '#" for md5secret */ 22562 if ((secret = strchr(username, ':'))) { 22563 *secret++ = '\0'; 22564 } else if ((md5secret = strchr(username, '#'))) { 22565 *md5secret++ = '\0'; 22566 } 22567 22568 if (!(auth = ast_calloc(1, sizeof(*auth)))) 22569 return authlist; 22570 22571 ast_copy_string(auth->realm, realm, sizeof(auth->realm)); 22572 ast_copy_string(auth->username, username, sizeof(auth->username)); 22573 if (secret) 22574 ast_copy_string(auth->secret, secret, sizeof(auth->secret)); 22575 if (md5secret) 22576 ast_copy_string(auth->md5secret, md5secret, sizeof(auth->md5secret)); 22577 22578 /* find the end of the list */ 22579 for (b = NULL, a = authlist; a ; b = a, a = a->next) 22580 ; 22581 if (b) 22582 b->next = auth; /* Add structure add end of list */ 22583 else 22584 authlist = auth; 22585 22586 ast_verb(3, "Added authentication for realm %s\n", realm); 22587 22588 return authlist; 22589 22590 }
| static void add_route | ( | struct sip_request * | req, | |
| struct sip_route * | route | |||
| ) | [static] |
Add route header into request per learned route.
Definition at line 8545 of file chan_sip.c.
References add_header(), ast_copy_string(), sip_route::hop, sip_route::next, and SIPBUFSIZE.
Referenced by initreqprep(), and reqprep().
08546 { 08547 char r[SIPBUFSIZE*2], *p; 08548 int n, rem = sizeof(r); 08549 08550 if (!route) 08551 return; 08552 08553 p = r; 08554 for (;route ; route = route->next) { 08555 n = strlen(route->hop); 08556 if (rem < n+3) /* we need room for ",<route>" */ 08557 break; 08558 if (p != r) { /* add a separator after fist route */ 08559 *p++ = ','; 08560 --rem; 08561 } 08562 *p++ = '<'; 08563 ast_copy_string(p, route->hop, rem); /* cannot fail */ 08564 p += n; 08565 *p++ = '>'; 08566 rem -= (n+2); 08567 } 08568 *p = '\0'; 08569 add_header(req, "Route", r); 08570 }
| 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 9378 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, offered_media::offered, 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(), offered_media::text, 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.
Referenced by transmit_invite(), transmit_reinvite_with_sdp(), transmit_response_with_sdp(), and transmit_response_with_t38_sdp().
09379 { 09380 int len = 0; 09381 int alreadysent = 0; 09382 09383 struct sockaddr_in sin; 09384 struct sockaddr_in vsin; 09385 struct sockaddr_in tsin; 09386 struct sockaddr_in dest; 09387 struct sockaddr_in udptlsin; 09388 struct sockaddr_in vdest = { 0, }; 09389 struct sockaddr_in tdest = { 0, }; 09390 struct sockaddr_in udptldest = { 0, }; 09391 09392 /* SDP fields */ 09393 char *version = "v=0\r\n"; /* Protocol version */ 09394 char subject[256]; /* Subject of the session */ 09395 char owner[256]; /* Session owner/creator */ 09396 char connection[256]; /* Connection data */ 09397 char *session_time = "t=0 0\r\n"; /* Time the session is active */ 09398 char bandwidth[256] = ""; /* Max bitrate */ 09399 char *hold = ""; 09400 struct ast_str *m_audio = ast_str_alloca(256); /* Media declaration line for audio */ 09401 struct ast_str *m_video = ast_str_alloca(256); /* Media declaration line for video */ 09402 struct ast_str *m_text = ast_str_alloca(256); /* Media declaration line for text */ 09403 struct ast_str *m_modem = ast_str_alloca(256); /* Media declaration line for modem */ 09404 struct ast_str *a_audio = ast_str_alloca(1024); /* Attributes for audio */ 09405 struct ast_str *a_video = ast_str_alloca(1024); /* Attributes for video */ 09406 struct ast_str *a_text = ast_str_alloca(1024); /* Attributes for text */ 09407 struct ast_str *a_modem = ast_str_alloca(1024); /* Attributes for modem */ 09408 09409 int x; 09410 int capability = 0; 09411 int needaudio = FALSE; 09412 int needvideo = FALSE; 09413 int needtext = FALSE; 09414 int debug = sip_debug_test_pvt(p); 09415 int min_audio_packet_size = 0; 09416 int min_video_packet_size = 0; 09417 int min_text_packet_size = 0; 09418 09419 char codecbuf[SIPBUFSIZE]; 09420 char buf[SIPBUFSIZE]; 09421 char dummy_answer[256]; 09422 09423 /* Set the SDP session name */ 09424 snprintf(subject, sizeof(subject), "s=%s\r\n", ast_strlen_zero(global_sdpsession) ? "-" : global_sdpsession); 09425 09426 if (!p->rtp) { 09427 ast_log(LOG_WARNING, "No way to add SDP without an RTP structure\n"); 09428 return AST_FAILURE; 09429 } 09430 /* XXX We should not change properties in the SIP dialog until 09431 we have acceptance of the offer if this is a re-invite */ 09432 09433 /* Set RTP Session ID and version */ 09434 if (!p->sessionid) { 09435 p->sessionid = (int)ast_random(); 09436 p->sessionversion = p->sessionid; 09437 } else { 09438 if (oldsdp == FALSE) 09439 p->sessionversion++; 09440 } 09441 09442 if (add_audio) { 09443 /* Check if we need video in this call */ 09444 if ((p->jointcapability & AST_FORMAT_VIDEO_MASK) && !p->novideo) { 09445 if (p->vrtp) { 09446 needvideo = TRUE; 09447 ast_debug(2, "This call needs video offers!\n"); 09448 } else 09449 ast_debug(2, "This call needs video offers, but there's no video support enabled!\n"); 09450 } 09451 /* Check if we need text in this call */ 09452 if ((p->jointcapability & AST_FORMAT_TEXT_MASK) && !p->notext) { 09453 if (sipdebug_text) 09454 ast_verbose("We think we can do text\n"); 09455 if (p->trtp) { 09456 if (sipdebug_text) { 09457 ast_verbose("And we have a text rtp object\n"); 09458 } 09459 needtext = TRUE; 09460 ast_debug(2, "This call needs text offers! \n"); 09461 } else { 09462 ast_debug(2, "This call needs text offers, but there's no text support enabled ! \n"); 09463 } 09464 } 09465 } 09466 09467 get_our_media_address(p, needvideo, &sin, &vsin, &tsin, &dest, &vdest); 09468 09469 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)); 09470 snprintf(connection, sizeof(connection), "c=IN IP4 %s\r\n", ast_inet_ntoa(dest.sin_addr)); 09471 09472 if (add_audio) { 09473 capability = p->jointcapability; 09474 09475 /* XXX note, Video and Text are negated - 'true' means 'no' */ 09476 ast_debug(1, "** Our capability: %s Video flag: %s Text flag: %s\n", ast_getformatname_multiple(codecbuf, sizeof(codecbuf), capability), 09477 p->novideo ? "True" : "False", p->notext ? "True" : "False"); 09478 ast_debug(1, "** Our prefcodec: %s \n", ast_getformatname_multiple(codecbuf, sizeof(codecbuf), p->prefcodec)); 09479 09480 /* Check if we need audio */ 09481 if (capability & AST_FORMAT_AUDIO_MASK) 09482 needaudio = TRUE; 09483 09484 if (debug) 09485 ast_verbose("Audio is at %s port %d\n", ast_inet_ntoa(p->ourip.sin_addr), ntohs(sin.sin_port)); 09486 09487 /* Ok, we need video. Let's add what we need for video and set codecs. 09488 Video is handled differently than audio since we can not transcode. */ 09489 if (needvideo) { 09490 ast_str_append(&m_video, 0, "m=video %d RTP/AVP", ntohs(vdest.sin_port)); 09491 09492 /* Build max bitrate string */ 09493 if (p->maxcallbitrate) 09494 snprintf(bandwidth, sizeof(bandwidth), "b=CT:%d\r\n", p->maxcallbitrate); 09495 if (debug) 09496 ast_verbose("Video is at %s port %d\n", ast_inet_ntoa(p->ourip.sin_addr), ntohs(vdest.sin_port)); 09497 } 09498 09499 /* Ok, we need text. Let's add what we need for text and set codecs. 09500 Text is handled differently than audio since we can not transcode. */ 09501 if (needtext) { 09502 if (sipdebug_text) 09503 ast_verbose("Lets set up the text sdp\n"); 09504 /* Determine text destination */ 09505 if (p->tredirip.sin_addr.s_addr) { 09506 tdest.sin_addr = p->tredirip.sin_addr; 09507 tdest.sin_port = p->tredirip.sin_port; 09508 } else { 09509 tdest.sin_addr = p->ourip.sin_addr; 09510 tdest.sin_port = tsin.sin_port; 09511 } 09512 ast_str_append(&m_text, 0, "m=text %d RTP/AVP", ntohs(tdest.sin_port)); 09513 09514 if (debug) /* XXX should I use tdest below ? */ 09515 ast_verbose("Text is at %s port %d\n", ast_inet_ntoa(p->ourip.sin_addr), ntohs(tsin.sin_port)); 09516 09517 } 09518 09519 /* Start building generic SDP headers */ 09520 09521 /* We break with the "recommendation" and send our IP, in order that our 09522 peer doesn't have to ast_gethostbyname() us */ 09523 09524 ast_str_append(&m_audio, 0, "m=audio %d RTP/AVP", ntohs(dest.sin_port)); 09525 09526 if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD) == SIP_PAGE2_CALL_ONHOLD_ONEDIR) 09527 hold = "a=recvonly\r\n"; 09528 else if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD) == SIP_PAGE2_CALL_ONHOLD_INACTIVE) 09529 hold = "a=inactive\r\n"; 09530 else 09531 hold = "a=sendrecv\r\n"; 09532 09533 /* Now, start adding audio codecs. These are added in this order: 09534 - First what was requested by the calling channel 09535 - Then preferences in order from sip.conf device config for this peer/user 09536 - Then other codecs in capabilities, including video 09537 */ 09538 09539 /* Prefer the audio codec we were requested to use, first, no matter what 09540 Note that p->prefcodec can include video codecs, so mask them out 09541 */ 09542 if (capability & p->prefcodec) { 09543 int codec = p->prefcodec & AST_FORMAT_AUDIO_MASK; 09544 09545 add_codec_to_sdp(p, codec, SDP_SAMPLE_RATE(codec), 09546 &m_audio, &a_audio, 09547 debug, &min_audio_packet_size); 09548 alreadysent |= codec; 09549 } 09550 09551 /* Start by sending our preferred audio/video codecs */ 09552 for (x = 0; x < 32; x++) { 09553 int codec; 09554 09555 if (!(codec = ast_codec_pref_index(&p->prefs, x))) 09556 break; 09557 09558 if (!(capability & codec)) 09559 continue; 09560 09561 if (alreadysent & codec) 09562 continue; 09563 09564 add_codec_to_sdp(p, codec, SDP_SAMPLE_RATE(codec), 09565 &m_audio, &a_audio, 09566 debug, &min_audio_packet_size); 09567 alreadysent |= codec; 09568 } 09569 09570 /* Now send any other common audio and video codecs, and non-codec formats: */ 09571 for (x = 1; x <= (needtext ? AST_FORMAT_TEXT_MASK : (needvideo ? AST_FORMAT_VIDEO_MASK : AST_FORMAT_AUDIO_MASK)); x <<= 1) { 09572 if (!(capability & x)) /* Codec not requested */ 09573 continue; 09574 09575 if (alreadysent & x) /* Already added to SDP */ 09576 continue; 09577 09578 if (x & AST_FORMAT_AUDIO_MASK) 09579 add_codec_to_sdp(p, x, SDP_SAMPLE_RATE(x), 09580 &m_audio, &a_audio, debug, &min_audio_packet_size); 09581 else if (x & AST_FORMAT_VIDEO_MASK) 09582 add_vcodec_to_sdp(p, x, 90000, 09583 &m_video, &a_video, debug, &min_video_packet_size); 09584 else if (x & AST_FORMAT_TEXT_MASK) 09585 add_tcodec_to_sdp(p, x, 1000, 09586 &m_text, &a_text, debug, &min_text_packet_size); 09587 } 09588 09589 /* Now add DTMF RFC2833 telephony-event as a codec */ 09590 for (x = 1; x <= AST_RTP_MAX; x <<= 1) { 09591 if (!(p->jointnoncodeccapability & x)) 09592 continue; 09593 09594 add_noncodec_to_sdp(p, x, 8000, &m_audio, &a_audio, debug); 09595 } 09596 09597 ast_debug(3, "-- Done with adding codecs to SDP\n"); 09598 09599 if (!p->owner || !ast_internal_timing_enabled(p->owner)) 09600 ast_str_append(&a_audio, 0, "a=silenceSupp:off - - - -\r\n"); 09601 09602 if (min_audio_packet_size) 09603 ast_str_append(&a_audio, 0, "a=ptime:%d\r\n", min_audio_packet_size); 09604 09605 /* XXX don't think you can have ptime for video */ 09606 if (min_video_packet_size) 09607 ast_str_append(&a_video, 0, "a=ptime:%d\r\n", min_video_packet_size); 09608 09609 /* XXX don't think you can have ptime for text */ 09610 if (min_text_packet_size) 09611 ast_str_append(&a_text, 0, "a=ptime:%d\r\n", min_text_packet_size); 09612 } 09613 09614 if (add_t38) { 09615 ast_udptl_get_us(p->udptl, &udptlsin); 09616 09617 /* Determine T.38 UDPTL destination */ 09618 if (p->udptlredirip.sin_addr.s_addr) { 09619 udptldest.sin_port = p->udptlredirip.sin_port; 09620 udptldest.sin_addr = p->udptlredirip.sin_addr; 09621 } else { 09622 udptldest.sin_addr = p->ourip.sin_addr; 09623 udptldest.sin_port = udptlsin.sin_port; 09624 } 09625 09626 if (debug) 09627 ast_debug(1, "T.38 UDPTL is at %s port %d\n", ast_inet_ntoa(p->ourip.sin_addr), ntohs(udptlsin.sin_port)); 09628 09629 /* We break with the "recommendation" and send our IP, in order that our 09630 peer doesn't have to ast_gethostbyname() us */ 09631 09632 ast_str_append(&m_modem, 0, "m=image %d udptl t38\r\n", ntohs(udptldest.sin_port)); 09633 09634 ast_str_append(&a_modem, 0, "a=T38FaxVersion:%d\r\n", p->t38.our_parms.version); 09635 ast_str_append(&a_modem, 0, "a=T38MaxBitRate:%d\r\n", t38_get_rate(p->t38.our_parms.rate)); 09636 if (p->t38.our_parms.fill_bit_removal) { 09637 ast_str_append(&a_modem, 0, "a=T38FaxFillBitRemoval\r\n"); 09638 } 09639 if (p->t38.our_parms.transcoding_mmr) { 09640 ast_str_append(&a_modem, 0, "a=T38FaxTranscodingMMR\r\n"); 09641 } 09642 if (p->t38.our_parms.transcoding_jbig) { 09643 ast_str_append(&a_modem, 0, "a=T38FaxTranscodingJBIG\r\n"); 09644 } 09645 switch (p->t38.our_parms.rate_management) { 09646 case AST_T38_RATE_MANAGEMENT_TRANSFERRED_TCF: 09647 ast_str_append(&a_modem, 0, "a=T38FaxRateManagement:transferredTCF\r\n"); 09648 break; 09649 case AST_T38_RATE_MANAGEMENT_LOCAL_TCF: 09650 ast_str_append(&a_modem, 0, "a=T38FaxRateManagement:localTCF\r\n"); 09651 break; 09652 } 09653 ast_str_append(&a_modem, 0, "a=T38FaxMaxDatagram:%u\r\n", ast_udptl_get_local_max_datagram(p->udptl)); 09654 switch (ast_udptl_get_error_correction_scheme(p->udptl)) { 09655 case UDPTL_ERROR_CORRECTION_NONE: 09656 break; 09657 case UDPTL_ERROR_CORRECTION_FEC: 09658 ast_str_append(&a_modem, 0, "a=T38FaxUdpEC:t38UDPFEC\r\n"); 09659 break; 09660 case UDPTL_ERROR_CORRECTION_REDUNDANCY: 09661 ast_str_append(&a_modem, 0, "a=T38FaxUdpEC:t38UDPRedundancy\r\n"); 09662 break; 09663 } 09664 } 09665 09666 if (m_audio->len - m_audio->used < 2 || m_video->len - m_video->used < 2 || 09667 m_text->len - m_text->used < 2 || a_text->len - a_text->used < 2 || 09668 a_audio->len - a_audio->used < 2 || a_video->len - a_video->used < 2) 09669 ast_log(LOG_WARNING, "SIP SDP may be truncated due to undersized buffer!!\n"); 09670 09671 if (needaudio) 09672 ast_str_append(&m_audio, 0, "\r\n"); 09673 if (needvideo) 09674 ast_str_append(&m_video, 0, "\r\n"); 09675 if (needtext) 09676 ast_str_append(&m_text, 0, "\r\n"); 09677 09678 len = strlen(version) + strlen(subject) + strlen(owner) + 09679 strlen(connection) + strlen(session_time); 09680 if (needaudio) 09681 len += m_audio->used + a_audio->used + strlen(hold); 09682 if (needvideo) /* only if video response is appropriate */ 09683 len += m_video->used + a_video->used + strlen(bandwidth) + strlen(hold); 09684 if (needtext) /* only if text response is appropriate */ 09685 len += m_text->used + a_text->used + strlen(hold); 09686 if (add_t38) 09687 len += m_modem->used + a_modem->used; 09688 09689 add_header(resp, "Content-Type", "application/sdp"); 09690 add_header_contentLength(resp, len); 09691 add_line(resp, version); 09692 add_line(resp, owner); 09693 add_line(resp, subject); 09694 add_line(resp, connection); 09695 if (needvideo) /* only if video response is appropriate */ 09696 add_line(resp, bandwidth); 09697 add_line(resp, session_time); 09698 if (needaudio) { 09699 add_line(resp, m_audio->str); 09700 add_line(resp, a_audio->str); 09701 add_line(resp, hold); 09702 } else if (p->offered_media[SDP_AUDIO].offered) { 09703 snprintf(dummy_answer, sizeof(dummy_answer), "m=audio 0 RTP/AVP %s\r\n", p->offered_media[SDP_AUDIO].text); 09704 add_line(resp, dummy_answer); 09705 } 09706 if (needvideo) { /* only if video response is appropriate */ 09707 add_line(resp, m_video->str); 09708 add_line(resp, a_video->str); 09709 add_line(resp, hold); /* Repeat hold for the video stream */ 09710 } else if (p->offered_media[SDP_VIDEO].offered) { 09711 snprintf(dummy_answer, sizeof(dummy_answer), "m=video 0 RTP/AVP %s\r\n", p->offered_media[SDP_VIDEO].text); 09712 add_line(resp, dummy_answer); 09713 } 09714 if (needtext) { /* only if text response is appropriate */ 09715 add_line(resp, m_text->str); 09716 add_line(resp, a_text->str); 09717 add_line(resp, hold); /* Repeat hold for the text stream */ 09718 } else if (p->offered_media[SDP_TEXT].offered) { 09719 snprintf(dummy_answer, sizeof(dummy_answer), "m=text 0 RTP/AVP %s\r\n", p->offered_media[SDP_TEXT].text); 09720 add_line(resp, dummy_answer); 09721 } 09722 if (add_t38) { 09723 add_line(resp, m_modem->str); 09724 add_line(resp, a_modem->str); 09725 } else if (p->offered_media[SDP_IMAGE].offered) { 09726 add_line(resp, "m=image 0 udptl t38\r\n"); 09727 } 09728 09729 /* Update lastrtprx when we send our SDP */ 09730 p->lastrtprx = p->lastrtptx = time(NULL); /* XXX why both ? */ 09731 09732 ast_debug(3, "Done building SDP. Settling with this capability: %s\n", ast_getformatname_multiple(buf, SIPBUFSIZE, capability)); 09733 09734 return AST_SUCCESS; 09735 }
| 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 22474 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::context, domain::domain, LOG_WARNING, and domain::mode.
Referenced by reload_config().
22475 { 22476 struct domain *d; 22477 22478 if (ast_strlen_zero(domain)) { 22479 ast_log(LOG_WARNING, "Zero length domain.\n"); 22480 return 1; 22481 } 22482 22483 if (!(d = ast_calloc(1, sizeof(*d)))) 22484 return 0; 22485 22486 ast_copy_string(d->domain, domain, sizeof(d->domain)); 22487 22488 if (!ast_strlen_zero(context)) 22489 ast_copy_string(d->context, context, sizeof(d->context)); 22490 22491 d->mode = mode; 22492 22493 AST_LIST_LOCK(&domain_list); 22494 AST_LIST_INSERT_TAIL(&domain_list, d, list); 22495 AST_LIST_UNLOCK(&domain_list); 22496 22497 if (sipdebug) 22498 ast_debug(1, "Added local SIP domain '%s'\n", domain); 22499 22500 return 1; 22501 }
| 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 9258 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().
09261 { 09262 int rtp_code; 09263 09264 if (!p->trtp) 09265 return; 09266 09267 if (debug) 09268 ast_verbose("Adding text codec 0x%x (%s) to SDP\n", codec, ast_getformatname(codec)); 09269 09270 if ((rtp_code = ast_rtp_lookup_code(p->trtp, 1, codec)) == -1) 09271 return; 09272 09273 ast_str_append(m_buf, 0, " %d", rtp_code); 09274 ast_str_append(a_buf, 0, "a=rtpmap:%d %s/%d\r\n", rtp_code, 09275 ast_rtp_lookup_mime_subtype(1, codec, 0), sample_rate); 09276 /* Add fmtp code here */ 09277 09278 if (codec == AST_FORMAT_T140RED) { 09279 ast_str_append(a_buf, 0, "a=fmtp:%d %d/%d/%d\r\n", rtp_code, 09280 ast_rtp_lookup_code(p->trtp, 1, AST_FORMAT_T140), 09281 ast_rtp_lookup_code(p->trtp, 1, AST_FORMAT_T140), 09282 ast_rtp_lookup_code(p->trtp, 1, AST_FORMAT_T140)); 09283 09284 } 09285 }
| static int add_text | ( | struct sip_request * | req, | |
| const char * | text | |||
| ) | [static] |
Add text body to SIP message.
Definition at line 9130 of file chan_sip.c.
References add_header(), add_header_contentLength(), and add_line().
Referenced by transmit_message_with_text().
09131 { 09132 /* XXX Convert \n's to \r\n's XXX */ 09133 add_header(req, "Content-Type", "text/plain;charset=UTF-8"); 09134 add_header_contentLength(req, strlen(text)); 09135 add_line(req, text); 09136 return 0; 09137 }
| static struct ast_variable* add_var | ( | const char * | buf, | |
| struct ast_variable * | list | |||
| ) | [static, read] |
implement the setvar config line
Definition at line 22623 of file chan_sip.c.
References ast_strdupa, ast_variable_new(), and ast_variable::next.
Referenced by build_peer().
22624 { 22625 struct ast_variable *tmpvar = NULL; 22626 char *varname = ast_strdupa(buf), *varval = NULL; 22627 22628 if ((varval = strchr(varname, '='))) { 22629 *varval++ = '\0'; 22630 if ((tmpvar = ast_variable_new(varname, varval, ""))) { 22631 tmpvar->next = list; 22632 list = tmpvar; 22633 } 22634 } 22635 return list; 22636 }
| 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 9236 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().
09239 { 09240 int rtp_code; 09241 09242 if (!p->vrtp) 09243 return; 09244 09245 if (debug) 09246 ast_verbose("Adding video codec 0x%x (%s) to SDP\n", codec, ast_getformatname(codec)); 09247 09248 if ((rtp_code = ast_rtp_lookup_code(p->vrtp, 1, codec)) == -1) 09249 return; 09250 09251 ast_str_append(m_buf, 0, " %d", rtp_code); 09252 ast_str_append(a_buf, 0, "a=rtpmap:%d %s/%d\r\n", rtp_code, 09253 ast_rtp_lookup_mime_subtype(1, codec, 0), sample_rate); 09254 /* Add fmtp code here */ 09255 }
| static int add_vidupdate | ( | struct sip_request * | req | ) | [static] |
add XML encoded media control with update
Definition at line 9173 of file chan_sip.c.
References add_header(), add_header_contentLength(), and add_line().
Referenced by transmit_info_with_vidupdate().
09174 { 09175 const char *xml_is_a_huge_waste_of_space = 09176 "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\r\n" 09177 " <media_control>\r\n" 09178 " <vc_primitive>\r\n" 09179 " <to_encoder>\r\n" 09180 " <picture_fast_update>\r\n" 09181 " </picture_fast_update>\r\n" 09182 " </to_encoder>\r\n" 09183 " </vc_primitive>\r\n" 09184 " </media_control>\r\n"; 09185 add_header(req, "Content-Type", "application/media_control+xml"); 09186 add_header_contentLength(req, strlen(xml_is_a_huge_waste_of_space)); 09187 add_line(req, xml_is_a_huge_waste_of_space); 09188 return 0; 09189 }
| static void append_date | ( | struct sip_request * | req | ) | [static] |
Append date to SIP message.
Definition at line 9064 of file chan_sip.c.
References add_header().
Referenced by transmit_invite(), transmit_response_with_date(), transmit_response_with_minse(), and transmit_response_with_unsupported().
09065 { 09066 char tmpdat[256]; 09067 struct tm tm; 09068 time_t t = time(NULL); 09069 09070 gmtime_r(&t, &tm); 09071 strftime(tmpdat, sizeof(tmpdat), "%a, %d %b %Y %T GMT", &tm); 09072 add_header(req, "Date", tmpdat); 09073 }
| static void append_history_full | ( | struct sip_pvt * | p, | |
| const char * | fmt, | |||
| ... | ||||
| ) | [static] |
Append to SIP dialog history with arg list.
Definition at line 3325 of file chan_sip.c.
References append_history_va(), and sip_pvt::do_history.
03326 { 03327 va_list ap; 03328 03329 if (!p) 03330 return; 03331 03332 if (!p->do_history && !recordhistory && !dumphistory) 03333 return; 03334 03335 va_start(ap, fmt); 03336 append_history_va(p, fmt, ap); 03337 va_end(ap); 03338 03339 return; 03340 }
| 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 3298 of file chan_sip.c.
References ast_calloc, ast_free, AST_LIST_INSERT_TAIL, AST_LIST_REMOVE_HEAD, buf, sip_history::event, MAX_HISTORY_ENTRIES, and strsep().
Referenced by append_history_full().
03299 { 03300 char buf[80], *c = buf; /* max history length */ 03301 struct sip_history *hist; 03302 int l; 03303 03304 vsnprintf(buf, sizeof(buf), fmt, ap); 03305 strsep(&c, "\r\n"); /* Trim up everything after \r or \n */ 03306 l = strlen(buf) + 1; 03307 if (!(hist = ast_calloc(1, sizeof(*hist) + l))) 03308 return; 03309 if (!p->history && !(p->history = ast_calloc(1, sizeof(*p->history)))) { 03310 ast_free(hist); 03311 return; 03312 } 03313 memcpy(hist->event, buf, l); 03314 if (p->history_entries == MAX_HISTORY_ENTRIES) { 03315 struct sip_history *oldest; 03316 oldest = AST_LIST_REMOVE_HEAD(p->history, list); 03317 p->history_entries--; 03318 ast_free(oldest); 03319 } 03320 AST_LIST_INSERT_TAIL(p->history, hist, list); 03321 p->history_entries++; 03322 }
| 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 18036 of file chan_sip.c.
References ast_channel::_state, ast_deactivate_generator(), AST_FLAG_MOH, ast_moh_stop(), AST_STATE_UP, ast_test_flag, and ast_channel::generatordata.
Referenced by attempt_transfer(), and handle_invite_replaces().
18037 { 18038 if (chan && chan->_state == AST_STATE_UP) { 18039 if (ast_test_flag(chan, AST_FLAG_MOH)) 18040 ast_moh_stop(chan); 18041 else if (chan->generatordata) 18042 ast_deactivate_generator(chan); 18043 } 18044 }
| 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 3223 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(), bindaddr, externip, get_transport(), internip, ast_tcptls_session_args::local_address, LOG_NOTICE, LOG_WARNING, PARSE_INADDR, SIP_TRANSPORT_TCP, SIP_TRANSPORT_TLS, SIP_TRANSPORT_UDP, sip_pvt::socket, stunaddr, 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().
03224 { 03225 struct sockaddr_in theirs; 03226 /* Set want_remap to non-zero if we want to remap 'us' to an externally 03227 * reachable IP address and port. This is done if: 03228 * 1. we have a localaddr list (containing 'internal' addresses marked 03229 * as 'deny', so ast_apply_ha() will return AST_SENSE_DENY on them, 03230 * and AST_SENSE_ALLOW on 'external' ones); 03231 * 2. either stunaddr or externip is set, so we know what to use as the 03232 * externally visible address; 03233 * 3. the remote address, 'them', is external; 03234 * 4. the address returned by ast_ouraddrfor() is 'internal' (AST_SENSE_DENY 03235 * when passed to ast_apply_ha() so it does need to be remapped. 03236 * This fourth condition is checked later. 03237 */ 03238 int want_remap; 03239 03240 *us = internip; /* starting guess for the internal address */ 03241 /* now ask the system what would it use to talk to 'them' */ 03242 ast_ouraddrfor(them, &us->sin_addr); 03243 theirs.sin_addr = *them; 03244 03245 want_remap = localaddr && 03246 (externip.sin_addr.s_addr || stunaddr.sin_addr.s_addr) && 03247 ast_apply_ha(localaddr, &theirs) == AST_SENSE_ALLOW ; 03248 03249 if (want_remap && 03250 (!global_matchexterniplocally || !ast_apply_ha(localaddr, us)) ) { 03251 /* if we used externhost or stun, see if it is time to refresh the info */ 03252 if (externexpire && time(NULL) >= externexpire) { 03253 if (stunaddr.sin_addr.s_addr) { 03254 ast_stun_request(sipsock, &stunaddr, NULL, &externip); 03255 } else { 03256 if (ast_parse_arg(externhost, PARSE_INADDR, &externip)) 03257 ast_log(LOG_NOTICE, "Warning: Re-lookup of '%s' failed!\n", externhost); 03258 } 03259 externexpire = time(NULL) + externrefresh; 03260 } 03261 if (externip.sin_addr.s_addr) 03262 *us = externip; 03263 else 03264 ast_log(LOG_WARNING, "stun failed\n"); 03265 ast_debug(1, "Target address %s is not local, substituting externip\n", 03266 ast_inet_ntoa(*(struct in_addr *)&them->s_addr)); 03267 } else if (p) { 03268 /* no remapping, but we bind to a specific address, so use it. */ 03269 switch (p->socket.type) { 03270 case SIP_TRANSPORT_TCP: 03271 if (sip_tcp_desc.local_address.sin_addr.s_addr) { 03272 *us = sip_tcp_desc.local_address; 03273 } else { 03274 us->sin_port = sip_tcp_desc.local_address.sin_port; 03275 } 03276 break; 03277 case SIP_TRANSPORT_TLS: 03278 if (sip_tls_desc.local_address.sin_addr.s_addr) { 03279 *us = sip_tls_desc.local_address; 03280 } else { 03281 us->sin_port = sip_tls_desc.local_address.sin_port; 03282 } 03283 break; 03284 case SIP_TRANSPORT_UDP: 03285 /* fall through on purpose */ 03286 default: 03287 if (bindaddr.sin_addr.s_addr) { 03288 *us = bindaddr; 03289 } 03290 } 03291 } else if (bindaddr.sin_addr.s_addr) { 03292 *us = bindaddr; 03293 } 03294 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)); 03295 }
Attempt transfer of SIP call This fix for attended transfers on a local PBX.
Definition at line 18048 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, and LOG_WARNING.
Referenced by local_attended_transfer().
18049 { 18050 int res = 0; 18051 struct ast_channel *peera = NULL, 18052 *peerb = NULL, 18053 *peerc = NULL, 18054 *peerd = NULL; 18055 18056 18057 /* We will try to connect the transferee with the target and hangup 18058 all channels to the transferer */ 18059 ast_debug(4, "Sip transfer:--------------------\n"); 18060 if (transferer->chan1) 18061 ast_debug(4, "-- Transferer to PBX channel: %s State %s\n", transferer->chan1->name, ast_state2str(transferer->chan1->_state)); 18062 else 18063 ast_debug(4, "-- No transferer first channel - odd??? \n"); 18064 if (target->chan1) 18065 ast_debug(4, "-- Transferer to PBX second channel (target): %s State %s\n", target->chan1->name, ast_state2str(target->chan1->_state)); 18066 else 18067 ast_debug(4, "-- No target first channel ---\n"); 18068 if (transferer->chan2) 18069 ast_debug(4, "-- Bridged call to transferee: %s State %s\n", transferer->chan2->name, ast_state2str(transferer->chan2->_state)); 18070 else 18071 ast_debug(4, "-- No bridged call to transferee\n"); 18072 if (target->chan2) 18073 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)"); 18074 else 18075 ast_debug(4, "-- No target second channel ---\n"); 18076 ast_debug(4, "-- END Sip transfer:--------------------\n"); 18077 if (transferer->chan2) { /* We have a bridge on the transferer's channel */ 18078 peera = transferer->chan1; /* Transferer - PBX -> transferee channel * the one we hangup */ 18079 peerb = target->chan1; /* Transferer - PBX -> target channel - This will get lost in masq */ 18080 peerc = transferer->chan2; /* Asterisk to Transferee */ 18081 peerd = target->chan2; /* Asterisk to Target */ 18082 ast_debug(3, "SIP transfer: Four channels to handle\n"); 18083 } else if (target->chan2) { /* Transferer has no bridge (IVR), but transferee */ 18084 peera = target->chan1; /* Transferer to PBX -> target channel */ 18085 peerb = transferer->chan1; /* Transferer to IVR*/ 18086 peerc = target->chan2; /* Asterisk to Target */ 18087 peerd = transferer->chan2; /* Nothing */ 18088 ast_debug(3, "SIP transfer: Three channels to handle\n"); 18089 } 18090 18091 if (peera && peerb && peerc && (peerb != peerc)) { 18092 ast_quiet_chan(peera); /* Stop generators */ 18093 ast_quiet_chan(peerb); 18094 ast_quiet_chan(peerc); 18095 if (peerd) 18096 ast_quiet_chan(peerd); 18097 18098 ast_debug(4, "SIP transfer: trying to masquerade %s into %s\n", peerc->name, peerb->name); 18099 if (ast_channel_masquerade(peerb, peerc)) { 18100 ast_log(LOG_WARNING, "Failed to masquerade %s into %s\n", peerb->name, peerc->name); 18101 res = -1; 18102 } else 18103 ast_debug(4, "SIP transfer: Succeeded to masquerade channels.\n"); 18104 return res; 18105 } else { 18106 ast_log(LOG_NOTICE, "SIP Transfer attempted with no appropriate bridged calls to transfer\n"); 18107 if (transferer->chan1) 18108 ast_softhangup_nolock(transferer->chan1, AST_SOFTHANGUP_DEV); 18109 if (target->chan1) 18110 ast_softhangup_nolock(target->chan1, AST_SOFTHANGUP_DEV); 18111 return -1; 18112 } 18113 return 0; 18114 }
| 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 11155 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().
11156 { 11157 if (code == WWW_AUTH) { /* 401 */ 11158 *header = "WWW-Authenticate"; 11159 *respheader = "Authorization"; 11160 } else if (code == PROXY_AUTH) { /* 407 */ 11161 *header = "Proxy-Authenticate"; 11162 *respheader = "Proxy-Authorization"; 11163 } else { 11164 ast_verbose("-- wrong response code %d\n", code); 11165 *header = *respheader = "Invalid"; 11166 } 11167 }
| 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 4969 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::initid, sip_pvt::owner, sip_pvt_lock, sip_pvt_unlock, and sip_scheddestroy().
Referenced by sip_call(), and sip_show_sched().
04970 { 04971 struct sip_pvt *p = (struct sip_pvt *)arg; 04972 04973 sip_pvt_lock(p); 04974 p->initid = -1; /* event gone, will not be rescheduled */ 04975 if (p->owner) { 04976 /* XXX fails on possible deadlock */ 04977 if (!ast_channel_trylock(p->owner)) { 04978 append_history(p, "Cong", "Auto-congesting (timer)"); 04979 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 04980 ast_channel_unlock(p->owner); 04981 } 04982 04983 /* Give the channel a chance to act before we proceed with destruction */ 04984 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 04985 } 04986 sip_pvt_unlock(p); 04987 dialog_unref(p, "unreffing arg passed into auto_congest callback (p->initid)"); 04988 return 0; 04989 }
| static void build_callid_pvt | ( | struct sip_pvt * | pvt | ) | [static] |
Build SIP Call-ID value for a non-REGISTER transaction.
Definition at line 6689 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().
06690 { 06691 char buf[33]; 06692 06693 const char *host = S_OR(pvt->fromdomain, ast_inet_ntoa(pvt->ourip.sin_addr)); 06694 06695 ast_string_field_build(pvt, callid, "%s@%s", generate_random_string(buf, sizeof(buf)), host); 06696 06697 }
| 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 6700 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().
06701 { 06702 char buf[33]; 06703 06704 const char *host = S_OR(fromdomain, ast_inet_ntoa(ourip)); 06705 06706 ast_string_field_build(reg, callid, "%s@%s", generate_random_string(buf, sizeof(buf)), host); 06707 }
| static void build_contact | ( | struct sip_pvt * | p | ) | [static] |
Build contact header - the contact header we send out.
Definition at line 9928 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().
09929 { 09930 int ourport = ntohs(p->ourip.sin_port); 09931 /* only add port if it's non-standard for the transport type */ 09932 if (!sip_standard_port(p->socket.type, ourport)) { 09933 if (p->socket.type == SIP_TRANSPORT_UDP) 09934 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); 09935 else 09936 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)); 09937 } else { 09938 if (p->socket.type == SIP_TRANSPORT_UDP) 09939 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)); 09940 else 09941 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)); 09942 } 09943 }
| static struct sip_peer * build_peer | ( | const char * | name, | |
| struct ast_variable * | v, | |||
| struct ast_variable * | alt, | |||
| int | realtime, | |||
| int | devstate_only | |||
| ) | [static, read] |
Build peer from configuration (file or realtime static/dynamic).
< The first transport listed should be default outbound
Definition at line 22739 of file chan_sip.c.
References __set_address_from_contact(), sip_peer::accountcode, add_peer_mailboxes(), add_peer_mwi_subs(), add_realm_authentication(), add_var(), sip_peer::addr, sip_peer::allowtransfer, sip_peer::amaflags, ao2_t_alloc, ao2_t_find, asprintf, ast_append_ha(), ast_atomic_fetchadd_int(), ast_callerid_split(), ast_cdr_amaflags2int(), ast_copy_flags, ast_copy_string(), ast_debug, ast_dnsmgr_lookup(), ast_free, ast_free_ha(), ast_get_group(), ast_get_ip(), ast_get_time_t(), ast_inet_ntoa(), AST_LIST_EMPTY, ast_log(), ast_parse_allow_disallow(), ast_parse_caller_presentation(), AST_SCHED_DEL_UNREF, ast_set2_flag, ast_skip_blanks(), ast_str_alloca, ast_str_append(), ast_str_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(), sip_peer::ha, handle_common_options(), handle_t38_options(), sip_peer::host_dynamic, sip_settings::ignore_regexpire, sip_peer::is_realtime, sip_peer::language, sip_peer::lastms, sip_peer::lastmsgssent, ast_variable::lineno, LOG_ERROR, LOG_NOTICE, LOG_WARNING, sip_peer::mailboxes, sip_peer::maxcallbitrate, MAXHOSTNAMELEN, sip_peer::maxms, sip_peer::md5secret, sip_peer::mohinterpret, sip_peer::mohsuggest, ast_variable::name, sip_peer::name, ast_variable::next, OBJ_POINTER, OBJ_UNLINK, sip_peer::outboundproxy, sip_peer::parkinglot, sip_peer::pickupgroup, sip_socket::port, 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, sip_peer::secret, set_peer_defaults(), set_socket_transport(), sip_cfg, sip_destroy_peer_fn(), SIP_NAT_ROUTE, SIP_PAGE2_ALLOWSUBSCRIBE, SIP_PAGE2_REGISTERTRYING, SIP_PAGE2_RTCACHEFRIENDS, SIP_PAGE2_SUBSCRIBEMWIONLY, sip_poke_peer(), sip_register(), sip_send_mwi_to_peer(), SIP_TRANSPORT_TCP, SIP_TRANSPORT_TLS, SIP_TRANSPORT_UDP, SIP_TYPE_PEER, SIP_TYPE_USER, SIP_USEREQPHONE, sip_peer::socket, srvlookup, sip_st_cfg::st_max_se, sip_st_cfg::st_min_se, sip_st_cfg::st_mode_oper, sip_st_cfg::st_ref, STANDARD_SIP_PORT, STANDARD_TLS_PORT, sip_peer::stimer, ast_str::str, str2stmode(), str2strefresher(), strsep(), sip_peer::subscribecontext, sip_peer::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.
Referenced by realtime_peer(), and reload_config().
22740 { 22741 struct sip_peer *peer = NULL; 22742 struct ast_ha *oldha = NULL; 22743 int found = 0; 22744 int firstpass = 1; 22745 uint16_t port = 0; 22746 int format = 0; /* Ama flags */ 22747 time_t regseconds = 0; 22748 struct ast_flags peerflags[2] = {{(0)}}; 22749 struct ast_flags mask[2] = {{(0)}}; 22750 char callback[256] = ""; 22751 struct sip_peer tmp_peer; 22752 const char *srvlookup = NULL; 22753 static int deprecation_warning = 1; 22754 int alt_fullcontact = alt ? 1 : 0; 22755 struct ast_str *fullcontact = ast_str_alloca(512); 22756 22757 if (!realtime || ast_test_flag(&global_flags[1], SIP_PAGE2_RTCACHEFRIENDS)) { 22758 /* Note we do NOT use find_peer here, to avoid realtime recursion */ 22759 /* We also use a case-sensitive comparison (unlike find_peer) so 22760 that case changes made to the peer name will be properly handled 22761 during reload 22762 */ 22763 ast_copy_string(tmp_peer.name, name, sizeof(tmp_peer.name)); 22764 peer = ao2_t_find(peers, &tmp_peer, OBJ_POINTER | OBJ_UNLINK, "find and unlink peer from peers table"); 22765 } 22766 22767 if (peer) { 22768 /* Already in the list, remove it and it will be added back (or FREE'd) */ 22769 found++; 22770 if (!(peer->the_mark)) 22771 firstpass = 0; 22772 } else { 22773 if (!(peer = ao2_t_alloc(sizeof(*peer), sip_destroy_peer_fn, "allocate a peer struct"))) 22774 return NULL; 22775 22776 if (realtime && !ast_test_flag(&global_flags[1], SIP_PAGE2_RTCACHEFRIENDS)) { 22777 ast_atomic_fetchadd_int(&rpeerobjs, 1); 22778 ast_debug(3, "-REALTIME- peer built. Name: %s. Peer objects: %d\n", name, rpeerobjs); 22779 } else 22780 ast_atomic_fetchadd_int(&speerobjs, 1); 22781 } 22782 22783 /* Note that our peer HAS had its reference count increased */ 22784 if (firstpass) { 22785 peer->lastmsgssent = -1; 22786 oldha = peer->ha; 22787 peer->ha = NULL; 22788 set_peer_defaults(peer); /* Set peer defaults */ 22789 peer->type = 0; 22790 } 22791 if (!found && name) 22792 ast_copy_string(peer->name, name, sizeof(peer->name)); 22793 22794 /* If we have channel variables, remove them (reload) */ 22795 if (peer->chanvars) { 22796 ast_variables_destroy(peer->chanvars); 22797 peer->chanvars = NULL; 22798 /* XXX should unregister ? */ 22799 } 22800 22801 if (found) 22802 peer->portinuri = 0; 22803 22804 /* If we have realm authentication information, remove them (reload) */ 22805 clear_realm_authentication(peer->auth); 22806 peer->auth = NULL; 22807 peer->default_outbound_transport = 0; 22808 peer->transports = 0; 22809 22810 for (; v || ((v = alt) && !(alt=NULL)); v = v->next) { 22811 if (!devstate_only) { 22812 if (handle_common_options(&peerflags[0], &mask[0], v)) { 22813 continue; 22814 } 22815 if (handle_t38_options(&peerflags[0], &mask[0], v, &peer->t38_maxdatagram)) { 22816 continue; 22817 } 22818 if (!strcasecmp(v->name, "transport") && !ast_strlen_zero(v->value)) { 22819 char *val = ast_strdupa(v->value); 22820 char *trans; 22821 22822 while ((trans = strsep(&val, ","))) { 22823 trans = ast_skip_blanks(trans); 22824 22825 if (!strncasecmp(trans, "udp", 3)) { 22826 peer->transports |= SIP_TRANSPORT_UDP; 22827 } else if (!strncasecmp(trans, "tcp", 3)) { 22828 peer->transports |= SIP_TRANSPORT_TCP; 22829 } else if (!strncasecmp(trans, "tls", 3)) { 22830 peer->transports |= SIP_TRANSPORT_TLS; 22831 } else { 22832 ast_log(LOG_NOTICE, "'%s' is not a valid transport type. if no other is specified, udp will be used.\n", trans); 22833 } 22834 22835 if (!peer->default_outbound_transport) { /*!< The first transport listed should be default outbound */ 22836 peer->default_outbound_transport = peer->transports; 22837 } 22838 } 22839 } else if (realtime && !strcasecmp(v->name, "regseconds")) { 22840 ast_get_time_t(v->value, ®seconds, 0, NULL); 22841 } else if (realtime && !strcasecmp(v->name, "name")) { 22842 ast_copy_string(peer->name, v->value, sizeof(peer->name)); 22843 } else if (!strcasecmp(v->name, "type")) { 22844 if (!strcasecmp(v->value, "peer")) { 22845 peer->type |= SIP_TYPE_PEER; 22846 } else if (!strcasecmp(v->value, "user")) { 22847 peer->type |= SIP_TYPE_USER; 22848 } else if (!strcasecmp(v->value, "friend")) { 22849 peer->type = SIP_TYPE_USER | SIP_TYPE_PEER; 22850 } 22851 } else if (!strcasecmp(v->name, "secret")) { 22852 ast_copy_string(peer->secret, v->value, sizeof(peer->secret)); 22853 } else if (!strcasecmp(v->name, "md5secret")) { 22854 ast_copy_string(peer->md5secret, v->value, sizeof(peer->md5secret)); 22855 } else if (!strcasecmp(v->name, "auth")) { 22856 peer->auth = add_realm_authentication(peer->auth, v->value, v->lineno); 22857 } else if (!strcasecmp(v->name, "callerid")) { 22858 ast_callerid_split(v->value, peer->cid_name, sizeof(peer->cid_name), peer->cid_num, sizeof(peer->cid_num)); 22859 } else if (!strcasecmp(v->name, "fullname")) { 22860 ast_copy_string(peer->cid_name, v->value, sizeof(peer->cid_name)); 22861 } else if (!strcasecmp(v->name, "trunkname")) { 22862 /* This is actually for a trunk, so we don't want to override callerid */ 22863 ast_copy_string(peer->cid_name, "", sizeof(peer->cid_name)); 22864 } else if (!strcasecmp(v->name, "cid_number")) { 22865 ast_copy_string(peer->cid_num, v->value, sizeof(peer->cid_num)); 22866 } else if (!strcasecmp(v->name, "context")) { 22867 ast_copy_string(peer->context, v->value, sizeof(peer->context)); 22868 } else if (!strcasecmp(v->name, "subscribecontext")) { 22869 ast_copy_string(peer->subscribecontext, v->value, sizeof(peer->subscribecontext)); 22870 } else if (!strcasecmp(v->name, "fromdomain")) { 22871 ast_copy_string(peer->fromdomain, v->value, sizeof(peer->fromdomain)); 22872 } else if (!strcasecmp(v->name, "usereqphone")) { 22873 ast_set2_flag(&peer->flags[0], ast_true(v->value), SIP_USEREQPHONE); 22874 } else if (!strcasecmp(v->name, "fromuser")) { 22875 ast_copy_string(peer->fromuser, v->value, sizeof(peer->fromuser)); 22876 } else if (!strcasecmp(v->name, "outboundproxy")) { 22877 char *port, *next, *force, *proxyname; 22878 int forceopt = FALSE; 22879 /* Set peer channel variable */ 22880 next = proxyname = ast_strdupa(v->value); 22881 if ((port = strchr(proxyname, ':'))) { 22882 *port++ = '\0'; 22883 next = port; 22884 } 22885 if ((force = strchr(next, ','))) { 22886 *force++ = '\0'; 22887 forceopt = strcmp(force, "force"); 22888 } 22889 /* Allocate proxy object */ 22890 peer->outboundproxy = proxy_allocate(proxyname, port, forceopt); 22891 } else if (!strcasecmp(v->name, "host")) { 22892 if (!strcasecmp(v->value, "dynamic")) { 22893 /* They'll register with us */ 22894 if (!found || !peer->host_dynamic) { 22895 /* Initialize stuff if this is a new peer, or if it used to 22896 * not be dynamic before the reload. */ 22897 memset(&peer->addr.sin_addr, 0, 4); 22898 peer->addr.sin_port = 0; 22899 } 22900 peer->host_dynamic = TRUE; 22901 } else { 22902 /* Non-dynamic. Make sure we become that way if we're not */ 22903 AST_SCHED_DEL_UNREF(sched, peer->expire, 22904 unref_peer(peer, "removing register expire ref")); 22905 /* the port will either be set to a default value or a config specified value once all option parsing is complete */ 22906 peer->addr.sin_port = 0; 22907 peer->host_dynamic = FALSE; 22908 srvlookup = v->value; 22909 if (global_dynamic_exclude_static) { 22910 int err = 0; 22911 global_contact_ha = ast_append_ha("deny", (char *)ast_inet_ntoa(peer->addr.sin_addr), global_contact_ha, &err); 22912 if (err) { 22913 ast_log(LOG_ERROR, "Bad ACL entry in configuration line %d : %s\n", v->lineno, v->value); 22914 } 22915 } 22916 } 22917 } else if (!strcasecmp(v->name, "defaultip")) { 22918 if (ast_get_ip(&peer->defaddr, v->value)) { 22919 unref_peer(peer, "unref_peer: from build_peer defaultip"); 22920 return NULL; 22921 } 22922 } else if (!strcasecmp(v->name, "permit") || !strcasecmp(v->name, "deny")) { 22923 int ha_error = 0; 22924 peer->ha = ast_append_ha(v->name, v->value, peer->ha, &ha_error); 22925 if (ha_error) { 22926 ast_log(LOG_ERROR, "Bad ACL entry in configuration line %d : %s\n", v->lineno, v->value); 22927 } 22928 } else if (!strcasecmp(v->name, "contactpermit") || !strcasecmp(v->name, "contactdeny")) { 22929 int ha_error = 0; 22930 peer->contactha = ast_append_ha(v->name + 7, v->value, peer->contactha, &ha_error); 22931 if (ha_error) { 22932 ast_log(LOG_ERROR, "Bad ACL entry in configuration line %d : %s\n", v->lineno, v->value); 22933 } 22934 } else if (!strcasecmp(v->name, "port")) { 22935 peer->portinuri = 1; 22936 if (!(port = port_str2int(v->value, 0))) { 22937 if (realtime) { 22938 /* If stored as integer, could be 0 for some DBs (notably MySQL) */ 22939 peer->portinuri = 0; 22940 } else { 22941 ast_log(LOG_WARNING, "Invalid peer port configuration at line %d : %s\n", v->lineno, v->value); 22942 } 22943 } 22944 } else if (!strcasecmp(v->name, "callingpres")) { 22945 peer->callingpres = ast_parse_caller_presentation(v->value); 22946 if (peer->callingpres == -1) { 22947 peer->callingpres = atoi(v->value); 22948 } 22949 } else if (!strcasecmp(v->name, "username") || !strcmp(v->name, "defaultuser")) { /* "username" is deprecated */ 22950 ast_copy_string(peer->username, v->value, sizeof(peer->username)); 22951 if (!strcasecmp(v->name, "username")) { 22952 if (deprecation_warning) { 22953 ast_log(LOG_NOTICE, "The 'username' field for sip peers has been deprecated in favor of the term 'defaultuser'\n"); 22954 deprecation_warning = 0; 22955 } 22956 peer->deprecated_username = 1; 22957 } 22958 } else if (!strcasecmp(v->name, "language")) { 22959 ast_copy_string(peer->language, v->value, sizeof(peer->language)); 22960 } else if (!strcasecmp(v->name, "regexten")) { 22961 ast_copy_string(peer->regexten, v->value, sizeof(peer->regexten)); 22962 } else if (!strcasecmp(v->name, "callbackextension")) { 22963 ast_copy_string(callback, v->value, sizeof(callback)); 22964 } else if (!strcasecmp(v->name, "amaflags")) { 22965 format = ast_cdr_amaflags2int(v->value); 22966 if (format < 0) { 22967 ast_log(LOG_WARNING, "Invalid AMA Flags for peer: %s at line %d\n", v->value, v->lineno); 22968 } else { 22969 peer->amaflags = format; 22970 } 22971 } else if (!strcasecmp(v->name, "accountcode")) { 22972 ast_copy_string(peer->accountcode, v->value, sizeof(peer->accountcode)); 22973 } else if (!strcasecmp(v->name, "mohinterpret")) { 22974 ast_copy_string(peer->mohinterpret, v->value, sizeof(peer->mohinterpret)); 22975 } else if (!strcasecmp(v->name, "mohsuggest")) { 22976 ast_copy_string(peer->mohsuggest, v->value, sizeof(peer->mohsuggest)); 22977 } else if (!strcasecmp(v->name, "parkinglot")) { 22978 ast_copy_string(peer->parkinglot, v->value, sizeof(peer->parkinglot)); 22979 } else if (!strcasecmp(v->name, "mailbox")) { 22980 add_peer_mailboxes(peer, v->value); 22981 } else if (!strcasecmp(v->name, "hasvoicemail")) { 22982 /* People expect that if 'hasvoicemail' is set, that the mailbox will 22983 * be also set, even if not explicitly specified. */ 22984 if (ast_true(v->value) && AST_LIST_EMPTY(&peer->mailboxes)) { 22985 add_peer_mailboxes(peer, name); 22986 } 22987 } else if (!strcasecmp(v->name, "subscribemwi")) { 22988 ast_set2_flag(&peer->flags[1], ast_true(v->value), SIP_PAGE2_SUBSCRIBEMWIONLY); 22989 } else if (!strcasecmp(v->name, "vmexten")) { 22990 ast_copy_string(peer->vmexten, v->value, sizeof(peer->vmexten)); 22991 } else if (!strcasecmp(v->name, "callgroup")) { 22992 peer->callgroup = ast_get_group(v->value); 22993 } else if (!strcasecmp(v->name, "allowtransfer")) { 22994 peer->allowtransfer = ast_true(v->value) ? TRANSFER_OPENFORALL : TRANSFER_CLOSED; 22995 } else if (!strcasecmp(v->name, "pickupgroup")) { 22996 peer->pickupgroup = ast_get_group(v->value); 22997 } else if (!strcasecmp(v->name, "allow")) { 22998 int error = ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, TRUE); 22999 if (error) { 23000 ast_log(LOG_WARNING, "Codec configuration errors found in line %d : %s = %s\n", v->lineno, v->name, v->value); 23001 } 23002 } else if (!strcasecmp(v->name, "disallow")) { 23003 int error = ast_parse_allow_disallow(&peer->prefs, &peer->capability, v->value, FALSE); 23004 if (error) { 23005 ast_log(LOG_WARNING, "Codec configuration errors found in line %d : %s = %s\n", v->lineno, v->name, v->value); 23006 } 23007 } else if (!strcasecmp(v->name, "registertrying")) { 23008 ast_set2_flag(&peer->flags[1], ast_true(v->value), SIP_PAGE2_REGISTERTRYING); 23009 } else if (!strcasecmp(v->name, "autoframing")) { 23010 peer->autoframing = ast_true(v->value); 23011 } else if (!strcasecmp(v->name, "rtptimeout")) { 23012 if ((sscanf(v->value, "%30d", &peer->rtptimeout) != 1) || (peer->rtptimeout < 0)) { 23013 ast_log(LOG_WARNING, "'%s' is not a valid RTP hold time at line %d. Using default.\n", v->value, v->lineno); 23014 peer->rtptimeout = global_rtptimeout; 23015 } 23016 } else if (!strcasecmp(v->name, "rtpholdtimeout")) { 23017 if ((sscanf(v->value, "%30d", &peer->rtpholdtimeout) != 1) || (peer->rtpholdtimeout < 0)) { 23018 ast_log(LOG_WARNING, "'%s' is not a valid RTP hold time at line %d. Using default.\n", v->value, v->lineno); 23019 peer->rtpholdtimeout = global_rtpholdtimeout; 23020 } 23021 } else if (!strcasecmp(v->name, "rtpkeepalive")) { 23022 if ((sscanf(v->value, "%30d", &peer->rtpkeepalive) != 1) || (peer->rtpkeepalive < 0)) { 23023 ast_log(LOG_WARNING, "'%s' is not a valid RTP keepalive time at line %d. Using default.\n", v->value, v->lineno); 23024 peer->rtpkeepalive = global_rtpkeepalive; 23025 } 23026 } else if (!strcasecmp(v->name, "timert1")) { 23027 if ((sscanf(v->value, "%30d", &peer->timer_t1) != 1) || (peer->timer_t1 < 0)) { 23028 ast_log(LOG_WARNING, "'%s' is not a valid T1 time at line %d. Using default.\n", v->value, v->lineno); 23029 peer->timer_t1 = global_t1; 23030 } 23031 /* Note that Timer B is dependent upon T1 and MUST NOT be lower 23032 * than T1 * 64, according to RFC 3261, Section 17.1.1.2 */ 23033 if (peer->timer_b < peer->timer_t1 * 64) { 23034 peer->timer_b = peer->timer_t1 * 64; 23035 } 23036 } else if (!strcasecmp(v->name, "timerb")) { 23037 if ((sscanf(v->value, "%30d", &peer->timer_b) != 1) || (peer->timer_b < 0)) { 23038 ast_log(LOG_WARNING, "'%s' is not a valid Timer B time at line %d. Using default.\n", v->value, v->lineno); 23039 peer->timer_b = global_timer_b; 23040 } 23041 if (peer->timer_b < peer->timer_t1 * 64) { 23042 static int warning = 0; 23043 if (warning++ % 20 == 0) { 23044 ast_log(LOG_WARNING, "Timer B has been set lower than recommended. (RFC 3261, 17.1.1.2)\n"); 23045 } 23046 } 23047 } else if (!strcasecmp(v->name, "setvar")) { 23048 peer->chanvars = add_var(v->value, peer->chanvars); 23049 } else if (!strcasecmp(v->name, "qualifyfreq")) { 23050 int i; 23051 if (sscanf(v->value, "%30d", &i) == 1) { 23052 peer->qualifyfreq = i * 1000; 23053 } else { 23054 ast_log(LOG_WARNING, "Invalid qualifyfreq number '%s' at line %d of %s\n", v->value, v->lineno, config); 23055 peer->qualifyfreq = global_qualifyfreq; 23056 } 23057 } else if (!strcasecmp(v->name, "maxcallbitrate")) { 23058 peer->maxcallbitrate = atoi(v->value); 23059 if (peer->maxcallbitrate < 0) { 23060 peer->maxcallbitrate = default_maxcallbitrate; 23061 } 23062 } else if (!strcasecmp(v->name, "session-timers")) { 23063 int i = (int) str2stmode(v->value); 23064 if (i < 0) { 23065 ast_log(LOG_WARNING, "Invalid session-timers '%s' at line %d of %s\n", v->value, v->lineno, config); 23066 peer->stimer.st_mode_oper = global_st_mode; 23067 } else { 23068 peer->stimer.st_mode_oper = i; 23069 } 23070 } else if (!strcasecmp(v->name, "session-expires")) { 23071 if (sscanf(v->value, "%30d", &peer->stimer.st_max_se) != 1) { 23072 ast_log(LOG_WARNING, "Invalid session-expires '%s' at line %d of %s\n", v->value, v->lineno, config); 23073 peer->stimer.st_max_se = global_max_se; 23074 } 23075 } else if (!strcasecmp(v->name, "session-minse")) { 23076 if (sscanf(v->value, "%30d", &peer->stimer.st_min_se) != 1) { 23077 ast_log(LOG_WARNING, "Invalid session-minse '%s' at line %d of %s\n", v->value, v->lineno, config); 23078 peer->stimer.st_min_se = global_min_se; 23079 } 23080 if (peer->stimer.st_min_se < 90) { 23081 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); 23082 peer->stimer.st_min_se = global_min_se; 23083 } 23084 } else if (!strcasecmp(v->name, "session-refresher")) { 23085 int i = (int) str2strefresher(v->value); 23086 if (i < 0) { 23087 ast_log(LOG_WARNING, "Invalid session-refresher '%s' at line %d of %s\n", v->value, v->lineno, config); 23088 peer->stimer.st_ref = global_st_refresher; 23089 } else { 23090 peer->stimer.st_ref = i; 23091 } 23092 } 23093 } 23094 23095 /* These apply to devstate lookups */ 23096 if (realtime && !strcasecmp(v->name, "lastms")) { 23097 sscanf(v->value, "%30d", &peer->lastms); 23098 } else if (realtime && !strcasecmp(v->name, "ipaddr") && !ast_strlen_zero(v->value) ) { 23099 inet_aton(v->value, &(peer->addr.sin_addr)); 23100 } else if (realtime && !strcasecmp(v->name, "fullcontact")) { 23101 if (alt_fullcontact && !alt) { 23102 /* Reset, because the alternate also has a fullcontact and we 23103 * do NOT want the field value to be doubled. It might be 23104 * tempting to skip this, but the first table might not have 23105 * fullcontact and since we're here, we know that the alternate 23106 * absolutely does. */ 23107 alt_fullcontact = 0; 23108 ast_str_reset(fullcontact); 23109 } 23110 /* Reconstruct field, because realtime separates our value at the ';' */ 23111 if (fullcontact->used > 0) { 23112 ast_str_append(&fullcontact, 0, ";%s", v->value); 23113 } else { 23114 ast_str_set(&fullcontact, 0, "%s", v->value); 23115 } 23116 } else if (!strcasecmp(v->name, "qualify")) { 23117 if (!strcasecmp(v->value, "no")) { 23118 peer->maxms = 0; 23119 } else if (!strcasecmp(v->value, "yes")) { 23120 peer->maxms = default_qualify ? default_qualify : DEFAULT_MAXMS; 23121 } else if (sscanf(v->value, "%30d", &peer->maxms) != 1) { 23122 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); 23123 peer->maxms = 0; 23124 } 23125 if (realtime && !ast_test_flag(&global_flags[1], SIP_PAGE2_RTCACHEFRIENDS) && peer->maxms > 0) { 23126 /* This would otherwise cause a network storm, where the 23127 * qualify response refreshes the peer from the database, 23128 * which in turn causes another qualify to be sent, ad 23129 * infinitum. */ 23130 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); 23131 peer->maxms = 0; 23132 } 23133 } else if (!strcasecmp(v->name, "callcounter")) { 23134 peer->call_limit = ast_true(v->value) ? INT_MAX : 0; 23135 } else if (!strcasecmp(v->name, "call-limit")) { 23136 peer->call_limit = atoi(v->value); 23137 if (peer->call_limit < 0) { 23138 peer->call_limit = 0; 23139 } 23140 } else if (!strcasecmp(v->name, "busylevel")) { 23141 peer->busy_level = atoi(v->value); 23142 if (peer->busy_level < 0) { 23143 peer->busy_level = 0; 23144 } 23145 } 23146 } 23147 23148 if (!peer->default_outbound_transport) { 23149 peer->transports = SIP_TRANSPORT_UDP; 23150 peer->default_outbound_transport = SIP_TRANSPORT_UDP; 23151 } 23152 23153 /* The default transport type set during build_peer should only replace the socket.type when... 23154 * 1. Registration is not present and the socket.type and default transport types are different. 23155 * 2. The socket.type is not an acceptable transport type after rebuilding peer. 23156 * 3. The socket.type is not set yet. */ 23157 if (((peer->socket.type != peer->default_outbound_transport) && (peer->expire == -1)) || 23158 !(peer->socket.type & peer->transports) || !(peer->socket.type)) { 23159 23160 set_socket_transport(&peer->socket, peer->default_outbound_transport); 23161 } 23162 23163 if (port && !realtime && peer->host_dynamic) { 23164 peer->defaddr.sin_port = htons(port); 23165 } else if (port) { 23166 peer->addr.sin_port = htons(port); 23167 } 23168 23169 if (ast_str_strlen(fullcontact)) { 23170 ast_copy_string(peer->fullcontact, fullcontact->str, sizeof(peer->fullcontact)); 23171 peer->rt_fromcontact = TRUE; 23172 /* We have a hostname in the fullcontact, but if we don't have an 23173 * address listed on the entry (or if it's 'dynamic'), then we need to 23174 * parse the entry to obtain the IP address, so a dynamic host can be 23175 * contacted immediately after reload (as opposed to waiting for it to 23176 * register once again). But if we have an address for this peer and NAT was 23177 * specified, use that address instead. */ 23178 /* XXX May need to revisit the final argument; does the realtime DB store whether 23179 * the original contact was over TLS or not? XXX */ 23180 if (!ast_test_flag(&peer->flags[0], SIP_NAT_ROUTE) || !peer->addr.sin_addr.s_addr) { 23181 __set_address_from_contact(fullcontact->str, &peer->addr, 0); 23182 } 23183 } 23184 23185 if (srvlookup && peer->dnsmgr == NULL) { 23186 char transport[MAXHOSTNAMELEN]; 23187 char _srvlookup[MAXHOSTNAMELEN]; 23188 char *params; 23189 23190 ast_copy_string(_srvlookup, srvlookup, sizeof(_srvlookup)); 23191 if ((params = strchr(_srvlookup, ';'))) { 23192 *params++ = '\0'; 23193 } 23194 23195 snprintf(transport, sizeof(transport), "_sip._%s", get_transport(peer->socket.type)); 23196 23197 if (ast_dnsmgr_lookup(_srvlookup, &peer->addr, &peer->dnsmgr, global_srvlookup && !peer->portinuri ? transport : NULL)) { 23198 ast_log(LOG_ERROR, "srvlookup failed for host: %s, on peer %s, removing peer\n", _srvlookup, peer->name); 23199 unref_peer(peer, "getting rid of a peer pointer"); 23200 return NULL; 23201 } 23202 23203 ast_copy_string(peer->tohost, srvlookup, sizeof(peer->tohost)); 23204 } 23205 23206 if (!peer->addr.sin_port) { 23207 peer->addr.sin_port = htons(((peer->socket.type & SIP_TRANSPORT_TLS) ? STANDARD_TLS_PORT : STANDARD_SIP_PORT)); 23208 } 23209 if (!peer->defaddr.sin_port) { 23210 peer->defaddr.sin_port = htons(((peer->socket.type & SIP_TRANSPORT_TLS) ? STANDARD_TLS_PORT : STANDARD_SIP_PORT)); 23211 } 23212 if (!peer->socket.port) { 23213 peer->socket.port = htons(((peer->socket.type & SIP_TRANSPORT_TLS) ? STANDARD_TLS_PORT : STANDARD_SIP_PORT)); 23214 } 23215 23216 if (!sip_cfg.ignore_regexpire && peer->host_dynamic && realtime) { 23217 time_t nowtime = time(NULL); 23218 23219 if ((nowtime - regseconds) > 0) { 23220 destroy_association(peer); 23221 memset(&peer->addr, 0, sizeof(peer->addr)); 23222 peer->lastms = -1; 23223 ast_debug(1, "Bah, we're expired (%d/%d/%d)!\n", (int)(nowtime - regseconds), (int)regseconds, (int)nowtime); 23224 } 23225 } 23226 23227 /* Startup regular pokes */ 23228 if (!devstate_only && realtime && peer->lastms > 0) { 23229 ref_peer(peer, "schedule qualify"); 23230 sip_poke_peer(peer, 0); 23231 } 23232 23233 ast_copy_flags(&peer->flags[0], &peerflags[0], mask[0].flags); 23234 ast_copy_flags(&peer->flags[1], &peerflags[1], mask[1].flags); 23235 if (ast_test_flag(&peer->flags[1], SIP_PAGE2_ALLOWSUBSCRIBE)) { 23236 global_allowsubscribe = TRUE; /* No global ban any more */ 23237 } 23238 if (!found && peer->host_dynamic && !peer->is_realtime) { 23239 reg_source_db(peer); 23240 } 23241 23242 /* If they didn't request that MWI is sent *only* on subscribe, go ahead and 23243 * subscribe to it now. */ 23244 if (!devstate_only && !ast_test_flag(&peer->flags[1], SIP_PAGE2_SUBSCRIBEMWIONLY) && 23245 !AST_LIST_EMPTY(&peer->mailboxes)) { 23246 add_peer_mwi_subs(peer); 23247 /* Send MWI from the event cache only. This is so we can send initial 23248 * MWI if app_voicemail got loaded before chan_sip. If it is the other 23249 * way, then we will get events when app_voicemail gets loaded. */ 23250 sip_send_mwi_to_peer(peer, NULL, 1); 23251 } 23252 23253 peer->the_mark = 0; 23254 23255 ast_free_ha(oldha); 23256 if (!ast_strlen_zero(callback)) { /* build string from peer info */ 23257 char *reg_string; 23258 23259 if (asprintf(®_string, "%s?%s:%s@%s/%s", peer->name, peer->username, peer->secret, peer->tohost, callback) < 0) { 23260 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno)); 23261 } else if (reg_string) { 23262 sip_register(reg_string, 0); /* XXX TODO: count in registry_count */ 23263 ast_free(reg_string); 23264 } 23265 } 23266 return peer; 23267 }
| static int build_reply_digest | ( | struct sip_pvt * | p, | |
| int | method, | |||
| char * | digest, | |||
| int | digest_len | |||
| ) | [static] |
Build reply digest.
Definition at line 16305 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(), 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().
16306 { 16307 char a1[256]; 16308 char a2[256]; 16309 char a1_hash[256]; 16310 char a2_hash[256]; 16311 char resp[256]; 16312 char resp_hash[256]; 16313 char uri[256]; 16314 char opaque[256] = ""; 16315 char cnonce[80]; 16316 const char *username; 16317 const char *secret; 16318 const char *md5secret; 16319 struct sip_auth *auth = NULL; /* Realm authentication */ 16320 16321 if (!ast_strlen_zero(p->domain)) 16322 ast_copy_string(uri, p->domain, sizeof(uri)); 16323 else if (!ast_strlen_zero(p->uri)) 16324 ast_copy_string(uri, p->uri, sizeof(uri)); 16325 else 16326 snprintf(uri, sizeof(uri), "sip:%s@%s", p->username, ast_inet_ntoa(p->sa.sin_addr)); 16327 16328 snprintf(cnonce, sizeof(cnonce), "%08lx", ast_random()); 16329 16330 /* Check if we have separate auth credentials */ 16331 if(!(auth = find_realm_authentication(p->peerauth, p->realm))) /* Start with peer list */ 16332 auth = find_realm_authentication(authl, p->realm); /* If not, global list */ 16333 16334 if (auth) { 16335 ast_log(LOG_DEBUG, "use realm [%s] from peer [%s][%s]\n", auth->username, p->peername, p->username); 16336 username = auth->username; 16337 secret = auth->secret; 16338 md5secret = auth->md5secret; 16339 if (sipdebug) 16340 ast_debug(1, "Using realm %s authentication for call %s\n", p->realm, p->callid); 16341 } else { 16342 /* No authentication, use peer or register= config */ 16343 username = p->authname; 16344 secret = p->peersecret; 16345 md5secret = p->peermd5secret; 16346 } 16347 if (ast_strlen_zero(username)) /* We have no authentication */ 16348 return -1; 16349 16350 /* Calculate SIP digest response */ 16351 snprintf(a1, sizeof(a1), "%s:%s:%s", username, p->realm, secret); 16352 snprintf(a2, sizeof(a2), "%s:%s", sip_methods[method].text, uri); 16353 if (!ast_strlen_zero(md5secret)) 16354 ast_copy_string(a1_hash, md5secret, sizeof(a1_hash)); 16355 else 16356 ast_md5_hash(a1_hash, a1); 16357 ast_md5_hash(a2_hash, a2); 16358 16359 p->noncecount++; 16360 if (!ast_strlen_zero(p->qop)) 16361 snprintf(resp, sizeof(resp), "%s:%s:%08x:%s:%s:%s", a1_hash, p->nonce, p->noncecount, cnonce, "auth", a2_hash); 16362 else 16363 snprintf(resp, sizeof(resp), "%s:%s:%s", a1_hash, p->nonce, a2_hash); 16364 ast_md5_hash(resp_hash, resp); 16365 16366 /* only include the opaque string if it's set */ 16367 if (!ast_strlen_zero(p->opaque)) { 16368 snprintf(opaque, sizeof(opaque), ", opaque=\"%s\"", p->opaque); 16369 } 16370 16371 /* XXX We hard code our qop to "auth" for now. XXX */ 16372 if (!ast_strlen_zero(p->qop)) 16373 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); 16374 else 16375 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); 16376 16377 append_history(p, "AuthResp", "Auth response sent for %s in realm %s - nc %d", username, p->realm, p->noncecount); 16378 16379 return 0; 16380 }
| 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 11652 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 handle_request_invite(), handle_request_subscribe(), and handle_response_invite().
11653 { 11654 struct sip_route *thishop, *head, *tail; 11655 int start = 0; 11656 int len; 11657 const char *rr, *contact, *c; 11658 11659 /* Once a persistant route is set, don't fool with it */ 11660 if (p->route && p->route_persistant) { 11661 ast_debug(1, "build_route: Retaining previous route: <%s>\n", p->route->hop); 11662 return; 11663 } 11664 11665 if (p->route) { 11666 free_old_route(p->route); 11667 p->route = NULL; 11668 } 11669 11670 /* We only want to create the route set the first time this is called */ 11671 p->route_persistant = 1; 11672 11673 /* Build a tailq, then assign it to p->route when done. 11674 * If backwards, we add entries from the head so they end up 11675 * in reverse order. However, we do need to maintain a correct 11676 * tail pointer because the contact is always at the end. 11677 */ 11678 head = NULL; 11679 tail = head; 11680 /* 1st we pass through all the hops in any Record-Route headers */ 11681 for (;;) { 11682 /* Each Record-Route header */ 11683 rr = __get_header(req, "Record-Route", &start); 11684 if (*rr == '\0') 11685 break; 11686 for (; (rr = strchr(rr, '<')) ; rr += len) { /* Each route entry */ 11687 ++rr; 11688 len = strcspn(rr, ">") + 1; 11689 /* Make a struct route */ 11690 if ((thishop = ast_malloc(sizeof(*thishop) + len))) { 11691 /* ast_calloc is not needed because all fields are initialized in this block */ 11692 ast_copy_string(thishop->hop, rr, len); 11693 ast_debug(2, "build_route: Record-Route hop: <%s>\n", thishop->hop); 11694 /* Link in */ 11695 if (backwards) { 11696 /* Link in at head so they end up in reverse order */ 11697 thishop->next = head; 11698 head = thishop; 11699 /* If this was the first then it'll be the tail */ 11700 if (!tail) 11701 tail = thishop; 11702 } else { 11703 thishop->next = NULL; 11704 /* Link in at the end */ 11705 if (tail) 11706 tail->next = thishop; 11707 else 11708 head = thishop; 11709 tail = thishop; 11710 } 11711 } 11712 } 11713 } 11714 11715 /* Only append the contact if we are dealing with a strict router */ 11716 if (!head || (!ast_strlen_zero(head->hop) && strstr(head->hop, ";lr") == NULL) ) { 11717 /* 2nd append the Contact: if there is one */ 11718 /* Can be multiple Contact headers, comma separated values - we just take the first */ 11719 contact = get_header(req, "Contact"); 11720 if (!ast_strlen_zero(contact)) { 11721 ast_debug(2, "build_route: Contact hop: %s\n", contact); 11722 /* Look for <: delimited address */ 11723 c = strchr(contact, '<'); 11724 if (c) { 11725 /* Take to > */ 11726 ++c; 11727 len = strcspn(c, ">") + 1; 11728 } else { 11729 /* No <> - just take the lot */ 11730 c = contact; 11731 len = strlen(contact) + 1; 11732 } 11733 if ((thishop = ast_malloc(sizeof(*thishop) + len))) { 11734 /* ast_calloc is not needed because all fields are initialized in this block */ 11735 ast_copy_string(thishop->hop, c, len); 11736 thishop->next = NULL; 11737 /* Goes at the end */ 11738 if (tail) 11739 tail->next = thishop; 11740 else 11741 head = thishop; 11742 } 11743 } 11744 } 11745 11746 /* Store as new route */ 11747 p->route = head; 11748 11749 /* For debugging dump what we ended up with */ 11750 if (sip_debug_test_pvt(p)) 11751 list_route(p->route); 11752 }
| static void build_rpid | ( | struct sip_pvt * | p | ) | [static] |
Build the Remote Party-ID & From using callingpres options.
Definition at line 9946 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().
09947 { 09948 int send_pres_tags = TRUE; 09949 const char *privacy=NULL; 09950 const char *screen=NULL; 09951 char buf[256]; 09952 const char *clid = default_callerid; 09953 const char *clin = NULL; 09954 const char *fromdomain; 09955 09956 if (!ast_strlen_zero(p->rpid) || !ast_strlen_zero(p->rpid_from)) 09957 return; 09958 09959 if (p->owner && !ast_strlen_zero(p->owner->cid.cid_num)) 09960 clid = p->owner->cid.cid_num; 09961 if (p->owner && p->owner->cid.cid_name) 09962 clin = p->owner->cid.cid_name; 09963 if (ast_strlen_zero(clin)) 09964 clin = clid; 09965 09966 switch (p->callingpres) { 09967 case AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED: 09968 privacy = "off"; 09969 screen = "no"; 09970 break; 09971 case AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN: 09972 privacy = "off"; 09973 screen = "yes"; 09974 break; 09975 case AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN: 09976 privacy = "off"; 09977 screen = "no"; 09978 break; 09979 case AST_PRES_ALLOWED_NETWORK_NUMBER: 09980 privacy = "off"; 09981 screen = "yes"; 09982 break; 09983 case AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED: 09984 privacy = "full"; 09985 screen = "no"; 09986 break; 09987 case AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN: 09988 privacy = "full"; 09989 screen = "yes"; 09990 break; 09991 case AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN: 09992 privacy = "full"; 09993 screen = "no"; 09994 break; 09995 case AST_PRES_PROHIB_NETWORK_NUMBER: 09996 privacy = "full"; 09997 screen = "yes"; 09998 break; 09999 case AST_PRES_NUMBER_NOT_AVAILABLE: 10000 send_pres_tags = FALSE; 10001 break; 10002 default: 10003 ast_log(LOG_WARNING, "Unsupported callingpres (%d)\n", p->callingpres); 10004 if ((p->callingpres & AST_PRES_RESTRICTION) != AST_PRES_ALLOWED) 10005 privacy = "full"; 10006 else 10007 privacy = "off"; 10008 screen = "no"; 10009 break; 10010 } 10011 10012 fromdomain = S_OR(p->fromdomain, ast_inet_ntoa(p->ourip.sin_addr)); 10013 10014 snprintf(buf, sizeof(buf), "\"%s\" <sip:%s@%s>", clin, clid, fromdomain); 10015 if (send_pres_tags) 10016 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ";privacy=%s;screen=%s", privacy, screen); 10017 ast_string_field_set(p, rpid, buf); 10018 10019 ast_string_field_build(p, rpid_from, "\"%s\" <sip:%s@%s>;tag=%s", clin, 10020 S_OR(p->fromuser, clid), 10021 fromdomain, p->tag); 10022 }
| static void build_via | ( | struct sip_pvt * | p | ) | [static] |
Build a Via header for a request.
Definition at line 3204 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().
03205 { 03206 /* Work around buggy UNIDEN UIP200 firmware */ 03207 const char *rport = ast_test_flag(&p->flags[0], SIP_NAT) & SIP_NAT_RFC3581 ? ";rport" : ""; 03208 03209 /* z9hG4bK is a magic cookie. See RFC 3261 section 8.1.1.7 */ 03210 snprintf(p->via, sizeof(p->via), "SIP/2.0/%s %s:%d;branch=z9hG4bK%08x%s", 03211 get_transport_pvt(p), 03212 ast_inet_ntoa(p->ourip.sin_addr), 03213 ntohs(p->ourip.sin_port), (int) p->branch, rport); 03214 }
| static int cb_extensionstate | ( | char * | context, | |
| char * | exten, | |||
| int | state, | |||
| void * | data | |||
| ) | [static] |
Callback for the devicestate notification (SUBSCRIBE) support subsystem.
Definition at line 11984 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().
11985 { 11986 struct sip_pvt *p = data; 11987 11988 sip_pvt_lock(p); 11989 11990 switch(state) { 11991 case AST_EXTENSION_DEACTIVATED: /* Retry after a while */ 11992 case AST_EXTENSION_REMOVED: /* Extension is gone */ 11993 if (p->autokillid > -1 && sip_cancel_destroy(p)) /* Remove subscription expiry for renewals */ 11994 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 11995 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); /* Delete subscription in 32 secs */ 11996 ast_verb(2, "Extension state: Watcher for hint %s %s. Notify User %s\n", exten, state == AST_EXTENSION_DEACTIVATED ? "deactivated" : "removed", p->username); 11997 p->stateid = -1; 11998 p->subscribed = NONE; 11999 append_history(p, "Subscribestatus", "%s", state == AST_EXTENSION_REMOVED ? "HintRemoved" : "Deactivated"); 12000 break; 12001 default: /* Tell user */ 12002 p->laststate = state; 12003 break; 12004 } 12005 if (p->subscribed != NONE) { /* Only send state NOTIFY if we know the format */ 12006 if (!p->pendinginvite) { 12007 transmit_state_notify(p, state, 1, FALSE); 12008 } else { 12009 /* We already have a NOTIFY sent that is not answered. Queue the state up. 12010 if many state changes happen meanwhile, we will only send a notification of the last one */ 12011 ast_set_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE); 12012 } 12013 } 12014 ast_verb(2, "Extension Changed %s[%s] new state %s for Notify User %s %s\n", exten, context, ast_extension_state2str(state), p->username, 12015 ast_test_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE) ? "(queued)" : ""); 12016 12017 sip_pvt_unlock(p); 12018 12019 return 0; 12020 }
| static void change_t38_state | ( | struct sip_pvt * | p, | |
| int | state | |||
| ) | [static] |
Change the T38 state on a SIP dialog.
Definition at line 4643 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, 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().
04644 { 04645 int old = p->t38.state; 04646 struct ast_channel *chan = p->owner; 04647 struct ast_control_t38_parameters parameters = { .request_response = 0 }; 04648 04649 /* Don't bother changing if we are already in the state wanted */ 04650 if (old == state) 04651 return; 04652 04653 p->t38.state = state; 04654 ast_debug(2, "T38 state changed to %d on channel %s\n", p->t38.state, chan ? chan->name : "<none>"); 04655 04656 /* If no channel was provided we can't send off a control frame */ 04657 if (!chan) 04658 return; 04659 04660 /* Given the state requested and old state determine what control frame we want to queue up */ 04661 switch (state) { 04662 case T38_PEER_REINVITE: 04663 parameters = p->t38.their_parms; 04664 parameters.max_ifp = ast_udptl_get_far_max_ifp(p->udptl); 04665 parameters.request_response = AST_T38_REQUEST_NEGOTIATE; 04666 ast_udptl_set_tag(p->udptl, "SIP/%s", p->username); 04667 break; 04668 case T38_ENABLED: 04669 parameters = p->t38.their_parms; 04670 parameters.max_ifp = ast_udptl_get_far_max_ifp(p->udptl); 04671 parameters.request_response = AST_T38_NEGOTIATED; 04672 ast_udptl_set_tag(p->udptl, "SIP/%s", p->username); 04673 break; 04674 case T38_DISABLED: 04675 if (old == T38_ENABLED) { 04676 parameters.request_response = AST_T38_TERMINATED; 04677 } else if (old == T38_LOCAL_REINVITE) { 04678 parameters.request_response = AST_T38_REFUSED; 04679 } 04680 break; 04681 case T38_LOCAL_REINVITE: 04682 /* wait until we get a peer response before responding to local reinvite */ 04683 break; 04684 } 04685 04686 /* Woot we got a message, create a control frame and send it on! */ 04687 if (parameters.request_response) 04688 ast_queue_control_data(chan, AST_CONTROL_T38_PARAMETERS, ¶meters, sizeof(parameters)); 04689 }
| 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 11776 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, ast_str::str, strsep(), text, transmit_response_with_auth(), TRUE, and WWW_AUTH.
Referenced by check_peer_ok(), and register_verify().
11779 { 11780 const char *response; 11781 char *reqheader, *respheader; 11782 const char *authtoken; 11783 char a1_hash[256]; 11784 char resp_hash[256]=""; 11785 char *c; 11786 int wrongnonce = FALSE; 11787 int good_response; 11788 const char *usednonce = p->randdata; 11789 struct ast_str *buf; 11790 int res; 11791 11792 /* table of recognised keywords, and their value in the digest */ 11793 enum keys { K_RESP, K_URI, K_USER, K_NONCE, K_LAST }; 11794 struct x { 11795 const char *key; 11796 const char *s; 11797 } *i, keys[] = { 11798 [K_RESP] = { "response=", "" }, 11799 [K_URI] = { "uri=", "" }, 11800 [K_USER] = { "username=", "" }, 11801 [K_NONCE] = { "nonce=", "" }, 11802 [K_LAST] = { NULL, NULL} 11803 }; 11804 11805 /* Always OK if no secret */ 11806 if (ast_strlen_zero(secret) && ast_strlen_zero(md5secret)) 11807 return AUTH_SUCCESSFUL; 11808 11809 /* Always auth with WWW-auth since we're NOT a proxy */ 11810 /* Using proxy-auth in a B2BUA may block proxy authorization in the same transaction */ 11811 response = "401 Unauthorized"; 11812 11813 /* 11814 * Note the apparent swap of arguments below, compared to other 11815 * usages of auth_headers(). 11816 */ 11817 auth_headers(WWW_AUTH, &respheader, &reqheader); 11818 11819 authtoken = get_header(req, reqheader); 11820 if (ignore && !ast_strlen_zero(p->randdata) && ast_strlen_zero(authtoken)) { 11821 /* This is a retransmitted invite/register/etc, don't reconstruct authentication 11822 information */ 11823 if (!reliable) { 11824 /* Resend message if this was NOT a reliable delivery. Otherwise the 11825 retransmission should get it */ 11826 transmit_response_with_auth(p, response, req, p->randdata, reliable, respheader, 0); 11827 /* Schedule auto destroy in 32 seconds (according to RFC 3261) */ 11828 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 11829 } 11830 return AUTH_CHALLENGE_SENT; 11831 } else if (ast_strlen_zero(p->randdata) || ast_strlen_zero(authtoken)) { 11832 /* We have no auth, so issue challenge and request authentication */ 11833 set_nonce_randdata(p, 1); /* Create nonce for challenge */ 11834 transmit_response_with_auth(p, response, req, p->randdata, reliable, respheader, 0); 11835 /* Schedule auto destroy in 32 seconds */ 11836 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 11837 return AUTH_CHALLENGE_SENT; 11838 } 11839 11840 /* --- We have auth, so check it */ 11841 11842 /* Whoever came up with the authentication section of SIP can suck my %&#$&* for not putting 11843 an example in the spec of just what it is you're doing a hash on. */ 11844 11845 if (!(buf = ast_str_thread_get(&check_auth_buf, CHECK_AUTH_BUF_INITLEN))) 11846 return AUTH_SECRET_FAILED; /*! XXX \todo need a better return code here */ 11847 11848 /* Make a copy of the response and parse it */ 11849 res = ast_str_set(&buf, 0, "%s", authtoken); 11850 11851 if (res == AST_DYNSTR_BUILD_FAILED) 11852 return AUTH_SECRET_FAILED; /*! XXX \todo need a better return code here */ 11853 11854 c = buf->str; 11855 11856 while(c && *(c = ast_skip_blanks(c)) ) { /* lookup for keys */ 11857 for (i = keys; i->key != NULL; i++) { 11858 const char *separator = ","; /* default */ 11859 11860 if (strncasecmp(c, i->key, strlen(i->key)) != 0) 11861 continue; 11862 /* Found. Skip keyword, take text in quotes or up to the separator. */ 11863 c += strlen(i->key); 11864 if (*c == '"') { /* in quotes. Skip first and look for last */ 11865 c++; 11866 separator = "\""; 11867 } 11868 i->s = c; 11869 strsep(&c, separator); 11870 break; 11871 } 11872 if (i->key == NULL) /* not found, jump after space or comma */ 11873 strsep(&c, " ,"); 11874 } 11875 11876 /* Verify that digest username matches the username we auth as */ 11877 if (strcmp(username, keys[K_USER].s)) { 11878 ast_log(LOG_WARNING, "username mismatch, have <%s>, digest has <%s>\n", 11879 username, keys[K_USER].s); 11880 /* Oops, we're trying something here */ 11881 return AUTH_USERNAME_MISMATCH; 11882 } 11883 11884 /* Verify nonce from request matches our nonce, and the nonce has not already been responded to. 11885 * If this check fails, send 401 with new nonce */ 11886 if (strcasecmp(p->randdata, keys[K_NONCE].s) || p->stalenonce) { /* XXX it was 'n'casecmp ? */ 11887 wrongnonce = TRUE; 11888 usednonce = keys[K_NONCE].s; 11889 } else { 11890 p->stalenonce = 1; /* now, since the nonce has a response, mark it as stale so it can't be sent or responded to again */ 11891 } 11892 11893 if (!ast_strlen_zero(md5secret)) 11894 ast_copy_string(a1_hash, md5secret, sizeof(a1_hash)); 11895 else { 11896 char a1[256]; 11897 snprintf(a1, sizeof(a1), "%s:%s:%s", username, global_realm, secret); 11898 ast_md5_hash(a1_hash, a1); 11899 } 11900 11901 /* compute the expected response to compare with what we received */ 11902 { 11903 char a2[256]; 11904 char a2_hash[256]; 11905 char resp[256]; 11906 11907 snprintf(a2, sizeof(a2), "%s:%s", sip_methods[sipmethod].text, 11908 S_OR(keys[K_URI].s, uri)); 11909 ast_md5_hash(a2_hash, a2); 11910 snprintf(resp, sizeof(resp), "%s:%s:%s", a1_hash, usednonce, a2_hash); 11911 ast_md5_hash(resp_hash, resp); 11912 } 11913 11914 good_response = keys[K_RESP].s && 11915 !strncasecmp(keys[K_RESP].s, resp_hash, strlen(resp_hash)); 11916 if (wrongnonce) { 11917 if (good_response) { 11918 if (sipdebug) 11919 ast_log(LOG_NOTICE, "Correct auth, but based on stale nonce received from '%s'\n", get_header(req, "To")); 11920 /* We got working auth token, based on stale nonce . */ 11921 set_nonce_randdata(p, 0); 11922 transmit_response_with_auth(p, response, req, p->randdata, reliable, respheader, TRUE); 11923 } else { 11924 /* Everything was wrong, so give the device one more try with a new challenge */ 11925 if (!req->ignore) { 11926 if (sipdebug) 11927 ast_log(LOG_NOTICE, "Bad authentication received from '%s'\n", get_header(req, "To")); 11928 set_nonce_randdata(p, 1); 11929 } else { 11930 if (sipdebug) 11931 ast_log(LOG_NOTICE, "Duplicate authentication received from '%s'\n", get_header(req, "To")); 11932 } 11933 transmit_response_with_auth(p, response, req, p->randdata, reliable, respheader, FALSE); 11934 } 11935 11936 /* Schedule auto destroy in 32 seconds */ 11937 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 11938 return AUTH_CHALLENGE_SENT; 11939 } 11940 if (good_response) { 11941 append_history(p, "AuthOK", "Auth challenge succesful for %s", username); 11942 return AUTH_SUCCESSFUL; 11943 } 11944 11945 /* Ok, we have a bad username/secret pair */ 11946 /* Tell the UAS not to re-send this authentication data, because 11947 it will continue to fail 11948 */ 11949 11950 return AUTH_SECRET_FAILED; 11951 }
| 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 13115 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(), sip_request::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().
13120 { 13121 enum check_auth_result res; 13122 int debug=sip_debug_test_addr(sin); 13123 struct sip_peer *peer; 13124 13125 if (sipmethod == SIP_SUBSCRIBE) { 13126 /* For subscribes, match on device name only; for other methods, 13127 * match on IP address-port of the incoming request. 13128 */ 13129 peer = find_peer(of, NULL, TRUE, FINDALLDEVICES, FALSE, 0); 13130 } else { 13131 /* First find devices based on username (avoid all type=peer's) */ 13132 peer = find_peer(of, NULL, TRUE, FINDUSERS, FALSE, 0); 13133 13134 /* Then find devices based on IP */ 13135 if (!peer) { 13136 peer = find_peer(NULL, &p->recv, TRUE, FINDPEERS, FALSE, p->socket.type); 13137 } 13138 } 13139 13140 if (!peer) { 13141 if (debug) 13142 ast_verbose("No matching peer for '%s' from '%s:%d'\n", 13143 of, ast_inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port)); 13144 return AUTH_DONT_KNOW; 13145 } 13146 if (!ast_apply_ha(peer->ha, sin)) { 13147 ast_debug(2, "Found peer '%s' for '%s', but fails host access\n", peer->name, of); 13148 unref_peer(peer, "unref_peer: check_peer_ok: from find_peer call, early return of AUTH_ACL_FAILED"); 13149 return AUTH_ACL_FAILED; 13150 } 13151 if (debug) 13152 ast_verbose("Found peer '%s' for '%s' from %s:%d\n", 13153 peer->name, of, ast_inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port)); 13154 13155 /* XXX what about p->prefs = peer->prefs; ? */ 13156 /* Set Frame packetization */ 13157 if (p->rtp) { 13158 ast_rtp_codec_setpref(p->rtp, &peer->prefs); 13159 p->autoframing = peer->autoframing; 13160 } 13161 13162 /* Take the peer */ 13163 ast_copy_flags(&p->flags[0], &peer->flags[0], SIP_FLAGS_TO_COPY); 13164 ast_copy_flags(&p->flags[1], &peer->flags[1], SIP_PAGE2_FLAGS_TO_COPY); 13165 13166 if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT) && p->udptl) { 13167 p->t38_maxdatagram = peer->t38_maxdatagram; 13168 set_t38_capabilities(p); 13169 } 13170 13171 /* Copy SIP extensions profile to peer */ 13172 /* XXX is this correct before a successful auth ? */ 13173 if (p->sipoptions) 13174 peer->sipoptions = p->sipoptions; 13175 13176 replace_cid(p, rpid_num, calleridname); 13177 do_setnat(p, ast_test_flag(&p->flags[0], SIP_NAT_ROUTE)); 13178 13179 ast_string_field_set(p, peersecret, peer->secret); 13180 ast_string_field_set(p, peermd5secret, peer->md5secret); 13181 ast_string_field_set(p, subscribecontext, peer->subscribecontext); 13182 ast_string_field_set(p, mohinterpret, peer->mohinterpret); 13183 ast_string_field_set(p, mohsuggest, peer->mohsuggest); 13184 ast_string_field_set(p, parkinglot, peer->parkinglot); 13185 if (peer->callingpres) /* Peer calling pres setting will override RPID */ 13186 p->callingpres = peer->callingpres; 13187 if (peer->maxms && peer->lastms) 13188 p->timer_t1 = peer->lastms < global_t1min ? global_t1min : peer->lastms; 13189 else 13190 p->timer_t1 = peer->timer_t1; 13191 13192 /* Set timer B to control transaction timeouts */ 13193 if (peer->timer_b) 13194 p->timer_b = peer->timer_b; 13195 else 13196 p->timer_b = 64 * p->timer_t1; 13197 13198 if (ast_test_flag(&peer->flags[0], SIP_INSECURE_INVITE)) { 13199 /* Pretend there is no required authentication */ 13200 ast_string_field_set(p, peersecret, NULL); 13201 ast_string_field_set(p, peermd5secret, NULL); 13202 } 13203 if (!(res = check_auth(p, req, peer->name, p->peersecret, p->peermd5secret, sipmethod, uri2, reliable, req->ignore))) { 13204 ast_copy_flags(&p->flags[0], &peer->flags[0], SIP_FLAGS_TO_COPY); 13205 ast_copy_flags(&p->flags[1], &peer->flags[1], SIP_PAGE2_FLAGS_TO_COPY); 13206 /* If we have a call limit, set flag */ 13207 if (peer->call_limit) 13208 ast_set_flag(&p->flags[0], SIP_CALL_LIMIT); 13209 ast_string_field_set(p, peername, peer->name); 13210 ast_string_field_set(p, authname, peer->name); 13211 13212 if (sipmethod == SIP_INVITE) { 13213 /* copy channel vars */ 13214 p->chanvars = copy_vars(peer->chanvars); 13215 } 13216 13217 if (authpeer) { 13218 ao2_t_ref(peer, 1, "copy pointer into (*authpeer)"); 13219 (*authpeer) = peer; /* Add a ref to the object here, to keep it in memory a bit longer if it is realtime */ 13220 } 13221 13222 if (!ast_strlen_zero(peer->username)) { 13223 ast_string_field_set(p, username, peer->username); 13224 /* Use the default username for authentication on outbound calls */ 13225 /* XXX this takes the name from the caller... can we override ? */ 13226 ast_string_field_set(p, authname, peer->username); 13227 } 13228 if (!ast_strlen_zero(peer->cid_num)) { 13229 char *tmp = ast_strdupa(peer->cid_num); 13230 if (global_shrinkcallerid && ast_is_shrinkable_phonenumber(tmp)) 13231 ast_shrink_phone_number(tmp); 13232 ast_string_field_set(p, cid_num, tmp); 13233 } 13234 if (!ast_strlen_zero(peer->cid_name)) 13235 ast_string_field_set(p, cid_name, peer->cid_name); 13236 ast_string_field_set(p, fullcontact, peer->fullcontact); 13237 if (!ast_strlen_zero(peer->context)) 13238 ast_string_field_set(p, context, peer->context); 13239 ast_string_field_set(p, peersecret, peer->secret); 13240 ast_string_field_set(p, peermd5secret, peer->md5secret); 13241 ast_string_field_set(p, language, peer->language); 13242 ast_string_field_set(p, accountcode, peer->accountcode); 13243 p->amaflags = peer->amaflags; 13244 p->callgroup = peer->callgroup; 13245 p->pickupgroup = peer->pickupgroup; 13246 p->capability = peer->capability; 13247 p->prefs = peer->prefs; 13248 p->jointcapability = peer->capability; 13249 if (p->peercapability) 13250 p->jointcapability &= p->peercapability; 13251 p->maxcallbitrate = peer->maxcallbitrate; 13252 if (!ast_test_flag(&p->flags[1], SIP_PAGE2_VIDEOSUPPORT_ALWAYS) && 13253 (!ast_test_flag(&p->flags[1], SIP_PAGE2_VIDEOSUPPORT) || 13254 !(p->capability & AST_FORMAT_VIDEO_MASK)) && 13255 p->vrtp) { 13256 ast_rtp_destroy(p->vrtp); 13257 p->vrtp = NULL; 13258 } 13259 if ((!ast_test_flag(&p->flags[1], SIP_PAGE2_TEXTSUPPORT) || !(p->capability & AST_FORMAT_TEXT_MASK)) && p->trtp) { 13260 ast_rtp_destroy(p->trtp); 13261 p->trtp = NULL; 13262 } 13263 if ((ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833) || 13264 (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO)) 13265 p->noncodeccapability |= AST_RTP_DTMF; 13266 else 13267 p->noncodeccapability &= ~AST_RTP_DTMF; 13268 p->jointnoncodeccapability = p->noncodeccapability; 13269 } 13270 unref_peer(peer, "check_peer_ok: unref_peer: tossing temp ptr to peer from find_peer"); 13271 return res; 13272 }
| static void check_pendings | ( | struct sip_pvt * | p | ) | [static] |
Check pending actions on SIP call.
Definition at line 16752 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::lastinvite, 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().
16753 { 16754 if (ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) { 16755 /* if we can't BYE, then this is really a pending CANCEL */ 16756 if (p->invitestate == INV_PROCEEDING || p->invitestate == INV_EARLY_MEDIA) 16757 transmit_request(p, SIP_CANCEL, p->lastinvite, XMIT_RELIABLE, FALSE); 16758 /* Actually don't destroy us yet, wait for the 487 on our original 16759 INVITE, but do set an autodestruct just in case we never get it. */ 16760 else { 16761 /* We have a pending outbound invite, don't send someting 16762 new in-transaction */ 16763 if (p->pendinginvite) 16764 return; 16765 16766 /* Perhaps there is an SD change INVITE outstanding */ 16767 transmit_request_with_auth(p, SIP_BYE, 0, XMIT_RELIABLE, TRUE); 16768 } 16769 ast_clear_flag(&p->flags[0], SIP_PENDINGBYE); 16770 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 16771 } else if (ast_test_flag(&p->flags[0], SIP_NEEDREINVITE)) { 16772 /* if we can't REINVITE, hold it for later */ 16773 if (p->pendinginvite || p->invitestate == INV_CALLING || p->invitestate == INV_PROCEEDING || p->invitestate == INV_EARLY_MEDIA || p->waitid > 0) { 16774 ast_debug(2, "NOT Sending pending reinvite (yet) on '%s'\n", p->callid); 16775 } else { 16776 ast_debug(2, "Sending pending reinvite on '%s'\n", p->callid); 16777 /* Didn't get to reinvite yet, so do it now */ 16778 transmit_reinvite_with_sdp(p, (p->t38.state == T38_LOCAL_REINVITE ? TRUE : FALSE), FALSE); 16779 ast_clear_flag(&p->flags[0], SIP_NEEDREINVITE); 16780 } 16781 } 16782 }
| 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
Do we need to move the lastrtptx to the RTP structure to have one for audio and one for video? It really does belong to the RTP structure.
Definition at line 21398 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, 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().
21399 { 21400 /* If we have no RTP or no active owner, no need to check timers */ 21401 if (!dialog->rtp || !dialog->owner) 21402 return; 21403 /* If the call is not in UP state or redirected outside Asterisk, no need to check timers */ 21404 21405 if (dialog->owner->_state != AST_STATE_UP || dialog->redirip.sin_addr.s_addr) 21406 return; 21407 21408 /* If the call is involved in a T38 fax session do not check RTP timeout */ 21409 if (dialog->t38.state == T38_ENABLED) 21410 return; 21411 21412 /* If we have no timers set, return now */ 21413 if ((ast_rtp_get_rtpkeepalive(dialog->rtp) == 0) && (ast_rtp_get_rtptimeout(dialog->rtp) == 0) && (ast_rtp_get_rtpholdtimeout(dialog->rtp) == 0)) 21414 return; 21415 21416 /* Check AUDIO RTP keepalives */ 21417 if (dialog->lastrtptx && ast_rtp_get_rtpkeepalive(dialog->rtp) && 21418 (t > dialog->lastrtptx + ast_rtp_get_rtpkeepalive(dialog->rtp))) { 21419 /* Need to send an empty RTP packet */ 21420 dialog->lastrtptx = time(NULL); 21421 ast_rtp_sendcng(dialog->rtp, 0); 21422 } 21423 21424 /*! \todo Check video RTP keepalives 21425 21426 Do we need to move the lastrtptx to the RTP structure to have one for audio and one 21427 for video? It really does belong to the RTP structure. 21428 */ 21429 21430 /* Check AUDIO RTP timers */ 21431 if (dialog->lastrtprx && (ast_rtp_get_rtptimeout(dialog->rtp) || ast_rtp_get_rtpholdtimeout(dialog->rtp)) && 21432 (t > dialog->lastrtprx + ast_rtp_get_rtptimeout(dialog->rtp))) { 21433 21434 /* Might be a timeout now -- see if we're on hold */ 21435 struct sockaddr_in sin; 21436 ast_rtp_get_peer(dialog->rtp, &sin); 21437 if (!ast_test_flag(&dialog->flags[1], SIP_PAGE2_CALL_ONHOLD) || (ast_rtp_get_rtpholdtimeout(dialog->rtp) && 21438 (t > dialog->lastrtprx + ast_rtp_get_rtpholdtimeout(dialog->rtp)))) { 21439 /* Needs a hangup */ 21440 if (ast_rtp_get_rtptimeout(dialog->rtp)) { 21441 while (dialog->owner && ast_channel_trylock(dialog->owner)) { 21442 sip_pvt_unlock(dialog); 21443 usleep(1); 21444 sip_pvt_lock(dialog); 21445 } 21446 ast_log(LOG_NOTICE, "Disconnecting call '%s' for lack of RTP activity in %ld seconds\n", 21447 dialog->owner->name, (long) (t - dialog->lastrtprx)); 21448 /* Issue a softhangup */ 21449 ast_softhangup_nolock(dialog->owner, AST_SOFTHANGUP_DEV); 21450 ast_channel_unlock(dialog->owner); 21451 /* forget the timeouts for this call, since a hangup 21452 has already been requested and we don't want to 21453 repeatedly request hangups 21454 */ 21455 ast_rtp_set_rtptimeout(dialog->rtp, 0); 21456 ast_rtp_set_rtpholdtimeout(dialog->rtp, 0); 21457 if (dialog->vrtp) { 21458 ast_rtp_set_rtptimeout(dialog->vrtp, 0); 21459 ast_rtp_set_rtpholdtimeout(dialog->vrtp, 0); 21460 } 21461 } 21462 } 21463 } 21464 }
| 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 22504 of file chan_sip.c.
References ast_copy_string(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strlen_zero(), domain::context, and domain::domain.
Referenced by func_check_sipdomain(), get_destination(), handle_request_refer(), and register_verify().
22505 { 22506 struct domain *d; 22507 int result = 0; 22508 22509 AST_LIST_LOCK(&domain_list); 22510 AST_LIST_TRAVERSE(&domain_list, d, list) { 22511 if (strcasecmp(d->domain, domain)) 22512 continue; 22513 22514 if (len && !ast_strlen_zero(d->context)) 22515 ast_copy_string(context, d->context, len); 22516 22517 result = 1; 22518 break; 22519 } 22520 AST_LIST_UNLOCK(&domain_list); 22521 22522 return result; 22523 }
| 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 13397 of file chan_sip.c.
References check_user_full().
Referenced by handle_request_invite().
13398 { 13399 return check_user_full(p, req, sipmethod, uri, reliable, sin, NULL); 13400 }
| 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 13280 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(), sip_pvt::callingpres, check_peer_ok(), cid_name, cid_num, dummy(), exten, sip_pvt::exten, sip_pvt::flags, get_calleridname(), get_header(), get_in_brackets(), get_rpid_num(), LOG_NOTICE, sip_pvt::our_contact, parse_uri(), replace_cid(), SIP_NAT_ROUTE, SIP_PAGE2_RPORT_PRESENT, strsep(), and terminate_uri().
Referenced by check_user(), and handle_request_subscribe().
13283 { 13284 char from[256]; 13285 char *dummy; /* dummy return value for parse_uri */ 13286 char *domain; /* dummy return value for parse_uri */ 13287 char *of; 13288 char rpid_num[50]; 13289 const char *rpid; 13290 enum check_auth_result res; 13291 char calleridname[50]; 13292 char *uri2 = ast_strdupa(uri); 13293 13294 terminate_uri(uri2); /* trim extra stuff */ 13295 13296 ast_copy_string(from, get_header(req, "From"), sizeof(from)); 13297 if (pedanticsipchecking) 13298 ast_uri_decode(from); 13299 /* XXX here tries to map the username for invite things */ 13300 memset(calleridname, 0, sizeof(calleridname)); 13301 get_calleridname(from, calleridname, sizeof(calleridname)); 13302 if (calleridname[0]) 13303 ast_string_field_set(p, cid_name, calleridname); 13304 13305 rpid = get_header(req, "Remote-Party-ID"); 13306 memset(rpid_num, 0, sizeof(rpid_num)); 13307 if (!ast_strlen_zero(rpid)) 13308 p->callingpres = get_rpid_num(rpid, rpid_num, sizeof(rpid_num)); 13309 13310 of = get_in_brackets(from); 13311 if (ast_strlen_zero(p->exten)) { 13312 char *t = uri2; 13313 if (!strncasecmp(t, "sip:", 4)) 13314 t+= 4; 13315 else if (!strncasecmp(t, "sips:", 5)) 13316 t += 5; 13317 ast_string_field_set(p, exten, t); 13318 t = strchr(p->exten, '@'); 13319 if (t) 13320 *t = '\0'; 13321 if (ast_strlen_zero(p->our_contact)) 13322 build_contact(p); 13323 } 13324 /* save the URI part of the From header */ 13325 ast_string_field_set(p, from, of); 13326 13327 13328 /* ignore all fields but name */ 13329 if (parse_uri(of, "sip:,sips:", &of, &dummy, &domain, &dummy, &dummy, NULL)) { 13330 ast_log(LOG_NOTICE, "From address missing 'sip:', using it anyway\n"); 13331 } 13332 13333 if (ast_strlen_zero(of)) { 13334 /* XXX note: the original code considered a missing @host 13335 * as a username-only URI. The SIP RFC (19.1.1) says that 13336 * this is wrong, and it should be considered as a domain-only URI. 13337 * For backward compatibility, we keep this block, but it is 13338 * really a mistake and should go away. 13339 */ 13340 of = domain; 13341 } else { 13342 char *tmp = ast_strdupa(of); 13343 /* We need to be able to handle auth-headers looking like 13344 <sip:8164444422;phone-context=+1@1.2.3.4:5060;user=phone;tag=SDadkoa01-gK0c3bdb43> 13345 */ 13346 tmp = strsep(&tmp, ";"); 13347 if (global_shrinkcallerid && ast_is_shrinkable_phonenumber(tmp)) 13348 ast_shrink_phone_number(tmp); 13349 ast_string_field_set(p, cid_num, tmp); 13350 } 13351 13352 if (global_match_auth_username) { 13353 /* 13354 * XXX This is experimental code to grab the search key from the 13355 * Auth header's username instead of the 'From' name, if available. 13356 * Do not enable this block unless you understand the side effects (if any!) 13357 * Note, the search for "username" should be done in a more robust way. 13358 * Note2, at the moment we check both fields, though maybe we should 13359 * pick one or another depending on the request ? XXX 13360 */ 13361 const char *hdr = get_header(req, "Authorization"); 13362 if (ast_strlen_zero(hdr)) 13363 hdr = get_header(req, "Proxy-Authorization"); 13364 13365 if ( !ast_strlen_zero(hdr) && (hdr = strstr(hdr, "username=\"")) ) { 13366 ast_copy_string(from, hdr + strlen("username=\""), sizeof(from)); 13367 of = from; 13368 of = strsep(&of, "\""); 13369 } 13370 } 13371 13372 res = check_peer_ok(p, of, req, sipmethod, sin, 13373 authpeer, reliable, rpid_num, calleridname, uri2); 13374 if (res != AUTH_DONT_KNOW) 13375 return res; 13376 13377 /* Finally, apply the guest policy */ 13378 if (global_allowguest) { 13379 replace_cid(p, rpid_num, calleridname); 13380 res = AUTH_SUCCESSFUL; 13381 } else if (global_alwaysauthreject) 13382 res = AUTH_FAKE_AUTH; /* reject with fake authorization request */ 13383 else 13384 res = AUTH_SECRET_FAILED; /* we don't want any guests, authentication will fail */ 13385 13386 13387 if (ast_test_flag(&p->flags[1], SIP_PAGE2_RPORT_PRESENT)) { 13388 ast_set_flag(&p->flags[0], SIP_NAT_ROUTE); 13389 } 13390 13391 return res; 13392 }
| 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 12947 of file chan_sip.c.
References 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().
12948 { 12949 char via[512]; 12950 char *c, *pt, *maddr; 12951 struct hostent *hp; 12952 struct ast_hostent ahp; 12953 12954 ast_copy_string(via, get_header(req, "Via"), sizeof(via)); 12955 12956 /* Work on the leftmost value of the topmost Via header */ 12957 c = strchr(via, ','); 12958 if (c) 12959 *c = '\0'; 12960 12961 /* Check for rport */ 12962 c = strstr(via, ";rport"); 12963 if (c && (c[6] != '=')) /* rport query, not answer */ 12964 ast_set_flag(&p->flags[1], SIP_PAGE2_RPORT_PRESENT); 12965 12966 /* Check for maddr */ 12967 maddr = strstr(via, "maddr="); 12968 if (maddr) { 12969 maddr += 6; 12970 c = maddr + strspn(maddr, "0123456789."); 12971 *c = '\0'; 12972 } 12973 12974 c = strchr(via, ';'); 12975 if (c) 12976 *c = '\0'; 12977 12978 c = strchr(via, ' '); 12979 if (c) { 12980 *c = '\0'; 12981 c = ast_skip_blanks(c+1); 12982 if (strcasecmp(via, "SIP/2.0/UDP") && strcasecmp(via, "SIP/2.0/TCP") && strcasecmp(via, "SIP/2.0/TLS")) { 12983 ast_log(LOG_WARNING, "Don't know how to respond via '%s'\n", via); 12984 return; 12985 } 12986 pt = strchr(c, ':'); 12987 if (pt) 12988 *pt++ = '\0'; /* remember port pointer */ 12989 /* Use maddr if found */ 12990 if (maddr) 12991 c = maddr; 12992 hp = ast_gethostbyname(c, &ahp); 12993 if (!hp) { 12994 ast_log(LOG_WARNING, "'%s' is not a valid host\n", c); 12995 return; 12996 } 12997 memset(&p->sa, 0, sizeof(p->sa)); 12998 p->sa.sin_family = AF_INET; 12999 memcpy(&p->sa.sin_addr, hp->h_addr, sizeof(p->sa.sin_addr)); 13000 p->sa.sin_port = htons(port_str2int(pt, STANDARD_SIP_PORT)); 13001 13002 if (sip_debug_test_pvt(p)) { 13003 const struct sockaddr_in *dst = sip_real_dst(p); 13004 ast_verbose("Sending to %s : %d (%s)\n", ast_inet_ntoa(dst->sin_addr), ntohs(dst->sin_port), sip_nat_mode(p)); 13005 } 13006 } 13007 }
| 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 12917 of file chan_sip.c.
References ast_copy_string(), ast_parse_arg(), get_header(), sip_pvt::ourip, PARSE_INADDR, and strsep().
12918 { 12919 char via[256]; 12920 char *cur, *opts; 12921 12922 ast_copy_string(via, get_header(req, "Via"), sizeof(via)); 12923 12924 /* Work on the leftmost value of the topmost Via header */ 12925 opts = strchr(via, ','); 12926 if (opts) 12927 *opts = '\0'; 12928 12929 /* parse all relevant options */ 12930 opts = strchr(via, ';'); 12931 if (!opts) 12932 return; /* no options to parse */ 12933 *opts++ = '\0'; 12934 while ( (cur = strsep(&opts, ";")) ) { 12935 if (!strncmp(cur, "rport=", 6)) { 12936 int port = strtol(cur+6, NULL, 10); 12937 /* XXX add error checking */ 12938 p->ourip.sin_port = ntohs(port); 12939 } else if (!strncmp(cur, "received=", 9)) { 12940 if (ast_parse_arg(cur+9, PARSE_INADDR, &p->ourip)) 12941 ; /* XXX add error checking */ 12942 } 12943 } 12944 }
| 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 14126 of file chan_sip.c.
References ast_context_destroy(), ast_context_find(), ast_copy_string(), AST_MAX_CONTEXT, and strsep().
Referenced by reload_config().
14127 { 14128 char *oldcontext, *newcontext, *stalecontext, *stringp, newlist[AST_MAX_CONTEXT]; 14129 14130 while ((oldcontext = strsep(&old, "&"))) { 14131 stalecontext = '\0'; 14132 ast_copy_string(newlist, new, sizeof(newlist)); 14133 stringp = newlist; 14134 while ((newcontext = strsep(&stringp, "&"))) { 14135 if (!strcmp(newcontext, oldcontext)) { 14136 /* This is not the context you're looking for */ 14137 stalecontext = '\0'; 14138 break; 14139 } else if (strcmp(newcontext, oldcontext)) { 14140 stalecontext = oldcontext; 14141 } 14142 14143 } 14144 if (stalecontext) 14145 ast_context_destroy(ast_context_find(stalecontext), "SIP"); 14146 } 14147 }
| static void clear_peer_mailboxes | ( | struct sip_peer * | peer | ) | [static] |
Destroy all peer-related mailbox subscriptions
Definition at line 4249 of file chan_sip.c.
References AST_LIST_REMOVE_HEAD, destroy_mailbox(), mailbox, and sip_peer::mailboxes.
Referenced by set_peer_defaults(), and sip_destroy_peer().
04250 { 04251 struct sip_mailbox *mailbox; 04252 04253 while ((mailbox = AST_LIST_REMOVE_HEAD(&peer->mailboxes, entry))) 04254 destroy_mailbox(mailbox); 04255 }
| static int clear_realm_authentication | ( | struct sip_auth * | authlist | ) | [static] |
Clear realm authentication list (at reload).
Definition at line 22593 of file chan_sip.c.
References ast_free, and sip_auth::next.
Referenced by build_peer(), reload_config(), sip_destroy_peer(), and unload_module().
| static void clear_sip_domains | ( | void | ) | [static] |
Clear our domain list (at reload).
Definition at line 22526 of file chan_sip.c.
References ast_free, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, and AST_LIST_UNLOCK.
Referenced by reload_config(), and unload_module().
22527 { 22528 struct domain *d; 22529 22530 AST_LIST_LOCK(&domain_list); 22531 while ((d = AST_LIST_REMOVE_HEAD(&domain_list, list))) 22532 ast_free(d); 22533 AST_LIST_UNLOCK(&domain_list); 22534 }
| 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 13637 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 15470 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, and unref_peer().
Referenced by complete_sip_show_peer(), complete_sipnotify(), sip_do_debug(), and sip_prune_realtime().
15471 { 15472 char *result = NULL; 15473 int wordlen = strlen(word); 15474 int which = 0; 15475 struct ao2_iterator i = ao2_iterator_init(peers, 0); 15476 struct sip_peer *peer; 15477 15478 while ((peer = ao2_t_iterator_next(&i, "iterate thru peers table"))) { 15479 /* locking of the object is not required because only the name and flags are being compared */ 15480 if (!strncasecmp(word, peer->name, wordlen) && 15481 (!flags2 || ast_test_flag(&peer->flags[1], flags2)) && 15482 ++which > state) 15483 result = ast_strdup(peer->name); 15484 unref_peer(peer, "toss iterator peer ptr before break"); 15485 if (result) { 15486 break; 15487 } 15488 } 15489 ao2_iterator_destroy(&i); 15490 return result; 15491 }
| static char * complete_sip_registered_peer | ( | const char * | word, | |
| int | state, | |||
| int | flags2 | |||
| ) | [static] |
Do completion on registered peer name.
Definition at line 15494 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, and unref_peer().
Referenced by complete_sip_unregister().
15495 { 15496 char *result = NULL; 15497 int wordlen = strlen(word); 15498 int which = 0; 15499 struct ao2_iterator i; 15500 struct sip_peer *peer; 15501 15502 i = ao2_iterator_init(peers, 0); 15503 while ((peer = ao2_t_iterator_next(&i, "iterate thru peers table"))) { 15504 if (!strncasecmp(word, peer->name, wordlen) && 15505 (!flags2 || ast_test_flag(&peer->flags[1], flags2)) && 15506 ++which > state && peer->expire > 0) 15507 result = ast_strdup(peer->name); 15508 if (result) { 15509 unref_peer(peer, "toss iterator peer ptr before break"); 15510 break; 15511 } 15512 unref_peer(peer, "toss iterator peer ptr"); 15513 } 15514 ao2_iterator_destroy(&i); 15515 return result; 15516 }
| 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 15519 of file chan_sip.c.
References complete_sipch().
Referenced by sip_show_history().
15520 { 15521 if (pos == 3) 15522 return complete_sipch(line, word, pos, state); 15523 15524 return NULL; 15525 }
| 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 15528 of file chan_sip.c.
References complete_sip_peer().
Referenced by sip_qualify_peer(), and sip_show_peer().
15529 { 15530 if (pos == 3) { 15531 return complete_sip_peer(word, state, 0); 15532 } 15533 15534 return NULL; 15535 }
| 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 14819 of file chan_sip.c.
References complete_sip_user().
Referenced by sip_show_user().
14820 { 14821 if (pos == 3) 14822 return complete_sip_user(word, state); 14823 14824 return NULL; 14825 }
| 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 15538 of file chan_sip.c.
References complete_sip_registered_peer().
Referenced by sip_unregister().
15539 { 15540 if (pos == 2) 15541 return complete_sip_registered_peer(word, state, 0); 15542 15543 return NULL; 15544 }
| static char* complete_sip_user | ( | const char * | word, | |
| int | state | |||
| ) | [static] |
Do completion on user name.
Definition at line 14792 of file chan_sip.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock(), ao2_unlock(), ast_strdup, sip_peer::name, SIP_TYPE_USER, sip_peer::type, and unref_peer().
Referenced by complete_sip_show_user().
14793 { 14794 char *result = NULL; 14795 int wordlen = strlen(word); 14796 int which = 0; 14797 struct ao2_iterator user_iter; 14798 struct sip_peer *user; 14799 14800 user_iter = ao2_iterator_init(peers, 0); 14801 while ((user = ao2_iterator_next(&user_iter))) { 14802 ao2_lock(user); 14803 if (!(user->type & SIP_TYPE_USER)) { 14804 ao2_unlock(user); 14805 unref_peer(user, "complete sip user"); 14806 continue; 14807 } 14808 /* locking of the object is not required because only the name and flags are being compared */ 14809 if (!strncasecmp(word, user->name, wordlen) && ++which > state) { 14810 result = ast_strdup(user->name); 14811 } 14812 ao2_unlock(user); 14813 unref_peer(user, "complete sip user"); 14814 } 14815 ao2_iterator_destroy(&user_iter); 14816 return result; 14817 }
| 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 15440 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().
15441 { 15442 int which=0; 15443 struct sip_pvt *cur; 15444 char *c = NULL; 15445 int wordlen = strlen(word); 15446 struct ao2_iterator i; 15447 15448 if (pos != 3) { 15449 return NULL; 15450 } 15451 15452 i = ao2_iterator_init(dialogs, 0); 15453 while ((cur = ao2_t_iterator_next(&i, "iterate thru dialogs"))) { 15454 sip_pvt_lock(cur); 15455 if (!strncasecmp(word, cur->callid, wordlen) && ++which > state) { 15456 c = ast_strdup(cur->callid); 15457 sip_pvt_unlock(cur); 15458 dialog_unref(cur, "drop ref in iterator loop break"); 15459 break; 15460 } 15461 sip_pvt_unlock(cur); 15462 dialog_unref(cur, "drop ref in iterator loop"); 15463 } 15464 ao2_iterator_destroy(&i); 15465 return c; 15466 }
| static char * complete_sipnotify | ( | const char * | line, | |
| const char * | word, | |||
| int | pos, | |||
| int | state | |||
| ) | [static] |
Support routine for 'sip notify' CLI.
Definition at line 15547 of file chan_sip.c.
References ast_category_browse(), ast_strdup, and complete_sip_peer().
Referenced by sip_cli_notify().
15548 { 15549 char *c = NULL; 15550 15551 if (pos == 2) { 15552 int which = 0; 15553 char *cat = NULL; 15554 int wordlen = strlen(word); 15555 15556 /* do completion for notify type */ 15557 15558 if (!notify_types) 15559 return NULL; 15560 15561 while ( (cat = ast_category_browse(notify_types, cat)) ) { 15562 if (!strncasecmp(word, cat, wordlen) && ++which > state) { 15563 c = ast_strdup(cat); 15564 break; 15565 } 15566 } 15567 return c; 15568 } 15569 15570 if (pos > 2) 15571 return complete_sip_peer(word, state, 0); 15572 15573 return NULL; 15574 }
| 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 8456 of file chan_sip.c.
References __get_header(), add_header(), and ast_strlen_zero().
Referenced by respprep().
08457 { 08458 int start = 0; 08459 int copied = 0; 08460 for (;;) { 08461 const char *tmp = __get_header(orig, field, &start); 08462 08463 if (ast_strlen_zero(tmp)) 08464 break; 08465 /* Add what we're responding to */ 08466 add_header(req, field, tmp); 08467 copied++; 08468 } 08469 return copied ? 0 : -1; 08470 }
| 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 8445 of file chan_sip.c.
References add_header(), ast_log(), ast_strlen_zero(), get_header(), and LOG_NOTICE.
Referenced by reqprep(), and respprep().
08446 { 08447 const char *tmp = get_header(orig, field); 08448 08449 if (!ast_strlen_zero(tmp)) /* Add what we're responding to */ 08450 return add_header(req, field, tmp); 08451 ast_log(LOG_NOTICE, "No field '%s' present to copy\n", field); 08452 return -1; 08453 }
| 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 9758 of file chan_sip.c.
References ast_str_create(), ast_str_make_space(), sip_request::data, ast_str::len, 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().
09759 { 09760 struct ast_str *duplicate = dst->data; 09761 09762 /* First copy stuff */ 09763 memcpy(dst, src, sizeof(*dst)); 09764 dst->data = duplicate; 09765 09766 /* All these + 1's are to account for the need to include the NULL terminator 09767 * Using typical string functions like ast_copy_string or ast_str_set will not 09768 * work in this case because the src's data string is riddled with \0's all over 09769 * the place and so a memcpy is the only way to accurately copy the string 09770 */ 09771 09772 if (!dst->data && !(dst->data = ast_str_create(src->data->used + 1))) 09773 return; 09774 else if (dst->data->len < src->data->used + 1) 09775 ast_str_make_space(&dst->data, src->data->used + 1); 09776 09777 memcpy(dst->data->str, src->data->str, src->data->used + 1); 09778 dst->data->used = src->data->used; 09779 }
| static void copy_socket_data | ( | struct sip_socket * | to_sock, | |
| const struct sip_socket * | from_sock | |||
| ) | [static] |
Definition at line 4705 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().
04706 { 04707 if (to_sock->tcptls_session) { 04708 ao2_ref(to_sock->tcptls_session, -1); 04709 to_sock->tcptls_session = NULL; 04710 } 04711 04712 if (from_sock->tcptls_session) { 04713 ao2_ref(from_sock->tcptls_session, +1); 04714 } 04715 04716 *to_sock = *from_sock; 04717 }
| static struct ast_variable* copy_vars | ( | struct ast_variable * | src | ) | [static, read] |
duplicate a list of channel variables,
Definition at line 13087 of file chan_sip.c.
References ast_variable_new(), and ast_variable::next.
Referenced by check_peer_ok().
13088 { 13089 struct ast_variable *res = NULL, *tmp, *v = NULL; 13090 13091 for (v = src ; v ; v = v->next) { 13092 if ((tmp = ast_variable_new(v->name, v->value, v->file))) { 13093 tmp->next = res; 13094 res = tmp; 13095 } 13096 } 13097 return res; 13098 }
| 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 8480 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().
08481 { 08482 int copied = 0; 08483 int start = 0; 08484 08485 for (;;) { 08486 char new[512]; 08487 const char *oh = __get_header(orig, field, &start); 08488 08489 if (ast_strlen_zero(oh)) 08490 break; 08491 08492 if (!copied) { /* Only check for empty rport in topmost via header */ 08493 char leftmost[512], *others, *rport; 08494 08495 /* Only work on leftmost value */ 08496 ast_copy_string(leftmost, oh, sizeof(leftmost)); 08497 others = strchr(leftmost, ','); 08498 if (others) 08499 *others++ = '\0'; 08500 08501 /* Find ;rport; (empty request) */ 08502 rport = strstr(leftmost, ";rport"); 08503 if (rport && *(rport+6) == '=') 08504 rport = NULL; /* We already have a parameter to rport */ 08505 08506 /* Check rport if NAT=yes or NAT=rfc3581 (which is the default setting) */ 08507 if (rport && ((ast_test_flag(&p->flags[0], SIP_NAT) == SIP_NAT_ALWAYS) || (ast_test_flag(&p->flags[0], SIP_NAT) == SIP_NAT_RFC3581))) { 08508 /* We need to add received port - rport */ 08509 char *end; 08510 08511 rport = strstr(leftmost, ";rport"); 08512 08513 if (rport) { 08514 end = strchr(rport + 1, ';'); 08515 if (end) 08516 memmove(rport, end, strlen(end) + 1); 08517 else 08518 *rport = '\0'; 08519 } 08520 08521 /* Add rport to first VIA header if requested */ 08522 snprintf(new, sizeof(new), "%s;received=%s;rport=%d%s%s", 08523 leftmost, ast_inet_ntoa(p->recv.sin_addr), 08524 ntohs(p->recv.sin_port), 08525 others ? "," : "", others ? others : ""); 08526 } else { 08527 /* We should *always* add a received to the topmost via */ 08528 snprintf(new, sizeof(new), "%s;received=%s%s%s", 08529 leftmost, ast_inet_ntoa(p->recv.sin_addr), 08530 others ? "," : "", others ? others : ""); 08531 } 08532 oh = new; /* the header to copy */ 08533 } /* else add the following via headers untouched */ 08534 add_header(req, field, oh); 08535 copied++; 08536 } 08537 if (!copied) { 08538 ast_log(LOG_NOTICE, "No header field '%s' present to copy\n", field); 08539 return -1; 08540 } 08541 return 0; 08542 }
| 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 4873 of file chan_sip.c.
References ast_copy_string(), ast_get_srv(), ast_gethostbyname(), ast_log(), ast_string_field_set, ast_strlen_zero(), ast_test_flag, bindaddr, 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().
Referenced by manager_sipnotify(), sip_cli_notify(), sip_request_call(), and transmit_register().
04874 { 04875 struct hostent *hp; 04876 struct ast_hostent ahp; 04877 struct sip_peer *peer; 04878 char *port; 04879 int portno = 0; 04880 char host[MAXHOSTNAMELEN], *hostn; 04881 char peername[256]; 04882 int srv_ret = 0; 04883 04884 ast_copy_string(peername, opeer, sizeof(peername)); 04885 port = strchr(peername, ':'); 04886 if (port) { 04887 *port++ = '\0'; 04888 dialog->portinuri = 1; 04889 } 04890 dialog->sa.sin_family = AF_INET; 04891 dialog->timer_t1 = global_t1; /* Default SIP retransmission timer T1 (RFC 3261) */ 04892 dialog->timer_b = global_timer_b; /* Default SIP transaction timer B (RFC 3261) */ 04893 peer = find_peer(peername, NULL, TRUE, FINDPEERS, FALSE, 0); 04894 04895 if (peer) { 04896 int res; 04897 if (newdialog) { 04898 set_socket_transport(&dialog->socket, 0); 04899 } 04900 res = create_addr_from_peer(dialog, peer); 04901 if (!ast_strlen_zero(port)) { 04902 if ((portno = atoi(port))) { 04903 dialog->sa.sin_port = dialog->recv.sin_port = htons(portno); 04904 } 04905 } 04906 unref_peer(peer, "create_addr: unref peer from find_peer hashtab lookup"); 04907 return res; 04908 } 04909 04910 do_setnat(dialog, ast_test_flag(&dialog->flags[0], SIP_NAT) & SIP_NAT_ROUTE); 04911 04912 ast_string_field_set(dialog, tohost, peername); 04913 04914 /* Get the outbound proxy information */ 04915 ref_proxy(dialog, obproxy_get(dialog, NULL)); 04916 04917 if (sin) { 04918 /* This address should be updated using dnsmgr */ 04919 memcpy(&dialog->sa.sin_addr, &sin->sin_addr, sizeof(dialog->sa.sin_addr)); 04920 if (!sin->sin_port) { 04921 portno = port_str2int(port, (dialog->socket.type == SIP_TRANSPORT_TLS) ? STANDARD_TLS_PORT : STANDARD_SIP_PORT); 04922 } else { 04923 portno = ntohs(sin->sin_port); 04924 } 04925 } else { 04926 04927 /* Let's see if we can find the host in DNS. First try DNS SRV records, 04928 then hostname lookup */ 04929 /*! \todo Fix this function. When we ask SRC, we should check all transports 04930 In the future, we should first check NAPTR to find out transport preference 04931 */ 04932 hostn = peername; 04933 /* Section 4.2 of RFC 3263 specifies that if a port number is specified, then 04934 * an A record lookup should be used instead of SRV. 04935 */ 04936 if (!port && global_srvlookup) { 04937 char service[MAXHOSTNAMELEN]; 04938 int tportno; 04939 04940 snprintf(service, sizeof(service), "_sip._%s.%s", get_transport(dialog->socket.type), peername); 04941 srv_ret = ast_get_srv(NULL, host, sizeof(host), &tportno, service); 04942 if (srv_ret > 0) { 04943 hostn = host; 04944 portno = tportno; 04945 } 04946 } 04947 if (!portno) 04948 portno = port_str2int(port, (dialog->socket.type == SIP_TRANSPORT_TLS) ? STANDARD_TLS_PORT : STANDARD_SIP_PORT); 04949 hp = ast_gethostbyname(hostn, &ahp); 04950 if (!hp) { 04951 ast_log(LOG_WARNING, "No such host: %s\n", peername); 04952 return -1; 04953 } 04954 memcpy(&dialog->sa.sin_addr, hp->h_addr, sizeof(dialog->sa.sin_addr)); 04955 } 04956 04957 if (!dialog->socket.type) 04958 set_socket_transport(&dialog->socket, SIP_TRANSPORT_UDP); 04959 if (!dialog->socket.port) 04960 dialog->socket.port = bindaddr.sin_port; 04961 dialog->sa.sin_port = htons(portno); 04962 dialog->recv = dialog->sa; 04963 return 0; 04964 }
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 4726 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_constantssrc(), 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, bindaddr, 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, 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, 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_CONSTANT_SSRC, 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().
04727 { 04728 /* this checks that the dialog is contacting the peer on a valid 04729 * transport type based on the peers transport configuration, 04730 * otherwise, this function bails out */ 04731 if (dialog->socket.type && check_request_transport(peer, dialog)) 04732 return -1; 04733 copy_socket_data(&dialog->socket, &peer->socket); 04734 04735 if ((peer->addr.sin_addr.s_addr || peer->defaddr.sin_addr.s_addr) && 04736 (!peer->maxms || ((peer->lastms >= 0) && (peer->lastms <= peer->maxms)))) { 04737 dialog->sa = (peer->addr.sin_addr.s_addr) ? peer->addr : peer->defaddr; 04738 dialog->recv = dialog->sa; 04739 } else 04740 return -1; 04741 04742 ast_copy_flags(&dialog->flags[0], &peer->flags[0], SIP_FLAGS_TO_COPY); 04743 ast_copy_flags(&dialog->flags[1], &peer->flags[1], SIP_PAGE2_FLAGS_TO_COPY); 04744 dialog->capability = peer->capability; 04745 if (!ast_test_flag(&dialog->flags[1], SIP_PAGE2_VIDEOSUPPORT_ALWAYS) && 04746 (!ast_test_flag(&dialog->flags[1], SIP_PAGE2_VIDEOSUPPORT) || 04747 !(dialog->capability & AST_FORMAT_VIDEO_MASK)) && 04748 dialog->vrtp) { 04749 ast_rtp_destroy(dialog->vrtp); 04750 dialog->vrtp = NULL; 04751 } 04752 if (!ast_test_flag(&dialog->flags[1], SIP_PAGE2_TEXTSUPPORT) && dialog->trtp) { 04753 ast_rtp_destroy(dialog->trtp); 04754 dialog->trtp = NULL; 04755 } 04756 dialog->prefs = peer->prefs; 04757 if (ast_test_flag(&dialog->flags[1], SIP_PAGE2_T38SUPPORT)) { 04758 if (!dialog->udptl) { 04759 /* t38pt_udptl was enabled in the peer and not in [general] */ 04760 dialog->udptl = ast_udptl_new_with_bindaddr(sched, io, 0, bindaddr.sin_addr); 04761 } 04762 dialog->t38_maxdatagram = peer->t38_maxdatagram; 04763 set_t38_capabilities(dialog); 04764 } else if (dialog->udptl) { 04765 ast_udptl_destroy(dialog->udptl); 04766 dialog->udptl = NULL; 04767 } 04768 do_setnat(dialog, ast_test_flag(&dialog->flags[0], SIP_NAT) & SIP_NAT_ROUTE); 04769 04770 if (dialog->rtp) { /* Audio */ 04771 ast_rtp_setdtmf(dialog->rtp, ast_test_flag(&dialog->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833); 04772 ast_rtp_setdtmfcompensate(dialog->rtp, ast_test_flag(&dialog->flags[1], SIP_PAGE2_RFC2833_COMPENSATE)); 04773 ast_rtp_set_rtptimeout(dialog->rtp, peer->rtptimeout); 04774 ast_rtp_set_rtpholdtimeout(dialog->rtp, peer->rtpholdtimeout); 04775 ast_rtp_set_rtpkeepalive(dialog->rtp, peer->rtpkeepalive); 04776 if (ast_test_flag(&dialog->flags[1], SIP_PAGE2_CONSTANT_SSRC)) { 04777 ast_rtp_set_constantssrc(dialog->rtp); 04778 } 04779 /* Set Frame packetization */ 04780 ast_rtp_codec_setpref(dialog->rtp, &dialog->prefs); 04781 dialog->autoframing = peer->autoframing; 04782 } 04783 if (dialog->vrtp) { /* Video */ 04784 ast_rtp_setdtmf(dialog->vrtp, 0); 04785 ast_rtp_setdtmfcompensate(dialog->vrtp, 0); 04786 ast_rtp_set_rtptimeout(dialog->vrtp, peer->rtptimeout); 04787 ast_rtp_set_rtpholdtimeout(dialog->vrtp, peer->rtpholdtimeout); 04788 ast_rtp_set_rtpkeepalive(dialog->vrtp, peer->rtpkeepalive); 04789 if (ast_test_flag(&dialog->flags[1], SIP_PAGE2_CONSTANT_SSRC)) { 04790 ast_rtp_set_constantssrc(dialog->vrtp); 04791 } 04792 } 04793 if (dialog->trtp) { /* Realtime text */ 04794 ast_rtp_setdtmf(dialog->trtp, 0); 04795 ast_rtp_setdtmfcompensate(dialog->trtp, 0); 04796 ast_rtp_set_rtptimeout(dialog->trtp, peer->rtptimeout); 04797 ast_rtp_set_rtpholdtimeout(dialog->trtp, peer->rtpholdtimeout); 04798 ast_rtp_set_rtpkeepalive(dialog->trtp, peer->rtpkeepalive); 04799 } 04800 04801 ast_string_field_set(dialog, peername, peer->name); 04802 ast_string_field_set(dialog, authname, peer->username); 04803 ast_string_field_set(dialog, username, peer->username); 04804 ast_string_field_set(dialog, peersecret, peer->secret); 04805 ast_string_field_set(dialog, peermd5secret, peer->md5secret); 04806 ast_string_field_set(dialog, mohsuggest, peer->mohsuggest); 04807 ast_string_field_set(dialog, mohinterpret, peer->mohinterpret); 04808 ast_string_field_set(dialog, tohost, peer->tohost); 04809 ast_string_field_set(dialog, fullcontact, peer->fullcontact); 04810 ast_string_field_set(dialog, context, peer->context); 04811 ast_string_field_set(dialog, parkinglot, peer->parkinglot); 04812 ref_proxy(dialog, obproxy_get(dialog, peer)); 04813 dialog->callgroup = peer->callgroup; 04814 dialog->pickupgroup = peer->pickupgroup; 04815 dialog->allowtransfer = peer->allowtransfer; 04816 dialog->jointnoncodeccapability = dialog->noncodeccapability; 04817 dialog->rtptimeout = peer->rtptimeout; 04818 dialog->peerauth = peer->auth; 04819 dialog->maxcallbitrate = peer->maxcallbitrate; 04820 if (ast_strlen_zero(dialog->tohost)) 04821 ast_string_field_set(dialog, tohost, ast_inet_ntoa(dialog->sa.sin_addr)); 04822 if (!ast_strlen_zero(peer->fromdomain)) { 04823 ast_string_field_set(dialog, fromdomain, peer->fromdomain); 04824 if (!dialog->initreq.headers) { 04825 char *c; 04826 char *tmpcall = ast_strdupa(dialog->callid); 04827 /* this sure looks to me like we are going to change the callid on this dialog!! */ 04828 c = strchr(tmpcall, '@'); 04829 if (c) { 04830 *c = '\0'; 04831 ao2_t_unlink(dialogs, dialog, "About to change the callid -- remove the old name"); 04832 ast_string_field_build(dialog, callid, "%s@%s", tmpcall, peer->fromdomain); 04833 ao2_t_link(dialogs, dialog, "New dialog callid -- inserted back into table"); 04834 } 04835 } 04836 } 04837 if (!ast_strlen_zero(peer->fromuser)) 04838 ast_string_field_set(dialog, fromuser, peer->fromuser); 04839 if (!ast_strlen_zero(peer->language)) 04840 ast_string_field_set(dialog, language, peer->language); 04841 /* Set timer T1 to RTT for this peer (if known by qualify=) */ 04842 /* Minimum is settable or default to 100 ms */ 04843 /* If there is a maxms and lastms from a qualify use that over a manual T1 04844 value. Otherwise, use the peer's T1 value. */ 04845 if (peer->maxms && peer->lastms) 04846 dialog->timer_t1 = peer->lastms < global_t1min ? global_t1min : peer->lastms; 04847 else 04848 dialog->timer_t1 = peer->timer_t1; 04849 04850 /* Set timer B to control transaction timeouts, the peer setting is the default and overrides 04851 the known timer */ 04852 if (peer->timer_b) 04853 dialog->timer_b = peer->timer_b; 04854 else 04855 dialog->timer_b = 64 * dialog->timer_t1; 04856 04857 if ((ast_test_flag(&dialog->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833) || 04858 (ast_test_flag(&dialog->flags[0], SIP_DTMF) == SIP_DTMF_AUTO)) 04859 dialog->noncodeccapability |= AST_RTP_DTMF; 04860 else 04861 dialog->noncodeccapability &= ~AST_RTP_DTMF; 04862 if (peer->call_limit) 04863 ast_set_flag(&dialog->flags[0], SIP_CALL_LIMIT); 04864 if (!dialog->portinuri) 04865 dialog->portinuri = peer->portinuri; 04866 04867 return 0; 04868 }
| static void destroy_association | ( | struct sip_peer * | peer | ) | [static] |
Remove registration data from realtime database or AST/DB when registration expires.
Definition at line 11202 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().
11203 { 11204 int realtimeregs = ast_check_realtime("sipregs"); 11205 char *tablename = (realtimeregs) ? "sipregs" : "sippeers"; 11206 11207 if (!sip_cfg.ignore_regexpire) { 11208 if (peer->rt_fromcontact && sip_cfg.peer_rtupdate) { 11209 ast_update_realtime(tablename, "name", peer->name, "fullcontact", "", "ipaddr", "", "port", "", "regseconds", "0", peer->deprecated_username ? "username" : "defaultuser", "", "regserver", "", "useragent", "", "lastms", "", SENTINEL); 11210 } else { 11211 ast_db_del("SIP/Registry", peer->name); 11212 } 11213 } 11214 }
| static void destroy_mailbox | ( | struct sip_mailbox * | mailbox | ) | [static] |
Destroy mailbox subscriptions
Definition at line 4237 of file chan_sip.c.
References ast_event_unsubscribe(), ast_free, sip_mailbox::context, sip_mailbox::event_sub, and sip_mailbox::mailbox.
Referenced by clear_peer_mailboxes().
| static int determine_firstline_parts | ( | struct sip_request * | req | ) | [static] |
Parse first line of incoming SIP request.
Definition at line 9812 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.
Referenced by parse_request().
09813 { 09814 char *e = ast_skip_blanks(req->data->str); /* there shouldn't be any */ 09815 char *local_rlPart1; 09816 09817 if (!*e) 09818 return -1; 09819 req->rlPart1 = e - req->data->str; /* method or protocol */ 09820 local_rlPart1 = e; 09821 e = ast_skip_nonblanks(e); 09822 if (*e) 09823 *e++ = '\0'; 09824 /* Get URI or status code */ 09825 e = ast_skip_blanks(e); 09826 if ( !*e ) 09827 return -1; 09828 ast_trim_blanks(e); 09829 09830 if (!strcasecmp(local_rlPart1, "SIP/2.0") ) { /* We have a response */ 09831 if (strlen(e) < 3) /* status code is 3 digits */ 09832 return -1; 09833 req->rlPart2 = e - req->data->str; 09834 } else { /* We have a request */ 09835 if ( *e == '<' ) { /* XXX the spec says it must not be in <> ! */ 09836 ast_debug(3, "Oops. Bogus uri in <> %s\n", e); 09837 e++; 09838 if (!*e) 09839 return -1; 09840 } 09841 req->rlPart2 = e - req->data->str; /* URI */ 09842 e = ast_skip_nonblanks(e); 09843 if (*e) 09844 *e++ = '\0'; 09845 e = ast_skip_blanks(e); 09846 if (strcasecmp(e, "SIP/2.0") ) { 09847 ast_debug(3, "Skipping packet - Bad request protocol %s\n", e); 09848 return -1; 09849 } 09850 } 09851 return 1; 09852 }
| static int dialog_cmp_cb | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 1792 of file chan_sip.c.
References sip_pvt::callid, CMP_MATCH, and CMP_STOP.
Referenced by load_module().
| static int dialog_dump_func | ( | void * | userobj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 14042 of file chan_sip.c.
References ao2_t_ref, ast_cli(), and sip_pvt::callid.
Referenced by sip_show_objects().
| static int dialog_hash_cb | ( | const void * | obj, | |
| const int | flags | |||
| ) | [static] |
Definition at line 1782 of file chan_sip.c.
References ast_str_case_hash(), and sip_pvt::callid.
Referenced by load_module().
01783 { 01784 const struct sip_pvt *pvt = obj; 01785 01786 return ast_str_case_hash(pvt->callid); 01787 }
| static int dialog_needdestroy | ( | void * | dialogobj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 14157 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, cfsip_methods::text, TRUE, and sip_pvt::vrtp.
Referenced by do_monitor().
14158 { 14159 struct sip_pvt *dialog = dialogobj; 14160 time_t *t = arg; 14161 14162 /* log_show_lock(ao2_object_get_lockaddr(dialog)); this is an example of how to use log_show_lock() */ 14163 14164 if (sip_pvt_trylock(dialog)) { 14165 /* In very short-duration calls via sipp, 14166 this path gets executed fairly frequently (3% or so) even in low load 14167 situations; the routines we most commonly fight for a lock with: 14168 sip_answer (7 out of 9) 14169 sip_hangup (2 out of 9) 14170 */ 14171 ao2_unlock(dialogs); 14172 usleep(1); 14173 ao2_lock(dialogs); 14174 14175 /* I had previously returned CMP_STOP here; but changed it to return 14176 a zero instead, because there is no need to stop at the first sign 14177 of trouble. The old algorithm would restart in such circumstances, 14178 but there is no need for this now in astobj2-land. We'll 14179 just skip over this element this time, and catch it on the 14180 next traversal, which is about once a second or so. See the 14181 ao2_callback call in do_monitor. We don't want the number of 14182 dialogs to back up too much between runs. 14183 */ 14184 return 0; 14185 } 14186 14187 /* Check RTP timeouts and kill calls if we have a timeout set and do not get RTP */ 14188 check_rtp_timeout(dialog, *t); 14189 14190 /* If we have sessions that needs to be destroyed, do it now */ 14191 /* Check if we have outstanding requests not responsed to or an active call 14192 - if that's the case, wait with destruction */ 14193 if (dialog->needdestroy && !dialog->packets && !dialog->owner) { 14194 /* We absolutely cannot destroy the rtp struct while a bridge is active or we WILL crash */ 14195 if (dialog->rtp && ast_rtp_get_bridged(dialog->rtp)) { 14196 ast_debug(2, "Bridge still active. Delaying destruction of SIP dialog '%s' Method: %s\n", dialog->callid, sip_methods[dialog->method].text); 14197 sip_pvt_unlock(dialog); 14198 return 0; 14199 } 14200 14201 if (dialog->vrtp && ast_rtp_get_bridged(dialog->vrtp)) { 14202 ast_debug(2, "Bridge still active. Delaying destroy of SIP dialog '%s' Method: %s\n", dialog->callid, sip_methods[dialog->method].text); 14203 sip_pvt_unlock(dialog); 14204 return 0; 14205 } 14206 14207 sip_pvt_unlock(dialog); 14208 /* no, the unlink should handle this: dialog_unref(dialog, "needdestroy: one more refcount decrement to allow dialog to be destroyed"); */ 14209 /* the CMP_MATCH will unlink this dialog from the dialog hash table */ 14210 dialog_unlink_all(dialog, TRUE, FALSE); 14211 return 0; /* the unlink_all should unlink this from the table, so.... no need to return a match */ 14212 } 14213 14214 sip_pvt_unlock(dialog); 14215 14216 return 0; 14217 }
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 1449 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().
| 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 2792 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, 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, 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().
02793 { 02794 struct sip_pkt *cp; 02795 02796 dialog_ref(dialog, "Let's bump the count in the unlink so it doesn't accidentally become dead before we are done"); 02797 02798 ao2_t_unlink(dialogs, dialog, "unlinking dialog via ao2_unlink"); 02799 02800 /* Unlink us from the owner (channel) if we have one */ 02801 if (dialog->owner) { 02802 if (lockowner) 02803 ast_channel_lock(dialog->owner); 02804 ast_debug(1, "Detaching from channel %s\n", dialog->owner->name); 02805 dialog->owner->tech_pvt = dialog_unref(dialog->owner->tech_pvt, "resetting channel dialog ptr in unlink_all"); 02806 if (lockowner) 02807 ast_channel_unlock(dialog->owner); 02808 } 02809 if (dialog->registry) { 02810 if (dialog->registry->call == dialog) 02811 dialog->registry->call = dialog_unref(dialog->registry->call, "nulling out the registry's call dialog field in unlink_all"); 02812 dialog->registry = registry_unref(dialog->registry, "delete dialog->registry"); 02813 } 02814 if (dialog->stateid > -1) { 02815 ast_extension_state_del(dialog->stateid, NULL); 02816 dialog_unref(dialog, "removing extension_state, should unref the associated dialog ptr that was stored there."); 02817 dialog->stateid = -1; /* shouldn't we 'zero' this out? */ 02818 } 02819 /* Remove link from peer to subscription of MWI */ 02820 if (dialog->relatedpeer && dialog->relatedpeer->mwipvt == dialog) 02821 dialog->relatedpeer->mwipvt = dialog_unref(dialog->relatedpeer->mwipvt, "delete ->relatedpeer->mwipvt"); 02822 if (dialog->relatedpeer && dialog->relatedpeer->call == dialog) 02823 dialog->relatedpeer->call = dialog_unref(dialog->relatedpeer->call, "unset the relatedpeer->call field in tandem with relatedpeer field itself"); 02824 02825 /* remove all current packets in this dialog */ 02826 while((cp = dialog->packets)) { 02827 dialog->packets = dialog->packets->next; 02828 AST_SCHED_DEL(sched, cp->retransid); 02829 dialog_unref(cp->owner, "remove all current packets in this dialog, and the pointer to the dialog too as part of __sip_destroy"); 02830 if (cp->data) { 02831 ast_free(cp->data); 02832 } 02833 ast_free(cp); 02834 } 02835 02836 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")); 02837 02838 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")); 02839 02840 if (dialog->autokillid > -1) 02841 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")); 02842 02843 if (dialog->request_queue_sched_id > -1) { 02844 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")); 02845 } 02846 02847 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")); 02848 02849 if (dialog->t38id > -1) { 02850 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")); 02851 } 02852 02853 dialog_unref(dialog, "Let's unbump the count in the unlink so the poor pvt can disappear if it is time"); 02854 return NULL; 02855 }
Definition at line 1458 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(), scheduler_process_request_queue(), 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().
01459 { 01460 if (p) 01461 ao2_ref(p, -1); 01462 return NULL; 01463 }
| static void * do_monitor | ( | void * | data | ) | [static] |
The SIP monitoring thread.
Definition at line 21470 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, monlock, OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, sip_do_reload(), sip_reload_lock, and sipsock_read().
Referenced by restart_monitor().
21471 { 21472 int res; 21473 time_t t; 21474 int reloading; 21475 21476 /* Add an I/O event to our SIP UDP socket */ 21477 if (sipsock > -1) 21478 sipsock_read_id = ast_io_add(io, sipsock, sipsock_read, AST_IO_IN, NULL); 21479 21480 /* From here on out, we die whenever asked */ 21481 for(;;) { 21482 /* Check for a reload request */ 21483 ast_mutex_lock(&sip_reload_lock); 21484 reloading = sip_reloading; 21485 sip_reloading = FALSE; 21486 ast_mutex_unlock(&sip_reload_lock); 21487 if (reloading) { 21488 ast_verb(1, "Reloading SIP\n"); 21489 sip_do_reload(sip_reloadreason); 21490 21491 /* Change the I/O fd of our UDP socket */ 21492 if (sipsock > -1) { 21493 if (sipsock_read_id) 21494 sipsock_read_id = ast_io_change(io, sipsock_read_id, sipsock, NULL, 0, NULL); 21495 else 21496 sipsock_read_id = ast_io_add(io, sipsock, sipsock_read, AST_IO_IN, NULL); 21497 } else if (sipsock_read_id) { 21498 ast_io_remove(io, sipsock_read_id); 21499 sipsock_read_id = NULL; 21500 } 21501 } 21502 21503 /* Check for dialogs needing to be killed */ 21504 t = time(NULL); 21505 /* don't scan the dialogs list if it hasn't been a reasonable period 21506 of time since the last time we did it (when MWI is being sent, we can 21507 get back to this point every millisecond or less) 21508 */ 21509 ao2_t_callback(dialogs, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, dialog_needdestroy, &t, 21510 "callback to remove dialogs w/needdestroy"); 21511 21512 /* the old methodology would be to restart the search for dialogs to delete with every 21513 dialog that was found and destroyed, probably because the list contents would change, 21514 so we'd need to restart. This isn't the best thing to do with callbacks. */ 21515 21516 /* XXX TODO The scheduler usage in this module does not have sufficient 21517 * synchronization being done between running the scheduler and places 21518 * scheduling tasks. As it is written, any scheduled item may not run 21519 * any sooner than about 1 second, regardless of whether a sooner time 21520 * was asked for. */ 21521 21522 pthread_testcancel(); 21523 /* Wait for sched or io */ 21524 res = ast_sched_wait(sched); 21525 if ((res < 0) || (res > 1000)) 21526 res = 1000; 21527 res = ast_io_wait(io, res); 21528 if (res > 20) 21529 ast_debug(1, "chan_sip: ast_io_wait ran %d all at once\n", res); 21530 ast_mutex_lock(&monlock); 21531 res = ast_sched_runq(sched); 21532 if (res >= 20) 21533 ast_debug(1, "chan_sip: ast_sched_runq ran %d all at once\n", res); 21534 ast_mutex_unlock(&monlock); 21535 } 21536 21537 /* Never reached */ 21538 return NULL; 21539 }
| 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 16205 of file chan_sip.c.
References ast_calloc, ast_debug, sip_invite_param::auth, auth_headers(), sip_invite_param::authheader, sip_pvt::authtries, sip_request::header, 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().
16206 { 16207 char *header, *respheader; 16208 char digest[1024]; 16209 16210 if (!p->options && !(p->options = ast_calloc(1, sizeof(*p->options)))) 16211 return -2; 16212 16213 p->authtries++; 16214 auth_headers(code, &header, &respheader); 16215 ast_debug(2, "Auth attempt %d on %s\n", p->authtries, sip_methods[sipmethod].text); 16216 memset(digest, 0, sizeof(digest)); 16217 if (reply_digest(p, req, header, sipmethod, digest, sizeof(digest) )) { 16218 /* No way to authenticate */ 16219 return -1; 16220 } 16221 /* Now we have a reply digest */ 16222 p->options->auth = digest; 16223 p->options->authheader = respheader; 16224 return transmit_invite(p, sipmethod, sipmethod == SIP_INVITE, init); 16225 }
| 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 16181 of file chan_sip.c.
References append_history, ast_verbose, auth_headers(), sip_pvt::authtries, sip_pvt::do_history, sip_request::header, sip_registry::hostname, sip_pvt::registry, reply_digest(), sip_debug_test_pvt(), SIP_REGISTER, and transmit_register().
Referenced by handle_response_register().
16182 { 16183 char *header, *respheader; 16184 char digest[1024]; 16185 16186 p->authtries++; 16187 auth_headers(code, &header, &respheader); 16188 memset(digest, 0, sizeof(digest)); 16189 if (reply_digest(p, req, header, SIP_REGISTER, digest, sizeof(digest))) { 16190 /* There's nothing to use for authentication */ 16191 /* No digest challenge in request */ 16192 if (sip_debug_test_pvt(p) && p->registry) 16193 ast_verbose("No authentication challenge, sending blank registration to domain/host name %s\n", p->registry->hostname); 16194 /* No old challenge */ 16195 return -1; 16196 } 16197 if (p->do_history) 16198 append_history(p, "RegistryAuth", "Try: %d", p->authtries); 16199 if (sip_debug_test_pvt(p) && p->registry) 16200 ast_verbose("Responding to challenge, registration to domain/host name %s\n", p->registry->hostname); 16201 return transmit_register(p->registry, SIP_REGISTER, digest, respheader); 16202 }
| static void do_setnat | ( | struct sip_pvt * | p, | |
| int | natflags | |||
| ) | [static] |
Set nat mode on the various data sockets.
Definition at line 4620 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().
04621 { 04622 const char *mode = natflags ? "On" : "Off"; 04623 04624 if (p->rtp) { 04625 ast_debug(1, "Setting NAT on RTP to %s\n", mode); 04626 ast_rtp_setnat(p->rtp, natflags); 04627 } 04628 if (p->vrtp) { 04629 ast_debug(1, "Setting NAT on VRTP to %s\n", mode); 04630 ast_rtp_setnat(p->vrtp, natflags); 04631 } 04632 if (p->udptl) { 04633 ast_debug(1, "Setting NAT on UDPTL to %s\n", mode); 04634 ast_udptl_setnat(p->udptl, natflags); 04635 } 04636 if (p->trtp) { 04637 ast_debug(1, "Setting NAT on TRTP to %s\n", mode); 04638 ast_rtp_setnat(p->trtp, natflags); 04639 } 04640 }
| static const char * domain_mode_to_text | ( | const enum domain_mode | mode | ) | [static] |
Print domain mode to cli.
Definition at line 14375 of file chan_sip.c.
References SIP_DOMAIN_AUTO, and SIP_DOMAIN_CONFIG.
Referenced by sip_show_domains().
14376 { 14377 switch (mode) { 14378 case SIP_DOMAIN_AUTO: 14379 return "[Automatic]"; 14380 case SIP_DOMAIN_CONFIG: 14381 return "[Configured]"; 14382 } 14383 14384 return ""; 14385 }
| static const char * dtmfmode2str | ( | int | mode | ) | [static] |
Convert DTMF mode to printable string.
Definition at line 14098 of file chan_sip.c.
References 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 11230 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, 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(), realtime_peer(), reg_source_db(), sip_show_sched(), and sip_unregister().
11231 { 11232 struct sip_peer *peer = (struct sip_peer *)data; 11233 11234 if (!peer) /* Hmmm. We have no peer. Weird. */ 11235 return 0; 11236 11237 peer->expire = -1; 11238 peer->portinuri = 0; 11239 memset(&peer->addr, 0, sizeof(peer->addr)); 11240 11241 destroy_association(peer); /* remove registration data from storage */ 11242 set_socket_transport(&peer->socket, peer->default_outbound_transport); 11243 11244 if (peer->socket.tcptls_session) { 11245 ao2_ref(peer->socket.tcptls_session, -1); 11246 peer->socket.tcptls_session = NULL; 11247 } 11248 11249 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: SIP\r\nPeer: SIP/%s\r\nPeerStatus: Unregistered\r\nCause: Expired\r\n", peer->name); 11250 register_peer_exten(peer, FALSE); /* Remove regexten */ 11251 ast_devstate_changed(AST_DEVICE_UNKNOWN, "SIP/%s", peer->name); 11252 11253 /* Do we need to release this peer from memory? 11254 Only for realtime peers and autocreated peers 11255 */ 11256 if (peer->is_realtime) 11257 ast_debug(3, "-REALTIME- peer expired registration. Name: %s. Realtime peer objects now %d\n", peer->name, rpeerobjs); 11258 11259 if (peer->selfdestruct || 11260 ast_test_flag(&peer->flags[1], SIP_PAGE2_RTAUTOCLEAR)) { 11261 ao2_t_unlink(peers, peer, "ao2_unlink of peer from peers table"); 11262 if (peer->addr.sin_addr.s_addr) { 11263 ao2_t_unlink(peers_by_ip, peer, "ao2_unlink of peer from peers_by_ip table"); 11264 } 11265 } 11266 11267 unref_peer(peer, "removing peer ref for expire_register"); 11268 11269 return 0; 11270 }
| static void extract_uri | ( | struct sip_pvt * | p, | |
| struct sip_request * | req | |||
| ) | [static] |
Check Contact: URI of SIP message.
Definition at line 9913 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().
09914 { 09915 char stripped[SIPBUFSIZE]; 09916 char *c; 09917 09918 ast_copy_string(stripped, get_header(req, "Contact"), sizeof(stripped)); 09919 c = get_in_brackets(stripped); 09920 /* Cut the URI at the at sign after the @, not in the username part */ 09921 c = remove_uri_parameters(c); 09922 if (!ast_strlen_zero(c)) 09923 ast_string_field_set(p, uri, c); 09924 09925 }
| static const char* faxec2str | ( | int | faxec | ) | [static] |
Definition at line 14545 of file chan_sip.c.
References map_x_s().
Referenced by _sip_show_peer(), and sip_show_settings().
14546 { 14547 return map_x_s(faxecmodes, faxec, "Unknown"); 14548 }
| 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 6459 of file chan_sip.c.
References aliases, and ARRAY_LEN.
Referenced by __get_header(), and add_header().
06460 { 06461 /*! \brief Structure for conversion between compressed SIP and "normal" SIP */ 06462 static const struct cfalias { 06463 char * const fullname; 06464 char * const shortname; 06465 } aliases[] = { 06466 { "Content-Type", "c" }, 06467 { "Content-Encoding", "e" }, 06468 { "From", "f" }, 06469 { "Call-ID", "i" }, 06470 { "Contact", "m" }, 06471 { "Content-Length", "l" }, 06472 { "Subject", "s" }, 06473 { "To", "t" }, 06474 { "Supported", "k" }, 06475 { "Refer-To", "r" }, 06476 { "Referred-By", "b" }, 06477 { "Allow-Events", "u" }, 06478 { "Event", "o" }, 06479 { "Via", "v" }, 06480 { "Accept-Contact", "a" }, 06481 { "Reject-Contact", "j" }, 06482 { "Request-Disposition", "d" }, 06483 { "Session-Expires", "x" }, 06484 { "Identity", "y" }, 06485 { "Identity-Info", "n" }, 06486 }; 06487 int x; 06488 06489 for (x = 0; x < ARRAY_LEN(aliases); x++) { 06490 if (!strcasecmp(aliases[x].fullname, name)) 06491 return aliases[x].shortname; 06492 } 06493 06494 return _default; 06495 }
| static int find_by_name | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 4546 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().
04547 { 04548 struct sip_peer *search = obj; 04549 struct peer_finding_info *pfi = arg; 04550 04551 /* Usernames in SIP uri's are case sensitive. Domains are not */ 04552 if (strcmp(search->name, pfi->tmp_peer.name)) { 04553 return 0; 04554 } 04555 04556 switch (pfi->which_objects) { 04557 case FINDUSERS: 04558 if (!(search->type & SIP_TYPE_USER)) { 04559 return 0; 04560 } 04561 break; 04562 case FINDPEERS: 04563 if (!(search->type & SIP_TYPE_PEER)) { 04564 return 0; 04565 } 04566 break; 04567 case FINDALLDEVICES: 04568 break; 04569 } 04570 04571 return CMP_MATCH | CMP_STOP; 04572 }
| static struct sip_pvt * find_call | ( | struct sip_request * | req, | |
| struct sockaddr_in * | sin, | |||
| const int | intended_method | |||
| ) | [static, read] |
find or create a dialog structure for an incoming SIP message. Connect incoming SIP message to current dialog or create new dialog structure Returns a reference to the sip_pvt object, remember to give it back once done. Called by handle_incoming(), sipsock_read
Definition at line 6936 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, CAN_CREATE_DIALOG_UNSUPPORTED_METHOD, dialogs, find_call_cb(), find_call_cb_arg::fromtag, get_header(), gettag(), sip_request::has_to_tag, 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().
06937 { 06938 struct sip_pvt *p = NULL; 06939 char *tag = ""; /* note, tag is never NULL */ 06940 char totag[128]; 06941 char fromtag[128]; 06942 struct find_call_cb_arg arg; 06943 const char *callid = get_header(req, "Call-ID"); 06944 const char *from = get_header(req, "From"); 06945 const char *to = get_header(req, "To"); 06946 const char *cseq = get_header(req, "Cseq"); 06947 struct sip_pvt *sip_pvt_ptr; 06948 06949 /* Call-ID, to, from and Cseq are required by RFC 3261. (Max-forwards and via too - ignored now) */ 06950 /* get_header always returns non-NULL so we must use ast_strlen_zero() */ 06951 if (ast_strlen_zero(callid) || ast_strlen_zero(to) || 06952 ast_strlen_zero(from) || ast_strlen_zero(cseq)) 06953 return NULL; /* Invalid packet */ 06954 06955 arg.method = req->method; 06956 arg.callid = callid; 06957 arg.fromtag = fromtag; 06958 arg.totag = totag; 06959 arg.tag = ""; /* make sure tag is never NULL */ 06960 06961 if (pedanticsipchecking) { 06962 /* In principle Call-ID's uniquely identify a call, but with a forking SIP proxy 06963 we need more to identify a branch - so we have to check branch, from 06964 and to tags to identify a call leg. 06965 For Asterisk to behave correctly, you need to turn on pedanticsipchecking 06966 in sip.conf 06967 */ 06968 if (gettag(req, "To", totag, sizeof(totag))) 06969 req->has_to_tag = 1; /* Used in handle_request/response */ 06970 gettag(req, "From", fromtag, sizeof(fromtag)); 06971 06972 tag = (req->method == SIP_RESPONSE) ? totag : fromtag; 06973 06974 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); 06975 06976 /* All messages must always have From: tag */ 06977 if (ast_strlen_zero(fromtag)) { 06978 ast_debug(5, "%s request has no from tag, dropping callid: %s from: %s\n", sip_methods[req->method].text , callid, from ); 06979 return NULL; 06980 } 06981 /* reject requests that must always have a To: tag */ 06982 if (ast_strlen_zero(totag) && (req->method == SIP_ACK || req->method == SIP_BYE || req->method == SIP_INFO )) { 06983 ast_debug(5, "%s must have a to tag. dropping callid: %s from: %s\n", sip_methods[req->method].text , callid, from ); 06984 return NULL; 06985 } 06986 } 06987 06988 restartsearch: 06989 if (!pedanticsipchecking) { 06990 struct sip_pvt tmp_dialog = { 06991 .callid = callid, 06992 }; 06993 sip_pvt_ptr = ao2_t_find(dialogs, &tmp_dialog, OBJ_POINTER, "ao2_find in dialogs"); 06994 if (sip_pvt_ptr) { /* well, if we don't find it-- what IS in there? */ 06995 /* Found the call */ 06996 sip_pvt_lock(sip_pvt_ptr); 06997 return sip_pvt_ptr; 06998 } 06999 } else { /* in pedantic mode! -- do the fancy linear search */ 07000 ao2_lock(dialogs); 07001 p = ao2_t_callback(dialogs, 0 /* single, data */, find_call_cb, &arg, "pedantic linear search for dialog"); 07002 if (p) { 07003 if (sip_pvt_trylock(p)) { 07004 ao2_unlock(dialogs); 07005 usleep(1); 07006 goto restartsearch; 07007 } 07008 ao2_unlock(dialogs); 07009 return p; 07010 } 07011 ao2_unlock(dialogs); 07012 } 07013 07014 /* See if the method is capable of creating a dialog */ 07015 if (sip_methods[intended_method].can_create == CAN_CREATE_DIALOG) { 07016 if (intended_method == SIP_REFER) { 07017 /* We do support REFER, but not outside of a dialog yet */ 07018 transmit_response_using_temp(callid, sin, 1, intended_method, req, "603 Declined (no dialog)"); 07019 } else if (intended_method == SIP_NOTIFY) { 07020 /* We do not support out-of-dialog NOTIFY either, 07021 like voicemail notification, so cancel that early */ 07022 transmit_response_using_temp(callid, sin, 1, intended_method, req, "489 Bad event"); 07023 } else { 07024 /* Ok, time to create a new SIP dialog object, a pvt */ 07025 if ((p = sip_alloc(callid, sin, 1, intended_method, req))) { 07026 /* Ok, we've created a dialog, let's go and process it */ 07027 sip_pvt_lock(p); 07028 } else { 07029 /* We have a memory or file/socket error (can't allocate RTP sockets or something) so we're not 07030 getting a dialog from sip_alloc. 07031 07032 Without a dialog we can't retransmit and handle ACKs and all that, but at least 07033 send an error message. 07034 07035 Sorry, we apologize for the inconvienience 07036 */ 07037 transmit_response_using_temp(callid, sin, 1, intended_method, req, "500 Server internal error"); 07038 ast_debug(4, "Failed allocating SIP dialog, sending 500 Server internal error and giving up\n"); 07039 } 07040 } 07041 return p; /* can be NULL */ 07042 } else if( sip_methods[intended_method].can_create == CAN_CREATE_DIALOG_UNSUPPORTED_METHOD) { 07043 /* A method we do not support, let's take it on the volley */ 07044 transmit_response_using_temp(callid, sin, 1, intended_method, req, "501 Method Not Implemented"); 07045 ast_debug(2, "Got a request with unsupported SIP method.\n"); 07046 } else if (intended_method != SIP_RESPONSE && intended_method != SIP_ACK) { 07047 /* This is a request outside of a dialog that we don't know about */ 07048 transmit_response_using_temp(callid, sin, 1, intended_method, req, "481 Call leg/transaction does not exist"); 07049 ast_debug(2, "That's odd... Got a request in unknown dialog. Callid %s\n", callid ? callid : "<unknown>"); 07050 } 07051 /* We do not respond to responses for dialogs that we don't know about, we just drop 07052 the session quickly */ 07053 if (intended_method == SIP_RESPONSE) 07054 ast_debug(2, "That's odd... Got a response on a call we dont know about. Callid %s\n", callid ? callid : "<unknown>"); 07055 07056 return NULL; 07057 }
| 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 6895 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, cfsip_methods::text, sip_pvt::theirtag, and find_call_cb_arg::totag.
Referenced by find_call().
06896 { 06897 struct sip_pvt *p = __pvt; 06898 struct find_call_cb_arg *arg = __arg; 06899 /* In pedantic, we do not want packets with bad syntax to be connected to a PVT */ 06900 int found = FALSE; 06901 06902 if (!ast_strlen_zero(p->callid)) { /* XXX double check, do we allow match on empty p->callid ? */ 06903 if (arg->method == SIP_REGISTER) 06904 found = (!strcmp(p->callid, arg->callid)); 06905 else { 06906 found = !strcmp(p->callid, arg->callid); 06907 if (pedanticsipchecking && found) { 06908 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); 06909 } 06910 } 06911 06912 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); 06913 06914 /* If we get a new request within an existing to-tag - check the to tag as well */ 06915 if (pedanticsipchecking && found && arg->method != SIP_RESPONSE) { /* SIP Request */ 06916 if (p->tag[0] == '\0' && arg->totag[0]) { 06917 /* We have no to tag, but they have. Wrong dialog */ 06918 found = FALSE; 06919 } else if (arg->totag[0]) { /* Both have tags, compare them */ 06920 if (strcmp(arg->totag, p->tag)) { 06921 found = FALSE; /* This is not our packet */ 06922 } 06923 } 06924 if (!found) 06925 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); 06926 } 06927 } 06928 return found; 06929 }
| 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 3932 of file chan_sip.c.
References s.
Referenced by get_in_brackets().
03933 { 03934 char last_char = '\0'; 03935 const char *s; 03936 for (s = start; *s && s != lim; last_char = *s++) { 03937 if (*s == '"' && last_char != '\\') 03938 break; 03939 } 03940 return s; 03941 }
| static struct sip_peer * find_peer | ( | const char * | peer, | |
| struct sockaddr_in * | sin, | |||
| int | realtime, | |||
| int | which_objects, | |||
| int | devstate_only, | |||
| int | transport | |||
| ) | [static, read] |
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. |
This is used on find matching device on name or ip/port. If the device was declared as type=peer, we don't match on peer name on incoming INVITEs.
Definition at line 4587 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, realtime_peer(), SIP_INSECURE_PORT, peer_finding_info::tmp_peer, sip_peer::transports, and peer_finding_info::which_objects.
Referenced by _sip_qualify_peer(), _sip_show_peer(), check_peer_ok(), create_addr(), function_sippeer(), register_verify(), sip_devicestate(), sip_do_debug_peer(), sip_peer_hold(), sip_show_user(), sip_unregister(), st_get_mode(), st_get_refresher(), st_get_se(), transmit_register(), and update_call_counter().
04588 { 04589 struct sip_peer *p = NULL; 04590 04591 if (peer) { 04592 struct peer_finding_info pfi = { 04593 .which_objects = which_objects, 04594 }; 04595 ast_copy_string(pfi.tmp_peer.name, peer, sizeof(pfi.tmp_peer.name)); 04596 p = ao2_t_callback(peers, OBJ_POINTER, find_by_name, &pfi, "ao2_callback in peers table"); 04597 } else if (sin) { /* search by addr? */ 04598 struct sip_peer tmp_peer; 04599 tmp_peer.addr.sin_addr.s_addr = sin->sin_addr.s_addr; 04600 tmp_peer.addr.sin_port = sin->sin_port; 04601 tmp_peer.flags[0].flags = 0; 04602 tmp_peer.transports = transport; 04603 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); */ 04604 if (!p) { 04605 ast_set_flag(&tmp_peer.flags[0], SIP_INSECURE_PORT); 04606 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); */ 04607 if (p) { 04608 return p; 04609 } 04610 } 04611 } 04612 04613 if (!p && (realtime || devstate_only)) 04614 p = realtime_peer(peer, sin, devstate_only); 04615 04616 return p; 04617 }
| static struct sip_auth * find_realm_authentication | ( | struct sip_auth * | authlist, | |
| const char * | realm | |||
| ) | [static, read] |
Find authentication for a specific realm.
Definition at line 22608 of file chan_sip.c.
References sip_auth::next, and sip_auth::realm.
Referenced by build_reply_digest().
| 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 |
Also updates req->sdp_start and req->sdp_count to indicate where the SDP lives in the message body.
Definition at line 7300 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().
07301 { 07302 const char *content_type; 07303 const char *content_length; 07304 const char *search; 07305 char *boundary; 07306 unsigned int x; 07307 int boundaryisquoted = FALSE; 07308 int found_application_sdp = FALSE; 07309 int found_end_of_headers = FALSE; 07310 07311 content_length = get_header(req, "Content-Length"); 07312 07313 if (!ast_strlen_zero(content_length)) { 07314 if (sscanf(content_length, "%30u", &x) != 1) { 07315 ast_log(LOG_WARNING, "Invalid Content-Length: %s\n", content_length); 07316 return 0; 07317 } 07318 07319 /* Content-Length of zero means there can't possibly be an 07320 SDP here, even if the Content-Type says there is */ 07321 if (x == 0) 07322 return 0; 07323 } 07324 07325 content_type = get_header(req, "Content-Type"); 07326 07327 /* if the body contains only SDP, this is easy */ 07328 if (!strncasecmp(content_type, "application/sdp", 15)) { 07329 req->sdp_start = 0; 07330 req->sdp_count = req->lines; 07331 return req->lines ? 1 : 0; 07332 } 07333 07334 /* if it's not multipart/mixed, there cannot be an SDP */ 07335 if (strncasecmp(content_type, "multipart/mixed", 15)) 07336 return 0; 07337 07338 /* if there is no boundary marker, it's invalid */ 07339 if ((search = strcasestr(content_type, ";boundary="))) 07340 search += 10; 07341 else if ((search = strcasestr(content_type, "; boundary="))) 07342 search += 11; 07343 else 07344 return 0; 07345 07346 if (ast_strlen_zero(search)) 07347 return 0; 07348 07349 /* If the boundary is quoted with ", remove quote */ 07350 if (*search == '\"') { 07351 search++; 07352 boundaryisquoted = TRUE; 07353 } 07354 07355 /* make a duplicate of the string, with two extra characters 07356 at the beginning */ 07357 boundary = ast_strdupa(search - 2); 07358 boundary[0] = boundary[1] = '-'; 07359 /* Remove final quote */ 07360 if (boundaryisquoted) 07361 boundary[strlen(boundary) - 1] = '\0'; 07362 07363 /* search for the boundary marker, the empty line delimiting headers from 07364 sdp part and the end boundry if it exists */ 07365 07366 for (x = 0; x < (req->lines); x++) { 07367 char *line = REQ_OFFSET_TO_STR(req, line[x]); 07368 if (!strncasecmp(line, boundary, strlen(boundary))){ 07369 if (found_application_sdp && found_end_of_headers) { 07370 req->sdp_count = (x - 1) - req->sdp_start; 07371 return 1; 07372 } 07373 found_application_sdp = FALSE; 07374 } 07375 if (!strcasecmp(line, "Content-Type: application/sdp")) 07376 found_application_sdp = TRUE; 07377 07378 if (ast_strlen_zero(line)) { 07379 if (found_application_sdp && !found_end_of_headers){ 07380 req->sdp_start = x; 07381 found_end_of_headers = TRUE; 07382 } 07383 } 07384 } 07385 if (found_application_sdp && found_end_of_headers) { 07386 req->sdp_count = x - req->sdp_start; 07387 return TRUE; 07388 } 07389 return FALSE; 07390 }
| static int find_sip_method | ( | const char * | msg | ) | [static] |
find_sip_method: Find SIP method from header
Definition at line 2997 of file chan_sip.c.
References ARRAY_LEN, ast_strlen_zero(), method_match(), and sip_methods.
Referenced by __sip_pretend_ack(), handle_request_do(), handle_response(), and sip_hangup().
02998 { 02999 int i, res = 0; 03000 03001 if (ast_strlen_zero(msg)) 03002 return 0; 03003 for (i = 1; i < ARRAY_LEN(sip_methods) && !res; i++) { 03004 if (method_match(i, msg)) 03005 res = sip_methods[i].id; 03006 } 03007 return res; 03008 }
| static struct cfsubscription_types * find_subscription_type | ( | enum subscriptiontype | subtype | ) | [static, read] |
Find subscription type in array.
Definition at line 15326 of file chan_sip.c.
References ARRAY_LEN, and subscription_types.
Referenced by transmit_state_notify().
15327 { 15328 int i; 15329 15330 for (i = 1; i < ARRAY_LEN(subscription_types); i++) { 15331 if (subscription_types[i].type == subtype) { 15332 return &subscription_types[i]; 15333 } 15334 } 15335 return &subscription_types[0]; 15336 }
| static void free_old_route | ( | struct sip_route * | route | ) | [static] |
Remove route from route list.
Definition at line 11629 of file chan_sip.c.
References ast_free, and sip_route::next.
Referenced by __sip_destroy(), and build_route().
| 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 16447 of file chan_sip.c.
References ast_copy_string(), ast_log(), ast_strlen_zero(), check_sip_domain(), and LOG_WARNING.
16448 { 16449 if (ast_strlen_zero(data)) { 16450 ast_log(LOG_WARNING, "CHECKSIPDOMAIN requires an argument - A domain name\n"); 16451 return -1; 16452 } 16453 if (check_sip_domain(data, NULL, 0)) 16454 ast_copy_string(buf, data, len); 16455 else 16456 buf[0] = '\0'; 16457 return 0; 16458 }
| 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 16383 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(), sip_request::header, sip_pvt::initreq, IS_SIP_TECH, LOG_WARNING, ast_channel::tech, and ast_channel::tech_pvt.
16384 { 16385 struct sip_pvt *p; 16386 const char *content = NULL; 16387 AST_DECLARE_APP_ARGS(args, 16388 AST_APP_ARG(header); 16389 AST_APP_ARG(number); 16390 ); 16391 int i, number, start = 0; 16392 16393 if (ast_strlen_zero(data)) { 16394 ast_log(LOG_WARNING, "This function requires a header name.\n"); 16395 return -1; 16396 } 16397 16398 ast_channel_lock(chan); 16399 if (!IS_SIP_TECH(chan->tech)) { 16400 ast_log(LOG_WARNING, "This function can only be used on SIP channels.\n"); 16401 ast_channel_unlock(chan); 16402 return -1; 16403 } 16404 16405 AST_STANDARD_APP_ARGS(args, data); 16406 if (!args.number) { 16407 number = 1; 16408 } else { 16409 sscanf(args.number, "%30d", &number); 16410 if (number < 1) 16411 number = 1; 16412 } 16413 16414 p = chan->tech_pvt; 16415 16416 /* If there is no private structure, this channel is no longer alive */ 16417 if (!p) { 16418 ast_channel_unlock(chan); 16419 return -1; 16420 } 16421 16422 for (i = 0; i < number; i++) 16423 content = __get_header(&p->initreq, args.header, &start); 16424 16425 if (ast_strlen_zero(content)) { 16426 ast_channel_unlock(chan); 16427 return -1; 16428 } 16429 16430 ast_copy_string(buf, content, len); 16431 ast_channel_unlock(chan); 16432 16433 return 0; 16434 }
| 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 16591 of file chan_sip.c.
References ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_inet_ntoa(), ast_log(), 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.
16592 { 16593 struct sip_pvt *p; 16594 static int deprecated = 0; 16595 16596 *buf = 0; 16597 16598 if (!data) { 16599 ast_log(LOG_WARNING, "This function requires a parameter name.\n"); 16600 return -1; 16601 } 16602 16603 ast_channel_lock(chan); 16604 if (!IS_SIP_TECH(chan->tech)) { 16605 ast_log(LOG_WARNING, "This function can only be used on SIP channels.\n"); 16606 ast_channel_unlock(chan); 16607 return -1; 16608 } 16609 16610 if (deprecated++ % 20 == 0) { 16611 /* Deprecated in 1.6.1 */ 16612 ast_log(LOG_WARNING, "SIPCHANINFO() is deprecated. Please transition to using CHANNEL().\n"); 16613 } 16614 16615 p = chan->tech_pvt; 16616 16617 /* If there is no private structure, this channel is no longer alive */ 16618 if (!p) { 16619 ast_channel_unlock(chan); 16620 return -1; 16621 } 16622 16623 if (!strcasecmp(data, "peerip")) { 16624 ast_copy_string(buf, p->sa.sin_addr.s_addr ? ast_inet_ntoa(p->sa.sin_addr) : "", len); 16625 } else if (!strcasecmp(data, "recvip")) { 16626 ast_copy_string(buf, p->recv.sin_addr.s_addr ? ast_inet_ntoa(p->recv.sin_addr) : "", len); 16627 } else if (!strcasecmp(data, "from")) { 16628 ast_copy_string(buf, p->from, len); 16629 } else if (!strcasecmp(data, "uri")) { 16630 ast_copy_string(buf, p->uri, len); 16631 } else if (!strcasecmp(data, "useragent")) { 16632 ast_copy_string(buf, p->useragent, len); 16633 } else if (!strcasecmp(data, "peername")) { 16634 ast_copy_string(buf, p->peername, len); 16635 } else if (!strcasecmp(data, "t38passthrough")) { 16636 if (p->t38.state == T38_DISABLED) { 16637 ast_copy_string(buf, "0", len); 16638 } else { /* T38 is offered or enabled in this call */ 16639 ast_copy_string(buf, "1", len); 16640 } 16641 } else { 16642 ast_channel_unlock(chan); 16643 return -1; 16644 } 16645 ast_channel_unlock(chan); 16646 16647 return 0; 16648 }
| 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 16472 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.
16473 { 16474 struct sip_peer *peer; 16475 char *colname; 16476 16477 if ((colname = strchr(data, ':'))) { /*! \todo Will be deprecated after 1.4 */ 16478 static int deprecation_warning = 0; 16479 *colname++ = '\0'; 16480 if (deprecation_warning++ % 10 == 0) 16481 ast_log(LOG_WARNING, "SIPPEER(): usage of ':' to separate arguments is deprecated. Please use ',' instead.\n"); 16482 } else if ((colname = strchr(data, ','))) 16483 *colname++ = '\0'; 16484 else 16485 colname = "ip"; 16486 16487 if (!(peer = find_peer(data, NULL, TRUE, FINDPEERS, FALSE, 0))) 16488 return -1; 16489 16490 if (!strcasecmp(colname, "ip")) { 16491 ast_copy_string(buf, peer->addr.sin_addr.s_addr ? ast_inet_ntoa(peer->addr.sin_addr) : "", len); 16492 } else if (!strcasecmp(colname, "port")) { 16493 snprintf(buf, len, "%d", ntohs(peer->addr.sin_port)); 16494 } else if (!strcasecmp(colname, "status")) { 16495 peer_status(peer, buf, len); 16496 } else if (!strcasecmp(colname, "language")) { 16497 ast_copy_string(buf, peer->language, len); 16498 } else if (!strcasecmp(colname, "regexten")) { 16499 ast_copy_string(buf, peer->regexten, len); 16500 } else if (!strcasecmp(colname, "limit")) { 16501 snprintf(buf, len, "%d", peer->call_limit); 16502 } else if (!strcasecmp(colname, "busylevel")) { 16503 snprintf(buf, len, "%d", peer->busy_level); 16504 } else if (!strcasecmp(colname, "curcalls")) { 16505 snprintf(buf, len, "%d", peer->inUse); 16506 } else if (!strcasecmp(colname, "accountcode")) { 16507 ast_copy_string(buf, peer->accountcode, len); 16508 } else if (!strcasecmp(colname, "callgroup")) { 16509 ast_print_group(buf, len, peer->callgroup); 16510 } else if (!strcasecmp(colname, "pickupgroup")) { 16511 ast_print_group(buf, len, peer->pickupgroup); 16512 } else if (!strcasecmp(colname, "useragent")) { 16513 ast_copy_string(buf, peer->useragent, len); 16514 } else if (!strcasecmp(colname, "mailbox")) { 16515 struct ast_str *mailbox_str = ast_str_alloca(512); 16516 peer_mailboxes_to_str(&mailbox_str, peer); 16517 ast_copy_string(buf, mailbox_str->str, len); 16518 } else if (!strcasecmp(colname, "context")) { 16519 ast_copy_string(buf, peer->context, len); 16520 } else if (!strcasecmp(colname, "expire")) { 16521 snprintf(buf, len, "%d", peer->expire); 16522 } else if (!strcasecmp(colname, "dynamic")) { 16523 ast_copy_string(buf, peer->host_dynamic ? "yes" : "no", len); 16524 } else if (!strcasecmp(colname, "callerid_name")) { 16525 ast_copy_string(buf, peer->cid_name, len); 16526 } else if (!strcasecmp(colname, "callerid_num")) { 16527 ast_copy_string(buf, peer->cid_num, len); 16528 } else if (!strcasecmp(colname, "codecs")) { 16529 ast_getformatname_multiple(buf, len -1, peer->capability); 16530 } else if (!strncasecmp(colname, "chanvar[", 8)) { 16531 char *chanvar=colname + 8; 16532 struct ast_variable *v; 16533 16534 chanvar = strsep(&chanvar, "]"); 16535 for (v = peer->chanvars ; v ; v = v->next) 16536 if (!strcasecmp(v->name, chanvar)) 16537 ast_copy_string(buf, v->value, len); 16538 } else if (!strncasecmp(colname, "codec[", 6)) { 16539 char *codecnum; 16540 int codec = 0; 16541 16542 codecnum = colname + 6; /* move past the '[' */ 16543 codecnum = strsep(&codecnum, "]"); /* trim trailing ']' if any */ 16544 if((codec = ast_codec_pref_index(&peer->prefs, atoi(codecnum)))) { 16545 ast_copy_string(buf, ast_getformatname(codec), len); 16546 } else { 16547 buf[0] = '\0'; 16548 } 16549 } else { 16550 buf[0] = '\0'; 16551 } 16552 16553 unref_peer(peer, "unref_peer from function_sippeer, just before return"); 16554 16555 return 0; 16556 }
| static char * generate_random_string | ( | char * | buf, | |
| size_t | size | |||
| ) | [static] |
Generate 32 byte random string for callid's etc.
Definition at line 6676 of file chan_sip.c.
References ast_random().
Referenced by build_callid_pvt(), and build_callid_registry().
06677 { 06678 long val[4]; 06679 int x; 06680 06681 for (x=0; x<4; x++) 06682 val[x] = ast_random(); 06683 snprintf(buf, size, "%08lx%08lx%08lx%08lx", val[0], val[1], val[2], val[3]); 06684 06685 return buf; 06686 }
| 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 12844 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().
12845 { 12846 char tmp[256] = "", *c, *a; 12847 struct sip_request *req = oreq ? oreq : &p->initreq; 12848 struct sip_refer *referdata = NULL; 12849 const char *transfer_context = NULL; 12850 12851 if (!p->refer && !sip_refer_allocate(p)) 12852 return -1; 12853 12854 referdata = p->refer; 12855 12856 ast_copy_string(tmp, get_header(req, "Also"), sizeof(tmp)); 12857 c = get_in_brackets(tmp); 12858 12859 if (pedanticsipchecking) 12860 ast_uri_decode(c); 12861 12862 if (!strncasecmp(c, "sip:", 4)) { 12863 c += 4; 12864 } else if (!strncasecmp(c, "sips:", 5)) { 12865 c += 5; 12866 } else { 12867 ast_log(LOG_WARNING, "Huh? Not a SIP header in Also: transfer (%s)?\n", c); 12868 return -1; 12869 } 12870 12871 if ((a = strchr(c, ';'))) /* Remove arguments */ 12872 *a = '\0'; 12873 12874 if ((a = strchr(c, '@'))) { /* Separate Domain */ 12875 *a++ = '\0'; 12876 ast_copy_string(referdata->refer_to_domain, a, sizeof(referdata->refer_to_domain)); 12877 } 12878 12879 if (sip_debug_test_pvt(p)) 12880 ast_verbose("Looking for %s in %s\n", c, p->context); 12881 12882 if (p->owner) /* Mimic behaviour in res_features.c */ 12883 transfer_context = pbx_builtin_getvar_helper(p->owner, "TRANSFER_CONTEXT"); 12884 12885 /* By default, use the context in the channel sending the REFER */ 12886 if (ast_strlen_zero(transfer_context)) { 12887 transfer_context = S_OR(p->owner->macrocontext, 12888 S_OR(p->context, default_context)); 12889 } 12890 if (ast_exists_extension(NULL, transfer_context, c, 1, NULL)) { 12891 /* This is a blind transfer */ 12892 ast_debug(1, "SIP Bye-also transfer to Extension %s@%s \n", c, transfer_context); 12893 ast_copy_string(referdata->refer_to, c, sizeof(referdata->refer_to)); 12894 ast_copy_string(referdata->referred_by, "", sizeof(referdata->referred_by)); 12895 ast_copy_string(referdata->refer_contact, "", sizeof(referdata->refer_contact)); 12896 referdata->refer_call = dialog_unref(referdata->refer_call, "unreffing referdata->refer_call"); 12897 /* Set new context */ 12898 ast_string_field_set(p, context, transfer_context); 12899 return 0; 12900 } else if (ast_canmatch_extension(NULL, p->context, c, 1, NULL)) { 12901 return 1; 12902 } 12903 12904 return -1; 12905 }
| static char* get_body | ( | struct sip_request * | req, | |
| char * | name | |||
| ) | [static] |
Get a specific line from the message body.
Definition at line 6443 of file chan_sip.c.
References get_body_by_line(), sip_request::lines, and REQ_OFFSET_TO_STR.
Referenced by handle_request_info().
06444 { 06445 int x; 06446 int len = strlen(name); 06447 char *r; 06448 06449 for (x = 0; x < req->lines; x++) { 06450 r = get_body_by_line(REQ_OFFSET_TO_STR(req, line[x]), name, len); 06451 if (r[0] != '\0') 06452 return r; 06453 } 06454 06455 return ""; 06456 }
| 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 6388 of file chan_sip.c.
References ast_skip_blanks().
Referenced by get_body(), and get_sdp_iterate().
06389 { 06390 if (!strncasecmp(line, name, nameLen) && line[nameLen] == '=') 06391 return ast_skip_blanks(line + nameLen + 1); 06392 06393 return ""; 06394 }
| 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 21313 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::context, sip_mailbox::mailbox, mailbox, sip_peer::mailboxes, and S_OR.
Referenced by sip_send_mwi_to_peer().
21314 { 21315 struct sip_mailbox *mailbox; 21316 21317 AST_LIST_TRAVERSE(&peer->mailboxes, mailbox, entry) { 21318 struct ast_event *event; 21319 event = ast_event_get_cached(AST_EVENT_MWI, 21320 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox->mailbox, 21321 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, S_OR(mailbox->context, "default"), 21322 AST_EVENT_IE_END); 21323 if (!event) 21324 continue; 21325 *new += ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS); 21326 *old += ast_event_get_ie_uint(event, AST_EVENT_IE_OLDMSGS); 21327 ast_event_destroy(event); 21328 } 21329 21330 return (*new || *old) ? 0 : 1; 21331 }
| static char * get_calleridname | ( | const char * | input, | |
| char * | output, | |||
| size_t | outputsize | |||
| ) | [static] |
Get caller id name from SIP headers.
Definition at line 13010 of file chan_sip.c.
References ast_copy_string(), and ast_skip_blanks().
Referenced by check_user_full().
13011 { 13012 const char *end = strchr(input, '<'); /* first_bracket */ 13013 const char *tmp = strchr(input, '"'); /* first quote */ 13014 int bytes = 0; 13015 int maxbytes = outputsize - 1; 13016 13017 if (!end || end == input) /* we require a part in brackets */ 13018 return NULL; 13019 13020 end--; /* move just before "<" */ 13021 13022 if (tmp && tmp <= end) { 13023 /* The quote (tmp) precedes the bracket (end+1). 13024 * Find the matching quote and return the content. 13025 */ 13026 end = strchr(tmp+1, '"'); 13027 if (!end) 13028 return NULL; 13029 bytes = (int) (end - tmp); 13030 /* protect the output buffer */ 13031 if (bytes > maxbytes) 13032 bytes = maxbytes; 13033 ast_copy_string(output, tmp + 1, bytes); 13034 } else { 13035 /* No quoted string, or it is inside brackets. */ 13036 /* clear the empty characters in the begining*/ 13037 input = ast_skip_blanks(input); 13038 /* clear the empty characters in the end */ 13039 while(*end && *end < 33 && end > input) 13040 end--; 13041 if (end >= input) { 13042 bytes = (int) (end - input) + 2; 13043 /* protect the output buffer */ 13044 if (bytes > maxbytes) 13045 bytes = maxbytes; 13046 ast_copy_string(output, input, bytes); 13047 } else 13048 return NULL; 13049 } 13050 return output; 13051 }
| 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 12454 of file chan_sip.c.
References ast_canmatch_extension(), ast_copy_string(), ast_debug, ast_exists_extension(), ast_get_hint(), AST_LIST_EMPTY, ast_log(), AST_MAX_EXTENSION, ast_pickup_ext(), ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_uri_decode(), ast_verbose, check_sip_domain(), sip_pvt::cid_num, sip_pvt::context, context, sip_pvt::domain, exten, sip_pvt::exten, get_header(), get_in_brackets(), sip_pvt::initreq, LOG_WARNING, sip_request::method, REQ_OFFSET_TO_STR, sip_request::rlPart2, S_OR, sip_debug_test_pvt(), SIP_INVITE, sip_methods, SIP_PAGE2_ALLOWOVERLAP, SIP_REFER, SIP_SUBSCRIBE, strsep(), sip_pvt::subscribecontext, and cfsip_methods::text.
Referenced by handle_request_invite(), handle_request_options(), and handle_request_subscribe().
12455 { 12456 char tmp[256] = "", *uri, *a; 12457 char tmpf[256] = "", *from = NULL; 12458 struct sip_request *req; 12459 char *colon; 12460 char *decoded_uri; 12461 12462 req = oreq; 12463 if (!req) 12464 req = &p->initreq; 12465 12466 /* Find the request URI */ 12467 if (req->rlPart2) 12468 ast_copy_string(tmp, REQ_OFFSET_TO_STR(req, rlPart2), sizeof(tmp)); 12469 12470 if (pedanticsipchecking) 12471 ast_uri_decode(tmp); 12472 12473 uri = get_in_brackets(tmp); 12474 12475 if (!strncasecmp(uri, "sip:", 4)) { 12476 uri += 4; 12477 } else if (!strncasecmp(uri, "sips:", 5)) { 12478 uri += 5; 12479 } else { 12480 ast_log(LOG_WARNING, "Huh? Not a SIP header (%s)?\n", uri); 12481 return -1; 12482 } 12483 12484 /* Now find the From: caller ID and name */ 12485 /* XXX Why is this done in get_destination? Isn't it already done? 12486 Needs to be checked 12487 */ 12488 ast_copy_string(tmpf, get_header(req, "From"), sizeof(tmpf)); 12489 if (!ast_strlen_zero(tmpf)) { 12490 if (pedanticsipchecking) 12491 ast_uri_decode(tmpf); 12492 from = get_in_brackets(tmpf); 12493 } 12494 12495 if (!ast_strlen_zero(from)) { 12496 if (!strncasecmp(from, "sip:", 4)) { 12497 from += 4; 12498 } else if (!strncasecmp(from, "sips:", 5)) { 12499 from += 5; 12500 } else { 12501 ast_log(LOG_WARNING, "Huh? Not a SIP header (%s)?\n", from); 12502 return -1; 12503 } 12504 if ((a = strchr(from, '@'))) 12505 *a++ = '\0'; 12506 else 12507 a = from; /* just a domain */ 12508 from = strsep(&from, ";"); /* Remove userinfo options */ 12509 a = strsep(&a, ";"); /* Remove URI options */ 12510 ast_string_field_set(p, fromdomain, a); 12511 } 12512 12513 /* Skip any options and find the domain */ 12514 12515 /* Get the target domain */ 12516 if ((a = strchr(uri, '@'))) { 12517 *a++ = '\0'; 12518 } else { /* No username part */ 12519 a = uri; 12520 uri = "s"; /* Set extension to "s" */ 12521 } 12522 colon = strchr(a, ':'); /* Remove :port */ 12523 if (colon) 12524 *colon = '\0'; 12525 12526 uri = strsep(&uri, ";"); /* Remove userinfo options */ 12527 a = strsep(&a, ";"); /* Remove URI options */ 12528 12529 ast_string_field_set(p, domain, a); 12530 12531 if (!AST_LIST_EMPTY(&domain_list)) { 12532 char domain_context[AST_MAX_EXTENSION]; 12533 12534 domain_context[0] = '\0'; 12535 if (!check_sip_domain(p->domain, domain_context, sizeof(domain_context))) { 12536 if (!allow_external_domains && (req->method == SIP_INVITE || req->method == SIP_REFER)) { 12537 ast_debug(1, "Got SIP %s to non-local domain '%s'; refusing request.\n", sip_methods[req->method].text, p->domain); 12538 return -2; 12539 } 12540 } 12541 /* If we have a context defined, overwrite the original context */ 12542 if (!ast_strlen_zero(domain_context)) 12543 ast_string_field_set(p, context, domain_context); 12544 } 12545 12546 /* If the request coming in is a subscription and subscribecontext has been specified use it */ 12547 if (req->method == SIP_SUBSCRIBE && !ast_strlen_zero(p->subscribecontext)) 12548 ast_string_field_set(p, context, p->subscribecontext); 12549 12550 if (sip_debug_test_pvt(p)) 12551 ast_verbose("Looking for %s in %s (domain %s)\n", uri, p->context, p->domain); 12552 12553 /* If this is a subscription we actually just need to see if a hint exists for the extension */ 12554 if (req->method == SIP_SUBSCRIBE) { 12555 char hint[AST_MAX_EXTENSION]; 12556 return (ast_get_hint(hint, sizeof(hint), NULL, 0, NULL, p->context, p->exten) ? 0 : -1); 12557 } else { 12558 decoded_uri = ast_strdupa(uri); 12559 ast_uri_decode(decoded_uri); 12560 /* Check the dialplan for the username part of the request URI, 12561 the domain will be stored in the SIPDOMAIN variable 12562 Since extensions.conf can have unescaped characters, try matching a decoded 12563 uri in addition to the non-decoded uri 12564 Return 0 if we have a matching extension */ 12565 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)) || 12566 !strcmp(decoded_uri, ast_pickup_ext())) { 12567 if (!oreq) 12568 ast_string_field_set(p, exten, decoded_uri); 12569 return 0; 12570 } 12571 } 12572 12573 /* Return 1 for pickup extension or overlap dialling support (if we support it) */ 12574 if((ast_test_flag(&global_flags[1], SIP_PAGE2_ALLOWOVERLAP) && 12575 ast_canmatch_extension(NULL, p->context, decoded_uri, 1, S_OR(p->cid_num, from))) || 12576 !strncmp(decoded_uri, ast_pickup_ext(), strlen(decoded_uri))) { 12577 return 1; 12578 } 12579 12580 return -1; 12581 }
| static const char * get_header | ( | const struct sip_request * | req, | |
| const char * | name | |||
| ) | [static] |
Get header from SIP request.
Definition at line 6536 of file chan_sip.c.
References __get_header().
Referenced by __transmit_response(), _sip_tcp_helper_thread(), build_route(), check_auth(), check_user_full(), check_via(), check_via_response(), copy_header(), extract_uri(), find_call(), find_sdp(), get_also_info(), get_destination(), get_rdnis(), get_refer_info(), gettag(), handle_incoming(), handle_request_bye(), handle_request_do(), handle_request_info(), handle_request_invite(), handle_request_notify(), handle_request_register(), handle_request_subscribe(), handle_response(), handle_response_invite(), handle_response_notify(), handle_response_refer(), handle_response_register(), parse_moved_contact(), parse_ok_contact(), parse_register_contact(), proc_422_rsp(), receive_message(), register_verify(), reply_digest(), reqprep(), respprep(), send_request(), send_response(), sip_sipredirect(), transmit_fake_auth_response(), transmit_refer(), transmit_response_with_auth(), transmit_response_with_sdp(), transmit_response_with_t38_sdp(), and transmit_state_notify().
06537 { 06538 int start = 0; 06539 return __get_header(req, name, &start); 06540 }
| 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 3955 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().
03956 { 03957 const char *parse = tmp; 03958 char *first_bracket; 03959 03960 /* 03961 * Skip any quoted text until we find the part in brackets. 03962 * On any error give up and return the full string. 03963 */ 03964 while ( (first_bracket = strchr(parse, '<')) ) { 03965 char *first_quote = strchr(parse, '"'); 03966 03967 if (!first_quote || first_quote > first_bracket) 03968 break; /* no need to look at quoted part */ 03969 /* the bracket is within quotes, so ignore it */ 03970 parse = find_closing_quote(first_quote + 1, NULL); 03971 if (!*parse) { /* not found, return full string ? */ 03972 /* XXX or be robust and return in-bracket part ? */ 03973 ast_log(LOG_WARNING, "No closing quote found in '%s'\n", tmp); 03974 break; 03975 } 03976 parse++; 03977 } 03978 if (first_bracket) { 03979 char *second_bracket = strchr(first_bracket + 1, '>'); 03980 if (second_bracket) { 03981 *second_bracket = '\0'; 03982 tmp = first_bracket + 1; 03983 } else { 03984 ast_log(LOG_WARNING, "No closing bracket found in '%s'\n", tmp); 03985 } 03986 } 03987 03988 return tmp; 03989 }
| static struct ast_variable * get_insecure_variable_from_config | ( | struct ast_config * | config | ) | [static, read] |
Definition at line 4318 of file chan_sip.c.
References ast_category_browse(), ast_category_root(), ast_test_flag, ast_variable_retrieve(), set_insecure_flags(), SIP_INSECURE_PORT, and var.
Referenced by realtime_peer().
04319 { 04320 struct ast_variable *var = NULL; 04321 struct ast_flags flags = {0}; 04322 char *cat = NULL; 04323 const char *insecure; 04324 while ((cat = ast_category_browse(cfg, cat))) { 04325 insecure = ast_variable_retrieve(cfg, cat, "insecure"); 04326 set_insecure_flags(&flags, insecure, -1); 04327 if (ast_test_flag(&flags, SIP_INSECURE_PORT)) { 04328 var = ast_category_root(cfg, cat); 04329 break; 04330 } 04331 } 04332 return var; 04333 }
| 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 7399 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().
07400 { 07401 const char *m; 07402 const char *c; 07403 int miterator = req->sdp_start; 07404 int citerator = req->sdp_start; 07405 int x = 0; 07406 int numberofports; 07407 int len; 07408 char host[258] = ""; /*Initialize to empty so we will know if we have any input */ 07409 struct ast_hostent audiohp; 07410 struct hostent *hp; 07411 07412 c = get_sdp_iterate(&citerator, req, "c"); 07413 if (sscanf(c, "IN IP4 %256s", host) != 1) { 07414 ast_log(LOG_WARNING, "Invalid host in c= line, '%s'\n", c); 07415 /* Continue since there may be a valid host in a c= line specific to the audio stream */ 07416 } 07417 /* We only want the m and c lines for audio */ 07418 for (m = get_sdp_iterate(&miterator, req, "m"); !ast_strlen_zero(m); m = get_sdp_iterate(&miterator, req, "m")) { 07419 if ((media == SDP_AUDIO && ((sscanf(m, "audio %30u/%30u RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) || 07420 (sscanf(m, "audio %30u RTP/AVP %n", &x, &len) == 1 && len > 0))) || 07421 (media == SDP_VIDEO && ((sscanf(m, "video %30u/%30u RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) || 07422 (sscanf(m, "video %30u RTP/AVP %n", &x, &len) == 1 && len > 0)))) { 07423 /* See if there's a c= line for this media stream. 07424 * XXX There is no guarantee that we'll be grabbing the c= line for this 07425 * particular media stream here. However, this is the same logic used in process_sdp. 07426 */ 07427 c = get_sdp_iterate(&citerator, req, "c"); 07428 if (!ast_strlen_zero(c)) { 07429 sscanf(c, "IN IP4 %256s", host); 07430 } 07431 break; 07432 } 07433 } 07434 07435 if (ast_strlen_zero(host) || x == 0) { 07436 ast_log(LOG_WARNING, "Failed to read an alternate host or port in SDP. Expect %s problems\n", media == SDP_AUDIO ? "audio" : "video"); 07437 return -1; 07438 } 07439 07440 hp = ast_gethostbyname(host, &audiohp); 07441 if (!hp) { 07442 ast_log(LOG_WARNING, "Could not look up IP address of alternate hostname. Expect %s problems\n", media == SDP_AUDIO? "audio" : "video"); 07443 return -1; 07444 } 07445 07446 memcpy(&sin->sin_addr, hp->h_addr, sizeof(sin->sin_addr)); 07447 sin->sin_port = htons(x); 07448 return 0; 07449 }
| 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 13403 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().
13404 { 13405 int x; 13406 int y; 13407 13408 buf[0] = '\0'; 13409 /*XXX isn't strlen(buf) going to always be 0? */ 13410 y = len - strlen(buf) - 5; 13411 if (y < 0) 13412 y = 0; 13413 for (x = 0; x < req->lines; x++) { 13414 char *line = REQ_OFFSET_TO_STR(req, line[x]); 13415 strncat(buf, line, y); /* safe */ 13416 y -= strlen(line) + 1; 13417 if (y < 0) 13418 y = 0; 13419 if (y != 0 && addnewline) 13420 strcat(buf, "\n"); /* safe */ 13421 } 13422 return 0; 13423 }
| static const char * get_name_from_variable | ( | struct ast_variable * | var, | |
| const char * | newpeername | |||
| ) | [static] |
Definition at line 4335 of file chan_sip.c.
References ast_variable::name, ast_variable::next, and ast_variable::value.
Referenced by realtime_peer().
04336 { 04337 struct ast_variable *tmp; 04338 for (tmp = var; tmp; tmp = tmp->next) { 04339 if (!newpeername && !strcasecmp(tmp->name, "name")) 04340 newpeername = tmp->value; 04341 } 04342 return newpeername; 04343 }
| 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 9332 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().
09335 { 09336 /* First, get our address */ 09337 ast_rtp_get_us(p->rtp, sin); 09338 if (p->vrtp) 09339 ast_rtp_get_us(p->vrtp, vsin); 09340 if (p->trtp) 09341 ast_rtp_get_us(p->trtp, tsin); 09342 09343 /* Now, try to figure out where we want them to send data */ 09344 /* Is this a re-invite to move the media out, then use the original offer from caller */ 09345 if (p->redirip.sin_addr.s_addr) { /* If we have a redirection IP, use it */ 09346 dest->sin_port = p->redirip.sin_port; 09347 dest->sin_addr = p->redirip.sin_addr; 09348 } else { 09349 dest->sin_addr = p->ourip.sin_addr; 09350 dest->sin_port = sin->sin_port; 09351 } 09352 if (needvideo) { 09353 /* Determine video destination */ 09354 if (p->vredirip.sin_addr.s_addr) { 09355 vdest->sin_addr = p->vredirip.sin_addr; 09356 vdest->sin_port = p->vredirip.sin_port; 09357 } else { 09358 vdest->sin_addr = p->ourip.sin_addr; 09359 vdest->sin_port = vsin->sin_port; 09360 } 09361 } 09362 09363 }
| static int get_rdnis | ( | struct sip_pvt * | p, | |
| struct sip_request * | oreq | |||
| ) | [static] |
Get referring dnis.
Definition at line 12387 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_pvt::redircause, sip_debug_test_pvt(), sip_set_redirstr(), strcasestr(), and strsep().
Referenced by handle_request_invite().
12388 { 12389 char tmp[256], *exten, *rexten, *rdomain; 12390 char *params, *reason = NULL; 12391 struct sip_request *req; 12392 12393 req = oreq ? oreq : &p->initreq; 12394 12395 ast_copy_string(tmp, get_header(req, "Diversion"), sizeof(tmp)); 12396 if (ast_strlen_zero(tmp)) 12397 return 0; 12398 12399 params = strchr(tmp, ';'); 12400 12401 exten = get_in_brackets(tmp); 12402 if (!strncasecmp(exten, "sip:", 4)) { 12403 exten += 4; 12404 } else if (!strncasecmp(exten, "sips:", 5)) { 12405 exten += 5; 12406 } else { 12407 ast_log(LOG_WARNING, "Huh? Not an RDNIS SIP header (%s)?\n", exten); 12408 return -1; 12409 } 12410 12411 /* Get diversion-reason param if present */ 12412 if (params) { 12413 *params = '\0'; /* Cut off parameters */ 12414 params++; 12415 while (*params == ';' || *params == ' ') 12416 params++; 12417 /* Check if we have a reason parameter */ 12418 if ((reason = strcasestr(params, "reason="))) { 12419 reason+=7; 12420 /* Remove enclosing double-quotes */ 12421 if (*reason == '"') 12422 ast_strip_quoted(reason, "\"", "\""); 12423 if (!ast_strlen_zero(reason)) { 12424 sip_set_redirstr(p, reason); 12425 if (p->owner) { 12426 pbx_builtin_setvar_helper(p->owner, "__PRIREDIRECTREASON", p->redircause); 12427 pbx_builtin_setvar_helper(p->owner, "__SIPREDIRECTREASON", reason); 12428 } 12429 } 12430 } 12431 } 12432 12433 rdomain = exten; 12434 rexten = strsep(&rdomain, "@"); /* trim anything after @ */ 12435 if (p->owner) 12436 pbx_builtin_setvar_helper(p->owner, "__SIPRDNISDOMAIN", rdomain); 12437 12438 if (sip_debug_test_pvt(p)) 12439 ast_verbose("RDNIS for this call is is %s (reason %s)\n", exten, reason ? reason : ""); 12440 12441 ast_string_field_set(p, rdnis, rexten); 12442 12443 return 0; 12444 }
| 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 12668 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().
12669 { 12670 12671 const char *p_referred_by = NULL; 12672 char *h_refer_to = NULL; 12673 char *h_referred_by = NULL; 12674 char *refer_to; 12675 const char *p_refer_to; 12676 char *referred_by_uri = NULL; 12677 char *ptr; 12678 struct sip_request *req = NULL; 12679 const char *transfer_context = NULL; 12680 struct sip_refer *referdata; 12681 12682 12683 req = outgoing_req; 12684 referdata = transferer->refer; 12685 12686 if (!req) 12687 req = &transferer->initreq; 12688 12689 p_refer_to = get_header(req, "Refer-To"); 12690 if (ast_strlen_zero(p_refer_to)) { 12691 ast_log(LOG_WARNING, "Refer-To Header missing. Skipping transfer.\n"); 12692 return -2; /* Syntax error */ 12693 } 12694 h_refer_to = ast_strdupa(p_refer_to); 12695 refer_to = get_in_brackets(h_refer_to); 12696 if (pedanticsipchecking) 12697 ast_uri_decode(refer_to); 12698 12699 if (!strncasecmp(refer_to, "sip:", 4)) { 12700 refer_to += 4; /* Skip sip: */ 12701 } else if (!strncasecmp(refer_to, "sips:", 5)) { 12702 refer_to += 5; 12703 } else { 12704 ast_log(LOG_WARNING, "Can't transfer to non-sip: URI. (Refer-to: %s)?\n", refer_to); 12705 return -3; 12706 } 12707 12708 /* Get referred by header if it exists */ 12709 p_referred_by = get_header(req, "Referred-By"); 12710 12711 /* Give useful transfer information to the dialplan */ 12712 if (transferer->owner) { 12713 struct ast_channel *peer = ast_bridged_channel(transferer->owner); 12714 if (peer) { 12715 pbx_builtin_setvar_helper(peer, "SIPREFERRINGCONTEXT", transferer->context); 12716 pbx_builtin_setvar_helper(peer, "SIPREFERREDBYHDR", p_referred_by); 12717 } 12718 } 12719 12720 if (!ast_strlen_zero(p_referred_by)) { 12721 char *lessthan; 12722 h_referred_by = ast_strdupa(p_referred_by); 12723 if (pedanticsipchecking) 12724 ast_uri_decode(h_referred_by); 12725 12726 /* Store referrer's caller ID name */ 12727 ast_copy_string(referdata->referred_by_name, h_referred_by, sizeof(referdata->referred_by_name)); 12728 if ((lessthan = strchr(referdata->referred_by_name, '<'))) { 12729 *(lessthan - 1) = '\0'; /* Space */ 12730 } 12731 12732 referred_by_uri = get_in_brackets(h_referred_by); 12733 if (!strncasecmp(referred_by_uri, "sip:", 4)) { 12734 referred_by_uri += 4; /* Skip sip: */ 12735 } else if (!strncasecmp(referred_by_uri, "sips:", 5)) { 12736 referred_by_uri += 5; /* Skip sips: */ 12737 } else { 12738 ast_log(LOG_WARNING, "Huh? Not a sip: header (Referred-by: %s). Skipping.\n", referred_by_uri); 12739 referred_by_uri = NULL; 12740 } 12741 } 12742 12743 /* Check for arguments in the refer_to header */ 12744 if ((ptr = strcasestr(refer_to, "replaces="))) { 12745 char *to = NULL, *from = NULL; 12746 12747 /* This is an attended transfer */ 12748 referdata->attendedtransfer = 1; 12749 ast_copy_string(referdata->replaces_callid, ptr+9, sizeof(referdata->replaces_callid)); 12750 ast_uri_decode(referdata->replaces_callid); 12751 if ((ptr = strchr(referdata->replaces_callid, ';'))) /* Find options */ { 12752 *ptr++ = '\0'; 12753 } 12754 12755 if (ptr) { 12756 /* Find the different tags before we destroy the string */ 12757 to = strcasestr(ptr, "to-tag="); 12758 from = strcasestr(ptr, "from-tag="); 12759 } 12760 12761 /* Grab the to header */ 12762 if (to) { 12763 ptr = to + 7; 12764 if ((to = strchr(ptr, '&'))) 12765 *to = '\0'; 12766 if ((to = strchr(ptr, ';'))) 12767 *to = '\0'; 12768 ast_copy_string(referdata->replaces_callid_totag, ptr, sizeof(referdata->replaces_callid_totag)); 12769 } 12770 12771 if (from) { 12772 ptr = from + 9; 12773 if ((to = strchr(ptr, '&'))) 12774 *to = '\0'; 12775 if ((to = strchr(ptr, ';'))) 12776 *to = '\0'; 12777 ast_copy_string(referdata->replaces_callid_fromtag, ptr, sizeof(referdata->replaces_callid_fromtag)); 12778 } 12779 12780 if (!pedanticsipchecking) 12781 ast_debug(2, "Attended transfer: Will use Replace-Call-ID : %s (No check of from/to tags)\n", referdata->replaces_callid ); 12782 else 12783 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>" ); 12784 } 12785 12786 if ((ptr = strchr(refer_to, '@'))) { /* Separate domain */ 12787 char *urioption = NULL, *domain; 12788 *ptr++ = '\0'; 12789 12790 if ((urioption = strchr(ptr, ';'))) /* Separate urioptions */ 12791 *urioption++ = '\0'; 12792 12793 domain = ptr; 12794 if ((ptr = strchr(domain, ':'))) /* Remove :port */ 12795 *ptr = '\0'; 12796 12797 /* Save the domain for the dial plan */ 12798 ast_copy_string(referdata->refer_to_domain, domain, sizeof(referdata->refer_to_domain)); 12799 if (urioption) 12800 ast_copy_string(referdata->refer_to_urioption, urioption, sizeof(referdata->refer_to_urioption)); 12801 } 12802 12803 if ((ptr = strchr(refer_to, ';'))) /* Remove options */ 12804 *ptr = '\0'; 12805 ast_copy_string(referdata->refer_to, refer_to, sizeof(referdata->refer_to)); 12806 12807 if (referred_by_uri) { 12808 if ((ptr = strchr(referred_by_uri, ';'))) /* Remove options */ 12809 *ptr = '\0'; 12810 ast_copy_string(referdata->referred_by, referred_by_uri, sizeof(referdata->referred_by)); 12811 } else { 12812 referdata->referred_by[0] = '\0'; 12813 } 12814 12815 /* Determine transfer context */ 12816 if (transferer->owner) /* Mimic behaviour in res_features.c */ 12817 transfer_context = pbx_builtin_getvar_helper(transferer->owner, "TRANSFER_CONTEXT"); 12818 12819 /* By default, use the context in the channel sending the REFER */ 12820 if (ast_strlen_zero(transfer_context)) { 12821 transfer_context = S_OR(transferer->owner->macrocontext, 12822 S_OR(transferer->context, default_context)); 12823 } 12824 12825 ast_copy_string(referdata->refer_to_context, transfer_context, sizeof(referdata->refer_to_context)); 12826 12827 /* Either an existing extension or the parking extension */ 12828 if (referdata->attendedtransfer || ast_exists_extension(NULL, transfer_context, refer_to, 1, NULL) ) { 12829 if (sip_debug_test_pvt(transferer)) { 12830 ast_verbose("SIP transfer to extension %s@%s by %s\n", refer_to, transfer_context, referred_by_uri); 12831 } 12832 /* We are ready to transfer to the extension */ 12833 return 0; 12834 } 12835 if (sip_debug_test_pvt(transferer)) 12836 ast_verbose("Failed SIP Transfer to non-existing extension %s in context %s\n n", refer_to, transfer_context); 12837 12838 /* Failure, we can't find this extension */ 12839 return -1; 12840 }
| 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 13057 of file chan_sip.c.
References ast_copy_string(), and AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED.
Referenced by check_user_full().
13058 { 13059 char *start; 13060 char *end; 13061 13062 start = strchr(input, ':'); 13063 if (!start) { 13064 output[0] = '\0'; 13065 return 0; 13066 } 13067 start++; 13068 13069 /* we found "number" */ 13070 ast_copy_string(output, start, maxlen); 13071 output[maxlen-1] = '\0'; 13072 13073 end = strchr(output, '@'); 13074 if (end) 13075 *end = '\0'; 13076 else 13077 output[0] = '\0'; 13078 if (strstr(input, "privacy=full") || strstr(input, "privacy=uri")) 13079 return AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED; 13080 13081 return 0; 13082 }
| 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 6400 of file chan_sip.c.
References get_body_by_line(), REQ_OFFSET_TO_STR, sip_request::sdp_count, and sip_request::sdp_start.
Referenced by get_ip_and_port_from_sdp(), and process_sdp().
06401 { 06402 int len = strlen(name); 06403 06404 while (*start < (req->sdp_start + req->sdp_count)) { 06405 const char *r = get_body_by_line(REQ_OFFSET_TO_STR(req, line[(*start)++]), name, len); 06406 if (r[0] != '\0') 06407 return r; 06408 } 06409 06410 /* if the line was not found, ensure that *start points past the SDP */ 06411 (*start)++; 06412 06413 return ""; 06414 }
| 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 6421 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().
06422 { 06423 char type = '\0'; 06424 const char *line = NULL; 06425 06426 if (stop > (req->sdp_start + req->sdp_count)) { 06427 stop = req->sdp_start + req->sdp_count; 06428 } 06429 06430 while (*start < stop) { 06431 line = REQ_OFFSET_TO_STR(req, line[(*start)++]); 06432 if (line[1] == '=') { 06433 type = line[0]; 06434 *value = ast_skip_blanks(line + 2); 06435 break; 06436 } 06437 } 06438 06439 return type; 06440 }
| static struct sip_pvt * get_sip_pvt_byid_locked | ( | const char * | callid, | |
| const char * | totag, | |||
| const char * | fromtag | |||
| ) | [static, read] |
Lock dialog lock and find matching pvt lock.
Definition at line 12586 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::outgoing_call, sip_pvt::owner, sip_pvt_lock, sip_pvt_unlock, sip_pvt::tag, sip_pvt::theirtag, and TRUE.
Referenced by handle_request_invite(), and local_attended_transfer().
12587 { 12588 struct sip_pvt *sip_pvt_ptr; 12589 struct sip_pvt tmp_dialog = { 12590 .callid = callid, 12591 }; 12592 12593 if (totag) 12594 ast_debug(4, "Looking for callid %s (fromtag %s totag %s)\n", callid, fromtag ? fromtag : "<no fromtag>", totag ? totag : "<no totag>"); 12595 12596 /* Search dialogs and find the match */ 12597 12598 sip_pvt_ptr = ao2_t_find(dialogs, &tmp_dialog, OBJ_POINTER, "ao2_find of dialog in dialogs table"); 12599 if (sip_pvt_ptr) { 12600 /* Go ahead and lock it (and its owner) before returning */ 12601 sip_pvt_lock(sip_pvt_ptr); 12602 if (pedanticsipchecking) { 12603 unsigned char frommismatch = 0, tomismatch = 0; 12604 12605 if (ast_strlen_zero(fromtag)) { 12606 sip_pvt_unlock(sip_pvt_ptr); 12607 ast_debug(4, "Matched %s call for callid=%s - no from tag specified, pedantic check fails\n", 12608 sip_pvt_ptr->outgoing_call == TRUE ? "OUTGOING": "INCOMING", sip_pvt_ptr->callid); 12609 return NULL; 12610 } 12611 12612 if (ast_strlen_zero(totag)) { 12613 sip_pvt_unlock(sip_pvt_ptr); 12614 ast_debug(4, "Matched %s call for callid=%s - no to tag specified, pedantic check fails\n", 12615 sip_pvt_ptr->outgoing_call == TRUE ? "OUTGOING": "INCOMING", sip_pvt_ptr->callid); 12616 return NULL; 12617 } 12618 /* RFC 3891 12619 * > 3. User Agent Server Behavior: Receiving a Replaces Header 12620 * > The Replaces header contains information used to match an existing 12621 * > SIP dialog (call-id, to-tag, and from-tag). Upon receiving an INVITE 12622 * > with a Replaces header, the User Agent (UA) attempts to match this 12623 * > information with a confirmed or early dialog. The User Agent Server 12624 * > (UAS) matches the to-tag and from-tag parameters as if they were tags 12625 * > present in an incoming request. In other words, the to-tag parameter 12626 * > is compared to the local tag, and the from-tag parameter is compared 12627 * > to the remote tag. 12628 * 12629 * Thus, the totag is always compared to the local tag, regardless if 12630 * this our call is an incoming or outgoing call. 12631 */ 12632 frommismatch = !!strcmp(fromtag, sip_pvt_ptr->theirtag); 12633 tomismatch = !!strcmp(totag, sip_pvt_ptr->tag); 12634 if (frommismatch || tomismatch) { 12635 sip_pvt_unlock(sip_pvt_ptr); 12636 if (frommismatch) { 12637 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", 12638 sip_pvt_ptr->outgoing_call == TRUE ? "OUTGOING": "INCOMING", sip_pvt_ptr->callid, 12639 fromtag, sip_pvt_ptr->theirtag); 12640 } 12641 if (tomismatch) { 12642 ast_debug(4, "Matched %s call for callid=%s - pedantic to tag check fails; their tag is %s our tag is %s\n", 12643 sip_pvt_ptr->outgoing_call == TRUE ? "OUTGOING": "INCOMING", sip_pvt_ptr->callid, 12644 totag, sip_pvt_ptr->tag); 12645 } 12646 return NULL; 12647 } 12648 } 12649 12650 if (totag) 12651 ast_debug(4, "Matched %s call - their tag is %s Our tag is %s\n", 12652 sip_pvt_ptr->outgoing_call == TRUE ? "OUTGOING": "INCOMING", 12653 sip_pvt_ptr->theirtag, sip_pvt_ptr->tag); 12654 12655 /* deadlock avoidance... */ 12656 while (sip_pvt_ptr->owner && ast_channel_trylock(sip_pvt_ptr->owner)) { 12657 sip_pvt_unlock(sip_pvt_ptr); 12658 usleep(1); 12659 sip_pvt_lock(sip_pvt_ptr); 12660 } 12661 } 12662 12663 return sip_pvt_ptr; 12664 }
| static const char* get_transport | ( | enum sip_transport | t | ) | [inline, static] |
Definition at line 3140 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().
03141 { 03142 switch (t) { 03143 case SIP_TRANSPORT_UDP: 03144 return "UDP"; 03145 case SIP_TRANSPORT_TCP: 03146 return "TCP"; 03147 case SIP_TRANSPORT_TLS: 03148 return "TLS"; 03149 } 03150 03151 return "UNKNOWN"; 03152 }
| static const char* get_transport_list | ( | struct sip_peer * | peer | ) | [inline, static] |
Definition at line 3120 of file chan_sip.c.
References SIP_TRANSPORT_TCP, SIP_TRANSPORT_TLS, SIP_TRANSPORT_UDP, and sip_peer::transports.
03120 { 03121 switch (peer->transports) { 03122 case SIP_TRANSPORT_UDP: 03123 return "UDP"; 03124 case SIP_TRANSPORT_TCP: 03125 return "TCP"; 03126 case SIP_TRANSPORT_TLS: 03127 return "TLS"; 03128 case SIP_TRANSPORT_UDP | SIP_TRANSPORT_TCP: 03129 return "TCP,UDP"; 03130 case SIP_TRANSPORT_UDP | SIP_TRANSPORT_TLS: 03131 return "TLS,UDP"; 03132 case SIP_TRANSPORT_TCP | SIP_TRANSPORT_TLS: 03133 return "TLS,TCP"; 03134 default: 03135 return peer->transports ? 03136 "TLS,TCP,UDP" : "UNKNOWN"; 03137 } 03138 }
| static const char* get_transport_pvt | ( | struct sip_pvt * | p | ) | [inline, static] |
Definition at line 3154 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().
03155 { 03156 if (p->outboundproxy && p->outboundproxy->transport) { 03157 set_socket_transport(&p->socket, p->outboundproxy->transport); 03158 } 03159 03160 return get_transport(p->socket.type); 03161 }
| 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 3099 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().
03100 { 03101 int res = 0; 03102 03103 if (ast_strlen_zero(transport)) { 03104 return res; 03105 } 03106 03107 if (!strcasecmp(transport, "udp")) { 03108 res |= SIP_TRANSPORT_UDP; 03109 } 03110 if (!strcasecmp(transport, "tcp")) { 03111 res |= SIP_TRANSPORT_TCP; 03112 } 03113 if (!strcasecmp(transport, "tls")) { 03114 res |= SIP_TRANSPORT_TLS; 03115 } 03116 03117 return res; 03118 }
| static const char * gettag | ( | const struct sip_request * | req, | |
| const char * | header, | |||
| char * | tagbuf, | |||
| int | tagbufsize | |||
| ) | [static] |
Get tag from packet.
Definition at line 18121 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().
18122 { 18123 const char *thetag; 18124 18125 if (!tagbuf) 18126 return NULL; 18127 tagbuf[0] = '\0'; /* reset the buffer */ 18128 thetag = get_header(req, header); 18129 thetag = strcasestr(thetag, ";tag="); 18130 if (thetag) { 18131 thetag += 5; 18132 ast_copy_string(tagbuf, thetag, tagbufsize); 18133 return strsep(&tagbuf, ";"); 18134 } 18135 return NULL; 18136 }
| 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 22355 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_variable::lineno, LOG_WARNING, ast_variable::name, 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_CONSTANT_SSRC, 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(), and reload_config().
22356 { 22357 int res = 1; 22358 22359 if (!strcasecmp(v->name, "trustrpid")) { 22360 ast_set_flag(&mask[0], SIP_TRUSTRPID); 22361 ast_set2_flag(&flags[0], ast_true(v->value), SIP_TRUSTRPID); 22362 } else if (!strcasecmp(v->name, "sendrpid")) { 22363 ast_set_flag(&mask[0], SIP_SENDRPID); 22364 ast_set2_flag(&flags[0], ast_true(v->value), SIP_SENDRPID); 22365 } else if (!strcasecmp(v->name, "g726nonstandard")) { 22366 ast_set_flag(&mask[0], SIP_G726_NONSTANDARD); 22367 ast_set2_flag(&flags[0], ast_true(v->value), SIP_G726_NONSTANDARD); 22368 } else if (!strcasecmp(v->name, "useclientcode")) { 22369 ast_set_flag(&mask[0], SIP_USECLIENTCODE); 22370 ast_set2_flag(&flags[0], ast_true(v->value), SIP_USECLIENTCODE); 22371 } else if (!strcasecmp(v->name, "dtmfmode")) { 22372 ast_set_flag(&mask[0], SIP_DTMF); 22373 ast_clear_flag(&flags[0], SIP_DTMF); 22374 if (!strcasecmp(v->value, "inband")) 22375 ast_set_flag(&flags[0], SIP_DTMF_INBAND); 22376 else if (!strcasecmp(v->value, "rfc2833")) 22377 ast_set_flag(&flags[0], SIP_DTMF_RFC2833); 22378 else if (!strcasecmp(v->value, "info")) 22379 ast_set_flag(&flags[0], SIP_DTMF_INFO); 22380 else if (!strcasecmp(v->value, "shortinfo")) 22381 ast_set_flag(&flags[0], SIP_DTMF_SHORTINFO); 22382 else if (!strcasecmp(v->value, "auto")) 22383 ast_set_flag(&flags[0], SIP_DTMF_AUTO); 22384 else { 22385 ast_log(LOG_WARNING, "Unknown dtmf mode '%s' on line %d, using rfc2833\n", v->value, v->lineno); 22386 ast_set_flag(&flags[0], SIP_DTMF_RFC2833); 22387 } 22388 } else if (!strcasecmp(v->name, "nat")) { 22389 ast_set_flag(&mask[0], SIP_NAT); 22390 ast_clear_flag(&flags[0], SIP_NAT); 22391 if (!strcasecmp(v->value, "never")) 22392 ast_set_flag(&flags[0], SIP_NAT_NEVER); 22393 else if (!strcasecmp(v->value, "route")) 22394 ast_set_flag(&flags[0], SIP_NAT_ROUTE); 22395 else if (ast_true(v->value)) 22396 ast_set_flag(&flags[0], SIP_NAT_ALWAYS); 22397 else 22398 ast_set_flag(&flags[0], SIP_NAT_RFC3581); 22399 } else if (!strcasecmp(v->name, "canreinvite")) { 22400 ast_set_flag(&mask[0], SIP_REINVITE); 22401 ast_clear_flag(&flags[0], SIP_REINVITE); 22402 if (ast_true(v->value)) { 22403 ast_set_flag(&flags[0], SIP_CAN_REINVITE | SIP_CAN_REINVITE_NAT); 22404 } else if (!ast_false(v->value)) { 22405 char buf[64]; 22406 char *word, *next = buf; 22407 22408 ast_copy_string(buf, v->value, sizeof(buf)); 22409 while ((word = strsep(&next, ","))) { 22410 if (!strcasecmp(word, "update")) { 22411 ast_set_flag(&flags[0], SIP_REINVITE_UPDATE | SIP_CAN_REINVITE); 22412 } else if (!strcasecmp(word, "nonat")) { 22413 ast_set_flag(&flags[0], SIP_CAN_REINVITE); 22414 ast_clear_flag(&flags[0], SIP_CAN_REINVITE_NAT); 22415 } else { 22416 ast_log(LOG_WARNING, "Unknown canreinvite mode '%s' on line %d\n", v->value, v->lineno); 22417 } 22418 } 22419 } 22420 } else if (!strcasecmp(v->name, "insecure")) { 22421 ast_set_flag(&mask[0], SIP_INSECURE); 22422 ast_clear_flag(&flags[0], SIP_INSECURE); 22423 set_insecure_flags(&flags[0], v->value, v->lineno); 22424 } else if (!strcasecmp(v->name, "progressinband")) { 22425 ast_set_flag(&mask[0], SIP_PROG_INBAND); 22426 ast_clear_flag(&flags[0], SIP_PROG_INBAND); 22427 if (ast_true(v->value)) 22428 ast_set_flag(&flags[0], SIP_PROG_INBAND_YES); 22429 else if (strcasecmp(v->value, "never")) 22430 ast_set_flag(&flags[0], SIP_PROG_INBAND_NO); 22431 } else if (!strcasecmp(v->name, "promiscredir")) { 22432 ast_set_flag(&mask[0], SIP_PROMISCREDIR); 22433 ast_set2_flag(&flags[0], ast_true(v->value), SIP_PROMISCREDIR); 22434 } else if (!strcasecmp(v->name, "videosupport")) { 22435 if (!strcasecmp(v->value, "always")) { 22436 ast_set_flag(&mask[1], SIP_PAGE2_VIDEOSUPPORT_ALWAYS); 22437 ast_set_flag(&flags[1], SIP_PAGE2_VIDEOSUPPORT_ALWAYS); 22438 } else { 22439 ast_set_flag(&mask[1], SIP_PAGE2_VIDEOSUPPORT); 22440 ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_VIDEOSUPPORT); 22441 } 22442 } else if (!strcasecmp(v->name, "textsupport")) { 22443 ast_set_flag(&mask[1], SIP_PAGE2_TEXTSUPPORT); 22444 ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_TEXTSUPPORT); 22445 res = 1; 22446 } else if (!strcasecmp(v->name, "allowoverlap")) { 22447 ast_set_flag(&mask[1], SIP_PAGE2_ALLOWOVERLAP); 22448 ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_ALLOWOVERLAP); 22449 } else if (!strcasecmp(v->name, "allowsubscribe")) { 22450 ast_set_flag(&mask[1], SIP_PAGE2_ALLOWSUBSCRIBE); 22451 ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_ALLOWSUBSCRIBE); 22452 } else if (!strcasecmp(v->name, "ignoresdpversion")) { 22453 ast_set_flag(&mask[1], SIP_PAGE2_IGNORESDPVERSION); 22454 ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_IGNORESDPVERSION); 22455 } else if (!strcasecmp(v->name, "rfc2833compensate")) { 22456 ast_set_flag(&mask[1], SIP_PAGE2_RFC2833_COMPENSATE); 22457 ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_RFC2833_COMPENSATE); 22458 } else if (!strcasecmp(v->name, "buggymwi")) { 22459 ast_set_flag(&mask[1], SIP_PAGE2_BUGGY_MWI); 22460 ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_BUGGY_MWI); 22461 } else if (!strcasecmp(v->name, "constantssrc")) { 22462 ast_set_flag(&mask[1], SIP_PAGE2_CONSTANT_SSRC); 22463 ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_CONSTANT_SSRC); 22464 } else if (!strcasecmp(v->name, "faxdetect")) { 22465 ast_set_flag(&mask[1], SIP_PAGE2_FAX_DETECT); 22466 ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_FAX_DETECT); 22467 } else 22468 res = 0; 22469 22470 return res; 22471 }
| 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 20621 of file chan_sip.c.
References __sip_ack(), sip_pvt::alreadygone, ast_debug, ast_inet_ntoa(), ast_log(), ast_skip_blanks(), ast_string_field_set, ast_strlen_zero(), ast_verbose, check_pendings(), sip_request::debug, DEFAULT_TRANS_TIMEOUT, extract_uri(), find_sdp(), get_header(), gettag(), sip_pvt::glareinvite, 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::header, sip_request::headers, sip_pvt::icseq, cfsip_methods::id, sip_request::ignore, sip_pvt::initreq, INV_TERMINATED, sip_pvt::invitestate, sip_pvt::lastinvite, sip_pvt::lastmsg, LOG_DEBUG, LOG_ERROR, LOG_NOTICE, LOG_WARNING, sip_request::method, sip_pvt::method, sip_pvt::needdestroy, sip_pvt::ocseq, option_debug, sip_pvt::pendinginvite, process_sdp(), sip_pvt::randdata, REQ_OFFSET_TO_STR, sip_request::rlPart1, sip_request::rlPart2, sip_pvt::sa, 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().
20622 { 20623 /* Called with p->lock held, as well as p->owner->lock if appropriate, keeping things 20624 relatively static */ 20625 const char *cmd; 20626 const char *cseq; 20627 const char *useragent; 20628 int seqno; 20629 int len; 20630 int respid; 20631 int res = 0; 20632 int debug = sip_debug_test_pvt(p); 20633 char *e; 20634 int error = 0; 20635 int oldmethod = p->method; 20636 int acked = 0; 20637 20638 /* Get Method and Cseq */ 20639 cseq = get_header(req, "Cseq"); 20640 cmd = REQ_OFFSET_TO_STR(req, header[0]); 20641 20642 /* Must have Cseq */ 20643 if (ast_strlen_zero(cmd) || ast_strlen_zero(cseq)) { 20644 ast_log(LOG_ERROR, "Missing Cseq. Dropping this SIP message, it's incomplete.\n"); 20645 error = 1; 20646 } 20647 if (!error && sscanf(cseq, "%30d%n", &seqno, &len) != 1) { 20648 ast_log(LOG_ERROR, "No seqno in '%s'. Dropping incomplete message.\n", cmd); 20649 error = 1; 20650 } 20651 if (error) { 20652 if (!p->initreq.headers) /* New call */ 20653 p->needdestroy = 1; /* Make sure we destroy this dialog */ 20654 return -1; 20655 } 20656 /* Get the command XXX */ 20657 20658 cmd = REQ_OFFSET_TO_STR(req, rlPart1); 20659 e = ast_skip_blanks(REQ_OFFSET_TO_STR(req, rlPart2)); 20660 20661 /* Save useragent of the client */ 20662 useragent = get_header(req, "User-Agent"); 20663 if (!ast_strlen_zero(useragent)) 20664 ast_string_field_set(p, useragent, useragent); 20665 20666 /* Find out SIP method for incoming request */ 20667 if (req->method == SIP_RESPONSE) { /* Response to our request */ 20668 /* ignore means "don't do anything with it" but still have to 20669 * respond appropriately. 20670 * But in this case this is a response already, so we really 20671 * have nothing to do with this message, and even setting the 20672 * ignore flag is pointless. 20673 */ 20674 if (ast_strlen_zero(e)) { 20675 return 0; 20676 } 20677 if (sscanf(e, "%30d %n", &respid, &len) != 1) { 20678 ast_log(LOG_WARNING, "Invalid response: '%s'\n", e); 20679 return 0; 20680 } 20681 if (respid <= 0) { 20682 ast_log(LOG_WARNING, "Invalid SIP response code: '%d'\n", respid); 20683 return 0; 20684 } 20685 if (p->ocseq && (p->ocseq < seqno)) { 20686 if (option_debug) 20687 ast_log(LOG_DEBUG, "Ignoring out of order response %d (expecting %d)\n", seqno, p->ocseq); 20688 return -1; 20689 } else { 20690 if ((respid == 200) || ((respid >= 300) && (respid <= 399))) { 20691 extract_uri(p, req); 20692 } 20693 handle_response(p, respid, e + len, req, seqno); 20694 } 20695 return 0; 20696 } 20697 20698 /* New SIP request coming in 20699 (could be new request in existing SIP dialog as well...) 20700 */ 20701 20702 p->method = req->method; /* Find out which SIP method they are using */ 20703 ast_debug(4, "**** Received %s (%d) - Command in SIP %s\n", sip_methods[p->method].text, sip_methods[p->method].id, cmd); 20704 20705 if (p->icseq && (p->icseq > seqno) ) { 20706 if (p->pendinginvite && seqno == p->pendinginvite && (req->method == SIP_ACK || req->method == SIP_CANCEL)) { 20707 ast_debug(2, "Got CANCEL or ACK on INVITE with transactions in between.\n"); 20708 } else { 20709 ast_debug(1, "Ignoring too old SIP packet packet %d (expecting >= %d)\n", seqno, p->icseq); 20710 if (req->method != SIP_ACK) 20711 transmit_response(p, "503 Server error", req); /* We must respond according to RFC 3261 sec 12.2 */ 20712 return -1; 20713 } 20714 } else if (p->icseq && 20715 p->icseq == seqno && 20716 req->method != SIP_ACK && 20717 (p->method != SIP_CANCEL || p->alreadygone)) { 20718 /* ignore means "don't do anything with it" but still have to 20719 respond appropriately. We do this if we receive a repeat of 20720 the last sequence number */ 20721 req->ignore = 1; 20722 ast_debug(3, "Ignoring SIP message because of retransmit (%s Seqno %d, ours %d)\n", sip_methods[p->method].text, p->icseq, seqno); 20723 } 20724 20725 if (seqno >= p->icseq) 20726 /* Next should follow monotonically (but not necessarily 20727 incrementally -- thanks again to the genius authors of SIP -- 20728 increasing */ 20729 p->icseq = seqno; 20730 20731 /* Find their tag if we haven't got it */ 20732 if (ast_strlen_zero(p->theirtag)) { 20733 char tag[128]; 20734 20735 gettag(req, "From", tag, sizeof(tag)); 20736 ast_string_field_set(p, theirtag, tag); 20737 } 20738 snprintf(p->lastmsg, sizeof(p->lastmsg), "Rx: %s", cmd); 20739 20740 if (pedanticsipchecking) { 20741 /* If this is a request packet without a from tag, it's not 20742 correct according to RFC 3261 */ 20743 /* Check if this a new request in a new dialog with a totag already attached to it, 20744 RFC 3261 - section 12.2 - and we don't want to mess with recovery */ 20745 if (!p->initreq.headers && req->has_to_tag) { 20746 /* If this is a first request and it got a to-tag, it is not for us */ 20747 if (!req->ignore && req->method == SIP_INVITE) { 20748 transmit_response_reliable(p, "481 Call/Transaction Does Not Exist", req); 20749 /* Will cease to exist after ACK */ 20750 } else if (req->method != SIP_ACK) { 20751 transmit_response(p, "481 Call/Transaction Does Not Exist", req); 20752 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 20753 } else { 20754 ast_debug(1, "Got ACK for unknown dialog... strange.\n"); 20755 } 20756 return res; 20757 } 20758 } 20759 20760 if (!e && (p->method == SIP_INVITE || p->method == SIP_SUBSCRIBE || p->method == SIP_REGISTER || p->method == SIP_NOTIFY)) { 20761 transmit_response(p, "400 Bad request", req); 20762 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 20763 return -1; 20764 } 20765 20766 /* Handle various incoming SIP methods in requests */ 20767 switch (p->method) { 20768 case SIP_OPTIONS: 20769 res = handle_request_options(p, req); 20770 break; 20771 case SIP_INVITE: 20772 res = handle_request_invite(p, req, debug, seqno, sin, recount, e, nounlock); 20773 break; 20774 case SIP_REFER: 20775 res = handle_request_refer(p, req, debug, seqno, nounlock); 20776 break; 20777 case SIP_CANCEL: 20778 res = handle_request_cancel(p, req); 20779 break; 20780 case SIP_BYE: 20781 res = handle_request_bye(p, req); 20782 break; 20783 case SIP_MESSAGE: 20784 res = handle_request_message(p, req); 20785 break; 20786 case SIP_SUBSCRIBE: 20787 res = handle_request_subscribe(p, req, sin, seqno, e); 20788 break; 20789 case SIP_REGISTER: 20790 res = handle_request_register(p, req, sin, e); 20791 break; 20792 case SIP_INFO: 20793 if (req->debug) 20794 ast_verbose("Receiving INFO!\n"); 20795 if (!req->ignore) 20796 handle_request_info(p, req); 20797 else /* if ignoring, transmit response */ 20798 transmit_response(p, "200 OK", req); 20799 break; 20800 case SIP_NOTIFY: 20801 res = handle_request_notify(p, req, sin, seqno, e); 20802 break; 20803 case SIP_ACK: 20804 /* Make sure we don't ignore this */ 20805 if (seqno == p->pendinginvite) { 20806 p->invitestate = INV_TERMINATED; 20807 p->pendinginvite = 0; 20808 acked = __sip_ack(p, seqno, 1 /* response */, 0); 20809 if (find_sdp(req)) { 20810 if (process_sdp(p, req, SDP_T38_NONE)) 20811 return -1; 20812 } 20813 check_pendings(p); 20814 } else if (p->glareinvite == seqno) { 20815 /* handle ack for the 491 pending sent for glareinvite */ 20816 p->glareinvite = 0; 20817 acked = __sip_ack(p, seqno, 1, 0); 20818 } 20819 if (!acked) { 20820 /* Got an ACK that did not match anything. Ignore 20821 * silently and restore previous method */ 20822 p->method = oldmethod; 20823 } 20824 if (!p->lastinvite && ast_strlen_zero(p->randdata)) 20825 p->needdestroy = 1; 20826 break; 20827 default: 20828 transmit_response_with_allow(p, "501 Method Not Implemented", req, 0); 20829 ast_log(LOG_NOTICE, "Unknown SIP command '%s' from '%s'\n", 20830 cmd, ast_inet_ntoa(p->sa.sin_addr)); 20831 /* If this is some new method, and we don't have a call, destroy it now */ 20832 if (!p->initreq.headers) 20833 p->needdestroy = 1; 20834 break; 20835 } 20836 return res; 20837 }
| 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 18321 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, 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().
18322 { 18323 int earlyreplace = 0; 18324 int oneleggedreplace = 0; /* Call with no bridge, propably IVR or voice message */ 18325 struct ast_channel *c = p->owner; /* Our incoming call */ 18326 struct ast_channel *replacecall = p->refer->refer_call->owner; /* The channel we're about to take over */ 18327 struct ast_channel *targetcall; /* The bridge to the take-over target */ 18328 18329 struct ast_channel *test; 18330 18331 /* Check if we're in ring state */ 18332 if (replacecall->_state == AST_STATE_RING) 18333 earlyreplace = 1; 18334 18335 /* Check if we have a bridge */ 18336 if (!(targetcall = ast_bridged_channel(replacecall))) { 18337 /* We have no bridge */ 18338 if (!earlyreplace) { 18339 ast_debug(2, " Attended transfer attempted to replace call with no bridge (maybe ringing). Channel %s!\n", replacecall->name); 18340 oneleggedreplace = 1; 18341 } 18342 } 18343 if (targetcall && targetcall->_state == AST_STATE_RINGING) 18344 ast_debug(4, "SIP transfer: Target channel is in ringing state\n"); 18345 18346 if (targetcall) 18347 ast_debug(4, "SIP transfer: Invite Replace incoming channel should bridge to channel %s while hanging up channel %s\n", targetcall->name, replacecall->name); 18348 else 18349 ast_debug(4, "SIP transfer: Invite Replace incoming channel should replace and hang up channel %s (one call leg)\n", replacecall->name); 18350 18351 if (req->ignore) { 18352 ast_log(LOG_NOTICE, "Ignoring this INVITE with replaces in a stupid way.\n"); 18353 /* We should answer something here. If we are here, the 18354 call we are replacing exists, so an accepted 18355 can't harm */ 18356 transmit_response_with_sdp(p, "200 OK", req, XMIT_RELIABLE, FALSE); 18357 /* Do something more clever here */ 18358 if (c) { 18359 *nounlock = 1; 18360 ast_channel_unlock(c); 18361 } 18362 ast_channel_unlock(replacecall); 18363 sip_pvt_unlock(p->refer->refer_call); 18364 return 1; 18365 } 18366 if (!c) { 18367 /* What to do if no channel ??? */ 18368 ast_log(LOG_ERROR, "Unable to create new channel. Invite/replace failed.\n"); 18369 transmit_response_reliable(p, "503 Service Unavailable", req); 18370 append_history(p, "Xfer", "INVITE/Replace Failed. No new channel."); 18371 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 18372 ast_channel_unlock(replacecall); 18373 sip_pvt_unlock(p->refer->refer_call); 18374 return 1; 18375 } 18376 append_history(p, "Xfer", "INVITE/Replace received"); 18377 /* We have three channels to play with 18378 channel c: New incoming call 18379 targetcall: Call from PBX to target 18380 p->refer->refer_call: SIP pvt dialog from transferer to pbx. 18381 replacecall: The owner of the previous 18382 We need to masq C into refer_call to connect to 18383 targetcall; 18384 If we are talking to internal audio stream, target call is null. 18385 */ 18386 18387 /* Fake call progress */ 18388 transmit_response(p, "100 Trying", req); 18389 ast_setstate(c, AST_STATE_RING); 18390 18391 /* Masquerade the new call into the referred call to connect to target call 18392 Targetcall is not touched by the masq */ 18393 18394 /* Answer the incoming call and set channel to UP state */ 18395 transmit_response_with_sdp(p, "200 OK", req, XMIT_RELIABLE, FALSE); 18396 18397 ast_setstate(c, AST_STATE_UP); 18398 18399 /* Stop music on hold and other generators */ 18400 ast_quiet_chan(replacecall); 18401 ast_quiet_chan(targetcall); 18402 ast_debug(4, "Invite/Replaces: preparing to masquerade %s into %s\n", c->name, replacecall->name); 18403 18404 /* Make sure that the masq does not free our PVT for the old call */ 18405 if (! earlyreplace && ! oneleggedreplace ) 18406 ast_set_flag(&p->refer->refer_call->flags[0], SIP_DEFER_BYE_ON_TRANSFER); /* Delay hangup */ 18407 18408 /* Prepare the masquerade - if this does not happen, we will be gone */ 18409 if(ast_channel_masquerade(replacecall, c)) 18410 ast_log(LOG_ERROR, "Failed to masquerade C into Replacecall\n"); 18411 else 18412 ast_debug(4, "Invite/Replaces: Going to masquerade %s into %s\n", c->name, replacecall->name); 18413 18414 /* C should now be in place of replacecall */ 18415 if (ast_do_masquerade(replacecall)) { 18416 ast_log(LOG_WARNING, "Failed to perform masquerade with INVITE replaces\n"); 18417 } 18418 18419 if (earlyreplace || oneleggedreplace ) { 18420 c->hangupcause = AST_CAUSE_SWITCH_CONGESTION; 18421 } 18422 18423 ast_setstate(c, AST_STATE_DOWN); 18424 ast_debug(4, "After transfer:----------------------------\n"); 18425 ast_debug(4, " -- C: %s State %s\n", c->name, ast_state2str(c->_state)); 18426 if (replacecall) 18427 ast_debug(4, " -- replacecall: %s State %s\n", replacecall->name, ast_state2str(replacecall->_state)); 18428 if (p->owner) { 18429 ast_debug(4, " -- P->owner: %s State %s\n", p->owner->name, ast_state2str(p->owner->_state)); 18430 test = ast_bridged_channel(p->owner); 18431 if (test) 18432 ast_debug(4, " -- Call bridged to P->owner: %s State %s\n", test->name, ast_state2str(test->_state)); 18433 else 18434 ast_debug(4, " -- No call bridged to C->owner \n"); 18435 } else 18436 ast_debug(4, " -- No channel yet \n"); 18437 ast_debug(4, "End After transfer:----------------------------\n"); 18438 18439 /* unlock sip pvt and owner so hangup can do its thing */ 18440 ast_channel_unlock(replacecall); 18441 ast_channel_unlock(c); 18442 sip_pvt_unlock(p->refer->refer_call); 18443 sip_pvt_unlock(p); 18444 *nounlock = 1; 18445 18446 /* The call should be down with no ast_channel, so hang it up */ 18447 c->tech_pvt = dialog_unref(c->tech_pvt, "unref dialog c->tech_pvt"); 18448 ast_hangup(c); 18449 sip_pvt_lock(p); /* lock PVT structure again after hangup */ 18450 18451 return 0; 18452 }
| static int handle_request_bye | ( | struct sip_pvt * | p, | |
| struct sip_request * | req | |||
| ) | [static] |
Handle incoming BYE request.
Definition at line 20090 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, cfsip_methods::text, transmit_response(), transmit_response_reliable(), sip_pvt::trtp, and sip_pvt::vrtp.
Referenced by handle_incoming().
20091 { 20092 struct ast_channel *c=NULL; 20093 int res; 20094 struct ast_channel *bridged_to; 20095 20096 /* If we have an INCOMING invite that we haven't answered, terminate that transaction */ 20097 if (p->pendinginvite && !ast_test_flag(&p->flags[0], SIP_OUTGOING) && !req->ignore) { 20098 transmit_response_reliable(p, "487 Request Terminated", &p->initreq); 20099 } 20100 20101 __sip_pretend_ack(p); 20102 20103 p->invitestate = INV_TERMINATED; 20104 20105 copy_request(&p->initreq, req); 20106 if (sipdebug) 20107 ast_debug(1, "Initializing initreq for method %s - callid %s\n", sip_methods[req->method].text, p->callid); 20108 check_via(p, req); 20109 sip_alreadygone(p); 20110 20111 /* Get RTCP quality before end of call */ 20112 if (p->do_history || p->owner) { 20113 struct ast_channel *bridge = p->owner ? ast_bridged_channel(p->owner) : NULL; 20114 char *videoqos, *textqos; 20115 20116 /* We need to get the lock on bridge because ast_rtp_set_vars will attempt 20117 * to lock the bridge. This may get hairy... 20118 */ 20119 while (bridge && ast_channel_trylock(bridge)) { 20120 ast_channel_unlock(p->owner); 20121 do { 20122 /* Can't use DEADLOCK_AVOIDANCE since p is an ao2 object */ 20123 sip_pvt_unlock(p); 20124 usleep(1); 20125 sip_pvt_lock(p); 20126 } while (p->owner && ast_channel_trylock(p->owner)); 20127 bridge = p->owner ? ast_bridged_channel(p->owner) : NULL; 20128 } 20129 20130 if (p->rtp) { 20131 if (p->do_history) { 20132 char *audioqos, 20133 *audioqos_jitter, 20134 *audioqos_loss, 20135 *audioqos_rtt; 20136 20137 audioqos = ast_rtp_get_quality(p->rtp, NULL, RTPQOS_SUMMARY); 20138 audioqos_jitter = ast_rtp_get_quality(p->rtp, NULL, RTPQOS_JITTER); 20139 audioqos_loss = ast_rtp_get_quality(p->rtp, NULL, RTPQOS_LOSS); 20140 audioqos_rtt = ast_rtp_get_quality(p->rtp, NULL, RTPQOS_RTT); 20141 20142 append_history(p, "RTCPaudio", "Quality:%s", audioqos); 20143 append_history(p, "RTCPaudioJitter", "Quality:%s", audioqos_jitter); 20144 append_history(p, "RTCPaudioLoss", "Quality:%s", audioqos_loss); 20145 append_history(p, "RTCPaudioRTT", "Quality:%s", audioqos_rtt); 20146 } 20147 20148 if (p->owner) { 20149 ast_rtp_set_vars(p->owner, p->rtp); 20150 } 20151 } 20152 20153 if (bridge) { 20154 struct sip_pvt *q = bridge->tech_pvt; 20155 20156 if (IS_SIP_TECH(bridge->tech) && q && q->rtp) 20157 ast_rtp_set_vars(bridge, q->rtp); 20158 ast_channel_unlock(bridge); 20159 } 20160 20161 if (p->vrtp) { 20162 videoqos = ast_rtp_get_quality(p->vrtp, NULL, RTPQOS_SUMMARY); 20163 if (p->do_history) 20164 append_history(p, "RTCPvideo", "Quality:%s", videoqos); 20165 if (p->owner) 20166 pbx_builtin_setvar_helper(p->owner, "RTPVIDEOQOS", videoqos); 20167 } 20168 20169 if (p->trtp) { 20170 textqos = ast_rtp_get_quality(p->trtp, NULL, RTPQOS_SUMMARY); 20171 if (p->do_history) 20172 append_history(p, "RTCPtext", "Quality:%s", textqos); 20173 if (p->owner) 20174 pbx_builtin_setvar_helper(p->owner, "RTPTEXTQOS", textqos); 20175 } 20176 } 20177 20178 stop_media_flows(p); /* Immediately stop RTP, VRTP and UDPTL as applicable */ 20179 stop_session_timer(p); /* Stop Session-Timer */ 20180 20181 if (!ast_strlen_zero(get_header(req, "Also"))) { 20182 ast_log(LOG_NOTICE, "Client '%s' using deprecated BYE/Also transfer method. Ask vendor to support REFER instead\n", 20183 ast_inet_ntoa(p->recv.sin_addr)); 20184 if (ast_strlen_zero(p->context)) 20185 ast_string_field_set(p, context, default_context); 20186 res = get_also_info(p, req); 20187 if (!res) { 20188 c = p->owner; 20189 if (c) { 20190 bridged_to = ast_bridged_channel(c); 20191 if (bridged_to) { 20192 /* Don't actually hangup here... */ 20193 ast_queue_control(c, AST_CONTROL_UNHOLD); 20194 ast_async_goto(bridged_to, p->context, p->refer->refer_to, 1); 20195 } else 20196 ast_queue_hangup(p->owner); 20197 } 20198 } else { 20199 ast_log(LOG_WARNING, "Invalid transfer information from '%s'\n", ast_inet_ntoa(p->recv.sin_addr)); 20200 if (p->owner) 20201 ast_queue_hangup_with_cause(p->owner, AST_CAUSE_PROTOCOL_ERROR); 20202 } 20203 } else if (p->owner) { 20204 ast_queue_hangup(p->owner); 20205 ast_debug(3, "Received bye, issuing owner hangup\n"); 20206 } else { 20207 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 20208 ast_debug(3, "Received bye, no owner, selfdestruct soon.\n"); 20209 } 20210 ast_clear_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED); 20211 transmit_response(p, "200 OK", req); 20212 20213 return 1; 20214 }
| static int handle_request_cancel | ( | struct sip_pvt * | p, | |
| struct sip_request * | req | |||
| ) | [static] |
Handle incoming CANCEL request.
Definition at line 19921 of file chan_sip.c.
References __sip_pretend_ack(), ast_channel::_state, ast_debug, ast_free, ast_queue_hangup(), AST_SCHED_DEL, AST_STATE_UP, ast_test_flag, check_via(), DEC_CALL_LIMIT, DEFAULT_TRANS_TIMEOUT, sip_pvt::flags, sip_pvt::initreq, INV_CANCELLED, INV_TERMINATED, sip_pvt::invitestate, sip_pvt::lastinvite, sip_request::len, sip_pkt::next, sip_pvt::owner, sip_pvt::packets, sip_pkt::response_code, sip_pkt::retransid, 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().
19922 { 19923 19924 check_via(p, req); 19925 sip_alreadygone(p); 19926 19927 /* At this point, we could have cancelled the invite at the same time 19928 as the other side sends a CANCEL. Our final reply with error code 19929 might not have been received by the other side before the CANCEL 19930 was sent, so let's just give up retransmissions and waiting for 19931 ACK on our error code. The call is hanging up any way. */ 19932 if (p->invitestate == INV_TERMINATED) 19933 __sip_pretend_ack(p); 19934 else 19935 p->invitestate = INV_CANCELLED; 19936 19937 if (p->owner && p->owner->_state == AST_STATE_UP) { 19938 /* This call is up, cancel is ignored, we need a bye */ 19939 transmit_response(p, "200 OK", req); 19940 ast_debug(1, "Got CANCEL on an answered call. Ignoring... \n"); 19941 return 0; 19942 } 19943 19944 if (ast_test_flag(&p->flags[0], SIP_INC_COUNT) || ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD)) 19945 update_call_counter(p, DEC_CALL_LIMIT); 19946 19947 stop_media_flows(p); /* Immediately stop RTP, VRTP and UDPTL as applicable */ 19948 if (p->owner) 19949 ast_queue_hangup(p->owner); 19950 else 19951 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 19952 if (p->initreq.len > 0) { 19953 struct sip_pkt *pkt, *prev_pkt; 19954 /* If the CANCEL we are receiving is a retransmission, and we already have scheduled 19955 * a reliable 487, then we don't want to schedule another one on top of the previous 19956 * one. 19957 * 19958 * As odd as this may sound, we can't rely on the previously-transmitted "reliable" 19959 * response in this situation. What if we've sent all of our reliable responses 19960 * already and now all of a sudden, we get this second CANCEL? 19961 * 19962 * The only way to do this correctly is to cancel our previously-scheduled reliably- 19963 * transmitted response and send a new one in its place. 19964 */ 19965 for (pkt = p->packets, prev_pkt = NULL; pkt; prev_pkt = pkt, pkt = pkt->next) { 19966 if (pkt->seqno == p->lastinvite && pkt->response_code == 487) { 19967 AST_SCHED_DEL(sched, pkt->retransid); 19968 UNLINK(pkt, p->packets, prev_pkt); 19969 ast_free(pkt); 19970 break; 19971 } 19972 } 19973 transmit_response_reliable(p, "487 Request Terminated", &p->initreq); 19974 transmit_response(p, "200 OK", req); 19975 return 1; 19976 } else { 19977 transmit_response(p, "481 Call Leg Does Not Exist", req); 19978 return 0; 19979 } 19980 }
| static int handle_request_do | ( | struct sip_request * | req, | |
| struct sockaddr_in * | sin | |||
| ) | [static] |
Definition at line 20979 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, 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, sip_request::rlPart1, sip_request::rlPart2, S_OR, 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().
20980 { 20981 struct sip_pvt *p; 20982 int recount = 0; 20983 int nounlock = 0; 20984 int lockretry; 20985 20986 if (sip_debug_test_addr(sin)) /* Set the debug flag early on packet level */ 20987 req->debug = 1; 20988 if (pedanticsipchecking) 20989 req->len = lws2sws(req->data->str, req->len); /* Fix multiline headers */ 20990 if (req->debug) { 20991 ast_verbose("\n<--- SIP read from %s://%s:%d --->\n%s\n<------------->\n", 20992 get_transport(req->socket.type), ast_inet_ntoa(sin->sin_addr), 20993 ntohs(sin->sin_port), req->data->str); 20994 } 20995 20996 if (parse_request(req) == -1) { /* Bad packet, can't parse */ 20997 ast_str_reset(req->data); /* nulling this out is NOT a good idea here. */ 20998 return 1; 20999 } 21000 req->method = find_sip_method(REQ_OFFSET_TO_STR(req, rlPart1)); 21001 21002 if (req->debug) 21003 ast_verbose("--- (%d headers %d lines)%s ---\n", req->headers, req->lines, (req->headers + req->lines == 0) ? " Nat keepalive" : ""); 21004 21005 if (req->headers < 2) { /* Must have at least two headers */ 21006 ast_str_reset(req->data); /* nulling this out is NOT a good idea here. */ 21007 return 1; 21008 } 21009 21010 /* Process request, with netlock held, and with usual deadlock avoidance */ 21011 for (lockretry = 10; lockretry > 0; lockretry--) { 21012 ast_mutex_lock(&netlock); 21013 21014 /* Find the active SIP dialog or create a new one */ 21015 p = find_call(req, sin, req->method); /* returns p locked */ 21016 if (p == NULL) { 21017 ast_debug(1, "Invalid SIP message - rejected , no callid, len %d\n", req->len); 21018 ast_mutex_unlock(&netlock); 21019 return 1; 21020 } 21021 21022 copy_socket_data(&p->socket, &req->socket); 21023 21024 /* Go ahead and lock the owner if it has one -- we may need it */ 21025 /* becaues this is deadlock-prone, we need to try and unlock if failed */ 21026 if (!p->owner || !ast_channel_trylock(p->owner)) 21027 break; /* locking succeeded */ 21028 21029 if (lockretry != 1) { 21030 sip_pvt_unlock(p); 21031 ao2_t_ref(p, -1, "release p (from find_call) inside lockretry loop"); /* we'll look for it again, but p is dead now */ 21032 ast_mutex_unlock(&netlock); 21033 /* Sleep for a very short amount of time */ 21034 usleep(1); 21035 } 21036 } 21037 p->recv = *sin; 21038 21039 if (p->do_history) /* This is a request or response, note what it was for */ 21040 append_history(p, "Rx", "%s / %s / %s", req->data->str, get_header(req, "CSeq"), REQ_OFFSET_TO_STR(req, rlPart2)); 21041 21042 if (!lockretry) { 21043 if (!queue_request(p, req)) { 21044 /* the request has been queued for later handling */ 21045 sip_pvt_unlock(p); 21046 ao2_t_ref(p, -1, "release p (from find_call) after queueing request"); 21047 ast_mutex_unlock(&netlock); 21048 return 1; 21049 } 21050 21051 if (p->owner) 21052 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 ??? - ")); 21053 ast_log(LOG_ERROR, "SIP transaction failed: %s \n", p->callid); 21054 if (req->method != SIP_ACK) 21055 transmit_response(p, "503 Server error", req); /* We must respond according to RFC 3261 sec 12.2 */ 21056 /* XXX We could add retry-after to make sure they come back */ 21057 append_history(p, "LockFail", "Owner lock failed, transaction failed."); 21058 sip_pvt_unlock(p); 21059 ao2_t_ref(p, -1, "release p (from find_call) at end of lockretry"); /* p is gone after the return */ 21060 ast_mutex_unlock(&netlock); 21061 return 1; 21062 } 21063 21064 /* if there are queued requests on this sip_pvt, process them first, so that everything is 21065 handled in order 21066 */ 21067 if (!AST_LIST_EMPTY(&p->request_queue)) { 21068 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")); 21069 process_request_queue(p, &recount, &nounlock); 21070 } 21071 21072 if (handle_incoming(p, req, sin, &recount, &nounlock) == -1) { 21073 /* Request failed */ 21074 ast_debug(1, "SIP message could not be handled, bad request: %-70.70s\n", p->callid[0] ? p->callid : "<no callid>"); 21075 } 21076 21077 if (recount) 21078 ast_update_use_count(); 21079 21080 if (p->owner && !nounlock) 21081 ast_channel_unlock(p->owner); 21082 sip_pvt_unlock(p); 21083 ast_mutex_unlock(&netlock); 21084 ao2_t_ref(p, -1, "throw away dialog ptr from find_call at end of routine"); /* p is gone after the return */ 21085 return 1; 21086 }
| static void handle_request_info | ( | struct sip_pvt * | p, | |
| struct sip_request * | req | |||
| ) | [static] |
Receive SIP INFO Message.
Definition at line 15777 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, sip_pvt::flags, get_body(), get_header(), get_msg_text(), ast_frame::len, LOG_WARNING, sip_pvt::owner, sip_scheddestroy(), SIP_USECLIENTCODE, ast_frame::subclass, transmit_response(), and TRUE.
Referenced by handle_incoming().
15778 { 15779 char buf[1024]; 15780 unsigned int event; 15781 const char *c = get_header(req, "Content-Type"); 15782 15783 /* Need to check the media/type */ 15784 if (!strcasecmp(c, "application/dtmf-relay") || 15785 !strcasecmp(c, "application/vnd.nortelnetworks.digits")) { 15786 unsigned int duration = 0; 15787 15788 if (!p->owner) { /* not a PBX call */ 15789 transmit_response(p, "481 Call leg/transaction does not exist", req); 15790 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 15791 return; 15792 } 15793 15794 /* Try getting the "signal=" part */ 15795 if (ast_strlen_zero(c = get_body(req, "Signal")) && ast_strlen_zero(c = get_body(req, "d"))) { 15796 ast_log(LOG_WARNING, "Unable to retrieve DTMF signal from INFO message from %s\n", p->callid); 15797 transmit_response(p, "200 OK", req); /* Should return error */ 15798 return; 15799 } else { 15800 ast_copy_string(buf, c, sizeof(buf)); 15801 } 15802 15803 if (!ast_strlen_zero((c = get_body(req, "Duration")))) 15804 duration = atoi(c); 15805 if (!duration) 15806 duration = 100; /* 100 ms */ 15807 15808 15809 if (ast_strlen_zero(buf)) { 15810 transmit_response(p, "200 OK", req); 15811 return; 15812 } 15813 15814 if (buf[0] == '*') 15815 event = 10; 15816 else if (buf[0] == '#') 15817 event = 11; 15818 else if ((buf[0] >= 'A') && (buf[0] <= 'D')) 15819 event = 12 + buf[0] - 'A'; 15820 else if (buf[0] == '!') 15821 event = 16; 15822 else 15823 event = atoi(buf); 15824 if (event == 16) { 15825 /* send a FLASH event */ 15826 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_FLASH, }; 15827 ast_queue_frame(p->owner, &f); 15828 if (sipdebug) 15829 ast_verbose("* DTMF-relay event received: FLASH\n"); 15830 } else { 15831 /* send a DTMF event */ 15832 struct ast_frame f = { AST_FRAME_DTMF, }; 15833 if (event < 10) { 15834 f.subclass = '0' + event; 15835 } else if (event < 11) { 15836 f.subclass = '*'; 15837 } else if (event < 12) { 15838 f.subclass = '#'; 15839 } else if (event < 16) { 15840 f.subclass = 'A' + (event - 12); 15841 } 15842 f.len = duration; 15843 ast_queue_frame(p->owner, &f); 15844 if (sipdebug) 15845 ast_verbose("* DTMF-relay event received: %c\n", f.subclass); 15846 } 15847 transmit_response(p, "200 OK", req); 15848 return; 15849 } else if (!strcasecmp(c, "application/dtmf")) { 15850 /*! \todo Note: Doesn't read the duration of the DTMF. Should be fixed. */ 15851 unsigned int duration = 0; 15852 15853 if (!p->owner) { /* not a PBX call */ 15854 transmit_response(p, "481 Call leg/transaction does not exist", req); 15855 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 15856 return; 15857 } 15858 15859 get_msg_text(buf, sizeof(buf), req, TRUE); 15860 duration = 100; /* 100 ms */ 15861 15862 if (ast_strlen_zero(buf)) { 15863 transmit_response(p, "200 OK", req); 15864 return; 15865 } 15866 event = atoi(buf); 15867 if (event == 16) { 15868 /* send a FLASH event */ 15869 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_FLASH, }; 15870 ast_queue_frame(p->owner, &f); 15871 if (sipdebug) 15872 ast_verbose("* DTMF-relay event received: FLASH\n"); 15873 } else { 15874 /* send a DTMF event */ 15875 struct ast_frame f = { AST_FRAME_DTMF, }; 15876 if (event < 10) { 15877 f.subclass = '0' + event; 15878 } else if (event < 11) { 15879 f.subclass = '*'; 15880 } else if (event < 12) { 15881 f.subclass = '#'; 15882 } else if (event < 16) { 15883 f.subclass = 'A' + (event - 12); 15884 } 15885 f.len = duration; 15886 ast_queue_frame(p->owner, &f); 15887 if (sipdebug) 15888 ast_verbose("* DTMF-relay event received: %c\n", f.subclass); 15889 } 15890 transmit_response(p, "200 OK", req); 15891 return; 15892 15893 } else if (!strcasecmp(c, "application/media_control+xml")) { 15894 /* Eh, we'll just assume it's a fast picture update for now */ 15895 if (p->owner) 15896 ast_queue_control(p->owner, AST_CONTROL_VIDUPDATE); 15897 transmit_response(p, "200 OK", req); 15898 return; 15899 } else if (!ast_strlen_zero(c = get_header(req, "X-ClientCode"))) { 15900 /* Client code (from SNOM phone) */ 15901 if (ast_test_flag(&p->flags[0], SIP_USECLIENTCODE)) { 15902 if (p->owner && p->owner->cdr) 15903 ast_cdr_setuserfield(p->owner, c); 15904 if (p->owner && ast_bridged_channel(p->owner) && ast_bridged_channel(p->owner)->cdr) 15905 ast_cdr_setuserfield(ast_bridged_channel(p->owner), c); 15906 transmit_response(p, "200 OK", req); 15907 } else { 15908 transmit_response(p, "403 Forbidden", req); 15909 } 15910 return; 15911 } else if (!ast_strlen_zero(c = get_header(req, "Record"))) { 15912 /* INFO messages generated by some phones to start/stop recording 15913 on phone calls. 15914 OEJ: I think this should be something that is enabled/disabled 15915 per device. I don't want incoming callers to record calls in my 15916 pbx. 15917 */ 15918 /* first, get the feature string, if it exists */ 15919 struct ast_call_feature *feat; 15920 int j; 15921 struct ast_frame f = { AST_FRAME_DTMF, }; 15922 15923 ast_rdlock_call_features(); 15924 feat = ast_find_call_feature("automon"); 15925 if (!feat || ast_strlen_zero(feat->exten)) { 15926 ast_log(LOG_WARNING, "Recording requested, but no One Touch Monitor registered. (See features.conf)\n"); 15927 /* 403 means that we don't support this feature, so don't request it again */ 15928 transmit_response(p, "403 Forbidden", req); 15929 ast_unlock_call_features(); 15930 return; 15931 } 15932 /* Send the feature code to the PBX as DTMF, just like the handset had sent it */ 15933 f.len = 100; 15934 for (j=0; j < strlen(feat->exten); j++) { 15935 f.subclass = feat->exten[j]; 15936 ast_queue_frame(p->owner, &f); 15937 if (sipdebug) 15938 ast_verbose("* DTMF-relay event faked: %c\n", f.subclass); 15939 } 15940 ast_unlock_call_features(); 15941 15942 ast_debug(1, "Got a Request to Record the channel, state %s\n", c); 15943 transmit_response(p, "200 OK", req); 15944 return; 15945 } else if (ast_strlen_zero(c = get_header(req, "Content-Length")) || !strcasecmp(c, "0")) { 15946 /* This is probably just a packet making sure the signalling is still up, just send back a 200 OK */ 15947 transmit_response(p, "200 OK", req); 15948 return; 15949 } 15950 15951 /* Other type of INFO message, not really understood by Asterisk */ 15952 /* if (get_msg_text(buf, sizeof(buf), req)) { */ 15953 15954 ast_log(LOG_WARNING, "Unable to parse INFO message from %s. Content %s\n", p->callid, buf); 15955 transmit_response(p, "415 Unsupported media type", req); 15956 return; 15957 }
| 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 18757 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_set_constantssrc(), 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, bindaddr, build_contact(), build_route(), 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, sip_pvt::jointcapability, sip_pvt::lastinvite, LOG_ERROR, LOG_NOTICE, LOG_WARNING, make_our_tag(), sip_request::method, msg, 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_request::rlPart2, sip_pvt::rtp, S_OR, 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_CONSTANT_SSRC, 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, cfsip_methods::text, transmit_fake_auth_response(), transmit_provisional_response(), transmit_response(), transmit_response_reliable(), transmit_response_with_minse(), transmit_response_with_sdp(), transmit_response_with_t38_sdp(), transmit_response_with_unsupported(), TRUE, sip_pvt::udptl, update_call_counter(), sip_pvt::username, sip_pvt::vrtp, XMIT_CRITICAL, XMIT_RELIABLE, and XMIT_UNRELIABLE.
Referenced by handle_incoming().
18758 { 18759 int res = 1; 18760 int gotdest; 18761 const char *p_replaces; 18762 char *replace_id = NULL; 18763 int refer_locked = 0; 18764 const char *required; 18765 unsigned int required_profile = 0; 18766 struct ast_channel *c = NULL; /* New channel */ 18767 int reinvite = 0; 18768 int rtn; 18769 18770 const char *p_uac_se_hdr; /* UAC's Session-Expires header string */ 18771 const char *p_uac_min_se; /* UAC's requested Min-SE interval (char string) */ 18772 int uac_max_se = -1; /* UAC's Session-Expires in integer format */ 18773 int uac_min_se = -1; /* UAC's Min-SE in integer format */ 18774 int st_active = FALSE; /* Session-Timer on/off boolean */ 18775 int st_interval = 0; /* Session-Timer negotiated refresh interval */ 18776 enum st_refresher st_ref; /* Session-Timer session refresher */ 18777 int dlg_min_se = -1; 18778 st_ref = SESSION_TIMER_REFRESHER_AUTO; 18779 18780 /* Find out what they support */ 18781 if (!p->sipoptions) { 18782 const char *supported = get_header(req, "Supported"); 18783 if (!ast_strlen_zero(supported)) 18784 parse_sip_options(p, supported); 18785 } 18786 18787 /* Find out what they require */ 18788 required = get_header(req, "Require"); 18789 if (!ast_strlen_zero(required)) { 18790 required_profile = parse_sip_options(NULL, required); 18791 if (required_profile && !(required_profile & (SIP_OPT_REPLACES | SIP_OPT_TIMER))) { 18792 /* At this point we only support REPLACES and Session-Timer */ 18793 transmit_response_with_unsupported(p, "420 Bad extension (unsupported)", req, required); 18794 ast_log(LOG_WARNING, "Received SIP INVITE with unsupported required extension: %s\n", required); 18795 p->invitestate = INV_COMPLETED; 18796 if (!p->lastinvite) 18797 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 18798 res = -1; 18799 goto request_invite_cleanup; 18800 } 18801 } 18802 18803 /* The option tags may be present in Supported: or Require: headers. 18804 Include the Require: option tags for further processing as well */ 18805 p->sipoptions |= required_profile; 18806 p->reqsipoptions = required_profile; 18807 18808 /* Check if this is a loop */ 18809 if (ast_test_flag(&p->flags[0], SIP_OUTGOING) && p->owner && (p->invitestate != INV_TERMINATED && p->invitestate != INV_CONFIRMED)) { 18810 /* This is a call to ourself. Send ourselves an error code and stop 18811 processing immediately, as SIP really has no good mechanism for 18812 being able to call yourself */ 18813 /* If pedantic is on, we need to check the tags. If they're different, this is 18814 in fact a forked call through a SIP proxy somewhere. */ 18815 int different; 18816 char *initial_rlPart2 = REQ_OFFSET_TO_STR(&p->initreq, rlPart2); 18817 char *this_rlPart2 = REQ_OFFSET_TO_STR(req, rlPart2); 18818 if (pedanticsipchecking) 18819 different = sip_uri_cmp(initial_rlPart2, this_rlPart2); 18820 else 18821 different = strcmp(initial_rlPart2, this_rlPart2); 18822 if (!different) { 18823 transmit_response(p, "482 Loop Detected", req); 18824 p->invitestate = INV_COMPLETED; 18825 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 18826 res = 0; 18827 goto request_invite_cleanup; 18828 } else { 18829 /*! This is a spiral. What we need to do is to just change the outgoing INVITE 18830 * so that it now routes to the new Request URI. Since we created the INVITE ourselves 18831 * that should be all we need to do. 18832 * 18833 * \todo XXX This needs to be reviewed. YOu don't change the request URI really, you route the packet 18834 * correctly instead... 18835 */ 18836 char *uri = ast_strdupa(this_rlPart2); 18837 char *at = strchr(uri, '@'); 18838 char *peerorhost; 18839 ast_debug(2, "Potential spiral detected. Original RURI was %s, new RURI is %s\n", initial_rlPart2, this_rlPart2); 18840 transmit_response(p, "100 Trying", req); 18841 if (at) { 18842 *at = '\0'; 18843 } 18844 /* Parse out "sip:" */ 18845 if ((peerorhost = strchr(uri, ':'))) { 18846 *peerorhost++ = '\0'; 18847 } 18848 ast_string_field_set(p, theirtag, NULL); 18849 /* Treat this as if there were a call forward instead... 18850 */ 18851 ast_string_field_set(p->owner, call_forward, peerorhost); 18852 ast_queue_control(p->owner, AST_CONTROL_BUSY); 18853 res = 0; 18854 goto request_invite_cleanup; 18855 } 18856 } 18857 18858 if (!req->ignore && p->pendinginvite) { 18859 if (!ast_test_flag(&p->flags[0], SIP_OUTGOING) && (p->invitestate == INV_COMPLETED || p->invitestate == INV_TERMINATED)) { 18860 /* What do these circumstances mean? We have received an INVITE for an "incoming" dialog for which we 18861 * have sent a final response. We have not yet received an ACK, though (which is why p->pendinginvite is non-zero). 18862 * We also know that the INVITE is not a retransmission, because otherwise the "ignore" flag would be set. 18863 * This means that either we are receiving a reinvite for a terminated dialog, or we are receiving an INVITE with 18864 * credentials based on one we challenged earlier. 18865 * 18866 * The action to take in either case is to treat the INVITE as though it contains an implicit ACK for the previous 18867 * transaction. Calling __sip_ack will take care of this by clearing the p->pendinginvite and removing the response 18868 * from the previous transaction from the list of outstanding packets. 18869 */ 18870 __sip_ack(p, p->pendinginvite, 1, 0); 18871 } else { 18872 /* We already have a pending invite. Sorry. You are on hold. */ 18873 p->glareinvite = seqno; 18874 if (p->rtp && find_sdp(req)) { 18875 struct sockaddr_in sin; 18876 if (get_ip_and_port_from_sdp(req, SDP_AUDIO, &sin)) { 18877 ast_log(LOG_WARNING, "Failed to set an alternate media source on glared reinvite. Audio may not work properly on this call.\n"); 18878 } else { 18879 ast_rtp_set_alt_peer(p->rtp, &sin); 18880 } 18881 if (p->vrtp) { 18882 if (get_ip_and_port_from_sdp(req, SDP_VIDEO, &sin)) { 18883 ast_log(LOG_WARNING, "Failed to set an alternate media source on glared reinvite. Video may not work properly on this call.\n"); 18884 } else { 18885 ast_rtp_set_alt_peer(p->vrtp, &sin); 18886 } 18887 } 18888 } 18889 transmit_response_reliable(p, "491 Request Pending", req); 18890 ast_debug(1, "Got INVITE on call where we already have pending INVITE, deferring that - %s\n", p->callid); 18891 /* Don't destroy dialog here */ 18892 res = 0; 18893 goto request_invite_cleanup; 18894 } 18895 } 18896 18897 p_replaces = get_header(req, "Replaces"); 18898 if (!ast_strlen_zero(p_replaces)) { 18899 /* We have a replaces header */ 18900 char *ptr; 18901 char *fromtag = NULL; 18902 char *totag = NULL; 18903 char *start, *to; 18904 int error = 0; 18905 18906 if (p->owner) { 18907 ast_debug(3, "INVITE w Replaces on existing call? Refusing action. [%s]\n", p->callid); 18908 transmit_response_reliable(p, "400 Bad request", req); /* The best way to not not accept the transfer */ 18909 /* Do not destroy existing call */ 18910 res = -1; 18911 goto request_invite_cleanup; 18912 } 18913 18914 if (sipdebug) 18915 ast_debug(3, "INVITE part of call transfer. Replaces [%s]\n", p_replaces); 18916 /* Create a buffer we can manipulate */ 18917 replace_id = ast_strdupa(p_replaces); 18918 ast_uri_decode(replace_id); 18919 18920 if (!p->refer && !sip_refer_allocate(p)) { 18921 transmit_response_reliable(p, "500 Server Internal Error", req); 18922 append_history(p, "Xfer", "INVITE/Replace Failed. Out of memory."); 18923 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 18924 p->invitestate = INV_COMPLETED; 18925 res = -1; 18926 goto request_invite_cleanup; 18927 } 18928 18929 /* Todo: (When we find phones that support this) 18930 if the replaces header contains ";early-only" 18931 we can only replace the call in early 18932 stage, not after it's up. 18933 18934 If it's not in early mode, 486 Busy. 18935 */ 18936 18937 /* Skip leading whitespace */ 18938 replace_id = ast_skip_blanks(replace_id); 18939 18940 start = replace_id; 18941 while ( (ptr = strsep(&start, ";")) ) { 18942 ptr = ast_skip_blanks(ptr); /* XXX maybe unnecessary ? */ 18943 if ( (to = strcasestr(ptr, "to-tag=") ) ) 18944 totag = to + 7; /* skip the keyword */ 18945 else if ( (to = strcasestr(ptr, "from-tag=") ) ) { 18946 fromtag = to + 9; /* skip the keyword */ 18947 fromtag = strsep(&fromtag, "&"); /* trim what ? */ 18948 } 18949 } 18950 18951 if (sipdebug) 18952 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>"); 18953 18954 18955 /* Try to find call that we are replacing 18956 If we have a Replaces header, we need to cancel that call if we succeed with this call 18957 */ 18958 if ((p->refer->refer_call = get_sip_pvt_byid_locked(replace_id, totag, fromtag)) == NULL) { 18959 ast_log(LOG_NOTICE, "Supervised transfer attempted to replace non-existent call id (%s)!\n", replace_id); 18960 transmit_response_reliable(p, "481 Call Leg Does Not Exist (Replaces)", req); 18961 error = 1; 18962 } else { 18963 refer_locked = 1; 18964 } 18965 18966 /* At this point, bot the pvt and the owner of the call to be replaced is locked */ 18967 18968 /* The matched call is the call from the transferer to Asterisk . 18969 We want to bridge the bridged part of the call to the 18970 incoming invite, thus taking over the refered call */ 18971 18972 if (p->refer->refer_call == p) { 18973 ast_log(LOG_NOTICE, "INVITE with replaces into it's own call id (%s == %s)!\n", replace_id, p->callid); 18974 p->refer->refer_call = dialog_unref(p->refer->refer_call, "unref dialog p->refer->refer_call"); 18975 transmit_response_reliable(p, "400 Bad request", req); /* The best way to not not accept the transfer */ 18976 error = 1; 18977 } 18978 18979 if (!error && !p->refer->refer_call->owner) { 18980 /* Oops, someting wrong anyway, no owner, no call */ 18981 ast_log(LOG_NOTICE, "Supervised transfer attempted to replace non-existing call id (%s)!\n", replace_id); 18982 /* Check for better return code */ 18983 transmit_response_reliable(p, "481 Call Leg Does Not Exist (Replace)", req); 18984 error = 1; 18985 } 18986 18987 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 ) { 18988 ast_log(LOG_NOTICE, "Supervised transfer attempted to replace non-ringing or active call id (%s)!\n", replace_id); 18989 transmit_response_reliable(p, "603 Declined (Replaces)", req); 18990 error = 1; 18991 } 18992 18993 if (error) { /* Give up this dialog */ 18994 append_history(p, "Xfer", "INVITE/Replace Failed."); 18995 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 18996 sip_pvt_unlock(p); 18997 if (p->refer->refer_call) { 18998 sip_pvt_unlock(p->refer->refer_call); 18999 if (p->refer->refer_call->owner) { 19000 ast_channel_unlock(p->refer->refer_call->owner); 19001 } 19002 } 19003 refer_locked = 0; 19004 p->invitestate = INV_COMPLETED; 19005 res = -1; 19006 goto request_invite_cleanup; 19007 } 19008 } 19009 19010 /* Check if this is an INVITE that sets up a new dialog or 19011 a re-invite in an existing dialog */ 19012 19013 if (!req->ignore) { 19014 int newcall = (p->initreq.headers ? TRUE : FALSE); 19015 19016 if (sip_cancel_destroy(p)) 19017 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 19018 /* This also counts as a pending invite */ 19019 p->pendinginvite = seqno; 19020 check_via(p, req); 19021 19022 copy_request(&p->initreq, req); /* Save this INVITE as the transaction basis */ 19023 if (sipdebug) 19024 ast_debug(1, "Initializing initreq for method %s - callid %s\n", sip_methods[req->method].text, p->callid); 19025 if (!p->owner) { /* Not a re-invite */ 19026 if (debug) 19027 ast_verbose("Using INVITE request as basis request - %s\n", p->callid); 19028 if (newcall) 19029 append_history(p, "Invite", "New call: %s", p->callid); 19030 parse_ok_contact(p, req); 19031 } else { /* Re-invite on existing call */ 19032 ast_clear_flag(&p->flags[0], SIP_OUTGOING); /* This is now an inbound dialog */ 19033 /* Handle SDP here if we already have an owner */ 19034 if (find_sdp(req)) { 19035 if (process_sdp(p, req, SDP_T38_INITIATE)) { 19036 transmit_response_reliable(p, "488 Not acceptable here", req); 19037 if (!p->lastinvite) 19038 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 19039 res = -1; 19040 goto request_invite_cleanup; 19041 } 19042 ast_queue_control(p->owner, AST_CONTROL_SRCUPDATE); 19043 } else { 19044 p->jointcapability = p->capability; 19045 ast_debug(1, "Hm.... No sdp for the moment\n"); 19046 } 19047 if (p->do_history) /* This is a response, note what it was for */ 19048 append_history(p, "ReInv", "Re-invite received"); 19049 } 19050 } else if (debug) 19051 ast_verbose("Ignoring this INVITE request\n"); 19052 19053 19054 if (!p->lastinvite && !req->ignore && !p->owner) { 19055 /* This is a new invite */ 19056 /* Handle authentication if this is our first invite */ 19057 res = check_user(p, req, SIP_INVITE, e, XMIT_RELIABLE, sin); 19058 if (res == AUTH_CHALLENGE_SENT) { 19059 p->invitestate = INV_COMPLETED; /* Needs to restart in another INVITE transaction */ 19060 res = 0; 19061 goto request_invite_cleanup; 19062 } 19063 if (res < 0) { /* Something failed in authentication */ 19064 if (res == AUTH_FAKE_AUTH) { 19065 ast_log(LOG_NOTICE, "Sending fake auth rejection for device %s\n", get_header(req, "From")); 19066 transmit_fake_auth_response(p, SIP_INVITE, req, XMIT_RELIABLE); 19067 } else { 19068 ast_log(LOG_NOTICE, "Failed to authenticate device %s\n", get_header(req, "From")); 19069 transmit_response_reliable(p, "403 Forbidden", req); 19070 } 19071 p->invitestate = INV_COMPLETED; 19072 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 19073 ast_string_field_set(p, theirtag, NULL); 19074 res = 0; 19075 goto request_invite_cleanup; 19076 } 19077 19078 /* If T38 is needed but not present, then make it magically appear */ 19079 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))) { 19080 p->t38_maxdatagram = global_t38_maxdatagram; 19081 set_t38_capabilities(p); 19082 } 19083 19084 /* We have a succesful authentication, process the SDP portion if there is one */ 19085 if (find_sdp(req)) { 19086 if (process_sdp(p, req, SDP_T38_INITIATE)) { 19087 /* Unacceptable codecs */ 19088 transmit_response_reliable(p, "488 Not acceptable here", req); 19089 p->invitestate = INV_COMPLETED; 19090 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 19091 ast_debug(1, "No compatible codecs for this SIP call.\n"); 19092 res = -1; 19093 goto request_invite_cleanup; 19094 } 19095 if (ast_test_flag(&p->flags[1], SIP_PAGE2_CONSTANT_SSRC)) { 19096 if (p->rtp) { 19097 ast_rtp_set_constantssrc(p->rtp); 19098 } 19099 if (p->vrtp) { 19100 ast_rtp_set_constantssrc(p->vrtp); 19101 } 19102 } 19103 } else { /* No SDP in invite, call control session */ 19104 p->jointcapability = p->capability; 19105 ast_debug(2, "No SDP in Invite, third party call control\n"); 19106 } 19107 19108 /* Queue NULL frame to prod ast_rtp_bridge if appropriate */ 19109 /* This seems redundant ... see !p-owner above */ 19110 if (p->owner) 19111 ast_queue_frame(p->owner, &ast_null_frame); 19112 19113 19114 /* Initialize the context if it hasn't been already */ 19115 if (ast_strlen_zero(p->context)) 19116 ast_string_field_set(p, context, default_context); 19117 19118 19119 /* Check number of concurrent calls -vs- incoming limit HERE */ 19120 ast_debug(1, "Checking SIP call limits for device %s\n", p->username); 19121 if ((res = update_call_counter(p, INC_CALL_LIMIT))) { 19122 if (res < 0) { 19123 ast_log(LOG_NOTICE, "Failed to place call for device %s, too many calls\n", p->username); 19124 transmit_response_reliable(p, "480 Temporarily Unavailable (Call limit) ", req); 19125 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 19126 p->invitestate = INV_COMPLETED; 19127 } 19128 res = 0; 19129 goto request_invite_cleanup; 19130 } 19131 gotdest = get_destination(p, NULL); /* Get destination right away */ 19132 get_rdnis(p, NULL); /* Get redirect information */ 19133 extract_uri(p, req); /* Get the Contact URI */ 19134 build_contact(p); /* Build our contact header */ 19135 19136 if (p->rtp) { 19137 ast_rtp_setdtmf(p->rtp, ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833); 19138 ast_rtp_setdtmfcompensate(p->rtp, ast_test_flag(&p->flags[1], SIP_PAGE2_RFC2833_COMPENSATE)); 19139 } 19140 19141 if (!replace_id && gotdest) { /* No matching extension found */ 19142 if (gotdest == 1 && ast_test_flag(&p->flags[1], SIP_PAGE2_ALLOWOVERLAP)) 19143 transmit_response_reliable(p, "484 Address Incomplete", req); 19144 else { 19145 char *decoded_exten = ast_strdupa(p->exten); 19146 19147 transmit_response_reliable(p, "404 Not Found", req); 19148 ast_uri_decode(decoded_exten); 19149 ast_log(LOG_NOTICE, "Call from '%s' to extension" 19150 " '%s' rejected because extension not found.\n", 19151 S_OR(p->username, p->peername), decoded_exten); 19152 } 19153 p->invitestate = INV_COMPLETED; 19154 update_call_counter(p, DEC_CALL_LIMIT); 19155 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 19156 res = 0; 19157 goto request_invite_cleanup; 19158 } else { 19159 19160 /* If no extension was specified, use the s one */ 19161 /* Basically for calling to IP/Host name only */ 19162 if (ast_strlen_zero(p->exten)) 19163 ast_string_field_set(p, exten, "s"); 19164 /* Initialize our tag */ 19165 19166 make_our_tag(p->tag, sizeof(p->tag)); 19167 /* First invitation - create the channel */ 19168 c = sip_new(p, AST_STATE_DOWN, S_OR(p->peername, NULL)); 19169 *recount = 1; 19170 19171 /* Save Record-Route for any later requests we make on this dialogue */ 19172 build_route(p, req, 0); 19173 19174 if (c) { 19175 /* Pre-lock the call */ 19176 ast_channel_lock(c); 19177 } 19178 } 19179 } else { 19180 if (sipdebug) { 19181 if (!req->ignore) 19182 ast_debug(2, "Got a SIP re-invite for call %s\n", p->callid); 19183 else 19184 ast_debug(2, "Got a SIP re-transmit of INVITE for call %s\n", p->callid); 19185 } 19186 if (!req->ignore) 19187 reinvite = 1; 19188 c = p->owner; 19189 } 19190 19191 /* Session-Timers */ 19192 if (p->sipoptions & SIP_OPT_TIMER) { 19193 /* The UAC has requested session-timers for this session. Negotiate 19194 the session refresh interval and who will be the refresher */ 19195 ast_debug(2, "Incoming INVITE with 'timer' option enabled\n"); 19196 19197 /* Allocate Session-Timers struct w/in the dialog */ 19198 if (!p->stimer) 19199 sip_st_alloc(p); 19200 19201 /* Parse the Session-Expires header */ 19202 p_uac_se_hdr = get_header(req, "Session-Expires"); 19203 if (!ast_strlen_zero(p_uac_se_hdr)) { 19204 rtn = parse_session_expires(p_uac_se_hdr, &uac_max_se, &st_ref); 19205 if (rtn != 0) { 19206 transmit_response_reliable(p, "400 Session-Expires Invalid Syntax", req); 19207 p->invitestate = INV_COMPLETED; 19208 if (!p->lastinvite) { 19209 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 19210 } 19211 res = -1; 19212 goto request_invite_cleanup; 19213 } 19214 } 19215 19216 /* Parse the Min-SE header */ 19217 p_uac_min_se = get_header(req, "Min-SE"); 19218 if (!ast_strlen_zero(p_uac_min_se)) { 19219 rtn = parse_minse(p_uac_min_se, &uac_min_se); 19220 if (rtn != 0) { 19221 transmit_response_reliable(p, "400 Min-SE Invalid Syntax", req); 19222 p->invitestate = INV_COMPLETED; 19223 if (!p->lastinvite) { 19224 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 19225 } 19226 res = -1; 19227 goto request_invite_cleanup; 19228 } 19229 } 19230 19231 dlg_min_se = st_get_se(p, FALSE); 19232 switch (st_get_mode(p)) { 19233 case SESSION_TIMER_MODE_ACCEPT: 19234 case SESSION_TIMER_MODE_ORIGINATE: 19235 if (uac_max_se > 0 && uac_max_se < dlg_min_se) { 19236 transmit_response_with_minse(p, "422 Session Interval Too Small", req, dlg_min_se); 19237 p->invitestate = INV_COMPLETED; 19238 if (!p->lastinvite) { 19239 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 19240 } 19241 res = -1; 19242 goto request_invite_cleanup; 19243 } 19244 19245 p->stimer->st_active_peer_ua = TRUE; 19246 st_active = TRUE; 19247 if (st_ref == SESSION_TIMER_REFRESHER_AUTO) { 19248 st_ref = st_get_refresher(p); 19249 } 19250 19251 if (uac_max_se > 0) { 19252 int dlg_max_se = st_get_se(p, TRUE); 19253 if (dlg_max_se >= uac_min_se) { 19254 st_interval = (uac_max_se < dlg_max_se) ? uac_max_se : dlg_max_se; 19255 } else { 19256 st_interval = uac_max_se; 19257 } 19258 } else { 19259 /* Set to default max value */ 19260 st_interval = global_max_se; 19261 } 19262 break; 19263 19264 case SESSION_TIMER_MODE_REFUSE: 19265 if (p->reqsipoptions & SIP_OPT_TIMER) { 19266 transmit_response_with_unsupported(p, "420 Option Disabled", req, required); 19267 ast_log(LOG_WARNING, "Received SIP INVITE with supported but disabled option: %s\n", required); 19268 p->invitestate = INV_COMPLETED; 19269 if (!p->lastinvite) { 19270 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 19271 } 19272 res = -1; 19273 goto request_invite_cleanup; 19274 } 19275 break; 19276 19277 default: 19278 ast_log(LOG_ERROR, "Internal Error %d at %s:%d\n", st_get_mode(p), __FILE__, __LINE__); 19279 break; 19280 } 19281 } else { 19282 /* The UAC did not request session-timers. Asterisk (UAS), will now decide 19283 (based on session-timer-mode in sip.conf) whether to run session-timers for 19284 this session or not. */ 19285 switch (st_get_mode(p)) { 19286 case SESSION_TIMER_MODE_ORIGINATE: 19287 st_active = TRUE; 19288 st_interval = st_get_se(p, TRUE); 19289 st_ref = SESSION_TIMER_REFRESHER_UAS; 19290 p->stimer->st_active_peer_ua = FALSE; 19291 break; 19292 19293 default: 19294 break; 19295 } 19296 } 19297 19298 if (reinvite == 0) { 19299 /* Session-Timers: Start session refresh timer based on negotiation/config */ 19300 if (st_active == TRUE) { 19301 p->stimer->st_active = TRUE; 19302 p->stimer->st_interval = st_interval; 19303 p->stimer->st_ref = st_ref; 19304 start_session_timer(p); 19305 } 19306 } else { 19307 if (p->stimer->st_active == TRUE) { 19308 /* Session-Timers: A re-invite request sent within a dialog will serve as 19309 a refresh request, no matter whether the re-invite was sent for refreshing 19310 the session or modifying it.*/ 19311 ast_debug (2, "Restarting session-timers on a refresh - %s\n", p->callid); 19312 19313 /* The UAC may be adjusting the session-timers mid-session */ 19314 if (st_interval > 0) { 19315 p->stimer->st_interval = st_interval; 19316 p->stimer->st_ref = st_ref; 19317 } 19318 19319 restart_session_timer(p); 19320 if (p->stimer->st_expirys > 0) { 19321 p->stimer->st_expirys--; 19322 } 19323 } 19324 } 19325 19326 if (!req->ignore && p) 19327 p->lastinvite = seqno; 19328 19329 if (replace_id) { /* Attended transfer or call pickup - we're the target */ 19330 /* Go and take over the target call */ 19331 if (sipdebug) 19332 ast_debug(4, "Sending this call to the invite/replcaes handler %s\n", p->callid); 19333 res = handle_invite_replaces(p, req, debug, seqno, sin, nounlock); 19334 refer_locked = 0; 19335 goto request_invite_cleanup; 19336 19337 } 19338 19339 19340 if (c) { /* We have a call -either a new call or an old one (RE-INVITE) */ 19341 enum ast_channel_state c_state = c->_state; 19342 19343 if (c_state != AST_STATE_UP && reinvite && 19344 (p->invitestate == INV_TERMINATED || p->invitestate == INV_CONFIRMED)) { 19345 /* If these conditions are true, and the channel is still in the 'ringing' 19346 * state, then this likely means that we have a situation where the initial 19347 * INVITE transaction has completed *but* the channel's state has not yet been 19348 * changed to UP. The reason this could happen is if the reinvite is received 19349 * on the SIP socket prior to an application calling ast_read on this channel 19350 * to read the answer frame we earlier queued on it. In this case, the reinvite 19351 * is completely legitimate so we need to handle this the same as if the channel 19352 * were already UP. Thus we are purposely falling through to the AST_STATE_UP case. 19353 */ 19354 c_state = AST_STATE_UP; 19355 } 19356 19357 switch(c_state) { 19358 case AST_STATE_DOWN: 19359 ast_debug(2, "%s: New call is still down.... Trying... \n", c->name); 19360 transmit_provisional_response(p, "100 Trying", req, 0); 19361 p->invitestate = INV_PROCEEDING; 19362 ast_setstate(c, AST_STATE_RING); 19363 if (strcmp(p->exten, ast_pickup_ext())) { /* Call to extension -start pbx on this call */ 19364 enum ast_pbx_result result; 19365 19366 result = ast_pbx_start(c); 19367 19368 switch(result) { 19369 case AST_PBX_FAILED: 19370 ast_log(LOG_WARNING, "Failed to start PBX :(\n"); 19371 p->invitestate = INV_COMPLETED; 19372 transmit_response_reliable(p, "503 Unavailable", req); 19373 break; 19374 case AST_PBX_CALL_LIMIT: 19375 ast_log(LOG_WARNING, "Failed to start PBX (call limit reached) \n"); 19376 p->invitestate = INV_COMPLETED; 19377 transmit_response_reliable(p, "480 Temporarily Unavailable", req); 19378 break; 19379 case AST_PBX_SUCCESS: 19380 /* nothing to do */ 19381 break; 19382 } 19383 19384 if (result) { 19385 19386 /* Unlock locks so ast_hangup can do its magic */ 19387 ast_channel_unlock(c); 19388 sip_pvt_unlock(p); 19389 ast_hangup(c); 19390 sip_pvt_lock(p); 19391 c = NULL; 19392 } 19393 } else { /* Pickup call in call group */ 19394 ast_channel_unlock(c); 19395 *nounlock = 1; 19396 if (ast_pickup_call(c)) { 19397 ast_log(LOG_NOTICE, "Nothing to pick up for %s\n", p->callid); 19398 transmit_response_reliable(p, "503 Unavailable", req); 19399 sip_alreadygone(p); 19400 /* Unlock locks so ast_hangup can do its magic */ 19401 sip_pvt_unlock(p); 19402 c->hangupcause = AST_CAUSE_CALL_REJECTED; 19403 } else { 19404 sip_pvt_unlock(p); 19405 ast_setstate(c, AST_STATE_DOWN); 19406 c->hangupcause = AST_CAUSE_NORMAL_CLEARING; 19407 } 19408 p->invitestate = INV_COMPLETED; 19409 ast_hangup(c); 19410 sip_pvt_lock(p); 19411 c = NULL; 19412 } 19413 break; 19414 case AST_STATE_RING: 19415 transmit_provisional_response(p, "100 Trying", req, 0); 19416 p->invitestate = INV_PROCEEDING; 19417 break; 19418 case AST_STATE_RINGING: 19419 transmit_provisional_response(p, "180 Ringing", req, 0); 19420 p->invitestate = INV_PROCEEDING; 19421 break; 19422 case AST_STATE_UP: 19423 ast_debug(2, "%s: This call is UP.... \n", c->name); 19424 19425 transmit_response(p, "100 Trying", req); 19426 19427 if (p->t38.state == T38_PEER_REINVITE) { 19428 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.")); 19429 } else if (p->t38.state == T38_ENABLED) { 19430 ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED); 19431 transmit_response_with_t38_sdp(p, "200 OK", req, (reinvite ? XMIT_RELIABLE : (req->ignore ? XMIT_UNRELIABLE : XMIT_CRITICAL))); 19432 } else if (p->t38.state == T38_DISABLED) { 19433 /* If this is not a re-invite or something to ignore - it's critical */ 19434 ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED); 19435 transmit_response_with_sdp(p, "200 OK", req, (reinvite ? XMIT_RELIABLE : (req->ignore ? XMIT_UNRELIABLE : XMIT_CRITICAL)), p->session_modify == TRUE ? FALSE:TRUE); 19436 } 19437 19438 p->invitestate = INV_TERMINATED; 19439 break; 19440 default: 19441 ast_log(LOG_WARNING, "Don't know how to handle INVITE in state %d\n", c->_state); 19442 transmit_response(p, "100 Trying", req); 19443 break; 19444 } 19445 } else { 19446 if (p && (p->autokillid == -1)) { 19447 const char *msg; 19448 19449 if (!p->jointcapability) 19450 msg = "488 Not Acceptable Here (codec error)"; 19451 else { 19452 ast_log(LOG_NOTICE, "Unable to create/find SIP channel for this INVITE\n"); 19453 msg = "503 Unavailable"; 19454 } 19455 transmit_response_reliable(p, msg, req); 19456 p->invitestate = INV_COMPLETED; 19457 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 19458 } 19459 } 19460 19461 request_invite_cleanup: 19462 19463 if (refer_locked && p->refer && p->refer->refer_call) { 19464 sip_pvt_unlock(p->refer->refer_call); 19465 if (p->refer->refer_call->owner) { 19466 ast_channel_unlock(p->refer->refer_call->owner); 19467 } 19468 } 19469 19470 return res; 19471 }
| static int handle_request_message | ( | struct sip_pvt * | p, | |
| struct sip_request * | req | |||
| ) | [static] |
Handle incoming MESSAGE request.
Definition at line 20217 of file chan_sip.c.
References ast_verbose, sip_request::debug, sip_request::ignore, receive_message(), and transmit_response().
Referenced by handle_incoming().
20218 { 20219 if (!req->ignore) { 20220 if (req->debug) 20221 ast_verbose("Receiving message!\n"); 20222 receive_message(p, req); 20223 } else 20224 transmit_response(p, "202 Accepted", req); 20225 return 1; 20226 }
| 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 18139 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().
18140 { 18141 /* This is mostly a skeleton for future improvements */ 18142 /* Mostly created to return proper answers on notifications on outbound REFER's */ 18143 int res = 0; 18144 const char *event = get_header(req, "Event"); 18145 char *eventid = NULL; 18146 char *sep; 18147 18148 if( (sep = strchr(event, ';')) ) { /* XXX bug here - overwriting string ? */ 18149 *sep++ = '\0'; 18150 eventid = sep; 18151 } 18152 18153 if (sipdebug) 18154 ast_debug(2, "Got NOTIFY Event: %s\n", event); 18155 18156 if (strcmp(event, "refer")) { 18157 /* We don't understand this event. */ 18158 /* Here's room to implement incoming voicemail notifications :-) */ 18159 transmit_response(p, "489 Bad event", req); 18160 res = -1; 18161 } else { 18162 /* Save nesting depth for now, since there might be other events we will 18163 support in the future */ 18164 18165 /* Handle REFER notifications */ 18166 18167 char buf[1024]; 18168 char *cmd, *code; 18169 int respcode; 18170 int success = TRUE; 18171 18172 /* EventID for each transfer... EventID is basically the REFER cseq 18173 18174 We are getting notifications on a call that we transfered 18175 We should hangup when we are getting a 200 OK in a sipfrag 18176 Check if we have an owner of this event */ 18177 18178 /* Check the content type */ 18179 if (strncasecmp(get_header(req, "Content-Type"), "message/sipfrag", strlen("message/sipfrag"))) { 18180 /* We need a sipfrag */ 18181 transmit_response(p, "400 Bad request", req); 18182 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 18183 return -1; 18184 } 18185 18186 /* Get the text of the attachment */ 18187 if (get_msg_text(buf, sizeof(buf), req, TRUE)) { 18188 ast_log(LOG_WARNING, "Unable to retrieve attachment from NOTIFY %s\n", p->callid); 18189 transmit_response(p, "400 Bad request", req); 18190 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 18191 return -1; 18192 } 18193 18194 /* 18195 From the RFC... 18196 A minimal, but complete, implementation can respond with a single 18197 NOTIFY containing either the body: 18198 SIP/2.0 100 Trying 18199 18200 if the subscription is pending, the body: 18201 SIP/2.0 200 OK 18202 if the reference was successful, the body: 18203 SIP/2.0 503 Service Unavailable 18204 if the reference failed, or the body: 18205 SIP/2.0 603 Declined 18206 18207 if the REFER request was accepted before approval to follow the 18208 reference could be obtained and that approval was subsequently denied 18209 (see Section 2.4.7). 18210 18211 If there are several REFERs in the same dialog, we need to 18212 match the ID of the event header... 18213 */ 18214 ast_debug(3, "* SIP Transfer NOTIFY Attachment: \n---%s\n---\n", buf); 18215 cmd = ast_skip_blanks(buf); 18216 code = cmd; 18217 /* We are at SIP/2.0 */ 18218 while(*code && (*code > 32)) { /* Search white space */ 18219 code++; 18220 } 18221 *code++ = '\0'; 18222 code = ast_skip_blanks(code); 18223 sep = code; 18224 sep++; 18225 while(*sep && (*sep > 32)) { /* Search white space */ 18226 sep++; 18227 } 18228 *sep++ = '\0'; /* Response string */ 18229 respcode = atoi(code); 18230 switch (respcode) { 18231 case 100: /* Trying: */ 18232 case 101: /* dialog establishment */ 18233 /* Don't do anything yet */ 18234 break; 18235 case 183: /* Ringing: */ 18236 /* Don't do anything yet */ 18237 break; 18238 case 200: /* OK: The new call is up, hangup this call */ 18239 /* Hangup the call that we are replacing */ 18240 break; 18241 case 301: /* Moved permenantly */ 18242 case 302: /* Moved temporarily */ 18243 /* Do we get the header in the packet in this case? */ 18244 success = FALSE; 18245 break; 18246 case 503: /* Service Unavailable: The new call failed */ 18247 /* Cancel transfer, continue the call */ 18248 success = FALSE; 18249 break; 18250 case 603: /* Declined: Not accepted */ 18251 /* Cancel transfer, continue the current call */ 18252 success = FALSE; 18253 break; 18254 } 18255 if (!success) { 18256 ast_log(LOG_NOTICE, "Transfer failed. Sorry. Nothing further to do with this call\n"); 18257 } 18258 18259 /* Confirm that we received this packet */ 18260 transmit_response(p, "200 OK", req); 18261 }; 18262 18263 if (!p->lastinvite) 18264 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 18265 18266 return res; 18267 }
| 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 18272 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().
18273 { 18274 int res; 18275 18276 /*! XXX get_destination assumes we're already authenticated. This means that a request from 18277 a known device (peer) will end up in the wrong context if this is out-of-dialog. 18278 However, we want to handle OPTIONS as light as possible, so we might want to have 18279 a configuration option whether we care or not. Some devices use this for testing 18280 capabilities, which means that we need to match device to answer with proper 18281 capabilities (including SDP). 18282 \todo Fix handle_request_options device handling with optional authentication 18283 (this needs to be fixed in 1.4 as well) 18284 */ 18285 18286 if (p->lastinvite) { 18287 /* if this is a request in an active dialog, just confirm that the dialog exists. */ 18288 transmit_response_with_allow(p, "200 OK", req, 0); 18289 return 0; 18290 } 18291 18292 res = get_destination(p, req); 18293 build_contact(p); 18294 18295 if (ast_strlen_zero(p->context)) 18296 ast_string_field_set(p, context, default_context); 18297 18298 if (ast_shutting_down()) 18299 transmit_response_with_allow(p, "503 Unavailable", req, 0); 18300 else if (res < 0) 18301 transmit_response_with_allow(p, "404 Not Found", req, 0); 18302 else 18303 transmit_response_with_allow(p, "200 OK", req, 0); 18304 18305 /* Destroy if this OPTIONS was the opening request, but not if 18306 it's in the middle of a normal call flow. */ 18307 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 18308 18309 return res; 18310 }
| static int handle_request_refer | ( | struct sip_pvt * | p, | |
| struct sip_request * | req, | |||
| int | debug, | |||
| int | seqno, | |||
| int * | nounlock | |||
| ) | [static] |
Definition at line 19638 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, 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(), and TRUE.
Referenced by handle_incoming().
19639 { 19640 struct sip_dual current; /* Chan1: Call between asterisk and transferer */ 19641 /* Chan2: Call between asterisk and transferee */ 19642 19643 int res = 0; 19644 current.req.data = NULL; 19645 19646 if (req->debug) 19647 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"); 19648 19649 if (!p->owner) { 19650 /* This is a REFER outside of an existing SIP dialog */ 19651 /* We can't handle that, so decline it */ 19652 ast_debug(3, "Call %s: Declined REFER, outside of dialog...\n", p->callid); 19653 transmit_response(p, "603 Declined (No dialog)", req); 19654 if (!req->ignore) { 19655 append_history(p, "Xfer", "Refer failed. Outside of dialog."); 19656 sip_alreadygone(p); 19657 p->needdestroy = 1; 19658 } 19659 return 0; 19660 } 19661 19662 19663 /* Check if transfer is allowed from this device */ 19664 if (p->allowtransfer == TRANSFER_CLOSED ) { 19665 /* Transfer not allowed, decline */ 19666 transmit_response(p, "603 Declined (policy)", req); 19667 append_history(p, "Xfer", "Refer failed. Allowtransfer == closed."); 19668 /* Do not destroy SIP session */ 19669 return 0; 19670 } 19671 19672 if (!req->ignore && ast_test_flag(&p->flags[0], SIP_GOTREFER)) { 19673 /* Already have a pending REFER */ 19674 transmit_response(p, "491 Request pending", req); 19675 append_history(p, "Xfer", "Refer failed. Request pending."); 19676 return 0; 19677 } 19678 19679 /* Allocate memory for call transfer data */ 19680 if (!p->refer && !sip_refer_allocate(p)) { 19681 transmit_response(p, "500 Internal Server Error", req); 19682 append_history(p, "Xfer", "Refer failed. Memory allocation error."); 19683 return -3; 19684 } 19685 19686 res = get_refer_info(p, req); /* Extract headers */ 19687 19688 p->refer->status = REFER_SENT; 19689 19690 if (res != 0) { 19691 switch (res) { 19692 case -2: /* Syntax error */ 19693 transmit_response(p, "400 Bad Request (Refer-to missing)", req); 19694 append_history(p, "Xfer", "Refer failed. Refer-to missing."); 19695 if (req->debug) 19696 ast_debug(1, "SIP transfer to black hole can't be handled (no refer-to: )\n"); 19697 break; 19698 case -3: 19699 transmit_response(p, "603 Declined (Non sip: uri)", req); 19700 append_history(p, "Xfer", "Refer failed. Non SIP uri"); 19701 if (req->debug) 19702 ast_debug(1, "SIP transfer to non-SIP uri denied\n"); 19703 break; 19704 default: 19705 /* Refer-to extension not found, fake a failed transfer */ 19706 transmit_response(p, "202 Accepted", req); 19707 append_history(p, "Xfer", "Refer failed. Bad extension."); 19708 transmit_notify_with_sipfrag(p, seqno, "404 Not found", TRUE); 19709 ast_clear_flag(&p->flags[0], SIP_GOTREFER); 19710 if (req->debug) 19711 ast_debug(1, "SIP transfer to bad extension: %s\n", p->refer->refer_to); 19712 break; 19713 } 19714 return 0; 19715 } 19716 if (ast_strlen_zero(p->context)) 19717 ast_string_field_set(p, context, default_context); 19718 19719 /* If we do not support SIP domains, all transfers are local */ 19720 if (allow_external_domains && check_sip_domain(p->refer->refer_to_domain, NULL, 0)) { 19721 p->refer->localtransfer = 1; 19722 if (sipdebug) 19723 ast_debug(3, "This SIP transfer is local : %s\n", p->refer->refer_to_domain); 19724 } else if (AST_LIST_EMPTY(&domain_list) || check_sip_domain(p->refer->refer_to_domain, NULL, 0)) { 19725 /* This PBX doesn't bother with SIP domains or domain is local, so this transfer is local */ 19726 p->refer->localtransfer = 1; 19727 } else if (sipdebug) 19728 ast_debug(3, "This SIP transfer is to a remote SIP extension (remote domain %s)\n", p->refer->refer_to_domain); 19729 19730 /* Is this a repeat of a current request? Ignore it */ 19731 /* Don't know what else to do right now. */ 19732 if (req->ignore) 19733 return res; 19734 19735 /* If this is a blind transfer, we have the following 19736 channels to work with: 19737 - chan1, chan2: The current call between transferer and transferee (2 channels) 19738 - target_channel: A new call from the transferee to the target (1 channel) 19739 We need to stay tuned to what happens in order to be able 19740 to bring back the call to the transferer */ 19741 19742 /* If this is a attended transfer, we should have all call legs within reach: 19743 - chan1, chan2: The call between the transferer and transferee (2 channels) 19744 - target_channel, targetcall_pvt: The call between the transferer and the target (2 channels) 19745 We want to bridge chan2 with targetcall_pvt! 19746 19747 The replaces call id in the refer message points 19748 to the call leg between Asterisk and the transferer. 19749 So we need to connect the target and the transferee channel 19750 and hangup the two other channels silently 19751 19752 If the target is non-local, the call ID could be on a remote 19753 machine and we need to send an INVITE with replaces to the 19754 target. We basically handle this as a blind transfer 19755 and let the sip_call function catch that we need replaces 19756 header in the INVITE. 19757 */ 19758 19759 19760 /* Get the transferer's channel */ 19761 current.chan1 = p->owner; 19762 19763 /* Find the other part of the bridge (2) - transferee */ 19764 current.chan2 = ast_bridged_channel(current.chan1); 19765 19766 if (sipdebug) 19767 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>"); 19768 19769 if (!current.chan2 && !p->refer->attendedtransfer) { 19770 /* No bridged channel, propably IVR or echo or similar... */ 19771 /* Guess we should masquerade or something here */ 19772 /* Until we figure it out, refuse transfer of such calls */ 19773 if (sipdebug) 19774 ast_debug(3, "Refused SIP transfer on non-bridged channel.\n"); 19775 p->refer->status = REFER_FAILED; 19776 append_history(p, "Xfer", "Refer failed. Non-bridged channel."); 19777 transmit_response(p, "603 Declined", req); 19778 return -1; 19779 } 19780 19781 if (current.chan2) { 19782 if (sipdebug) 19783 ast_debug(4, "Got SIP transfer, applying to bridged peer '%s'\n", current.chan2->name); 19784 19785 ast_queue_control(current.chan1, AST_CONTROL_UNHOLD); 19786 } 19787 19788 ast_set_flag(&p->flags[0], SIP_GOTREFER); 19789 19790 /* Attended transfer: Find all call legs and bridge transferee with target*/ 19791 if (p->refer->attendedtransfer) { 19792 if ((res = local_attended_transfer(p, ¤t, req, seqno))) 19793 return res; /* We're done with the transfer */ 19794 /* Fall through for remote transfers that we did not find locally */ 19795 if (sipdebug) 19796 ast_debug(4, "SIP attended transfer: Still not our call - generating INVITE with replaces\n"); 19797 /* Fallthrough if we can't find the call leg internally */ 19798 } 19799 19800 19801 /* Parking a call */ 19802 if (p->refer->localtransfer && !strcmp(p->refer->refer_to, ast_parking_ext())) { 19803 /* Must release c's lock now, because it will not longer be accessible after the transfer! */ 19804 *nounlock = 1; 19805 ast_channel_unlock(current.chan1); 19806 copy_request(¤t.req, req); 19807 ast_clear_flag(&p->flags[0], SIP_GOTREFER); 19808 p->refer->status = REFER_200OK; 19809 append_history(p, "Xfer", "REFER to call parking."); 19810 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", 19811 current.chan1->name, 19812 current.chan1->uniqueid, 19813 p->callid, 19814 current.chan2->name, 19815 current.chan2->uniqueid, 19816 p->refer->refer_to); 19817 if (sipdebug) 19818 ast_debug(4, "SIP transfer to parking: trying to park %s. Parked by %s\n", current.chan2->name, current.chan1->name); 19819 sip_park(current.chan2, current.chan1, req, seqno); 19820 return res; 19821 } 19822 19823 /* Blind transfers and remote attended xfers */ 19824 transmit_response(p, "202 Accepted", req); 19825 19826 if (current.chan1 && current.chan2) { 19827 ast_debug(3, "chan1->name: %s\n", current.chan1->name); 19828 pbx_builtin_setvar_helper(current.chan1, "BLINDTRANSFER", current.chan2->name); 19829 } 19830 if (current.chan2) { 19831 pbx_builtin_setvar_helper(current.chan2, "BLINDTRANSFER", current.chan1->name); 19832 pbx_builtin_setvar_helper(current.chan2, "SIPDOMAIN", p->refer->refer_to_domain); 19833 pbx_builtin_setvar_helper(current.chan2, "SIPTRANSFER", "yes"); 19834 /* One for the new channel */ 19835 pbx_builtin_setvar_helper(current.chan2, "_SIPTRANSFER", "yes"); 19836 /* Attended transfer to remote host, prepare headers for the INVITE */ 19837 if (p->refer->referred_by) 19838 pbx_builtin_setvar_helper(current.chan2, "_SIPTRANSFER_REFERER", p->refer->referred_by); 19839 } 19840 /* Generate a Replaces string to be used in the INVITE during attended transfer */ 19841 if (!ast_strlen_zero(p->refer->replaces_callid)) { 19842 char tempheader[SIPBUFSIZE]; 19843 snprintf(tempheader, sizeof(tempheader), "%s%s%s%s%s", p->refer->replaces_callid, 19844 p->refer->replaces_callid_totag ? ";to-tag=" : "", 19845 p->refer->replaces_callid_totag, 19846 p->refer->replaces_callid_fromtag ? ";from-tag=" : "", 19847 p->refer->replaces_callid_fromtag); 19848 if (current.chan2) 19849 pbx_builtin_setvar_helper(current.chan2, "_SIPTRANSFER_REPLACES", tempheader); 19850 } 19851 /* Must release lock now, because it will not longer 19852 be accessible after the transfer! */ 19853 *nounlock = 1; 19854 ast_channel_unlock(current.chan1); 19855 19856 /* Connect the call */ 19857 19858 /* FAKE ringing if not attended transfer */ 19859 if (!p->refer->attendedtransfer) 19860 transmit_notify_with_sipfrag(p, seqno, "183 Ringing", FALSE); 19861 19862 /* For blind transfer, this will lead to a new call */ 19863 /* For attended transfer to remote host, this will lead to 19864 a new SIP call with a replaces header, if the dial plan allows it 19865 */ 19866 if (!current.chan2) { 19867 /* We have no bridge, so we're talking with Asterisk somehow */ 19868 /* We need to masquerade this call */ 19869 /* What to do to fix this situation: 19870 * Set up the new call in a new channel 19871 * Let the new channel masq into this channel 19872 Please add that code here :-) 19873 */ 19874 p->refer->status = REFER_FAILED; 19875 transmit_notify_with_sipfrag(p, seqno, "503 Service Unavailable (can't handle one-legged xfers)", TRUE); 19876 ast_clear_flag(&p->flags[0], SIP_GOTREFER); 19877 append_history(p, "Xfer", "Refer failed (only bridged calls)."); 19878 return -1; 19879 } 19880 ast_set_flag(&p->flags[0], SIP_DEFER_BYE_ON_TRANSFER); /* Delay hangup */ 19881 19882 19883 /* For blind transfers, move the call to the new extensions. For attended transfers on multiple 19884 servers - generate an INVITE with Replaces. Either way, let the dial plan decided */ 19885 res = ast_async_goto(current.chan2, p->refer->refer_to_context, p->refer->refer_to, 1); 19886 19887 if (!res) { 19888 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", 19889 current.chan1->name, 19890 current.chan1->uniqueid, 19891 p->callid, 19892 current.chan2->name, 19893 current.chan2->uniqueid, 19894 p->refer->refer_to, p->refer->refer_to_context); 19895 /* Success - we have a new channel */ 19896 ast_debug(3, "%s transfer succeeded. Telling transferer.\n", p->refer->attendedtransfer? "Attended" : "Blind"); 19897 transmit_notify_with_sipfrag(p, seqno, "200 Ok", TRUE); 19898 if (p->refer->localtransfer) 19899 p->refer->status = REFER_200OK; 19900 if (p->owner) 19901 p->owner->hangupcause = AST_CAUSE_NORMAL_CLEARING; 19902 append_history(p, "Xfer", "Refer succeeded."); 19903 ast_clear_flag(&p->flags[0], SIP_GOTREFER); 19904 /* Do not hangup call, the other side do that when we say 200 OK */ 19905 /* We could possibly implement a timer here, auto congestion */ 19906 res = 0; 19907 } else { 19908 ast_clear_flag(&p->flags[0], SIP_DEFER_BYE_ON_TRANSFER); /* Don't delay hangup */ 19909 ast_debug(3, "%s transfer failed. Resuming original call.\n", p->refer->attendedtransfer? "Attended" : "Blind"); 19910 append_history(p, "Xfer", "Refer failed."); 19911 /* Failure of some kind */ 19912 p->refer->status = REFER_FAILED; 19913 transmit_notify_with_sipfrag(p, seqno, "503 Service Unavailable", TRUE); 19914 ast_clear_flag(&p->flags[0], SIP_GOTREFER); 19915 res = -1; 19916 } 19917 return res; 19918 }
| 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 20565 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, sip_scheddestroy(), and cfsip_methods::text.
Referenced by handle_incoming().
20566 { 20567 enum check_auth_result res; 20568 20569 /* Use this as the basis */ 20570 copy_request(&p->initreq, req); 20571 if (sipdebug) 20572 ast_debug(4, "Initializing initreq for method %s - callid %s\n", sip_methods[req->method].text, p->callid); 20573 check_via(p, req); 20574 if ((res = register_verify(p, sin, req, e)) < 0) { 20575 const char *reason; 20576 20577 switch (res) { 20578 case AUTH_SECRET_FAILED: 20579 reason = "Wrong password"; 20580 break; 20581 case AUTH_USERNAME_MISMATCH: 20582 reason = "Username/auth name mismatch"; 20583 break; 20584 case AUTH_NOT_FOUND: 20585 reason = "No matching peer found"; 20586 break; 20587 case AUTH_UNKNOWN_DOMAIN: 20588 reason = "Not a local domain"; 20589 break; 20590 case AUTH_PEER_NOT_DYNAMIC: 20591 reason = "Peer is not supposed to register"; 20592 break; 20593 case AUTH_ACL_FAILED: 20594 reason = "Device does not match ACL"; 20595 break; 20596 case AUTH_BAD_TRANSPORT: 20597 reason = "Device not configured to use this transport type"; 20598 break; 20599 default: 20600 reason = "Unknown failure"; 20601 break; 20602 } 20603 ast_log(LOG_NOTICE, "Registration from '%s' failed for '%s' - %s\n", 20604 get_header(req, "To"), ast_inet_ntoa(sin->sin_addr), 20605 reason); 20606 append_history(p, "RegRequest", "Failed : Account %s : %s", get_header(req, "To"), reason); 20607 } else 20608 append_history(p, "RegRequest", "Succeeded : Account %s", get_header(req, "To")); 20609 20610 if (res < 1) { 20611 /* Destroy the session, but keep us around for just a bit in case they don't 20612 get our 200 OK */ 20613 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 20614 } 20615 return res; 20616 }
| 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 20241 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, MWI_NOTIFICATION, 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().
20242 { 20243 int gotdest = 0; 20244 int res = 0; 20245 int firststate = AST_EXTENSION_REMOVED; 20246 struct sip_peer *authpeer = NULL; 20247 const char *eventheader = get_header(req, "Event"); /* Get Event package name */ 20248 const char *acceptheader = get_header(req, "Accept"); 20249 int resubscribe = (p->subscribed != NONE); 20250 char *temp, *event; 20251 struct ao2_iterator i; 20252 20253 if (p->initreq.headers) { 20254 /* We already have a dialog */ 20255 if (p->initreq.method != SIP_SUBSCRIBE) { 20256 /* This is a SUBSCRIBE within another SIP dialog, which we do not support */ 20257 /* For transfers, this could happen, but since we haven't seen it happening, let us just refuse this */ 20258 transmit_response(p, "403 Forbidden (within dialog)", req); 20259 /* Do not destroy session, since we will break the call if we do */ 20260 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); 20261 return 0; 20262 } else if (req->debug) { 20263 if (resubscribe) 20264 ast_debug(1, "Got a re-subscribe on existing subscription %s\n", p->callid); 20265 else 20266 ast_debug(1, "Got a new subscription %s (possibly with auth)\n", p->callid); 20267 } 20268 } 20269 20270 /* Check if we have a global disallow setting on subscriptions. 20271 if so, we don't have to check peer settings after auth, which saves a lot of processing 20272 */ 20273 if (!global_allowsubscribe) { 20274 transmit_response(p, "403 Forbidden (policy)", req); 20275 p->needdestroy = 1; 20276 return 0; 20277 } 20278 20279 if (!req->ignore && !resubscribe) { /* Set up dialog, new subscription */ 20280 const char *to = get_header(req, "To"); 20281 char totag[128]; 20282 20283 /* Check to see if a tag was provided, if so this is actually a resubscription of a dialog we no longer know about */ 20284 if (!ast_strlen_zero(to) && gettag(req, "To", totag, sizeof(totag))) { 20285 if (req->debug) 20286 ast_verbose("Received resubscription for a dialog we no longer know about. Telling remote side to subscribe again.\n"); 20287 transmit_response(p, "481 Subscription does not exist", req); 20288 p->needdestroy = 1; 20289 return 0; 20290 } 20291 20292 /* Use this as the basis */ 20293 if (req->debug) 20294 ast_verbose("Creating new subscription\n"); 20295 20296 copy_request(&p->initreq, req); 20297 if (sipdebug) 20298 ast_debug(4, "Initializing initreq for method %s - callid %s\n", sip_methods[req->method].text, p->callid); 20299 check_via(p, req); 20300 build_route(p, req, 0); 20301 } else if (req->debug && req->ignore) 20302 ast_verbose("Ignoring this SUBSCRIBE request\n"); 20303 20304 /* Find parameters to Event: header value and remove them for now */ 20305 if (ast_strlen_zero(eventheader)) { 20306 transmit_response(p, "489 Bad Event", req); 20307 ast_debug(2, "Received SIP subscribe for unknown event package: <none>\n"); 20308 p->needdestroy = 1; 20309 return 0; 20310 } 20311 20312 if ( (strchr(eventheader, ';'))) { 20313 event = ast_strdupa(eventheader); /* Since eventheader is a const, we can't change it */ 20314 temp = strchr(event, ';'); 20315 *temp = '\0'; /* Remove any options for now */ 20316 /* We might need to use them later :-) */ 20317 } else 20318 event = (char *) eventheader; /* XXX is this legal ? */ 20319 20320 /* Handle authentication */ 20321 res = check_user_full(p, req, SIP_SUBSCRIBE, e, 0, sin, &authpeer); 20322 /* if an authentication response was sent, we are done here */ 20323 if (res == AUTH_CHALLENGE_SENT) /* authpeer = NULL here */ 20324 return 0; 20325 if (res < 0) { 20326 if (res == AUTH_FAKE_AUTH) { 20327 ast_log(LOG_NOTICE, "Sending fake auth rejection for device %s\n", get_header(req, "From")); 20328 transmit_fake_auth_response(p, SIP_SUBSCRIBE, req, XMIT_UNRELIABLE); 20329 } else { 20330 ast_log(LOG_NOTICE, "Failed to authenticate device %s for SUBSCRIBE\n", get_header(req, "From")); 20331 transmit_response_reliable(p, "403 Forbidden", req); 20332 } 20333 p->needdestroy = 1; 20334 return 0; 20335 } 20336 20337 /* At this point, authpeer cannot be NULL. Remember we hold a reference, 20338 * so we must release it when done. 20339 * XXX must remove all the checks for authpeer == NULL. 20340 */ 20341 20342 /* Check if this device is allowed to subscribe at all */ 20343 if (!ast_test_flag(&p->flags[1], SIP_PAGE2_ALLOWSUBSCRIBE)) { 20344 transmit_response(p, "403 Forbidden (policy)", req); 20345 p->needdestroy = 1; 20346 if (authpeer) 20347 unref_peer(authpeer, "unref_peer, from handle_request_subscribe (authpeer 1)"); 20348 return 0; 20349 } 20350 20351 if (strcmp(event, "message-summary")) { 20352 /* Get destination right away */ 20353 gotdest = get_destination(p, NULL); 20354 } 20355 20356 /* Get full contact header - this needs to be used as a request URI in NOTIFY's */ 20357 parse_ok_contact(p, req); 20358 20359 build_contact(p); 20360 if (gotdest) { 20361 transmit_response(p, "404 Not Found", req); 20362 p->needdestroy = 1; 20363 if (authpeer) 20364 unref_peer(authpeer, "unref_peer, from handle_request_subscribe (authpeer 2)"); 20365 return 0; 20366 } 20367 20368 /* Initialize tag for new subscriptions */ 20369 if (ast_strlen_zero(p->tag)) 20370 make_our_tag(p->tag, sizeof(p->tag)); 20371 20372 if (!strcmp(event, "presence") || !strcmp(event, "dialog")) { /* Presence, RFC 3842 */ 20373 unsigned int pidf_xml; 20374 20375 if (authpeer) /* We do not need the authpeer any more */ 20376 unref_peer(authpeer, "unref_peer, from handle_request_subscribe (authpeer 2)"); 20377 20378 /* Header from Xten Eye-beam Accept: multipart/related, application/rlmi+xml, application/pidf+xml, application/xpidf+xml */ 20379 20380 pidf_xml = strstr(acceptheader, "application/pidf+xml") ? 1 : 0; 20381 20382 /* Older versions of Polycom firmware will claim pidf+xml, but really 20383 * they only support xpidf+xml. */ 20384 if (pidf_xml && strstr(p->useragent, "Polycom")) { 20385 p->subscribed = XPIDF_XML; 20386 } else if (pidf_xml) { 20387 p->subscribed = PIDF_XML; /* RFC 3863 format */ 20388 } else if (strstr(acceptheader, "application/dialog-info+xml")) { 20389 p->subscribed = DIALOG_INFO_XML; 20390 /* IETF draft: draft-ietf-sipping-dialog-package-05.txt */ 20391 } else if (strstr(acceptheader, "application/cpim-pidf+xml")) { 20392 p->subscribed = CPIM_PIDF_XML; /* RFC 3863 format */ 20393 } else if (strstr(acceptheader, "application/xpidf+xml")) { 20394 p->subscribed = XPIDF_XML; /* Early pre-RFC 3863 format with MSN additions (Microsoft Messenger) */ 20395 } else if (ast_strlen_zero(acceptheader)) { 20396 if (p->subscribed == NONE) { /* if the subscribed field is not already set, and there is no accept header... */ 20397 transmit_response(p, "489 Bad Event", req); 20398 20399 ast_log(LOG_WARNING, "SUBSCRIBE failure: no Accept header: pvt: stateid: %d, laststate: %d, dialogver: %d, subscribecont: '%s', subscribeuri: '%s'\n", 20400 p->stateid, p->laststate, p->dialogver, p->subscribecontext, p->subscribeuri); 20401 p->needdestroy = 1; 20402 return 0; 20403 } 20404 /* if p->subscribed is non-zero, then accept is not obligatory; according to rfc 3265 section 3.1.3, at least. 20405 so, we'll just let it ride, keeping the value from a previous subscription, and not abort the subscription */ 20406 } else { 20407 /* Can't find a format for events that we know about */ 20408 char mybuf[200]; 20409 snprintf(mybuf, sizeof(mybuf), "489 Bad Event (format %s)", acceptheader); 20410 transmit_response(p, mybuf, req); 20411 20412 ast_log(LOG_WARNING, "SUBSCRIBE failure: unrecognized format: '%s' pvt: subscribed: %d, stateid: %d, laststate: %d, dialogver: %d, subscribecont: '%s', subscribeuri: '%s'\n", 20413 acceptheader, (int)p->subscribed, p->stateid, p->laststate, p->dialogver, p->subscribecontext, p->subscribeuri); 20414 p->needdestroy = 1; 20415 return 0; 20416 } 20417 } else if (!strcmp(event, "message-summary")) { 20418 if (!ast_strlen_zero(acceptheader) && strcmp(acceptheader, "application/simple-message-summary")) { 20419 /* Format requested that we do not support */ 20420 transmit_response(p, "406 Not Acceptable", req); 20421 ast_debug(2, "Received SIP mailbox subscription for unknown format: %s\n", acceptheader); 20422 p->needdestroy = 1; 20423 if (authpeer) 20424 unref_peer(authpeer, "unref_peer, from handle_request_subscribe (authpeer 3)"); 20425 return 0; 20426 } 20427 /* Looks like they actually want a mailbox status 20428 This version of Asterisk supports mailbox subscriptions 20429 The subscribed URI needs to exist in the dial plan 20430 In most devices, this is configurable to the voicemailmain extension you use 20431 */ 20432 if (!authpeer || AST_LIST_EMPTY(&authpeer->mailboxes)) { 20433 transmit_response(p, "404 Not found (no mailbox)", req); 20434 p->needdestroy = 1; 20435 ast_log(LOG_NOTICE, "Received SIP subscribe for peer without mailbox: %s\n", authpeer->name); 20436 if (authpeer) 20437 unref_peer(authpeer, "unref_peer, from handle_request_subscribe (authpeer 4)"); 20438 return 0; 20439 } 20440 20441 p->subscribed = MWI_NOTIFICATION; 20442 if (ast_test_flag(&authpeer->flags[1], SIP_PAGE2_SUBSCRIBEMWIONLY)) { 20443 add_peer_mwi_subs(authpeer); 20444 } 20445 if (authpeer->mwipvt && authpeer->mwipvt != p) { /* Destroy old PVT if this is a new one */ 20446 /* We only allow one subscription per peer */ 20447 dialog_unlink_all(authpeer->mwipvt, TRUE, TRUE); 20448 authpeer->mwipvt = dialog_unref(authpeer->mwipvt, "unref dialog authpeer->mwipvt"); 20449 /* sip_destroy(authpeer->mwipvt); */ 20450 } 20451 if (authpeer->mwipvt) 20452 dialog_unref(authpeer->mwipvt, "Unref previously stored mwipvt dialog pointer"); 20453 authpeer->mwipvt = dialog_ref(p, "setting peers' mwipvt to p"); /* Link from peer to pvt UH- should this be dialog_ref()? */ 20454 if (p->relatedpeer) 20455 unref_peer(p->relatedpeer, "Unref previously stored relatedpeer ptr"); 20456 p->relatedpeer = ref_peer(authpeer, "setting dialog's relatedpeer pointer"); /* already refcounted...Link from pvt to peer UH- should this be dialog_ref()? */ 20457 /* Do not release authpeer here */ 20458 } else { /* At this point, Asterisk does not understand the specified event */ 20459 transmit_response(p, "489 Bad Event", req); 20460 ast_debug(2, "Received SIP subscribe for unknown event package: %s\n", event); 20461 p->needdestroy = 1; 20462 if (authpeer) 20463 unref_peer(authpeer, "unref_peer, from handle_request_subscribe (authpeer 5)"); 20464 return 0; 20465 } 20466 20467 /* Add subscription for extension state from the PBX core */ 20468 if (p->subscribed != MWI_NOTIFICATION && !resubscribe) { 20469 if (p->stateid > -1) { 20470 ast_extension_state_del(p->stateid, cb_extensionstate); 20471 /* we need to dec the refcount, now that the extensionstate is removed */ 20472 dialog_unref(p, "the extensionstate containing this dialog ptr was deleted"); 20473 } 20474 p->stateid = ast_extension_state_add(p->context, p->exten, cb_extensionstate, dialog_ref(p,"copying dialog ptr into extension state struct")); 20475 } 20476 20477 if (!req->ignore && p) 20478 p->lastinvite = seqno; 20479 if (p && !p->needdestroy) { 20480 p->expiry = atoi(get_header(req, "Expires")); 20481 20482 /* check if the requested expiry-time is within the approved limits from sip.conf */ 20483 if (p->expiry > max_expiry) 20484 p->expiry = max_expiry; 20485 if (p->expiry < min_expiry && p->expiry > 0) 20486 p->expiry = min_expiry; 20487 20488 if (sipdebug) { 20489 if (p->subscribed == MWI_NOTIFICATION && p->relatedpeer) 20490 ast_debug(2, "Adding subscription for mailbox notification - peer %s\n", p->relatedpeer->name); 20491 else 20492 ast_debug(2, "Adding subscription for extension %s context %s for peer %s\n", p->exten, p->context, p->username); 20493 } 20494 if (p->autokillid > -1 && sip_cancel_destroy(p)) /* Remove subscription expiry for renewals */ 20495 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 20496 if (p->expiry > 0) 20497 sip_scheddestroy(p, (p->expiry + 10) * 1000); /* Set timer for destruction of call at expiration */ 20498 20499 if (p->subscribed == MWI_NOTIFICATION) { 20500 ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED); 20501 transmit_response(p, "200 OK", req); 20502 if (p->relatedpeer) { /* Send first notification */ 20503 ao2_lock(p->relatedpeer); /* was WRLOCK */ 20504 sip_send_mwi_to_peer(p->relatedpeer, NULL, 0); 20505 ao2_unlock(p->relatedpeer); 20506 } 20507 } else { 20508 struct sip_pvt *p_old; 20509 20510 if ((firststate = ast_extension_state(NULL, p->context, p->exten)) < 0) { 20511 20512 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)); 20513 transmit_response(p, "404 Not found", req); 20514 p->needdestroy = 1; 20515 return 0; 20516 } 20517 ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED); 20518 transmit_response(p, "200 OK", req); 20519 transmit_state_notify(p, firststate, 1, FALSE); /* Send first notification */ 20520 append_history(p, "Subscribestatus", "%s", ast_extension_state2str(firststate)); 20521 /* hide the 'complete' exten/context in the refer_to field for later display */ 20522 ast_string_field_build(p, subscribeuri, "%s@%s", p->exten, p->context); 20523 20524 /* remove any old subscription from this peer for the same exten/context, 20525 as the peer has obviously forgotten about it and it's wasteful to wait 20526 for it to expire and send NOTIFY messages to the peer only to have them 20527 ignored (or generate errors) 20528 */ 20529 i = ao2_iterator_init(dialogs, 0); 20530 while ((p_old = ao2_t_iterator_next(&i, "iterate thru dialogs"))) { 20531 if (p_old == p) { 20532 ao2_t_ref(p_old, -1, "toss dialog ptr from iterator_next before continue"); 20533 continue; 20534 } 20535 if (p_old->initreq.method != SIP_SUBSCRIBE) { 20536 ao2_t_ref(p_old, -1, "toss dialog ptr from iterator_next before continue"); 20537 continue; 20538 } 20539 if (p_old->subscribed == NONE) { 20540 ao2_t_ref(p_old, -1, "toss dialog ptr from iterator_next before continue"); 20541 continue; 20542 } 20543 sip_pvt_lock(p_old); 20544 if (!strcmp(p_old->username, p->username)) { 20545 if (!strcmp(p_old->exten, p->exten) && 20546 !strcmp(p_old->context, p->context)) { 20547 p_old->needdestroy = 1; 20548 sip_pvt_unlock(p_old); 20549 ao2_t_ref(p_old, -1, "toss dialog ptr from iterator_next before break"); 20550 break; 20551 } 20552 } 20553 sip_pvt_unlock(p_old); 20554 ao2_t_ref(p_old, -1, "toss dialog ptr from iterator_next"); 20555 } 20556 ao2_iterator_destroy(&i); 20557 } 20558 if (!p->expiry) 20559 p->needdestroy = 1; 20560 } 20561 return 1; 20562 }
| 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 17430 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, sip_invite_param::auth_type, sip_pvt::authname, sip_pvt::authtries, sip_pvt::callid, 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::initreq, sip_pvt::laststate, LOG_NOTICE, LOG_WARNING, MAX_AUTHTRIES, sip_pvt::method, msg, sip_pvt::needdestroy, sip_pvt::options, sip_pvt::owner, parse_moved_contact(), sip_pvt::pendinginvite, process_sdp(), sip_pvt::recv, sip_pvt::refer, sip_pvt::registry, sip_pvt::relatedpeer, sip_pvt::sa, 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, sip_pvt::username, and XMIT_UNRELIABLE.
Referenced by handle_incoming().
17431 { 17432 struct ast_channel *owner; 17433 int sipmethod; 17434 int res = 1; 17435 const char *c = get_header(req, "Cseq"); 17436 /* 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 */ 17437 char *c_copy = ast_strdupa(c); 17438 /* Skip the Cseq and its subsequent spaces */ 17439 const char *msg = ast_skip_blanks(ast_skip_nonblanks(c_copy)); 17440 17441 if (!msg) 17442 msg = ""; 17443 17444 sipmethod = find_sip_method(msg); 17445 17446 owner = p->owner; 17447 if (owner) 17448 owner->hangupcause = hangup_sip2cause(resp); 17449 17450 if (p->socket.type == SIP_TRANSPORT_UDP) { 17451 int ack_res; 17452 17453 /* Acknowledge whatever it is destined for */ 17454 if ((resp >= 100) && (resp <= 199)) { 17455 ack_res = __sip_semi_ack(p, seqno, 0, sipmethod); 17456 } else { 17457 ack_res = __sip_ack(p, seqno, 0, sipmethod); 17458 } 17459 17460 if (ack_res == FALSE) { 17461 append_history(p, "Ignore", "Ignoring this retransmit\n"); 17462 return; 17463 } 17464 } 17465 17466 /* If this is a NOTIFY for a subscription clear the flag that indicates that we have a NOTIFY pending */ 17467 if (!p->owner && sipmethod == SIP_NOTIFY && p->pendinginvite) 17468 p->pendinginvite = 0; 17469 17470 /* Get their tag if we haven't already */ 17471 if (ast_strlen_zero(p->theirtag) || (resp >= 200)) { 17472 char tag[128]; 17473 17474 gettag(req, "To", tag, sizeof(tag)); 17475 ast_string_field_set(p, theirtag, tag); 17476 } 17477 /* This needs to be configurable on a channel/peer level, 17478 not mandatory for all communication. Sadly enough, NAT implementations 17479 are not so stable so we can always rely on these headers. 17480 Temporarily disabled, while waiting for fix. 17481 Fix assigned to Rizzo :-) 17482 */ 17483 /* check_via_response(p, req); */ 17484 17485 /* RFC 3261 Section 15 specifies that if we receive a 408 or 481 17486 * in response to a BYE, then we should end the current dialog 17487 * and session. It is known that at least one phone manufacturer 17488 * potentially will send a 404 in response to a BYE, so we'll be 17489 * liberal in what we accept and end the dialog and session if we 17490 * receive any of those responses to a BYE. 17491 */ 17492 if ((resp == 404 || resp == 408 || resp == 481) && sipmethod == SIP_BYE) { 17493 p->needdestroy = 1; 17494 return; 17495 } 17496 17497 if (p->relatedpeer && p->method == SIP_OPTIONS) { 17498 /* We don't really care what the response is, just that it replied back. 17499 Well, as long as it's not a 100 response... since we might 17500 need to hang around for something more "definitive" */ 17501 if (resp != 100) 17502 handle_response_peerpoke(p, resp, req); 17503 } else if (ast_test_flag(&p->flags[0], SIP_OUTGOING)) { 17504 switch(resp) { 17505 case 100: /* 100 Trying */ 17506 case 101: /* 101 Dialog establishment */ 17507 if (sipmethod == SIP_INVITE) 17508 handle_response_invite(p, resp, rest, req, seqno); 17509 break; 17510 case 183: /* 183 Session Progress */ 17511 if (sipmethod == SIP_INVITE) 17512 handle_response_invite(p, resp, rest, req, seqno); 17513 break; 17514 case 180: /* 180 Ringing */ 17515 if (sipmethod == SIP_INVITE) 17516 handle_response_invite(p, resp, rest, req, seqno); 17517 break; 17518 case 182: /* 182 Queued */ 17519 if (sipmethod == SIP_INVITE) 17520 handle_response_invite(p, resp, rest, req, seqno); 17521 break; 17522 case 200: /* 200 OK */ 17523 p->authtries = 0; /* Reset authentication counter */ 17524 if (sipmethod == SIP_MESSAGE || sipmethod == SIP_INFO) { 17525 /* We successfully transmitted a message 17526 or a video update request in INFO */ 17527 /* Nothing happens here - the message is inside a dialog */ 17528 } else if (sipmethod == SIP_INVITE) { 17529 handle_response_invite(p, resp, rest, req, seqno); 17530 } else if (sipmethod == SIP_NOTIFY) { 17531 handle_response_notify(p, resp, rest, req, seqno); 17532 } else if (sipmethod == SIP_REGISTER) 17533 res = handle_response_register(p, resp, rest, req, seqno); 17534 else if (sipmethod == SIP_BYE) { /* Ok, we're ready to go */ 17535 p->needdestroy = 1; 17536 ast_clear_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED); 17537 } else if (sipmethod == SIP_SUBSCRIBE) { 17538 ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED); 17539 } 17540 break; 17541 case 202: /* Transfer accepted */ 17542 if (sipmethod == SIP_REFER) 17543 handle_response_refer(p, resp, rest, req, seqno); 17544 break; 17545 case 401: /* Not www-authorized on SIP method */ 17546 case 407: /* Proxy auth required */ 17547 if (sipmethod == SIP_INVITE) 17548 handle_response_invite(p, resp, rest, req, seqno); 17549 else if (sipmethod == SIP_NOTIFY) 17550 handle_response_notify(p, resp, rest, req, seqno); 17551 else if (sipmethod == SIP_REFER) 17552 handle_response_refer(p, resp, rest, req, seqno); 17553 else if (p->registry && sipmethod == SIP_REGISTER) 17554 res = handle_response_register(p, resp, rest, req, seqno); 17555 else if (sipmethod == SIP_BYE) { 17556 if (p->options) 17557 p->options->auth_type = resp; 17558 if (ast_strlen_zero(p->authname)) { 17559 ast_log(LOG_WARNING, "Asked to authenticate %s, to %s:%d but we have no matching peer!\n", 17560 msg, ast_inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port)); 17561 p->needdestroy = 1; 17562 } else if ((p->authtries == MAX_AUTHTRIES) || do_proxy_auth(p, req, resp, sipmethod, 0)) { 17563 ast_log(LOG_NOTICE, "Failed to authenticate on %s to '%s'\n", msg, get_header(&p->initreq, "From")); 17564 p->needdestroy = 1; 17565 } 17566 } else { 17567 ast_log(LOG_WARNING, "Got authentication request (%d) on %s to '%s'\n", resp, sip_methods[sipmethod].text, get_header(req, "To")); 17568 p->needdestroy = 1; 17569 } 17570 break; 17571 case 403: /* Forbidden - we failed authentication */ 17572 if (sipmethod == SIP_INVITE) 17573 handle_response_invite(p, resp, rest, req, seqno); 17574 else if (p->registry && sipmethod == SIP_REGISTER) 17575 res = handle_response_register(p, resp, rest, req, seqno); 17576 else { 17577 ast_log(LOG_WARNING, "Forbidden - maybe wrong password on authentication for %s\n", msg); 17578 p->needdestroy = 1; 17579 } 17580 break; 17581 case 404: /* Not found */ 17582 if (p->registry && sipmethod == SIP_REGISTER) 17583 res = handle_response_register(p, resp, rest, req, seqno); 17584 else if (sipmethod == SIP_INVITE) 17585 handle_response_invite(p, resp, rest, req, seqno); 17586 else if (owner) 17587 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 17588 break; 17589 case 423: /* Interval too brief */ 17590 if (sipmethod == SIP_REGISTER) 17591 res = handle_response_register(p, resp, rest, req, seqno); 17592 break; 17593 case 408: /* Request timeout - terminate dialog */ 17594 if (sipmethod == SIP_INVITE) 17595 handle_response_invite(p, resp, rest, req, seqno); 17596 else if (sipmethod == SIP_REGISTER) 17597 res = handle_response_register(p, resp, rest, req, seqno); 17598 else if (sipmethod == SIP_BYE) { 17599 p->needdestroy = 1; 17600 ast_debug(4, "Got timeout on bye. Thanks for the answer. Now, kill this call\n"); 17601 } else { 17602 if (owner) 17603 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 17604 p->needdestroy = 1; 17605 } 17606 break; 17607 17608 case 422: /* Session-Timers: Session Interval Too Small */ 17609 if (sipmethod == SIP_INVITE) { 17610 handle_response_invite(p, resp, rest, req, seqno); 17611 } 17612 break; 17613 17614 case 481: /* Call leg does not exist */ 17615 if (sipmethod == SIP_INVITE) { 17616 handle_response_invite(p, resp, rest, req, seqno); 17617 } else if (sipmethod == SIP_REFER) { 17618 handle_response_refer(p, resp, rest, req, seqno); 17619 } else if (sipmethod == SIP_BYE) { 17620 /* The other side has no transaction to bye, 17621 just assume it's all right then */ 17622 ast_log(LOG_WARNING, "Remote host can't match request %s to call '%s'. Giving up.\n", sip_methods[sipmethod].text, p->callid); 17623 } else if (sipmethod == SIP_CANCEL) { 17624 /* The other side has no transaction to cancel, 17625 just assume it's all right then */ 17626 ast_log(LOG_WARNING, "Remote host can't match request %s to call '%s'. Giving up.\n", sip_methods[sipmethod].text, p->callid); 17627 } else { 17628 ast_log(LOG_WARNING, "Remote host can't match request %s to call '%s'. Giving up.\n", sip_methods[sipmethod].text, p->callid); 17629 /* Guessing that this is not an important request */ 17630 } 17631 break; 17632 case 487: 17633 if (sipmethod == SIP_INVITE) 17634 handle_response_invite(p, resp, rest, req, seqno); 17635 break; 17636 case 415: /* Unsupported media type */ 17637 case 488: /* Not acceptable here - codec error */ 17638 case 606: /* Not Acceptable */ 17639 if (sipmethod == SIP_INVITE) 17640 handle_response_invite(p, resp, rest, req, seqno); 17641 break; 17642 case 491: /* Pending */ 17643 if (sipmethod == SIP_INVITE) 17644 handle_response_invite(p, resp, rest, req, seqno); 17645 else { 17646 ast_debug(1, "Got 491 on %s, unspported. Call ID %s\n", sip_methods[sipmethod].text, p->callid); 17647 p->needdestroy = 1; 17648 } 17649 break; 17650 case 501: /* Not Implemented */ 17651 if (sipmethod == SIP_INVITE) 17652 handle_response_invite(p, resp, rest, req, seqno); 17653 else if (sipmethod == SIP_REFER) 17654 handle_response_refer(p, resp, rest, req, seqno); 17655 else 17656 ast_log(LOG_WARNING, "Host '%s' does not implement '%s'\n", ast_inet_ntoa(p->sa.sin_addr), msg); 17657 break; 17658 case 603: /* Declined transfer */ 17659 if (sipmethod == SIP_REFER) { 17660 handle_response_refer(p, resp, rest, req, seqno); 17661 break; 17662 } 17663 /* Fallthrough */ 17664 default: 17665 if ((resp >= 300) && (resp < 700)) { 17666 /* Fatal response */ 17667 if ((resp != 487)) 17668 ast_verb(3, "Got SIP response %d \"%s\" back from %s\n", resp, rest, ast_inet_ntoa(p->sa.sin_addr)); 17669 17670 if (sipmethod == SIP_INVITE) 17671 stop_media_flows(p); /* Immediately stop RTP, VRTP and UDPTL as applicable */ 17672 17673 /* XXX Locking issues?? XXX */ 17674 switch(resp) { 17675 case 300: /* Multiple Choices */ 17676 case 301: /* Moved permanently */ 17677 case 302: /* Moved temporarily */ 17678 case 305: /* Use Proxy */ 17679 parse_moved_contact(p, req); 17680 /* Fall through */ 17681 case 486: /* Busy here */ 17682 case 600: /* Busy everywhere */ 17683 case 603: /* Decline */ 17684 if (p->owner) 17685 ast_queue_control(p->owner, AST_CONTROL_BUSY); 17686 break; 17687 case 482: /*! 17688 \note SIP is incapable of performing a hairpin call, which 17689 is yet another failure of not having a layer 2 (again, YAY 17690 IETF for thinking ahead). So we treat this as a call 17691 forward and hope we end up at the right place... */ 17692 ast_debug(1, "Hairpin detected, setting up call forward for what it's worth\n"); 17693 if (p->owner) 17694 ast_string_field_build(p->owner, call_forward, 17695 "Local/%s@%s", p->username, p->context); 17696 /* Fall through */ 17697 case 480: /* Temporarily Unavailable */ 17698 case 404: /* Not Found */ 17699 case 410: /* Gone */ 17700 case 400: /* Bad Request */ 17701 case 500: /* Server error */ 17702 if (sipmethod == SIP_REFER) { 17703 handle_response_refer(p, resp, rest, req, seqno); 17704 break; 17705 } 17706 /* Fall through */ 17707 case 502: /* Bad gateway */ 17708 case 503: /* Service Unavailable */ 17709 case 504: /* Server Timeout */ 17710 if (owner) 17711 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 17712 break; 17713 default: 17714 /* Send hangup */ 17715 if (owner && sipmethod != SIP_MESSAGE && sipmethod != SIP_INFO && sipmethod != SIP_BYE) 17716 ast_queue_hangup_with_cause(p->owner, AST_CAUSE_PROTOCOL_ERROR); 17717 break; 17718 } 17719 /* ACK on invite */ 17720 if (sipmethod == SIP_INVITE) 17721 transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); 17722 if (sipmethod != SIP_MESSAGE && sipmethod != SIP_INFO) 17723 sip_alreadygone(p); 17724 if (!p->owner) 17725 p->needdestroy = 1; 17726 } else if ((resp >= 100) && (resp < 200)) { 17727 if (sipmethod == SIP_INVITE) { 17728 if (!req->ignore && sip_cancel_destroy(p)) 17729 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 17730 if (find_sdp(req)) 17731 process_sdp(p, req, SDP_T38_NONE); 17732 if (p->owner) { 17733 /* Queue a progress frame */ 17734 ast_queue_control(p->owner, AST_CONTROL_PROGRESS); 17735 } 17736 } 17737 } else 17738 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)); 17739 } 17740 } else { 17741 /* Responses to OUTGOING SIP requests on INCOMING calls 17742 get handled here. As well as out-of-call message responses */ 17743 if (req->debug) 17744 ast_verbose("SIP Response message for INCOMING dialog %s arrived\n", msg); 17745 17746 if (sipmethod == SIP_INVITE && resp == 200) { 17747 /* Tags in early session is replaced by the tag in 200 OK, which is 17748 the final reply to our INVITE */ 17749 char tag[128]; 17750 17751 gettag(req, "To", tag, sizeof(tag)); 17752 ast_string_field_set(p, theirtag, tag); 17753 } 17754 17755 switch(resp) { 17756 case 200: 17757 if (sipmethod == SIP_INVITE) { 17758 handle_response_invite(p, resp, rest, req, seqno); 17759 } else if (sipmethod == SIP_CANCEL) { 17760 ast_debug(1, "Got 200 OK on CANCEL\n"); 17761 17762 /* Wait for 487, then destroy */ 17763 } else if (sipmethod == SIP_NOTIFY) { 17764 /* They got the notify, this is the end */ 17765 if (p->owner) { 17766 if (p->refer) { 17767 ast_debug(1, "Got 200 OK on NOTIFY for transfer\n"); 17768 } else 17769 ast_log(LOG_WARNING, "Notify answer on an owned channel?\n"); 17770 /* ast_queue_hangup(p->owner); Disabled */ 17771 } else { 17772 if (!p->subscribed && !p->refer) 17773 p->needdestroy = 1; 17774 if (ast_test_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE)) { 17775 /* Ready to send the next state we have on queue */ 17776 ast_clear_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE); 17777 cb_extensionstate((char *)p->context, (char *)p->exten, p->laststate, (void *) p); 17778 } 17779 } 17780 } else if (sipmethod == SIP_BYE) 17781 p->needdestroy = 1; 17782 else if (sipmethod == SIP_MESSAGE || sipmethod == SIP_INFO) 17783 /* We successfully transmitted a message or 17784 a video update request in INFO */ 17785 ; 17786 else if (sipmethod == SIP_BYE) 17787 /* Ok, we're ready to go */ 17788 p->needdestroy = 1; 17789 break; 17790 case 202: /* Transfer accepted */ 17791 if (sipmethod == SIP_REFER) 17792 handle_response_refer(p, resp, rest, req, seqno); 17793 break; 17794 case 401: /* www-auth */ 17795 case 407: 17796 if (sipmethod == SIP_REFER) 17797 handle_response_refer(p, resp, rest, req, seqno); 17798 else if (sipmethod == SIP_INVITE) 17799 handle_response_invite(p, resp, rest, req, seqno); 17800 else if (sipmethod == SIP_BYE) { 17801 if (p->authtries == MAX_AUTHTRIES || do_proxy_auth(p, req, resp, sipmethod, 0)) { 17802 ast_log(LOG_NOTICE, "Failed to authenticate on %s to '%s'\n", msg, get_header(&p->initreq, "From")); 17803 p->needdestroy = 1; 17804 } 17805 } 17806 break; 17807 case 481: /* Call leg does not exist */ 17808 if (sipmethod == SIP_INVITE) { 17809 /* Re-invite failed */ 17810 handle_response_invite(p, resp, rest, req, seqno); 17811 } else if (sipmethod == SIP_BYE) { 17812 p->needdestroy = 1; 17813 } else if (sipdebug) { 17814 ast_debug(1, "Remote host can't match request %s to call '%s'. Giving up\n", sip_methods[sipmethod].text, p->callid); 17815 } 17816 break; 17817 case 501: /* Not Implemented */ 17818 if (sipmethod == SIP_INVITE) 17819 handle_response_invite(p, resp, rest, req, seqno); 17820 else if (sipmethod == SIP_REFER) 17821 handle_response_refer(p, resp, rest, req, seqno); 17822 break; 17823 case 603: /* Declined transfer */ 17824 if (sipmethod == SIP_REFER) { 17825 handle_response_refer(p, resp, rest, req, seqno); 17826 break; 17827 } 17828 /* Fallthrough */ 17829 default: /* Errors without handlers */ 17830 if ((resp >= 100) && (resp < 200)) { 17831 if (sipmethod == SIP_INVITE) { /* re-invite */ 17832 if (!req->ignore && sip_cancel_destroy(p)) 17833 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 17834 } 17835 } 17836 if ((resp >= 300) && (resp < 700)) { 17837 if ((resp != 487)) 17838 ast_verb(3, "Incoming call: Got SIP response %d \"%s\" back from %s\n", resp, rest, ast_inet_ntoa(p->sa.sin_addr)); 17839 switch(resp) { 17840 case 415: /* Unsupported media type */ 17841 case 488: /* Not acceptable here - codec error */ 17842 case 603: /* Decline */ 17843 case 500: /* Server error */ 17844 case 502: /* Bad gateway */ 17845 case 503: /* Service Unavailable */ 17846 case 504: /* Server timeout */ 17847 17848 /* re-invite failed */ 17849 if (sipmethod == SIP_INVITE && sip_cancel_destroy(p)) 17850 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 17851 break; 17852 } 17853 } 17854 break; 17855 } 17856 } 17857 }
| 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 16803 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, 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(), sip_pvt::route, sip_pvt::rtp, 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, update_call_counter(), sip_pvt::waitid, XMIT_ERROR, and XMIT_UNRELIABLE.
Referenced by handle_response().
16804 { 16805 int outgoing = ast_test_flag(&p->flags[0], SIP_OUTGOING); 16806 int res = 0; 16807 int xmitres = 0; 16808 int reinvite = (p->owner && p->owner->_state == AST_STATE_UP); 16809 char *p_hdrval; 16810 int rtn; 16811 16812 if (reinvite) 16813 ast_debug(4, "SIP response %d to RE-invite on %s call %s\n", resp, outgoing ? "outgoing" : "incoming", p->callid); 16814 else 16815 ast_debug(4, "SIP response %d to standard invite\n", resp); 16816 16817 if (p->alreadygone) { /* This call is already gone */ 16818 ast_debug(1, "Got response on call that is already terminated: %s (ignoring)\n", p->callid); 16819 return; 16820 } 16821 16822 /* Acknowledge sequence number - This only happens on INVITE from SIP-call */ 16823 /* Don't auto congest anymore since we've gotten something useful back */ 16824 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")); 16825 16826 /* RFC3261 says we must treat every 1xx response (but not 100) 16827 that we don't recognize as if it was 183. 16828 */ 16829 if (resp > 100 && resp < 200 && resp!=101 && resp != 180 && resp != 182 && resp != 183) 16830 resp = 183; 16831 16832 /* Any response between 100 and 199 is PROCEEDING */ 16833 if (resp >= 100 && resp < 200 && p->invitestate == INV_CALLING) 16834 p->invitestate = INV_PROCEEDING; 16835 16836 /* Final response, not 200 ? */ 16837 if (resp >= 300 && (p->invitestate == INV_CALLING || p->invitestate == INV_PROCEEDING || p->invitestate == INV_EARLY_MEDIA )) 16838 p->invitestate = INV_COMPLETED; 16839 16840 /* Final response, clear out pending invite */ 16841 if ((resp == 200 || resp >= 300) && p->pendinginvite && seqno == p->pendinginvite) 16842 p->pendinginvite = 0; 16843 16844 switch (resp) { 16845 case 100: /* Trying */ 16846 case 101: /* Dialog establishment */ 16847 if (!req->ignore && p->invitestate != INV_CANCELLED && sip_cancel_destroy(p)) 16848 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 16849 check_pendings(p); 16850 break; 16851 16852 case 180: /* 180 Ringing */ 16853 case 182: /* 182 Queued */ 16854 if (!req->ignore && p->invitestate != INV_CANCELLED && sip_cancel_destroy(p)) 16855 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 16856 if (!req->ignore && p->owner) { 16857 ast_queue_control(p->owner, AST_CONTROL_RINGING); 16858 if (p->owner->_state != AST_STATE_UP) { 16859 ast_setstate(p->owner, AST_STATE_RINGING); 16860 } 16861 } 16862 if (find_sdp(req)) { 16863 if (p->invitestate != INV_CANCELLED) 16864 p->invitestate = INV_EARLY_MEDIA; 16865 res = process_sdp(p, req, SDP_T38_NONE); 16866 if (!req->ignore && p->owner) { 16867 /* Queue a progress frame only if we have SDP in 180 or 182 */ 16868 ast_queue_control(p->owner, AST_CONTROL_PROGRESS); 16869 } 16870 } 16871 check_pendings(p); 16872 break; 16873 16874 case 183: /* Session progress */ 16875 if (!req->ignore && (p->invitestate != INV_CANCELLED) && sip_cancel_destroy(p)) 16876 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 16877 if (find_sdp(req)) { 16878 if (p->invitestate != INV_CANCELLED) 16879 p->invitestate = INV_EARLY_MEDIA; 16880 res = process_sdp(p, req, SDP_T38_NONE); 16881 if (!req->ignore && p->owner) { 16882 /* Queue a progress frame */ 16883 ast_queue_control(p->owner, AST_CONTROL_PROGRESS); 16884 } 16885 } else { 16886 /* Alcatel PBXs are known to send 183s with no SDP after sending 16887 * a 100 Trying response. We're just going to treat this sort of thing 16888 * the same as we would treat a 180 Ringing 16889 */ 16890 if (!req->ignore && p->owner) { 16891 ast_queue_control(p->owner, AST_CONTROL_RINGING); 16892 } 16893 } 16894 check_pendings(p); 16895 break; 16896 16897 case 200: /* 200 OK on invite - someone's answering our call */ 16898 if (!req->ignore && (p->invitestate != INV_CANCELLED) && sip_cancel_destroy(p)) 16899 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 16900 p->authtries = 0; 16901 if (find_sdp(req)) { 16902 if ((res = process_sdp(p, req, SDP_T38_ACCEPT)) && !req->ignore) 16903 if (!reinvite) 16904 /* This 200 OK's SDP is not acceptable, so we need to ack, then hangup */ 16905 /* For re-invites, we try to recover */ 16906 ast_set_flag(&p->flags[0], SIP_PENDINGBYE); 16907 } 16908 16909 /* Parse contact header for continued conversation */ 16910 /* When we get 200 OK, we know which device (and IP) to contact for this call */ 16911 /* This is important when we have a SIP proxy between us and the phone */ 16912 if (outgoing) { 16913 update_call_counter(p, DEC_CALL_RINGING); 16914 parse_ok_contact(p, req); 16915 /* Save Record-Route for any later requests we make on this dialogue */ 16916 if (!reinvite) 16917 build_route(p, req, 1); 16918 16919 if(set_address_from_contact(p)) { 16920 /* Bad contact - we don't know how to reach this device */ 16921 /* We need to ACK, but then send a bye */ 16922 if (!p->route && !req->ignore) 16923 ast_set_flag(&p->flags[0], SIP_PENDINGBYE); 16924 } 16925 16926 } 16927 16928 if (!req->ignore && p->owner) { 16929 if (!reinvite) { 16930 ast_queue_control(p->owner, AST_CONTROL_ANSWER); 16931 if (global_callevents) 16932 manager_event(EVENT_FLAG_SYSTEM, "ChannelUpdate", 16933 "Channel: %s\r\nChanneltype: %s\r\nUniqueid: %s\r\nSIPcallid: %s\r\nSIPfullcontact: %s\r\nPeername: %s\r\n", 16934 p->owner->name, "SIP", p->owner->uniqueid, p->callid, p->fullcontact, p->peername); 16935 } else { /* RE-invite */ 16936 ast_queue_frame(p->owner, &ast_null_frame); 16937 } 16938 } else { 16939 /* It's possible we're getting an 200 OK after we've tried to disconnect 16940 by sending CANCEL */ 16941 /* First send ACK, then send bye */ 16942 if (!req->ignore) 16943 ast_set_flag(&p->flags[0], SIP_PENDINGBYE); 16944 } 16945 16946 /* Check for Session-Timers related headers */ 16947 if (st_get_mode(p) != SESSION_TIMER_MODE_REFUSE && p->outgoing_call == TRUE && !reinvite) { 16948 p_hdrval = (char*)get_header(req, "Session-Expires"); 16949 if (!ast_strlen_zero(p_hdrval)) { 16950 /* UAS supports Session-Timers */ 16951 enum st_refresher tmp_st_ref = SESSION_TIMER_REFRESHER_AUTO; 16952 int tmp_st_interval = 0; 16953 rtn = parse_session_expires(p_hdrval, &tmp_st_interval, &tmp_st_ref); 16954 if (rtn != 0) { 16955 ast_set_flag(&p->flags[0], SIP_PENDINGBYE); 16956 } 16957 if (tmp_st_ref == SESSION_TIMER_REFRESHER_UAC || 16958 tmp_st_ref == SESSION_TIMER_REFRESHER_UAS) { 16959 p->stimer->st_ref = tmp_st_ref; 16960 } 16961 if (tmp_st_interval) { 16962 p->stimer->st_interval = tmp_st_interval; 16963 } 16964 p->stimer->st_active = TRUE; 16965 p->stimer->st_active_peer_ua = TRUE; 16966 start_session_timer(p); 16967 } else { 16968 /* UAS doesn't support Session-Timers */ 16969 if (st_get_mode(p) == SESSION_TIMER_MODE_ORIGINATE) { 16970 p->stimer->st_ref = SESSION_TIMER_REFRESHER_UAC; 16971 p->stimer->st_active_peer_ua = FALSE; 16972 start_session_timer(p); 16973 } 16974 } 16975 } 16976 16977 16978 /* If I understand this right, the branch is different for a non-200 ACK only */ 16979 p->invitestate = INV_TERMINATED; 16980 ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED); 16981 xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, TRUE); 16982 check_pendings(p); 16983 break; 16984 16985 case 407: /* Proxy authentication */ 16986 case 401: /* Www auth */ 16987 /* First we ACK */ 16988 xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); 16989 if (p->options) 16990 p->options->auth_type = resp; 16991 16992 /* Then we AUTH */ 16993 ast_string_field_set(p, theirtag, NULL); /* forget their old tag, so we don't match tags when getting response */ 16994 if (!req->ignore) { 16995 if (p->authtries < MAX_AUTHTRIES) 16996 p->invitestate = INV_CALLING; 16997 if (p->authtries == MAX_AUTHTRIES || do_proxy_auth(p, req, resp, SIP_INVITE, 1)) { 16998 ast_log(LOG_NOTICE, "Failed to authenticate on INVITE to '%s'\n", get_header(&p->initreq, "From")); 16999 p->needdestroy = 1; 17000 sip_alreadygone(p); 17001 if (p->owner) 17002 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 17003 } 17004 } 17005 break; 17006 17007 case 403: /* Forbidden */ 17008 /* First we ACK */ 17009 xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); 17010 ast_log(LOG_WARNING, "Received response: \"Forbidden\" from '%s'\n", get_header(&p->initreq, "From")); 17011 if (!req->ignore && p->owner) 17012 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 17013 p->needdestroy = 1; 17014 sip_alreadygone(p); 17015 break; 17016 17017 case 404: /* Not found */ 17018 xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); 17019 if (p->owner && !req->ignore) 17020 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 17021 sip_alreadygone(p); 17022 break; 17023 17024 case 408: /* Request timeout */ 17025 case 481: /* Call leg does not exist */ 17026 /* Could be REFER caused INVITE with replaces */ 17027 ast_log(LOG_WARNING, "Re-invite to non-existing call leg on other UA. SIP dialog '%s'. Giving up.\n", p->callid); 17028 xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); 17029 if (p->owner) 17030 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 17031 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 17032 break; 17033 17034 case 422: /* Session-Timers: Session interval too small */ 17035 xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); 17036 ast_string_field_set(p, theirtag, NULL); 17037 proc_422_rsp(p, req); 17038 break; 17039 17040 case 487: /* Cancelled transaction */ 17041 /* We have sent CANCEL on an outbound INVITE 17042 This transaction is already scheduled to be killed by sip_hangup(). 17043 */ 17044 xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); 17045 if (p->owner && !req->ignore) { 17046 ast_queue_hangup_with_cause(p->owner, AST_CAUSE_NORMAL_CLEARING); 17047 append_history(p, "Hangup", "Got 487 on CANCEL request from us. Queued AST hangup request"); 17048 } else if (!req->ignore) { 17049 update_call_counter(p, DEC_CALL_LIMIT); 17050 append_history(p, "Hangup", "Got 487 on CANCEL request from us on call without owner. Killing this dialog."); 17051 p->needdestroy = 1; 17052 sip_alreadygone(p); 17053 } 17054 break; 17055 case 415: /* Unsupported media type */ 17056 case 488: /* Not acceptable here */ 17057 case 606: /* Not Acceptable */ 17058 xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); 17059 if (p->udptl && p->t38.state == T38_LOCAL_REINVITE) { 17060 change_t38_state(p, T38_DISABLED); 17061 /* Try to reset RTP timers */ 17062 ast_rtp_set_rtptimers_onhold(p->rtp); 17063 17064 /* Trigger a reinvite back to audio */ 17065 transmit_reinvite_with_sdp(p, FALSE, FALSE); 17066 } else { 17067 /* We can't set up this call, so give up */ 17068 if (p->owner && !req->ignore) 17069 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 17070 p->needdestroy = 1; 17071 /* If there's no dialog to end, then mark p as already gone */ 17072 if (!reinvite) 17073 sip_alreadygone(p); 17074 } 17075 break; 17076 case 491: /* Pending */ 17077 xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); 17078 if (p->owner && !req->ignore) { 17079 if (p->owner->_state != AST_STATE_UP) { 17080 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 17081 p->needdestroy = 1; 17082 } else { 17083 /* This is a re-invite that failed. */ 17084 /* Reset the flag after a while 17085 */ 17086 int wait; 17087 /* RFC 3261, if owner of call, wait between 2.1 to 4 seconds, 17088 * if not owner of call, wait 0 to 2 seconds */ 17089 if (p->outgoing_call) { 17090 wait = 2100 + ast_random() % 2000; 17091 } else { 17092 wait = ast_random() % 2000; 17093 } 17094 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.")); 17095 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); 17096 ast_debug(2, "Reinvite race. Waiting %d secs before retry\n", wait); 17097 } 17098 } 17099 break; 17100 17101 case 501: /* Not implemented */ 17102 xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); 17103 if (p->owner) 17104 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 17105 break; 17106 } 17107 if (xmitres == XMIT_ERROR) 17108 ast_log(LOG_WARNING, "Could not transmit message in dialog %s\n", p->callid); 17109 }
| static void handle_response_notify | ( | struct sip_pvt * | p, | |
| int | resp, | |||
| char * | rest, | |||
| struct sip_request * | req, | |||
| int | seqno | |||
| ) | [static] |
Definition at line 17114 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, 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().
17115 { 17116 switch (resp) { 17117 case 200: /* Notify accepted */ 17118 /* They got the notify, this is the end */ 17119 if (p->owner) { 17120 if (!p->refer) { 17121 ast_log(LOG_WARNING, "Notify answer on an owned channel? - %s\n", p->owner->name); 17122 ast_queue_hangup_with_cause(p->owner, AST_CAUSE_NORMAL_UNSPECIFIED); 17123 } else { 17124 ast_debug(4, "Got OK on REFER Notify message\n"); 17125 } 17126 } else { 17127 if (p->subscribed == NONE) { 17128 ast_debug(4, "Got 200 accepted on NOTIFY\n"); 17129 p->needdestroy = 1; 17130 } 17131 if (ast_test_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE)) { 17132 /* Ready to send the next state we have on queue */ 17133 ast_clear_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE); 17134 cb_extensionstate((char *)p->context, (char *)p->exten, p->laststate, (void *) p); 17135 } 17136 } 17137 break; 17138 case 401: /* Not www-authorized on SIP method */ 17139 case 407: /* Proxy auth */ 17140 if (!p->notify_headers) { 17141 break; /* Only device notify can use NOTIFY auth */ 17142 } 17143 ast_string_field_set(p, theirtag, NULL); 17144 if (ast_strlen_zero(p->authname)) { 17145 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)); 17146 p->needdestroy = 1; 17147 } 17148 if (p->authtries > 1 || do_proxy_auth(p, req, resp, SIP_NOTIFY, 0)) { 17149 ast_log(LOG_NOTICE, "Failed to authenticate on NOTYFY to '%s'\n", get_header(&p->initreq, "From")); 17150 p->needdestroy = 1; 17151 } 17152 break; 17153 } 17154 }
| static void handle_response_peerpoke | ( | struct sip_pvt * | p, | |
| int | resp, | |||
| struct sip_request * | req | |||
| ) | [static] |
Handle qualification responses (OPTIONS).
Definition at line 17360 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, SENTINEL, sip_cfg, sip_poke_peer_s(), TRUE, and unref_peer().
Referenced by handle_response().
17361 { 17362 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! */ 17363 int statechanged, is_reachable, was_reachable; 17364 int pingtime = ast_tvdiff_ms(ast_tvnow(), peer->ps); 17365 17366 /* 17367 * Compute the response time to a ping (goes in peer->lastms.) 17368 * -1 means did not respond, 0 means unknown, 17369 * 1..maxms is a valid response, >maxms means late response. 17370 */ 17371 if (pingtime < 1) /* zero = unknown, so round up to 1 */ 17372 pingtime = 1; 17373 17374 /* Now determine new state and whether it has changed. 17375 * Use some helper variables to simplify the writing 17376 * of the expressions. 17377 */ 17378 was_reachable = peer->lastms > 0 && peer->lastms <= peer->maxms; 17379 is_reachable = pingtime <= peer->maxms; 17380 statechanged = peer->lastms == 0 /* yes, unknown before */ 17381 || was_reachable != is_reachable; 17382 17383 peer->lastms = pingtime; 17384 peer->call = dialog_unref(peer->call, "unref dialog peer->call"); 17385 if (statechanged) { 17386 const char *s = is_reachable ? "Reachable" : "Lagged"; 17387 char str_lastms[20]; 17388 snprintf(str_lastms, sizeof(str_lastms), "%d", pingtime); 17389 17390 ast_log(LOG_NOTICE, "Peer '%s' is now %s. (%dms / %dms)\n", 17391 peer->name, s, pingtime, peer->maxms); 17392 ast_devstate_changed(AST_DEVICE_UNKNOWN, "SIP/%s", peer->name); 17393 if (sip_cfg.peer_rtupdate) { 17394 ast_update_realtime(ast_check_realtime("sipregs") ? "sipregs" : "sippeers", "name", peer->name, "lastms", str_lastms, SENTINEL); 17395 } 17396 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", 17397 "ChannelType: SIP\r\nPeer: SIP/%s\r\nPeerStatus: %s\r\nTime: %d\r\n", 17398 peer->name, s, pingtime); 17399 if (is_reachable && global_regextenonqualify) 17400 register_peer_exten(peer, TRUE); 17401 } 17402 17403 p->needdestroy = 1; 17404 17405 /* Try again eventually */ 17406 AST_SCHED_REPLACE_UNREF(peer->pokeexpire, sched, 17407 is_reachable ? peer->qualifyfreq : DEFAULT_FREQ_NOTOK, 17408 sip_poke_peer_s, peer, 17409 unref_peer(_data, "removing poke peer ref"), 17410 unref_peer(peer, "removing poke peer ref"), 17411 ref_peer(peer, "adding poke peer ref")); 17412 }
| static void handle_response_refer | ( | struct sip_pvt * | p, | |
| int | resp, | |||
| char * | rest, | |||
| struct sip_request * | req, | |||
| int | seqno | |||
| ) | [static] |
Definition at line 17159 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().
17160 { 17161 /* If no refer structure exists, then do nothing */ 17162 if (!p->refer) 17163 return; 17164 17165 switch (resp) { 17166 case 202: /* Transfer accepted */ 17167 /* We need to do something here */ 17168 /* The transferee is now sending INVITE to target */ 17169 p->refer->status = REFER_ACCEPTED; 17170 /* Now wait for next message */ 17171 ast_debug(3, "Got 202 accepted on transfer\n"); 17172 /* We should hang along, waiting for NOTIFY's here */ 17173 break; 17174 17175 case 401: /* Not www-authorized on SIP method */ 17176 case 407: /* Proxy auth */ 17177 if (ast_strlen_zero(p->authname)) { 17178 ast_log(LOG_WARNING, "Asked to authenticate REFER to %s:%d but we have no matching peer or realm auth!\n", 17179 ast_inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port)); 17180 p->needdestroy = 1; 17181 } 17182 if (p->authtries > 1 || do_proxy_auth(p, req, resp, SIP_REFER, 0)) { 17183 ast_log(LOG_NOTICE, "Failed to authenticate on REFER to '%s'\n", get_header(&p->initreq, "From")); 17184 p->refer->status = REFER_NOAUTH; 17185 p->needdestroy = 1; 17186 } 17187 break; 17188 case 481: /* Call leg does not exist */ 17189 17190 /* A transfer with Replaces did not work */ 17191 /* OEJ: We should Set flag, cancel the REFER, go back 17192 to original call - but right now we can't */ 17193 ast_log(LOG_WARNING, "Remote host can't match REFER request to call '%s'. Giving up.\n", p->callid); 17194 if (p->owner) 17195 ast_queue_control(p->owner, AST_CONTROL_CONGESTION); 17196 p->needdestroy = 1; 17197 break; 17198 17199 case 500: /* Server error */ 17200 case 501: /* Method not implemented */ 17201 /* Return to the current call onhold */ 17202 /* Status flag needed to be reset */ 17203 ast_log(LOG_NOTICE, "SIP transfer to %s failed, call miserably fails. \n", p->refer->refer_to); 17204 p->needdestroy = 1; 17205 p->refer->status = REFER_FAILED; 17206 break; 17207 case 603: /* Transfer declined */ 17208 ast_log(LOG_NOTICE, "SIP transfer to %s declined, call miserably fails. \n", p->refer->refer_to); 17209 p->refer->status = REFER_FAILED; 17210 p->needdestroy = 1; 17211 break; 17212 } 17213 }
| 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 17216 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, SIP_REGISTER, sip_reregister(), sip_scheddestroy(), strcasestr(), sip_registry::timeout, transmit_register(), sip_pvt::username, and sip_registry::username.
Referenced by handle_response().
17217 { 17218 int expires, expires_ms; 17219 struct sip_registry *r; 17220 r=p->registry; 17221 17222 switch (resp) { 17223 case 401: /* Unauthorized */ 17224 if (p->authtries == MAX_AUTHTRIES || do_register_auth(p, req, resp)) { 17225 ast_log(LOG_NOTICE, "Failed to authenticate on REGISTER to '%s@%s' (Tries %d)\n", p->registry->username, p->registry->hostname, p->authtries); 17226 p->needdestroy = 1; 17227 } 17228 break; 17229 case 403: /* Forbidden */ 17230 ast_log(LOG_WARNING, "Forbidden - wrong password on authentication for REGISTER for '%s' to '%s'\n", p->registry->username, p->registry->hostname); 17231 AST_SCHED_DEL_UNREF(sched, r->timeout, registry_unref(r, "reg ptr unref from handle_response_register 403")); 17232 r->regstate = REG_STATE_NOAUTH; 17233 p->needdestroy = 1; 17234 break; 17235 case 404: /* Not found */ 17236 ast_log(LOG_WARNING, "Got 404 Not found on SIP register to service %s@%s, giving up\n", p->registry->username, p->registry->hostname); 17237 p->needdestroy = 1; 17238 if (r->call) 17239 r->call = dialog_unref(r->call, "unsetting registry->call pointer-- case 404"); 17240 r->regstate = REG_STATE_REJECTED; 17241 AST_SCHED_DEL_UNREF(sched, r->timeout, registry_unref(r, "reg ptr unref from handle_response_register 404")); 17242 break; 17243 case 407: /* Proxy auth */ 17244 if (p->authtries == MAX_AUTHTRIES || do_register_auth(p, req, resp)) { 17245 ast_log(LOG_NOTICE, "Failed to authenticate on REGISTER to '%s' (tries '%d')\n", get_header(&p->initreq, "From"), p->authtries); 17246 p->needdestroy = 1; 17247 } 17248 break; 17249 case 408: /* Request timeout */ 17250 /* Got a timeout response, so reset the counter of failed responses */ 17251 if (r) { 17252 r->regattempts = 0; 17253 } else { 17254 ast_log(LOG_WARNING, "Got a 408 response to our REGISTER on call %s after we had destroyed the registry object\n", p->callid); 17255 } 17256 break; 17257 case 423: /* Interval too brief */ 17258 r->expiry = atoi(get_header(req, "Min-Expires")); 17259 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); 17260 AST_SCHED_DEL_UNREF(sched, r->timeout, registry_unref(r, "reg ptr unref from handle_response_register 423")); 17261 if (r->call) { 17262 r->call = dialog_unref(r->call, "unsetting registry->call pointer-- case 423"); 17263 p->needdestroy = 1; 17264 } 17265 if (r->expiry > max_expiry) { 17266 ast_log(LOG_WARNING, "Required expiration time from %s@%s is too high, giving up\n", p->registry->username, p->registry->hostname); 17267 r->expiry = r->configured_expiry; 17268 r->regstate = REG_STATE_REJECTED; 17269 } else { 17270 r->regstate = REG_STATE_UNREGISTERED; 17271 transmit_register(r, SIP_REGISTER, NULL, NULL); 17272 } 17273 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)); 17274 break; 17275 case 479: /* SER: Not able to process the URI - address is wrong in register*/ 17276 ast_log(LOG_WARNING, "Got error 479 on register to %s@%s, giving up (check config)\n", p->registry->username, p->registry->hostname); 17277 p->needdestroy = 1; 17278 if (r->call) 17279 r->call = dialog_unref(r->call, "unsetting registry->call pointer-- case 479"); 17280 r->regstate = REG_STATE_REJECTED; 17281 AST_SCHED_DEL_UNREF(sched, r->timeout, registry_unref(r, "reg ptr unref from handle_response_register 479")); 17282 break; 17283 case 200: /* 200 OK */ 17284 if (!r) { 17285 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)); 17286 p->needdestroy = 1; 17287 return 0; 17288 } 17289 17290 r->regstate = REG_STATE_REGISTERED; 17291 r->regtime = ast_tvnow(); /* Reset time of last succesful registration */ 17292 manager_event(EVENT_FLAG_SYSTEM, "Registry", "ChannelType: SIP\r\nDomain: %s\r\nStatus: %s\r\n", r->hostname, regstate2str(r->regstate)); 17293 r->regattempts = 0; 17294 ast_debug(1, "Registration successful\n"); 17295 if (r->timeout > -1) { 17296 ast_debug(1, "Cancelling timeout %d\n", r->timeout); 17297 } 17298 AST_SCHED_DEL_UNREF(sched, r->timeout, registry_unref(r, "reg ptr unref from handle_response_register 200")); 17299 if (r->call) 17300 r->call = dialog_unref(r->call, "unsetting registry->call pointer-- case 200"); 17301 p->registry = registry_unref(p->registry, "unref registry entry p->registry"); 17302 /* Let this one hang around until we have all the responses */ 17303 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 17304 /* p->needdestroy = 1; */ 17305 17306 /* set us up for re-registering 17307 * figure out how long we got registered for 17308 * according to section 6.13 of RFC, contact headers override 17309 * expires headers, so check those first */ 17310 expires = 0; 17311 17312 /* XXX todo: try to save the extra call */ 17313 if (!ast_strlen_zero(get_header(req, "Contact"))) { 17314 const char *contact = NULL; 17315 const char *tmptmp = NULL; 17316 int start = 0; 17317 for(;;) { 17318 contact = __get_header(req, "Contact", &start); 17319 /* this loop ensures we get a contact header about our register request */ 17320 if(!ast_strlen_zero(contact)) { 17321 if( (tmptmp=strstr(contact, p->our_contact))) { 17322 contact=tmptmp; 17323 break; 17324 } 17325 } else 17326 break; 17327 } 17328 tmptmp = strcasestr(contact, "expires="); 17329 if (tmptmp) { 17330 if (sscanf(tmptmp + 8, "%30d;", &expires) != 1) 17331 expires = 0; 17332 } 17333 17334 } 17335 if (!expires) 17336 expires=atoi(get_header(req, "expires")); 17337 if (!expires) 17338 expires=default_expiry; 17339 17340 expires_ms = expires * 1000; 17341 if (expires <= EXPIRY_GUARD_LIMIT) 17342 expires_ms -= MAX((expires_ms * EXPIRY_GUARD_PCT), EXPIRY_GUARD_MIN); 17343 else 17344 expires_ms -= EXPIRY_GUARD_SECS * 1000; 17345 if (sipdebug) 17346 ast_log(LOG_NOTICE, "Outbound Registration: Expiry for %s is %d sec (Scheduling reregistration in %d s)\n", r->hostname, expires, expires_ms/1000); 17347 17348 r->refresh= (int) expires_ms / 1000; 17349 17350 /* Schedule re-registration before we expire */ 17351 AST_SCHED_REPLACE_UNREF(r->expire, sched, expires_ms, sip_reregister, r, 17352 registry_unref(_data,"unref in REPLACE del fail"), 17353 registry_unref(r,"unref in REPLACE add fail"), 17354 registry_addref(r,"The Addition side of REPLACE")); 17355 } 17356 return 1; 17357 }
| 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 22310 of file chan_sip.c.
References ast_clear_flag, ast_log(), ast_set2_flag, ast_set_flag, ast_strdupa, ast_true(), buf, ast_variable::lineno, LOG_WARNING, ast_variable::name, 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(), and reload_config().
22312 { 22313 int res = 1; 22314 22315 if (!strcasecmp(v->name, "t38pt_udptl")) { 22316 char *buf = ast_strdupa(v->value); 22317 char *word, *next = buf; 22318 22319 ast_set_flag(&mask[1], SIP_PAGE2_T38SUPPORT); 22320 22321 while ((word = strsep(&next, ","))) { 22322 if (ast_true(word) || !strcasecmp(word, "fec")) { 22323 ast_clear_flag(&flags[1], SIP_PAGE2_T38SUPPORT); 22324 ast_set_flag(&flags[1], SIP_PAGE2_T38SUPPORT_UDPTL_FEC); 22325 } else if (!strcasecmp(word, "redundancy")) { 22326 ast_clear_flag(&flags[1], SIP_PAGE2_T38SUPPORT); 22327 ast_set_flag(&flags[1], SIP_PAGE2_T38SUPPORT_UDPTL_REDUNDANCY); 22328 } else if (!strcasecmp(word, "none")) { 22329 ast_clear_flag(&flags[1], SIP_PAGE2_T38SUPPORT); 22330 ast_set_flag(&flags[1], SIP_PAGE2_T38SUPPORT_UDPTL); 22331 } else if (!strncasecmp(word, "maxdatagram=", 12)) { 22332 if (sscanf(&word[12], "%30u", maxdatagram) != 1) { 22333 ast_log(LOG_WARNING, "Invalid maxdatagram '%s' at line %d of %s\n", v->value, v->lineno, config); 22334 *maxdatagram = global_t38_maxdatagram; 22335 } 22336 } 22337 } 22338 } else if (!strcasecmp(v->name, "t38pt_usertpsource")) { 22339 ast_set_flag(&mask[1], SIP_PAGE2_UDPTL_DESTINATION); 22340 ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_UDPTL_DESTINATION); 22341 } else { 22342 res = 0; 22343 } 22344 22345 return res; 22346 }
| 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 5507 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().
05508 { 05509 switch (cause) { 05510 case AST_CAUSE_UNALLOCATED: /* 1 */ 05511 case AST_CAUSE_NO_ROUTE_DESTINATION: /* 3 IAX2: Can't find extension in context */ 05512 case AST_CAUSE_NO_ROUTE_TRANSIT_NET: /* 2 */ 05513 return "404 Not Found"; 05514 case AST_CAUSE_CONGESTION: /* 34 */ 05515 case AST_CAUSE_SWITCH_CONGESTION: /* 42 */ 05516 return "503 Service Unavailable"; 05517 case AST_CAUSE_NO_USER_RESPONSE: /* 18 */ 05518 return "408 Request Timeout"; 05519 case AST_CAUSE_NO_ANSWER: /* 19 */ 05520 case AST_CAUSE_UNREGISTERED: /* 20 */ 05521 return "480 Temporarily unavailable"; 05522 case AST_CAUSE_CALL_REJECTED: /* 21 */ 05523 return "403 Forbidden"; 05524 case AST_CAUSE_NUMBER_CHANGED: /* 22 */ 05525 return "410 Gone"; 05526 case AST_CAUSE_NORMAL_UNSPECIFIED: /* 31 */ 05527 return "480 Temporarily unavailable"; 05528 case AST_CAUSE_INVALID_NUMBER_FORMAT: 05529 return "484 Address incomplete"; 05530 case AST_CAUSE_USER_BUSY: 05531 return "486 Busy here"; 05532 case AST_CAUSE_FAILURE: 05533 return "500 Server internal failure"; 05534 case AST_CAUSE_FACILITY_REJECTED: /* 29 */ 05535 return "501 Not Implemented"; 05536 case AST_CAUSE_CHAN_NOT_IMPLEMENTED: 05537 return "503 Service Unavailable"; 05538 /* Used in chan_iax2 */ 05539 case AST_CAUSE_DESTINATION_OUT_OF_ORDER: 05540 return "502 Bad Gateway"; 05541 case AST_CAUSE_BEARERCAPABILITY_NOTAVAIL: /* Can't find codec to connect to host */ 05542 return "488 Not Acceptable Here"; 05543 05544 case AST_CAUSE_NOTDEFINED: 05545 default: 05546 ast_debug(1, "AST hangup cause %d (no match found in SIP)\n", cause); 05547 return NULL; 05548 } 05549 05550 /* Never reached */ 05551 return 0; 05552 }
| static int hangup_sip2cause | ( | int | cause | ) | [static] |
Convert SIP hangup causes to Asterisk hangup causes.
Definition at line 5395 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().
05396 { 05397 /* Possible values taken from causes.h */ 05398 05399 switch(cause) { 05400 case 401: /* Unauthorized */ 05401 return AST_CAUSE_CALL_REJECTED; 05402 case 403: /* Not found */ 05403 return AST_CAUSE_CALL_REJECTED; 05404 case 404: /* Not found */ 05405 return AST_CAUSE_UNALLOCATED; 05406 case 405: /* Method not allowed */ 05407 return AST_CAUSE_INTERWORKING; 05408 case 407: /* Proxy authentication required */ 05409 return AST_CAUSE_CALL_REJECTED; 05410 case 408: /* No reaction */ 05411 return AST_CAUSE_NO_USER_RESPONSE; 05412 case 409: /* Conflict */ 05413 return AST_CAUSE_NORMAL_TEMPORARY_FAILURE; 05414 case 410: /* Gone */ 05415 return AST_CAUSE_NUMBER_CHANGED; 05416 case 411: /* Length required */ 05417 return AST_CAUSE_INTERWORKING; 05418 case 413: /* Request entity too large */ 05419 return AST_CAUSE_INTERWORKING; 05420 case 414: /* Request URI too large */ 05421 return AST_CAUSE_INTERWORKING; 05422 case 415: /* Unsupported media type */ 05423 return AST_CAUSE_INTERWORKING; 05424 case 420: /* Bad extension */ 05425 return AST_CAUSE_NO_ROUTE_DESTINATION; 05426 case 480: /* No answer */ 05427 return AST_CAUSE_NO_ANSWER; 05428 case 481: /* No answer */ 05429 return AST_CAUSE_INTERWORKING; 05430 case 482: /* Loop detected */ 05431 return AST_CAUSE_INTERWORKING; 05432 case 483: /* Too many hops */ 05433 return AST_CAUSE_NO_ANSWER; 05434 case 484: /* Address incomplete */ 05435 return AST_CAUSE_INVALID_NUMBER_FORMAT; 05436 case 485: /* Ambiguous */ 05437 return AST_CAUSE_UNALLOCATED; 05438 case 486: /* Busy everywhere */ 05439 return AST_CAUSE_BUSY; 05440 case 487: /* Request terminated */ 05441 return AST_CAUSE_INTERWORKING; 05442 case 488: /* No codecs approved */ 05443 return AST_CAUSE_BEARERCAPABILITY_NOTAVAIL; 05444 case 491: /* Request pending */ 05445 return AST_CAUSE_INTERWORKING; 05446 case 493: /* Undecipherable */ 05447 return AST_CAUSE_INTERWORKING; 05448 case 500: /* Server internal failure */ 05449 return AST_CAUSE_FAILURE; 05450 case 501: /* Call rejected */ 05451 return AST_CAUSE_FACILITY_REJECTED; 05452 case 502: 05453 return AST_CAUSE_DESTINATION_OUT_OF_ORDER; 05454 case 503: /* Service unavailable */ 05455 return AST_CAUSE_CONGESTION; 05456 case 504: /* Gateway timeout */ 05457 return AST_CAUSE_RECOVERY_ON_TIMER_EXPIRE; 05458 case 505: /* SIP version not supported */ 05459 return AST_CAUSE_INTERWORKING; 05460 case 600: /* Busy everywhere */ 05461 return AST_CAUSE_USER_BUSY; 05462 case 603: /* Decline */ 05463 return AST_CAUSE_CALL_REJECTED; 05464 case 604: /* Does not exist anywhere */ 05465 return AST_CAUSE_UNALLOCATED; 05466 case 606: /* Not acceptable */ 05467 return AST_CAUSE_BEARERCAPABILITY_NOTAVAIL; 05468 default: 05469 return AST_CAUSE_NORMAL; 05470 } 05471 /* Never reached */ 05472 return 0; 05473 }
| static int init_req | ( | struct sip_request * | req, | |
| int | sipmethod, | |||
| const char * | recip | |||
| ) | [static] |
Initialize SIP request.
Definition at line 8652 of file chan_sip.c.
References ast_str_create(), ast_str_set(), sip_request::data, sip_request::header, sip_request::headers, sip_request::len, sip_request::method, sip_methods, SIP_MIN_PACKET, cfsip_methods::text, and ast_str::used.
Referenced by initreqprep(), reqprep(), and transmit_register().
08653 { 08654 /* Initialize a request */ 08655 memset(req, 0, sizeof(*req)); 08656 if (!(req->data = ast_str_create(SIP_MIN_PACKET))) 08657 return -1; 08658 req->method = sipmethod; 08659 req->header[0] = 0; 08660 ast_str_set(&req->data, 0, "%s %s SIP/2.0\r\n", sip_methods[sipmethod].text, recip); 08661 req->len = req->data->used; 08662 req->headers++; 08663 return 0; 08664 }
| static int init_resp | ( | struct sip_request * | resp, | |
| const char * | msg | |||
| ) | [static] |
Initialize SIP response, based on SIP request.
Definition at line 8637 of file chan_sip.c.
References ast_str_create(), ast_str_set(), sip_request::data, sip_request::header, sip_request::headers, sip_request::len, sip_request::method, SIP_MIN_PACKET, SIP_RESPONSE, and ast_str::used.
Referenced by respprep().
08638 { 08639 /* Initialize a response */ 08640 memset(resp, 0, sizeof(*resp)); 08641 resp->method = SIP_RESPONSE; 08642 if (!(resp->data = ast_str_create(SIP_MIN_PACKET))) 08643 return -1; 08644 resp->header[0] = 0; 08645 ast_str_set(&resp->data, 0, "SIP/2.0 %s\r\n", msg); 08646 resp->len = resp->data->used; 08647 resp->headers++; 08648 return 0; 08649 }
| 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 2891 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(), sip_methods, and cfsip_methods::text.
Referenced by transmit_invite(), transmit_notify_custom(), transmit_notify_with_mwi(), transmit_notify_with_sipfrag(), transmit_register(), and transmit_reinvite_with_sdp().
02892 { 02893 if (p->initreq.headers) 02894 ast_debug(1, "Initializing already initialized SIP dialog %s (presumably reinvite)\n", p->callid); 02895 else 02896 ast_debug(1, "Initializing initreq for method %s - callid %s\n", sip_methods[req->method].text, p->callid); 02897 /* Use this as the basis */ 02898 copy_request(&p->initreq, req); 02899 parse_request(&p->initreq); 02900 if (req->debug) 02901 ast_verbose("Initreq: %d headers, %d lines\n", p->initreq.headers, p->initreq.lines); 02902 }
| static void initreqprep | ( | struct sip_request * | req, | |
| struct sip_pvt * | p, | |||
| int | sipmethod | |||
| ) | [static] |
Initiate new SIP request to peer/user.
Definition at line 10025 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, sip_pvt::rpid_from, 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().
10026 { 10027 struct ast_str *invite = ast_str_alloca(256); 10028 char from[256]; 10029 char to[256]; 10030 char tmp_n[SIPBUFSIZE/2]; /* build a local copy of 'n' if needed */ 10031 char tmp_l[SIPBUFSIZE/2]; /* build a local copy of 'l' if needed */ 10032 const char *l = NULL; /* XXX what is this, exactly ? */ 10033 const char *n = NULL; /* XXX what is this, exactly ? */ 10034 const char *d = NULL; /* domain in from header */ 10035 const char *urioptions = ""; 10036 int ourport; 10037 10038 if (ast_test_flag(&p->flags[0], SIP_USEREQPHONE)) { 10039 const char *s = p->username; /* being a string field, cannot be NULL */ 10040 10041 /* Test p->username against allowed characters in AST_DIGIT_ANY 10042 If it matches the allowed characters list, then sipuser = ";user=phone" 10043 If not, then sipuser = "" 10044 */ 10045 /* + is allowed in first position in a tel: uri */ 10046 if (*s == '+') 10047 s++; 10048 for (; *s; s++) { 10049 if (!strchr(AST_DIGIT_ANYNUM, *s) ) 10050 break; 10051 } 10052 /* If we have only digits, add ;user=phone to the uri */ 10053 if (!*s) 10054 urioptions = ";user=phone"; 10055 } 10056 10057 10058 snprintf(p->lastmsg, sizeof(p->lastmsg), "Init: %s", sip_methods[sipmethod].text); 10059 10060 d = S_OR(p->fromdomain, ast_inet_ntoa(p->ourip.sin_addr)); 10061 if (p->owner) { 10062 l = p->owner->cid.cid_num; 10063 n = p->owner->cid.cid_name; 10064 } 10065 /* if we are not sending RPID and user wants his callerid restricted */ 10066 if (!ast_test_flag(&p->flags[0], SIP_SENDRPID) && 10067 ((p->callingpres & AST_PRES_RESTRICTION) != AST_PRES_ALLOWED)) { 10068 l = CALLERID_UNKNOWN; 10069 n = l; 10070 d = FROMDOMAIN_INVALID; 10071 } 10072 if (ast_strlen_zero(l)) 10073 l = default_callerid; 10074 if (ast_strlen_zero(n)) 10075 n = l; 10076 /* Allow user to be overridden */ 10077 if (!ast_strlen_zero(p->fromuser)) 10078 l = p->fromuser; 10079 else /* Save for any further attempts */ 10080 ast_string_field_set(p, fromuser, l); 10081 10082 /* Allow user to be overridden */ 10083 if (!ast_strlen_zero(p->fromname)) 10084 n = p->fromname; 10085 else /* Save for any further attempts */ 10086 ast_string_field_set(p, fromname, n); 10087 10088 if (pedanticsipchecking) { 10089 ast_uri_encode(n, tmp_n, sizeof(tmp_n), 0); 10090 n = tmp_n; 10091 ast_uri_encode(l, tmp_l, sizeof(tmp_l), 0); 10092 l = tmp_l; 10093 } 10094 10095 ourport = ntohs(p->ourip.sin_port); 10096 if (!sip_standard_port(p->socket.type, ourport) && ast_strlen_zero(p->fromdomain)) 10097 snprintf(from, sizeof(from), "\"%s\" <sip:%s@%s:%d>;tag=%s", n, l, d, ourport, p->tag); 10098 else 10099 snprintf(from, sizeof(from), "\"%s\" <sip:%s@%s>;tag=%s", n, l, d, p->tag); 10100 10101 /* If we're calling a registered SIP peer, use the fullcontact to dial to the peer */ 10102 if (!ast_strlen_zero(p->fullcontact)) { 10103 /* If we have full contact, trust it */ 10104 ast_str_append(&invite, 0, "%s", p->fullcontact); 10105 } else { 10106 /* Otherwise, use the username while waiting for registration */ 10107 ast_str_append(&invite, 0, "sip:"); 10108 if (!ast_strlen_zero(p->username)) { 10109 n = p->username; 10110 if (pedanticsipchecking) { 10111 ast_uri_encode(n, tmp_n, sizeof(tmp_n), 0); 10112 n = tmp_n; 10113 } 10114 ast_str_append(&invite, 0, "%s@", n); 10115 } 10116 ast_str_append(&invite, 0, "%s", p->tohost); 10117 if (p->portinuri) 10118 ast_str_append(&invite, 0, ":%d", ntohs(p->sa.sin_port)); 10119 ast_str_append(&invite, 0, "%s", urioptions); 10120 } 10121 10122 /* If custom URI options have been provided, append them */ 10123 if (p->options && !ast_strlen_zero(p->options->uri_options)) 10124 ast_str_append(&invite, 0, ";%s", p->options->uri_options); 10125 10126 /* This is the request URI, which is the next hop of the call 10127 which may or may not be the destination of the call 10128 */ 10129 ast_string_field_set(p, uri, invite->str); 10130 10131 if (!ast_strlen_zero(p->todnid)) { 10132 /*! \todo Need to add back the VXML URL here at some point, possibly use build_string for all this junk */ 10133 if (!strchr(p->todnid, '@')) { 10134 /* We have no domain in the dnid */ 10135 snprintf(to, sizeof(to), "<sip:%s@%s>%s%s", p->todnid, p->tohost, ast_strlen_zero(p->theirtag) ? "" : ";tag=", p->theirtag); 10136 } else { 10137 snprintf(to, sizeof(to), "<sip:%s>%s%s", p->todnid, ast_strlen_zero(p->theirtag) ? "" : ";tag=", p->theirtag); 10138 } 10139 } else { 10140 if (sipmethod == SIP_NOTIFY && !ast_strlen_zero(p->theirtag)) { 10141 /* If this is a NOTIFY, use the From: tag in the subscribe (RFC 3265) */ 10142 snprintf(to, sizeof(to), "<%s%s>;tag=%s", (!strncasecmp(p->uri, "sip:", 4) ? "sip:" : ""), p->uri, p->theirtag); 10143 } else if (p->options && p->options->vxml_url) { 10144 /* If there is a VXML URL append it to the SIP URL */ 10145 snprintf(to, sizeof(to), "<%s>;%s", p->uri, p->options->vxml_url); 10146 } else 10147 snprintf(to, sizeof(to), "<%s>", p->uri); 10148 } 10149 10150 init_req(req, sipmethod, p->uri); 10151 /* now tmp_n is available so reuse it to build the CSeq */ 10152 snprintf(tmp_n, sizeof(tmp_n), "%d %s", ++p->ocseq, sip_methods[sipmethod].text); 10153 10154 add_header(req, "Via", p->via); 10155 add_header(req, "Max-Forwards", DEFAULT_MAX_FORWARDS); 10156 /* This will be a no-op most of the time. However, under certain circumstances, 10157 * NOTIFY messages will use this function for preparing the request and should 10158 * have Route headers present. 10159 */ 10160 add_route(req, p->route); 10161 10162 /* Build Remote Party-ID and From */ 10163 if (ast_test_flag(&p->flags[0], SIP_SENDRPID) && (sipmethod == SIP_INVITE)) { 10164 build_rpid(p); 10165 add_header(req, "From", p->rpid_from); 10166 } else 10167 add_header(req, "From", from); 10168 add_header(req, "To", to); 10169 ast_string_field_set(p, exten, l); 10170 build_contact(p); 10171 add_header(req, "Contact", p->our_contact); 10172 add_header(req, "Call-ID", p->callid); 10173 add_header(req, "CSeq", tmp_n); 10174 if (!ast_strlen_zero(global_useragent)) 10175 add_header(req, "User-Agent", global_useragent); 10176 if (!ast_strlen_zero(p->rpid)) 10177 add_header(req, "Remote-Party-ID", p->rpid); 10178 }
| static const char * insecure2str | ( | int | mode | ) | [static] |
Convert Insecure setting to printable string.
Definition at line 14118 of file chan_sip.c.
References map_x_s().
Referenced by _sip_show_peer().
14119 { 14120 return map_x_s(insecurestr, mode, "<error>"); 14121 }
| 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 6021 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, 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().
06022 { 06023 if (!ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT)) { 06024 return; 06025 } 06026 switch (parameters->request_response) { 06027 case AST_T38_NEGOTIATED: 06028 case AST_T38_REQUEST_NEGOTIATE: /* Request T38 */ 06029 /* Negotiation can not take place without a valid max_ifp value. */ 06030 if (!parameters->max_ifp) { 06031 change_t38_state(p, T38_DISABLED); 06032 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 transmit_response_reliable(p, "488 Not acceptable here", &p->initreq); 06035 } 06036 break; 06037 } else if (p->t38.state == T38_PEER_REINVITE) { 06038 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")); 06039 p->t38.our_parms = *parameters; 06040 /* modify our parameters to conform to the peer's parameters, 06041 * based on the rules in the ITU T.38 recommendation 06042 */ 06043 if (!p->t38.their_parms.fill_bit_removal) { 06044 p->t38.our_parms.fill_bit_removal = FALSE; 06045 } 06046 if (!p->t38.their_parms.transcoding_mmr) { 06047 p->t38.our_parms.transcoding_mmr = FALSE; 06048 } 06049 if (!p->t38.their_parms.transcoding_jbig) { 06050 p->t38.our_parms.transcoding_jbig = FALSE; 06051 } 06052 p->t38.our_parms.version = MIN(p->t38.our_parms.version, p->t38.their_parms.version); 06053 p->t38.our_parms.rate_management = p->t38.their_parms.rate_management; 06054 ast_udptl_set_local_max_ifp(p->udptl, p->t38.our_parms.max_ifp); 06055 change_t38_state(p, T38_ENABLED); 06056 transmit_response_with_t38_sdp(p, "200 OK", &p->initreq, XMIT_CRITICAL); 06057 } else if (p->t38.state != T38_ENABLED) { 06058 p->t38.our_parms = *parameters; 06059 ast_udptl_set_local_max_ifp(p->udptl, p->t38.our_parms.max_ifp); 06060 change_t38_state(p, T38_LOCAL_REINVITE); 06061 if (!p->pendinginvite) { 06062 transmit_reinvite_with_sdp(p, TRUE, FALSE); 06063 } else if (!ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) { 06064 ast_set_flag(&p->flags[0], SIP_NEEDREINVITE); 06065 } 06066 } 06067 break; 06068 case AST_T38_TERMINATED: 06069 case AST_T38_REFUSED: 06070 case AST_T38_REQUEST_TERMINATE: /* Shutdown T38 */ 06071 if (p->t38.state == T38_PEER_REINVITE) { 06072 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")); 06073 change_t38_state(p, T38_DISABLED); 06074 transmit_response_reliable(p, "488 Not acceptable here", &p->initreq); 06075 } else if (p->t38.state == T38_ENABLED) 06076 transmit_reinvite_with_sdp(p, FALSE, FALSE); 06077 break; 06078 default: 06079 break; 06080 } 06081 }
| static void list_route | ( | struct sip_route * | route | ) | [static] |
List all routes - mostly for debugging.
Definition at line 11641 of file chan_sip.c.
References ast_verbose, sip_route::hop, and sip_route::next.
Referenced by build_route().
11642 { 11643 if (!route) 11644 ast_verbose("list_route: no route\n"); 11645 else { 11646 for (;route; route = route->next) 11647 ast_verbose("list_route: hop: <%s>\n", route->hop); 11648 } 11649 }
| static int load_module | ( | void | ) | [static] |
PBX load module - initialization.
Definition at line 24653 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, dialog_cmp_cb(), dialog_hash_cb(), dialogs, EVENT_FLAG_REPORTING, EVENT_FLAG_SYSTEM, 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(), peer_cmp_cb(), peer_hash_cb(), peer_ipcmp_cb(), peer_iphash_cb(), regl, reload_config(), restart_monitor(), RQ_CHAR, RQ_INTEGER4, RQ_UINTEGER2, sched_context_create(), sched_context_destroy(), ast_channel_tech::send_digit_begin, SENTINEL, sip_addheader(), sip_dtmfmode(), sip_poke_all_peers(), sip_send_all_registers(), sip_tech_info, threadt_cmp_cb(), and threadt_hash_cb().
24654 { 24655 ast_verbose("SIP channel loading...\n"); 24656 /* the fact that ao2_containers can't resize automatically is a major worry! */ 24657 /* if the number of objects gets above MAX_XXX_BUCKETS, things will slow down */ 24658 peers = ao2_t_container_alloc(hash_peer_size, peer_hash_cb, peer_cmp_cb, "allocate peers"); 24659 peers_by_ip = ao2_t_container_alloc(hash_peer_size, peer_iphash_cb, peer_ipcmp_cb, "allocate peers_by_ip"); 24660 dialogs = ao2_t_container_alloc(hash_dialog_size, dialog_hash_cb, dialog_cmp_cb, "allocate dialogs"); 24661 threadt = ao2_t_container_alloc(hash_dialog_size, threadt_hash_cb, threadt_cmp_cb, "allocate threadt table"); 24662 24663 ASTOBJ_CONTAINER_INIT(®l); /* Registry object list -- not searched for anything */ 24664 24665 if (!(sched = sched_context_create())) { 24666 ast_log(LOG_ERROR, "Unable to create scheduler context\n"); 24667 return AST_MODULE_LOAD_FAILURE; 24668 } 24669 24670 if (!(io = io_context_create())) { 24671 ast_log(LOG_ERROR, "Unable to create I/O context\n"); 24672 sched_context_destroy(sched); 24673 return AST_MODULE_LOAD_FAILURE; 24674 } 24675 24676 sip_reloadreason = CHANNEL_MODULE_LOAD; 24677 24678 if(reload_config(sip_reloadreason)) /* Load the configuration from sip.conf */ 24679 return AST_MODULE_LOAD_DECLINE; 24680 24681 /* Prepare the version that does not require DTMF BEGIN frames. 24682 * We need to use tricks such as memcpy and casts because the variable 24683 * has const fields. 24684 */ 24685 memcpy(&sip_tech_info, &sip_tech, sizeof(sip_tech)); 24686 memset((void *) &sip_tech_info.send_digit_begin, 0, sizeof(sip_tech_info.send_digit_begin)); 24687 24688 /* Make sure we can register our sip channel type */ 24689 if (ast_channel_register(&sip_tech)) { 24690 ast_log(LOG_ERROR, "Unable to register channel type 'SIP'\n"); 24691 io_context_destroy(io); 24692 sched_context_destroy(sched); 24693 return AST_MODULE_LOAD_FAILURE; 24694 } 24695 24696 /* Register all CLI functions for SIP */ 24697 ast_cli_register_multiple(cli_sip, sizeof(cli_sip)/ sizeof(struct ast_cli_entry)); 24698 24699 /* Tell the RTP subdriver that we're here */ 24700 ast_rtp_proto_register(&sip_rtp); 24701 24702 /* Tell the UDPTL subdriver that we're here */ 24703 ast_udptl_proto_register(&sip_udptl); 24704 24705 /* Register dialplan applications */ 24706 ast_register_application(app_dtmfmode, sip_dtmfmode, synopsis_dtmfmode, descrip_dtmfmode); 24707 ast_register_application(app_sipaddheader, sip_addheader, synopsis_sipaddheader, descrip_sipaddheader); 24708 24709 /* Register dialplan functions */ 24710 ast_custom_function_register(&sip_header_function); 24711 ast_custom_function_register(&sippeer_function); 24712 ast_custom_function_register(&sipchaninfo_function); 24713 ast_custom_function_register(&checksipdomain_function); 24714 24715 /* Register manager commands */ 24716 ast_manager_register2("SIPpeers", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_sip_show_peers, 24717 "List SIP peers (text format)", mandescr_show_peers); 24718 ast_manager_register2("SIPshowpeer", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_sip_show_peer, 24719 "Show SIP peer (text format)", mandescr_show_peer); 24720 ast_manager_register2("SIPqualifypeer", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_sip_qualify_peer, 24721 "Show SIP peer (text format)", mandescr_show_peer); /*! \todo Fix this XXX This must be all wrong XXXX */ 24722 ast_manager_register2("SIPshowregistry", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_show_registry, 24723 "Show SIP registrations (text format)", mandescr_show_registry); 24724 ast_manager_register2("SIPnotify", EVENT_FLAG_SYSTEM, manager_sipnotify, 24725 "Send a SIP notify", mandescr_sipnotify); 24726 sip_poke_all_peers(); 24727 sip_send_all_registers(); 24728 24729 /* And start the monitor for the first time */ 24730 restart_monitor(); 24731 24732 ast_realtime_require_field(ast_check_realtime("sipregs") ? "sipregs" : "sippeers", 24733 "name", RQ_CHAR, 10, 24734 "ipaddr", RQ_CHAR, 15, 24735 "port", RQ_UINTEGER2, 5, 24736 "regseconds", RQ_INTEGER4, 11, 24737 "defaultuser", RQ_CHAR, 10, 24738 "fullcontact", RQ_CHAR, 35, 24739 "regserver", RQ_CHAR, 20, 24740 "useragent", RQ_CHAR, 20, 24741 "lastms", RQ_INTEGER4, 11, 24742 SENTINEL); 24743 24744 return AST_MODULE_LOAD_SUCCESS; 24745 }
| 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 19475 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, 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(), and TRUE.
Referenced by handle_request_refer().
19476 { 19477 struct sip_dual target; /* Chan 1: Call from tranferer to Asterisk */ 19478 /* Chan 2: Call from Asterisk to target */ 19479 int res = 0; 19480 struct sip_pvt *targetcall_pvt; 19481 19482 /* Check if the call ID of the replaces header does exist locally */ 19483 if (!(targetcall_pvt = get_sip_pvt_byid_locked(transferer->refer->replaces_callid, transferer->refer->replaces_callid_totag, 19484 transferer->refer->replaces_callid_fromtag))) { 19485 if (transferer->refer->localtransfer) { 19486 /* We did not find the refered call. Sorry, can't accept then */ 19487 transmit_response(transferer, "202 Accepted", req); 19488 /* Let's fake a response from someone else in order 19489 to follow the standard */ 19490 transmit_notify_with_sipfrag(transferer, seqno, "481 Call leg/transaction does not exist", TRUE); 19491 append_history(transferer, "Xfer", "Refer failed"); 19492 ast_clear_flag(&transferer->flags[0], SIP_GOTREFER); 19493 transferer->refer->status = REFER_FAILED; 19494 return -1; 19495 } 19496 /* Fall through for remote transfers that we did not find locally */ 19497 ast_debug(3, "SIP attended transfer: Not our call - generating INVITE with replaces\n"); 19498 return 0; 19499 } 19500 19501 /* Ok, we can accept this transfer */ 19502 transmit_response(transferer, "202 Accepted", req); 19503 append_history(transferer, "Xfer", "Refer accepted"); 19504 if (!targetcall_pvt->owner) { /* No active channel */ 19505 ast_debug(4, "SIP attended transfer: Error: No owner of target call\n"); 19506 /* Cancel transfer */ 19507 transmit_notify_with_sipfrag(transferer, seqno, "503 Service Unavailable", TRUE); 19508 append_history(transferer, "Xfer", "Refer failed"); 19509 ast_clear_flag(&transferer->flags[0], SIP_GOTREFER); 19510 transferer->refer->status = REFER_FAILED; 19511 sip_pvt_unlock(targetcall_pvt); 19512 if (targetcall_pvt) 19513 ao2_t_ref(targetcall_pvt, -1, "Drop targetcall_pvt pointer"); 19514 return -1; 19515 } 19516 19517 /* We have a channel, find the bridge */ 19518 target.chan1 = targetcall_pvt->owner; /* Transferer to Asterisk */ 19519 target.chan2 = ast_bridged_channel(targetcall_pvt->owner); /* Asterisk to target */ 19520 19521 if (!target.chan2 || !(target.chan2->_state == AST_STATE_UP || target.chan2->_state == AST_STATE_RINGING) ) { 19522 /* Wrong state of new channel */ 19523 if (target.chan2) 19524 ast_debug(4, "SIP attended transfer: Error: Wrong state of target call: %s\n", ast_state2str(target.chan2->_state)); 19525 else if (target.chan1->_state != AST_STATE_RING) 19526 ast_debug(4, "SIP attended transfer: Error: No target channel\n"); 19527 else 19528 ast_debug(4, "SIP attended transfer: Attempting transfer in ringing state\n"); 19529 } 19530 19531 /* Transfer */ 19532 if (sipdebug) { 19533 if (current->chan2) /* We have two bridges */ 19534 ast_debug(4, "SIP attended transfer: trying to bridge %s and %s\n", target.chan1->name, current->chan2->name); 19535 else /* One bridge, propably transfer of IVR/voicemail etc */ 19536 ast_debug(4, "SIP attended transfer: trying to make %s take over (masq) %s\n", target.chan1->name, current->chan1->name); 19537 } 19538 19539 ast_set_flag(&transferer->flags[0], SIP_DEFER_BYE_ON_TRANSFER); /* Delay hangup */ 19540 19541 /* Perform the transfer */ 19542 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", 19543 transferer->owner->name, 19544 transferer->owner->uniqueid, 19545 transferer->callid, 19546 target.chan1->name, 19547 target.chan1->uniqueid); 19548 res = attempt_transfer(current, &target); 19549 sip_pvt_unlock(targetcall_pvt); 19550 if (res) { 19551 /* Failed transfer */ 19552 transmit_notify_with_sipfrag(transferer, seqno, "486 Busy Here", TRUE); 19553 append_history(transferer, "Xfer", "Refer failed"); 19554 if (targetcall_pvt->owner) 19555 ast_channel_unlock(targetcall_pvt->owner); 19556 ast_clear_flag(&transferer->flags[0], SIP_DEFER_BYE_ON_TRANSFER); 19557 } else { 19558 /* Transfer succeeded! */ 19559 19560 /* Tell transferer that we're done. */ 19561 transmit_notify_with_sipfrag(transferer, seqno, "200 OK", TRUE); 19562 append_history(transferer, "Xfer", "Refer succeeded"); 19563 transferer->refer->status = REFER_200OK; 19564 if (targetcall_pvt->owner) { 19565 ast_debug(1, "SIP attended transfer: Unlocking channel %s\n", targetcall_pvt->owner->name); 19566 ast_channel_unlock(targetcall_pvt->owner); 19567 } 19568 } 19569 if (targetcall_pvt) 19570 ao2_t_ref(targetcall_pvt, -1, "drop targetcall_pvt"); 19571 return 1; 19572 }
| 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 7154 of file chan_sip.c.
Referenced by handle_request_do().
07155 { 07156 int h = 0, t = 0; 07157 int lws = 0; 07158 07159 for (; h < len;) { 07160 /* Eliminate all CRs */ 07161 if (msgbuf[h] == '\r') { 07162 h++; 07163 continue; 07164 } 07165 /* Check for end-of-line */ 07166 if (msgbuf[h] == '\n') { 07167 /* Check for end-of-message */ 07168 if (h + 1 == len) 07169 break; 07170 /* Check for a continuation line */ 07171 if (msgbuf[h + 1] == ' ' || msgbuf[h + 1] == '\t') { 07172 /* Merge continuation line */ 07173 h++; 07174 continue; 07175 } 07176 /* Propagate LF and start new line */ 07177 msgbuf[t++] = msgbuf[h++]; 07178 lws = 0; 07179 continue; 07180 } 07181 if (msgbuf[h] == ' ' || msgbuf[h] == '\t') { 07182 if (lws) { 07183 h++; 07184 continue; 07185 } 07186 msgbuf[t++] = msgbuf[h++]; 07187 lws = 1; 07188 continue; 07189 } 07190 msgbuf[t++] = msgbuf[h++]; 07191 if (lws) 07192 lws = 0; 07193 } 07194 msgbuf[t] = '\0'; 07195 return t; 07196 }
| static void make_our_tag | ( | char * | tagbuf, | |
| size_t | len | |||
| ) | [static] |
Make our SIP dialog tag.
Definition at line 6710 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().
06711 { 06712 snprintf(tagbuf, len, "as%08lx", ast_random()); 06713 }
| static int manager_show_registry | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Show SIP registrations in the manager API.
Definition at line 13760 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(), STANDARD_SIP_PORT, and total.
Referenced by load_module().
13761 { 13762 const char *id = astman_get_header(m, "ActionID"); 13763 char idtext[256] = ""; 13764 int total = 0; 13765 13766 if (!ast_strlen_zero(id)) 13767 snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id); 13768 13769 astman_send_listack(s, m, "Registrations will follow", "start"); 13770 13771 ASTOBJ_CONTAINER_TRAVERSE(®l, 1, do { 13772 ASTOBJ_RDLOCK(iterator); 13773 astman_append(s, 13774 "Event: RegistryEntry\r\n" 13775 "%s" 13776 "Host: %s\r\n" 13777 "Port: %d\r\n" 13778 "Username: %s\r\n" 13779 "Refresh: %d\r\n" 13780 "State: %s\r\n" 13781 "RegistrationTime: %ld\r\n" 13782 "\r\n", idtext, iterator->hostname, iterator->portno ? iterator->portno : STANDARD_SIP_PORT, 13783 iterator->username, iterator->refresh, regstate2str(iterator->regstate), (long) iterator->regtime.tv_sec); 13784 ASTOBJ_UNLOCK(iterator); 13785 total++; 13786 } while(0)); 13787 13788 astman_append(s, 13789 "Event: RegistrationsComplete\r\n" 13790 "EventList: Complete\r\n" 13791 "ListItems: %d\r\n" 13792 "%s" 13793 "\r\n", total, idtext); 13794 13795 return 0; 13796 }
| static int manager_sip_qualify_peer | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Qualify SIP peers in the manager API.
Definition at line 14487 of file chan_sip.c.
References _sip_qualify_peer(), ast_strlen_zero(), astman_append(), astman_get_header(), and astman_send_error().
Referenced by load_module().
14488 { 14489 const char *a[4]; 14490 const char *peer; 14491 14492 peer = astman_get_header(m, "Peer"); 14493 if (ast_strlen_zero(peer)) { 14494 astman_send_error(s, m, "Peer: <name> missing."); 14495 return 0; 14496 } 14497 a[0] = "sip"; 14498 a[1] = "qualify"; 14499 a[2] = "peer"; 14500 a[3] = peer; 14501 14502 _sip_qualify_peer(1, -1, s, m, 4, a); 14503 astman_append(s, "\r\n\r\n" ); 14504 return 0; 14505 }
| static int manager_sip_show_peer | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Show SIP peers in the manager API.
Definition at line 14428 of file chan_sip.c.
References _sip_show_peer(), ast_strlen_zero(), astman_append(), astman_get_header(), and astman_send_error().
Referenced by load_module().
14429 { 14430 const char *a[4]; 14431 const char *peer; 14432 14433 peer = astman_get_header(m, "Peer"); 14434 if (ast_strlen_zero(peer)) { 14435 astman_send_error(s, m, "Peer: <name> missing."); 14436 return 0; 14437 } 14438 a[0] = "sip"; 14439 a[1] = "show"; 14440 a[2] = "peer"; 14441 a[3] = peer; 14442 14443 _sip_show_peer(1, -1, s, m, 4, a); 14444 astman_append(s, "\r\n\r\n" ); 14445 return 0; 14446 }
| static int manager_sip_show_peers | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Show SIP peers in the manager API.
Definition at line 13807 of file chan_sip.c.
References _sip_show_peers(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_listack(), and total.
Referenced by load_module().
13808 { 13809 const char *id = astman_get_header(m, "ActionID"); 13810 const char *a[] = {"sip", "show", "peers"}; 13811 char idtext[256] = ""; 13812 int total = 0; 13813 13814 if (!ast_strlen_zero(id)) 13815 snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id); 13816 13817 astman_send_listack(s, m, "Peer status list will follow", "start"); 13818 /* List the peers in separate manager events */ 13819 _sip_show_peers(-1, &total, s, m, 3, a); 13820 /* Send final confirmation */ 13821 astman_append(s, 13822 "Event: PeerlistComplete\r\n" 13823 "EventList: Complete\r\n" 13824 "ListItems: %d\r\n" 13825 "%s" 13826 "\r\n", total, idtext); 13827 return 0; 13828 }
| static int manager_sipnotify | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 10596 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, sip_pvt::sa, sip_alloc(), SIP_NOTIFY, SIP_OUTGOING, sip_scheddestroy(), SIP_TRANS_TIMEOUT, transmit_notify_custom(), and TRUE.
Referenced by load_module().
10597 { 10598 const char *channame = astman_get_header(m, "Channel"); 10599 struct ast_variable *vars = astman_get_variables(m); 10600 struct sip_pvt *p; 10601 10602 if (ast_strlen_zero(channame)) { 10603 astman_send_error(s, m, "SIPNotify requires a channel name"); 10604 return 0; 10605 } 10606 10607 if (!strncasecmp(channame, "sip/", 4)) { 10608 channame += 4; 10609 } 10610 10611 if (!(p = sip_alloc(NULL, NULL, 0, SIP_NOTIFY, NULL))) { 10612 astman_send_error(s, m, "Unable to build sip pvt data for notify (memory/socket error)"); 10613 return 0; 10614 } 10615 10616 if (create_addr(p, channame, NULL, 0)) { 10617 /* Maybe they're not registered, etc. */ 10618 dialog_unlink_all(p, TRUE, TRUE); 10619 dialog_unref(p, "unref dialog inside for loop" ); 10620 /* sip_destroy(p); */ 10621 astman_send_error(s, m, "Could not create address"); 10622 return 0; 10623 } 10624 10625 /* Notify is outgoing call */ 10626 ast_set_flag(&p->flags[0], SIP_OUTGOING); 10627 10628 /* Recalculate our side, and recalculate Call ID */ 10629 ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip, p); 10630 build_via(p); 10631 ao2_t_unlink(dialogs, p, "About to change the callid -- remove the old name"); 10632 build_callid_pvt(p); 10633 ao2_t_link(dialogs, p, "Linking in new name"); 10634 dialog_ref(p, "bump the count of p, which transmit_sip_request will decrement."); 10635 sip_scheddestroy(p, SIP_TRANS_TIMEOUT); 10636 10637 if (!transmit_notify_custom(p, vars)) { 10638 astman_send_ack(s, m, "Notify Sent"); 10639 } else { 10640 astman_send_error(s, m, "Unable to send notify"); 10641 } 10642 ast_variables_destroy(vars); 10643 return 0; 10644 }
| 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 2389 of file chan_sip.c.
References _map_x_s::s, and _map_x_s::x.
Referenced by str2dtmfmode(), str2stmode(), and str2strefresher().
| 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 2376 of file chan_sip.c.
References _map_x_s::s, and _map_x_s::x.
Referenced by dtmfmode2str(), faxec2str(), insecure2str(), nat2str(), referstatus2str(), regstate2str(), stmode2str(), and strefresher2str().
| 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 2987 of file chan_sip.c.
References sip_methods, and text.
Referenced by __sip_autodestruct(), __sip_semi_ack(), and find_sip_method().
02988 { 02989 int len = strlen(sip_methods[id].text); 02990 int l_name = name ? strlen(name) : 0; 02991 /* true if the string is long enough, and ends with whitespace, and matches */ 02992 return (l_name >= len && name[len] < 33 && 02993 !strncasecmp(sip_methods[id].text, name, len)); 02994 }
| static void mwi_event_cb | ( | const struct ast_event * | event, | |
| void * | userdata | |||
| ) | [static] |
Receive MWI events that we have subscribed to.
Definition at line 11972 of file chan_sip.c.
References ao2_lock(), ao2_unlock(), and sip_send_mwi_to_peer().
Referenced by add_peer_mwi_subs().
11973 { 11974 struct sip_peer *peer = userdata; 11975 11976 ao2_lock(peer); 11977 sip_send_mwi_to_peer(peer, event, 0); 11978 ao2_unlock(peer); 11979 }
| static const char * nat2str | ( | int | nat | ) | [static] |
Convert NAT setting to text string.
Definition at line 13542 of file chan_sip.c.
References map_x_s().
Referenced by _sip_show_peer(), sip_show_channel(), sip_show_settings(), and sip_show_users().
| static struct sip_proxy* obproxy_get | ( | struct sip_pvt * | dialog, | |
| struct sip_peer * | peer | |||
| ) | [static, read] |
Get default outbound proxy or global proxy.
Definition at line 2962 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().
02963 { 02964 if (peer && peer->outboundproxy) { 02965 if (sipdebug) 02966 ast_debug(1, "OBPROXY: Applying peer OBproxy to this call\n"); 02967 append_history(dialog, "OBproxy", "Using peer obproxy %s", peer->outboundproxy->name); 02968 return peer->outboundproxy; 02969 } 02970 if (global_outboundproxy.name[0]) { 02971 if (sipdebug) 02972 ast_debug(1, "OBPROXY: Applying global OBproxy to this call\n"); 02973 append_history(dialog, "OBproxy", "Using global obproxy %s", global_outboundproxy.name); 02974 return &global_outboundproxy; 02975 } 02976 if (sipdebug) 02977 ast_debug(1, "OBPROXY: Not applying OBproxy to this call\n"); 02978 return NULL; 02979 }
| static void parse_copy | ( | struct sip_request * | dst, | |
| const struct sip_request * | src | |||
| ) | [static] |
Copy SIP request, parse it.
Definition at line 3755 of file chan_sip.c.
References copy_request(), and parse_request().
Referenced by send_request(), and send_response().
03756 { 03757 copy_request(dst, src); 03758 parse_request(dst); 03759 }
| int parse_minse | ( | const char * | p_hdrval, | |
| int *const | p_interval | |||
| ) | [static] |
Session-Timers: Function for parsing Min-SE header.
Definition at line 21703 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().
21704 { 21705 if (ast_strlen_zero(p_hdrval)) { 21706 ast_log(LOG_WARNING, "Null Min-SE header\n"); 21707 return -1; 21708 } 21709 21710 *p_interval = 0; 21711 p_hdrval = ast_skip_blanks(p_hdrval); 21712 if (!sscanf(p_hdrval, "%30d", p_interval)) { 21713 ast_log(LOG_WARNING, "Parsing of Min-SE header failed %s\n", p_hdrval); 21714 return -1; 21715 } 21716 21717 ast_debug(2, "Received Min-SE: %d\n", *p_interval); 21718 return 0; 21719 }
| static void parse_moved_contact | ( | struct sip_pvt * | p, | |
| struct sip_request * | req | |||
| ) | [static] |
Parse 302 Moved temporalily response.
Definition at line 16667 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().
16668 { 16669 char tmp[SIPBUFSIZE]; 16670 char *s, *e, *t, *trans; 16671 char *domain; 16672 enum sip_transport transport = SIP_TRANSPORT_UDP; 16673 16674 ast_copy_string(tmp, get_header(req, "Contact"), sizeof(tmp)); 16675 if ((t = strchr(tmp, ','))) 16676 *t = '\0'; 16677 16678 s = get_in_brackets(tmp); 16679 if ((trans = strcasestr(s, ";transport="))) do { 16680 trans += 11; 16681 16682 if ((e = strchr(trans, ';'))) 16683 *e = '\0'; 16684 16685 if (!strncasecmp(trans, "tcp", 3)) 16686 transport = SIP_TRANSPORT_TCP; 16687 else if (!strncasecmp(trans, "tls", 3)) 16688 transport = SIP_TRANSPORT_TLS; 16689 else { 16690 if (strncasecmp(trans, "udp", 3)) 16691 ast_debug(1, "received contact with an invalid transport, '%s'\n", s); 16692 transport = SIP_TRANSPORT_UDP; 16693 } 16694 } while(0); 16695 s = remove_uri_parameters(s); 16696 16697 if (p->socket.tcptls_session) { 16698 ao2_ref(p->socket.tcptls_session, -1); 16699 p->socket.tcptls_session = NULL; 16700 } 16701 16702 set_socket_transport(&p->socket, transport); 16703 16704 if (ast_test_flag(&p->flags[0], SIP_PROMISCREDIR)) { 16705 char *host = NULL; 16706 if (!strncasecmp(s, "sip:", 4)) 16707 s += 4; 16708 else if (!strncasecmp(s, "sips:", 5)) 16709 s += 5; 16710 e = strchr(s, '/'); 16711 if (e) 16712 *e = '\0'; 16713 if ((host = strchr(s, '@'))) { 16714 *host++ = '\0'; 16715 ast_debug(2, "Found promiscuous redirection to 'SIP/%s::::%s@%s'\n", s, get_transport(transport), host); 16716 if (p->owner) 16717 ast_string_field_build(p->owner, call_forward, "SIP/%s::::%s@%s", s, get_transport(transport), host); 16718 } else { 16719 ast_debug(2, "Found promiscuous redirection to 'SIP/::::%s@%s'\n", get_transport(transport), s); 16720 if (p->owner) 16721 ast_string_field_build(p->owner, call_forward, "SIP/::::%s@%s", get_transport(transport), s); 16722 } 16723 } else { 16724 e = strchr(tmp, '@'); 16725 if (e) { 16726 *e++ = '\0'; 16727 domain = e; 16728 } else { 16729 /* No username part */ 16730 domain = tmp; 16731 } 16732 e = strchr(tmp, '/'); /* WHEN do we hae a forward slash in the URI? */ 16733 if (e) 16734 *e = '\0'; 16735 16736 if (!strncasecmp(s, "sip:", 4)) 16737 s += 4; 16738 else if (!strncasecmp(s, "sips:", 5)) 16739 s += 5; 16740 e = strchr(s, ';'); /* And username ; parameters? */ 16741 if (e) 16742 *e = '\0'; 16743 ast_debug(2, "Received 302 Redirect to extension '%s' (domain %s)\n", s, domain); 16744 if (p->owner) { 16745 pbx_builtin_setvar_helper(p->owner, "SIPDOMAIN", domain); 16746 ast_string_field_set(p->owner, call_forward, s); 16747 } 16748 } 16749 }
| 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 11349 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().
11350 { 11351 char contact[SIPBUFSIZE]; 11352 char *c; 11353 11354 /* Look for brackets */ 11355 ast_copy_string(contact, get_header(req, "Contact"), sizeof(contact)); 11356 c = get_in_brackets(contact); 11357 11358 /* Save full contact to call pvt for later bye or re-invite */ 11359 ast_string_field_set(pvt, fullcontact, c); 11360 11361 /* Save URI for later ACKs, BYE or RE-invites */ 11362 ast_string_field_set(pvt, okcontacturi, c); 11363 11364 /* We should return false for URI:s we can't handle, 11365 like tel:, mailto:,ldap: etc */ 11366 return TRUE; 11367 }
| 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 11428 of file chan_sip.c.
References sip_peer::addr, 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_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(), 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(), port_str2int(), sip_peer::portinuri, sip_pvt::recv, ref_peer(), register_peer_exten(), sip_peer::rt_fromcontact, s, 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().
11429 { 11430 char contact[SIPBUFSIZE]; 11431 char data[SIPBUFSIZE]; 11432 const char *expires = get_header(req, "Expires"); 11433 int expire = atoi(expires); 11434 char *curi, *host, *pt, *transport; 11435 int port; 11436 int transport_type; 11437 const char *useragent; 11438 struct hostent *hp; 11439 struct ast_hostent ahp; 11440 struct sockaddr_in oldsin, testsin; 11441 11442 11443 ast_copy_string(contact, get_header(req, "Contact"), sizeof(contact)); 11444 11445 if (ast_strlen_zero(expires)) { /* No expires header, try look in Contact: */ 11446 char *s = strcasestr(contact, ";expires="); 11447 if (s) { 11448 expires = strsep(&s, ";"); /* trim ; and beyond */ 11449 if (sscanf(expires + 9, "%30d", &expire) != 1) 11450 expire = default_expiry; 11451 } else { 11452 /* Nothing has been specified */ 11453 expire = default_expiry; 11454 } 11455 } 11456 11457 copy_socket_data(&pvt->socket, &req->socket); 11458 11459 /* Look for brackets */ 11460 curi = contact; 11461 if (strchr(contact, '<') == NULL) /* No <, check for ; and strip it */ 11462 strsep(&curi, ";"); /* This is Header options, not URI options */ 11463 curi = get_in_brackets(contact); 11464 11465 /* if they did not specify Contact: or Expires:, they are querying 11466 what we currently have stored as their contact address, so return 11467 it 11468 */ 11469 if (ast_strlen_zero(curi) && ast_strlen_zero(expires)) { 11470 /* If we have an active registration, tell them when the registration is going to expire */ 11471 if (peer->expire > -1 && !ast_strlen_zero(peer->fullcontact)) 11472 pvt->expiry = ast_sched_when(sched, peer->expire); 11473 return PARSE_REGISTER_QUERY; 11474 } else if (!strcasecmp(curi, "*") || !expire) { /* Unregister this peer */ 11475 /* This means remove all registrations and return OK */ 11476 memset(&peer->addr, 0, sizeof(peer->addr)); 11477 set_socket_transport(&peer->socket, peer->default_outbound_transport); 11478 11479 AST_SCHED_DEL_UNREF(sched, peer->expire, 11480 unref_peer(peer, "remove register expire ref")); 11481 11482 destroy_association(peer); 11483 11484 register_peer_exten(peer, FALSE); /* Remove extension from regexten= setting in sip.conf */ 11485 peer->fullcontact[0] = '\0'; 11486 peer->useragent[0] = '\0'; 11487 peer->sipoptions = 0; 11488 peer->lastms = 0; 11489 peer->portinuri = 0; 11490 pvt->expiry = 0; 11491 11492 ast_verb(3, "Unregistered SIP '%s'\n", peer->name); 11493 11494 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: SIP\r\nPeer: SIP/%s\r\nPeerStatus: Unregistered\r\n", peer->name); 11495 return PARSE_REGISTER_UPDATE; 11496 } 11497 11498 /* Store whatever we got as a contact from the client */ 11499 ast_copy_string(peer->fullcontact, curi, sizeof(peer->fullcontact)); 11500 11501 /* For the 200 OK, we should use the received contact */ 11502 ast_string_field_build(pvt, our_contact, "<%s>", curi); 11503 11504 /* Make sure it's a SIP URL */ 11505 if (parse_uri(curi, "sip:,sips:", &curi, NULL, &host, &pt, NULL, &transport)) { 11506 ast_log(LOG_NOTICE, "Not a valid SIP contact (missing sip:) trying to use anyway\n"); 11507 } 11508 11509 /* If we have a port number in the given URI, make sure we do remember to not check for NAPTR/SRV records. 11510 The domain part is actually a host. */ 11511 peer->portinuri = !ast_strlen_zero(pt) ? TRUE : FALSE; 11512 11513 /* handle the transport type specified in Contact header. */ 11514 if ((transport_type = get_transport_str2enum(transport))) { 11515 /* if the port is not specified but the transport is, make sure to set the 11516 * default port to match the specified transport. This may or may not be the 11517 * same transport used by the pvt struct for the Register dialog. */ 11518 11519 port = port_str2int(pt, (transport_type == SIP_TRANSPORT_TLS) ? STANDARD_TLS_PORT : STANDARD_SIP_PORT); 11520 } else { 11521 port = port_str2int(pt, STANDARD_SIP_PORT); 11522 transport_type = pvt->socket.type; 11523 } 11524 11525 /* if the peer's socket type is different than the Registration 11526 * transport type, change it. If it got this far, it is a 11527 * supported type, but check just in case */ 11528 if ((peer->socket.type != transport_type) && (peer->transports & transport_type)) { 11529 set_socket_transport(&peer->socket, transport_type); 11530 } 11531 11532 oldsin = peer->addr; 11533 11534 /* If we were already linked into the peers_by_ip container unlink ourselves so nobody can find us */ 11535 if (peer->addr.sin_addr.s_addr) { 11536 ao2_t_unlink(peers_by_ip, peer, "ao2_unlink of peer from peers_by_ip table"); 11537 } 11538 11539 /* Check that they're allowed to register at this IP */ 11540 /* XXX This could block for a long time XXX */ 11541 hp = ast_gethostbyname(host, &ahp); 11542 if (!hp) { 11543 ast_log(LOG_WARNING, "Invalid host '%s'\n", host); 11544 *peer->fullcontact = '\0'; 11545 ast_string_field_set(pvt, our_contact, ""); 11546 return PARSE_REGISTER_FAILED; 11547 } 11548 memcpy(&testsin.sin_addr, hp->h_addr, sizeof(testsin.sin_addr)); 11549 if ( ast_apply_ha(global_contact_ha, &testsin) != AST_SENSE_ALLOW || 11550 ast_apply_ha(peer->contactha, &testsin) != AST_SENSE_ALLOW) { 11551 ast_log(LOG_WARNING, "Host '%s' disallowed by contact ACL (violating IP %s)\n", host, ast_inet_ntoa(testsin.sin_addr)); 11552 *peer->fullcontact = '\0'; 11553 ast_string_field_set(pvt, our_contact, ""); 11554 return PARSE_REGISTER_DENIED; 11555 } 11556 11557 if (!ast_test_flag(&peer->flags[0], SIP_NAT_ROUTE)) { 11558 peer->addr.sin_family = AF_INET; 11559 memcpy(&peer->addr.sin_addr, hp->h_addr, sizeof(peer->addr.sin_addr)); 11560 peer->addr.sin_port = htons(port); 11561 } else { 11562 /* Don't trust the contact field. Just use what they came to us 11563 with */ 11564 peer->addr = pvt->recv; 11565 } 11566 11567 /* if the Contact header information copied into peer->addr matches the 11568 * received address, and the transport types are the same, then copy socket 11569 * data into the peer struct */ 11570 if ((peer->socket.type == pvt->socket.type) && 11571 (peer->addr.sin_addr.s_addr == pvt->recv.sin_addr.s_addr) && 11572 (peer->addr.sin_port == pvt->recv.sin_port)){ 11573 11574 copy_socket_data(&peer->socket, &pvt->socket); 11575 } 11576 11577 /* Now that our address has been updated put ourselves back into the container for lookups */ 11578 ao2_t_link(peers_by_ip, peer, "ao2_link into peers_by_ip table"); 11579 11580 /* Save SIP options profile */ 11581 peer->sipoptions = pvt->sipoptions; 11582 11583 if (!ast_strlen_zero(curi) && ast_strlen_zero(peer->username)) 11584 ast_copy_string(peer->username, curi, sizeof(peer->username)); 11585 11586 AST_SCHED_DEL_UNREF(sched, peer->expire, 11587 unref_peer(peer, "remove register expire ref")); 11588 11589 if (expire > max_expiry) 11590 expire = max_expiry; 11591 if (expire < min_expiry) 11592 expire = min_expiry; 11593 if (peer->is_realtime && !ast_test_flag(&peer->flags[1], SIP_PAGE2_RTCACHEFRIENDS)) { 11594 peer->expire = -1; 11595 } else { 11596 peer->expire = ast_sched_add(sched, (expire + 10) * 1000, expire_register, 11597 ref_peer(peer, "add registration ref")); 11598 if (peer->expire == -1) { 11599 unref_peer(peer, "remote registration ref"); 11600 } 11601 } 11602 pvt->expiry = expire; 11603 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); 11604 /* Saving TCP connections is useless, we won't be able to reconnect 11605 XXX WHY???? XXX 11606 \todo check this 11607 */ 11608 if (!peer->rt_fromcontact && (peer->socket.type & SIP_TRANSPORT_UDP)) 11609 ast_db_put("SIP/Registry", peer->name, data); 11610 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)); 11611 11612 /* Is this a new IP address for us? */ 11613 if (VERBOSITY_ATLEAST(2) && inaddrcmp(&peer->addr, &oldsin)) { 11614 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)); 11615 } 11616 sip_poke_peer(peer, 0); 11617 register_peer_exten(peer, 1); 11618 11619 /* Save User agent */ 11620 useragent = get_header(req, "User-Agent"); 11621 if (strcasecmp(useragent, peer->useragent)) { /* XXX copy if they are different ? */ 11622 ast_copy_string(peer->useragent, useragent, sizeof(peer->useragent)); 11623 ast_verb(4, "Saved useragent \"%s\" for peer %s\n", peer->useragent, peer->name); 11624 } 11625 return PARSE_REGISTER_UPDATE; 11626 }
| static int parse_request | ( | struct sip_request * | req | ) | [static] |
Parse a SIP message.
Definition at line 7201 of file chan_sip.c.
References ast_debug, ast_log(), ast_strlen_zero(), sip_request::data, determine_firstline_parts(), sip_request::header, sip_request::headers, sip_request::line, sip_request::lines, LOG_WARNING, SIP_MAX_HEADERS, SIP_MAX_LINES, ast_str::str, and ast_str::used.
Referenced by _sip_tcp_helper_thread(), handle_request_do(), initialize_initreq(), and parse_copy().
07202 { 07203 char *c = req->data->str; 07204 ptrdiff_t *dst = req->header; 07205 int i = 0, lim = SIP_MAX_HEADERS - 1; 07206 unsigned int skipping_headers = 0; 07207 ptrdiff_t current_header_offset = 0; 07208 char *previous_header = ""; 07209 07210 req->header[0] = 0; 07211 req->headers = -1; /* mark that we are working on the header */ 07212 for (; *c; c++) { 07213 if (*c == '\r') { /* remove \r */ 07214 *c = '\0'; 07215 } else if (*c == '\n') { /* end of this line */ 07216 *c = '\0'; 07217 current_header_offset = (c + 1) - req->data->str; 07218 previous_header = req->data->str + dst[i]; 07219 if (skipping_headers) { 07220 /* check to see if this line is blank; if so, turn off 07221 the skipping flag, so the next line will be processed 07222 as a body line */ 07223 if (ast_strlen_zero(previous_header)) { 07224 skipping_headers = 0; 07225 } 07226 dst[i] = current_header_offset; /* record start of next line */ 07227 continue; 07228 } 07229 if (sipdebug) { 07230 ast_debug(4, "%7s %2d [%3d]: %s\n", 07231 req->headers < 0 ? "Header" : "Body", 07232 i, (int) strlen(previous_header), previous_header); 07233 } 07234 if (ast_strlen_zero(previous_header) && req->headers < 0) { 07235 req->headers = i; /* record number of header lines */ 07236 dst = req->line; /* start working on the body */ 07237 i = 0; 07238 lim = SIP_MAX_LINES - 1; 07239 } else { /* move to next line, check for overflows */ 07240 if (i++ == lim) { 07241 /* if we're processing headers, then skip any remaining 07242 headers and move on to processing the body, otherwise 07243 we're done */ 07244 if (req->headers != -1) { 07245 break; 07246 } else { 07247 req->headers = i; 07248 dst = req->line; 07249 i = 0; 07250 lim = SIP_MAX_LINES - 1; 07251 skipping_headers = 1; 07252 } 07253 } 07254 } 07255 dst[i] = current_header_offset; /* record start of next line */ 07256 } 07257 } 07258 07259 /* Check for last header or body line without CRLF. The RFC for SDP requires CRLF, 07260 but since some devices send without, we'll be generous in what we accept. However, 07261 if we've already reached the maximum number of lines for portion of the message 07262 we were parsing, we can't accept any more, so just ignore it. 07263 */ 07264 previous_header = req->data->str + dst[i]; 07265 if ((i < lim) && !ast_strlen_zero(previous_header)) { 07266 if (sipdebug) { 07267 ast_debug(4, "%7s %2d [%3d]: %s\n", 07268 req->headers < 0 ? "Header" : "Body", 07269 i, (int) strlen(previous_header), previous_header ); 07270 } 07271 i++; 07272 } 07273 07274 /* update count of header or body lines */ 07275 if (req->headers >= 0) { /* we are in the body */ 07276 req->lines = i; 07277 } else { /* no body */ 07278 req->headers = i; 07279 req->lines = 0; 07280 /* req->data->used will be a NULL byte */ 07281 req->line[0] = req->data->used; 07282 } 07283 07284 if (*c) { 07285 ast_log(LOG_WARNING, "Too many lines, skipping <%s>\n", c); 07286 } 07287 07288 /* Split up the first line parts */ 07289 return determine_firstline_parts(req); 07290 }
| 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 21723 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().
21724 { 21725 char *p_token; 21726 int ref_idx; 21727 char *p_se_hdr; 21728 21729 if (ast_strlen_zero(p_hdrval)) { 21730 ast_log(LOG_WARNING, "Null Session-Expires header\n"); 21731 return -1; 21732 } 21733 21734 *p_ref = SESSION_TIMER_REFRESHER_AUTO; 21735 *p_interval = 0; 21736 21737 p_se_hdr = ast_strdupa(p_hdrval); 21738 p_se_hdr = ast_skip_blanks(p_se_hdr); 21739 21740 while ((p_token = strsep(&p_se_hdr, ";"))) { 21741 p_token = ast_skip_blanks(p_token); 21742 if (!sscanf(p_token, "%30d", p_interval)) { 21743 ast_log(LOG_WARNING, "Parsing of Session-Expires failed\n"); 21744 return -1; 21745 } 21746 21747 ast_debug(2, "Session-Expires: %d\n", *p_interval); 21748 21749 if (!p_se_hdr) 21750 continue; 21751 21752 p_se_hdr = ast_skip_blanks(p_se_hdr); 21753 ref_idx = strlen("refresher="); 21754 if (!strncasecmp(p_se_hdr, "refresher=", ref_idx)) { 21755 p_se_hdr += ref_idx; 21756 p_se_hdr = ast_skip_blanks(p_se_hdr); 21757 21758 if (!strncasecmp(p_se_hdr, "uac", strlen("uac"))) { 21759 *p_ref = SESSION_TIMER_REFRESHER_UAC; 21760 ast_debug(2, "Refresher: UAC\n"); 21761 } else if (!strncasecmp(p_se_hdr, "uas", strlen("uas"))) { 21762 *p_ref = SESSION_TIMER_REFRESHER_UAS; 21763 ast_debug(2, "Refresher: UAS\n"); 21764 } else { 21765 ast_log(LOG_WARNING, "Invalid refresher value %s\n", p_se_hdr); 21766 return -1; 21767 } 21768 break; 21769 } 21770 } 21771 return 0; 21772 }
| static unsigned int parse_sip_options | ( | struct sip_pvt * | pvt, | |
| const char * | supported | |||
| ) | [static] |
Parse supported header in incoming packet.
Definition at line 3011 of file chan_sip.c.
References ARRAY_LEN, ast_debug, ast_skip_blanks(), ast_strdupa, ast_strlen_zero(), FALSE, cfsip_options::id, SIP_OPT_UNKNOWN, sip_options, sip_pvt::sipoptions, text, and TRUE.
Referenced by handle_request_invite().
03012 { 03013 char *next, *sep; 03014 char *temp; 03015 unsigned int profile = 0; 03016 int i, found; 03017 03018 if (ast_strlen_zero(supported) ) 03019 return 0; 03020 temp = ast_strdupa(supported); 03021 03022 if (sipdebug) 03023 ast_debug(3, "Begin: parsing SIP \"Supported: %s\"\n", supported); 03024 03025 for (next = temp; next; next = sep) { 03026 found = FALSE; 03027 if ( (sep = strchr(next, ',')) != NULL) 03028 *sep++ = '\0'; 03029 next = ast_skip_blanks(next); 03030 if (sipdebug) 03031 ast_debug(3, "Found SIP option: -%s-\n", next); 03032 for (i = 0; i < ARRAY_LEN(sip_options); i++) { 03033 if (!strcasecmp(next, sip_options[i].text)) { 03034 profile |= sip_options[i].id; 03035 found = TRUE; 03036 if (sipdebug) 03037 ast_debug(3, "Matched SIP option: %s\n", next); 03038 break; 03039 } 03040 } 03041 03042 /* This function is used to parse both Suported: and Require: headers. 03043 Let the caller of this function know that an unknown option tag was 03044 encountered, so that if the UAC requires it then the request can be 03045 rejected with a 420 response. */ 03046 if (!found) 03047 profile |= SIP_OPT_UNKNOWN; 03048 03049 if (!found && sipdebug) { 03050 if (!strncasecmp(next, "x-", 2)) 03051 ast_debug(3, "Found private SIP option, not supported: %s\n", next); 03052 else 03053 ast_debug(3, "Found no match for SIP option: %s (Please file bug report!)\n", next); 03054 } 03055 } 03056 03057 if (pvt) 03058 pvt->sipoptions = profile; 03059 return profile; 03060 }
| 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.
This means that if we don't have domain, we cannot split name:pass and domain:port. It is safe to call with ret_name, pass, domain, port pointing all to the same place. Init pointers to empty string so we never get NULL dereferencing. Overwrites the string. return 0 on success, other values on error.
* general form we are expecting is sip[s]:username[:password][;parameter]@host[:port][;...] *
Definition at line 4009 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().
04011 { 04012 char *name = NULL; 04013 int error = 0; 04014 04015 /* init field as required */ 04016 if (pass) 04017 *pass = ""; 04018 if (port) 04019 *port = ""; 04020 if (scheme) { 04021 int l; 04022 char *scheme2 = ast_strdupa(scheme); 04023 char *cur = strsep(&scheme2, ","); 04024 for (; !ast_strlen_zero(cur); cur = strsep(&scheme2, ",")) { 04025 l = strlen(cur); 04026 if (!strncasecmp(uri, cur, l)) { 04027 uri += l; 04028 break; 04029 } 04030 } 04031 if (ast_strlen_zero(cur)) { 04032 ast_debug(1, "No supported scheme found in '%s' using the scheme[s] %s\n", uri, scheme); 04033 error = -1; 04034 } 04035 } 04036 if (transport) { 04037 char *t, *type = ""; 04038 *transport = ""; 04039 if ((t = strstr(uri, "transport="))) { 04040 strsep(&t, "="); 04041 if ((type = strsep(&t, ";"))) { 04042 *transport = type; 04043 } 04044 } 04045 } 04046 04047 if (!domain) { 04048 /* if we don't want to split around domain, keep everything as a name, 04049 * so we need to do nothing here, except remember why. 04050 */ 04051 } else { 04052 /* store the result in a temp. variable to avoid it being 04053 * overwritten if arguments point to the same place. 04054 */ 04055 char *c, *dom = ""; 04056 04057 if ((c = strchr(uri, '@')) == NULL) { 04058 /* domain-only URI, according to the SIP RFC. */ 04059 dom = uri; 04060 name = ""; 04061 } else { 04062 *c++ = '\0'; 04063 dom = c; 04064 name = uri; 04065 } 04066 04067 /* Remove options in domain and name */ 04068 dom = strsep(&dom, ";"); 04069 name = strsep(&name, ";"); 04070 04071 if (port && (c = strchr(dom, ':'))) { /* Remove :port */ 04072 *c++ = '\0'; 04073 *port = c; 04074 } 04075 if (pass && (c = strchr(name, ':'))) { /* user:password */ 04076 *c++ = '\0'; 04077 *pass = c; 04078 } 04079 *domain = dom; 04080 } 04081 if (ret_name) /* same as for domain, store the result only at the end */ 04082 *ret_name = name; 04083 if (options) 04084 *options = uri ? uri : ""; 04085 04086 return error; 04087 }
| static int peer_cmp_cb | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 1702 of file chan_sip.c.
References CMP_MATCH, CMP_STOP, and sip_peer::name.
Referenced by load_module().
| static int peer_dump_func | ( | void * | userobj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 14031 of file chan_sip.c.
References ao2_t_ref, ast_cli(), and sip_peer::name.
Referenced by sip_show_objects().
| static int peer_hash_cb | ( | const void * | obj, | |
| const int | flags | |||
| ) | [static] |
Definition at line 1692 of file chan_sip.c.
References ast_str_case_hash(), and sip_peer::name.
Referenced by load_module().
01693 { 01694 const struct sip_peer *peer = obj; 01695 01696 return ast_str_case_hash(peer->name); 01697 }
| 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.
Definition at line 1740 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().
01741 { 01742 struct sip_peer *peer = obj, *peer2 = arg; 01743 01744 if (peer->addr.sin_addr.s_addr != peer2->addr.sin_addr.s_addr) { 01745 /* IP doesn't match */ 01746 return 0; 01747 } 01748 01749 /* We matched the IP, check to see if we need to match by port as well. */ 01750 if ((peer->transports & peer2->transports) & (SIP_TRANSPORT_TLS | SIP_TRANSPORT_TCP)) { 01751 /* peer matching on port is not possible with TCP/TLS */ 01752 return CMP_MATCH | CMP_STOP; 01753 } else if (ast_test_flag(&peer2->flags[0], SIP_INSECURE_PORT)) { 01754 /* We are allowing match without port for peers configured that 01755 * way in this pass through the peers. */ 01756 return ast_test_flag(&peer->flags[0], SIP_INSECURE_PORT) ? 01757 (CMP_MATCH | CMP_STOP) : 0; 01758 } 01759 01760 /* Now only return a match if the port matches, as well. */ 01761 return peer->addr.sin_port == peer2->addr.sin_port ? (CMP_MATCH | CMP_STOP) : 0; 01762 }
| static int peer_iphash_cb | ( | const void * | obj, | |
| const int | flags | |||
| ) | [static] |
Definition at line 1712 of file chan_sip.c.
References sip_peer::addr.
Referenced by load_module().
| static int peer_is_marked | ( | void * | peerobj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 14221 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 14525 of file chan_sip.c.
References AST_LIST_NEXT, AST_LIST_TRAVERSE, ast_str_append(), ast_strlen_zero(), sip_mailbox::context, sip_mailbox::mailbox, mailbox, sip_peer::mailboxes, and S_OR.
Referenced by _sip_show_peer(), function_sippeer(), show_channels_cb(), and sip_send_mwi_to_peer().
14526 { 14527 struct sip_mailbox *mailbox; 14528 14529 AST_LIST_TRAVERSE(&peer->mailboxes, mailbox, entry) { 14530 ast_str_append(mailbox_str, 0, "%s%s%s%s", 14531 mailbox->mailbox, 14532 ast_strlen_zero(mailbox->context) ? "" : "@", 14533 S_OR(mailbox->context, ""), 14534 AST_LIST_NEXT(mailbox, entry) ? "," : ""); 14535 } 14536 }
| static int peer_markall_func | ( | void * | device, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 23269 of file chan_sip.c.
References sip_peer::the_mark.
Referenced by reload_config().
| static int peer_status | ( | struct sip_peer * | peer, | |
| char * | status, | |||
| int | statuslen | |||
| ) | [static] |
Definition at line 13609 of file chan_sip.c.
References ast_copy_string(), sip_peer::lastms, and sip_peer::maxms.
Referenced by _sip_show_peer(), _sip_show_peers(), and function_sippeer().
13610 { 13611 int res = 0; 13612 if (peer->maxms) { 13613 if (peer->lastms < 0) { 13614 ast_copy_string(status, "UNREACHABLE", statuslen); 13615 } else if (peer->lastms > peer->maxms) { 13616 snprintf(status, statuslen, "LAGGED (%d ms)", peer->lastms); 13617 res = 1; 13618 } else if (peer->lastms) { 13619 snprintf(status, statuslen, "OK (%d ms)", peer->lastms); 13620 res = 1; 13621 } else { 13622 ast_copy_string(status, "UNKNOWN", statuslen); 13623 } 13624 } else { 13625 ast_copy_string(status, "Unmonitored", statuslen); 13626 /* Checking if port is 0 */ 13627 res = -1; 13628 } 13629 return res; 13630 }
| int peercomparefunc | ( | const void * | a, | |
| const void * | b | |||
| ) |
Definition at line 13850 of file chan_sip.c.
Referenced by _sip_show_peers().
| 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 2932 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().
02933 { 02934 int port = standard; 02935 if (ast_strlen_zero(pt) || (sscanf(pt, "%30d", &port) != 1) || (port < 1) || (port > 65535)) { 02936 port = standard; 02937 } 02938 02939 return port; 02940 }
| 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 14357 of file chan_sip.c.
References ast_cli(), ast_codec_pref_index(), ast_getformatname(), and ast_codec_pref::framing.
Referenced by _sip_show_peer(), sip_show_settings(), and sip_show_user().
14358 { 14359 int x, codec; 14360 14361 for(x = 0; x < 32 ; x++) { 14362 codec = ast_codec_pref_index(pref, x); 14363 if (!codec) 14364 break; 14365 ast_cli(fd, "%s", ast_getformatname(codec)); 14366 ast_cli(fd, ":%d", pref->framing[x]); 14367 if (x < 31 && ast_codec_pref_index(pref, x + 1)) 14368 ast_cli(fd, ","); 14369 } 14370 if (!x) 14371 ast_cli(fd, "none"); 14372 }
| static void print_group | ( | int | fd, | |
| ast_group_t | group, | |||
| int | crlf | |||
| ) | [static] |
Print call group and pickup group.
Definition at line 14081 of file chan_sip.c.
References ast_cli(), ast_print_group(), and buf.
Referenced by _sip_show_peer(), and sip_show_user().
14082 { 14083 char buf[256]; 14084 ast_cli(fd, crlf ? "%s\r\n" : "%s\n", ast_print_group(buf, sizeof(buf), group) ); 14085 }
| 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 21782 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().
21783 { 21784 int rtn; 21785 const char *p_hdrval; 21786 int minse; 21787 21788 p_hdrval = get_header(rsp, "Min-SE"); 21789 if (ast_strlen_zero(p_hdrval)) { 21790 ast_log(LOG_WARNING, "422 response without a Min-SE header %s\n", p_hdrval); 21791 return; 21792 } 21793 rtn = parse_minse(p_hdrval, &minse); 21794 if (rtn != 0) { 21795 ast_log(LOG_WARNING, "Parsing of Min-SE header failed %s\n", p_hdrval); 21796 return; 21797 } 21798 p->stimer->st_interval = minse; 21799 transmit_invite(p, SIP_INVITE, 1, 2); 21800 }
| static int proc_session_timer | ( | const void * | vp | ) | [static] |
Session-Timers: Process session refresh timeout event.
Definition at line 21622 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().
21623 { 21624 struct sip_pvt *p = (struct sip_pvt *) vp; 21625 int sendreinv = FALSE; 21626 int res = 0; 21627 21628 if (!p->stimer) { 21629 ast_log(LOG_WARNING, "Null stimer in proc_session_timer - %s\n", p->callid); 21630 goto return_unref; 21631 } 21632 21633 ast_debug(2, "Session timer expired: %d - %s\n", p->stimer->st_schedid, p->callid); 21634 21635 if (!p->owner) { 21636 goto return_unref; 21637 } 21638 21639 if ((p->stimer->st_active != TRUE) || (p->owner->_state != AST_STATE_UP)) { 21640 goto return_unref; 21641 } 21642 21643 switch (p->stimer->st_ref) { 21644 case SESSION_TIMER_REFRESHER_UAC: 21645 if (p->outgoing_call == TRUE) { 21646 sendreinv = TRUE; 21647 } 21648 break; 21649 case SESSION_TIMER_REFRESHER_UAS: 21650 if (p->outgoing_call != TRUE) { 21651 sendreinv = TRUE; 21652 } 21653 break; 21654 default: 21655 ast_log(LOG_ERROR, "Unknown session refresher %d\n", p->stimer->st_ref); 21656 goto return_unref; 21657 } 21658 21659 if (sendreinv == TRUE) { 21660 res = 1; 21661 transmit_reinvite_with_sdp(p, FALSE, TRUE); 21662 } else { 21663 p->stimer->st_expirys++; 21664 if (p->stimer->st_expirys >= 2) { 21665 if (p->stimer->quit_flag) { 21666 goto return_unref; 21667 } 21668 ast_log(LOG_WARNING, "Session-Timer expired - %s\n", p->callid); 21669 sip_pvt_lock(p); 21670 while (p->owner && ast_channel_trylock(p->owner)) { 21671 sip_pvt_unlock(p); 21672 usleep(1); 21673 if (p->stimer && p->stimer->quit_flag) { 21674 goto return_unref; 21675 } 21676 sip_pvt_lock(p); 21677 } 21678 21679 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_DEV); 21680 ast_channel_unlock(p->owner); 21681 sip_pvt_unlock(p); 21682 } 21683 } 21684 21685 return_unref: 21686 if (!res) { 21687 /* An error occurred. Stop session timer processing */ 21688 if (p->stimer) { 21689 p->stimer->st_schedid = -1; 21690 stop_session_timer(p); 21691 } 21692 21693 /* If we are not asking to be rescheduled, then we need to release our 21694 * reference to the dialog. */ 21695 dialog_unref(p, "removing session timer ref"); 21696 } 21697 21698 return res; 21699 }
| static void process_request_queue | ( | struct sip_pvt * | p, | |
| int * | recount, | |||
| int * | nounlock | |||
| ) | [static] |
Definition at line 20839 of file chan_sip.c.
References ast_free, AST_LIST_REMOVE_HEAD, ast_log(), sip_pvt::callid, handle_incoming(), LOG_DEBUG, option_debug, sip_pvt::recv, and sip_pvt::request_queue.
Referenced by handle_request_do(), and scheduler_process_request_queue().
20840 { 20841 struct sip_request *req; 20842 20843 while ((req = AST_LIST_REMOVE_HEAD(&p->request_queue, next))) { 20844 if (handle_incoming(p, req, &p->recv, recount, nounlock) == -1) { 20845 /* Request failed */ 20846 if (option_debug) { 20847 ast_log(LOG_DEBUG, "SIP message could not be handled, bad request: %-70.70s\n", p->callid[0] ? p->callid : "<no callid>"); 20848 } 20849 } 20850 ast_free(req); 20851 } 20852 }
| 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 7456 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::nativeformats, 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, offered_media::text, text, t38properties::their_parms, sip_pvt::trtp, TRUE, sip_pvt::udptl, sip_pvt::vrtp, and ast_channel::writeformat.
Referenced by handle_incoming(), handle_request_invite(), handle_response(), and handle_response_invite().
07457 { 07458 /* Iterators for SDP parsing */ 07459 int start = req->sdp_start; 07460 int next = start; 07461 int iterator = start; 07462 07463 /* Temporary vars for SDP parsing */ 07464 char type = '\0'; 07465 const char *value = NULL; 07466 const char *m = NULL; /* SDP media offer */ 07467 const char *nextm = NULL; 07468 int len = -1; 07469 07470 /* Host information */ 07471 struct ast_hostent sessionhp; 07472 struct ast_hostent audiohp; 07473 struct ast_hostent videohp; 07474 struct ast_hostent texthp; 07475 struct ast_hostent imagehp; 07476 struct hostent *hp = NULL; /*!< RTP Audio host IP */ 07477 struct hostent *vhp = NULL; /*!< RTP video host IP */ 07478 struct hostent *thp = NULL; /*!< RTP text host IP */ 07479 struct hostent *ihp = NULL; /*!< UDPTL host ip */ 07480 int portno = -1; /*!< RTP Audio port number */ 07481 int vportno = -1; /*!< RTP Video port number */ 07482 int tportno = -1; /*!< RTP Text port number */ 07483 int udptlportno = -1; /*!< UDPTL Image port number */ 07484 struct sockaddr_in sin; /*!< media socket address */ 07485 struct sockaddr_in vsin; /*!< video socket address */ 07486 struct sockaddr_in isin; /*!< image socket address */ 07487 struct sockaddr_in tsin; /*!< text socket address */ 07488 07489 /* Peer capability is the capability in the SDP, non codec is RFC2833 DTMF (101) */ 07490 int peercapability = 0, peernoncodeccapability = 0; 07491 int vpeercapability = 0, vpeernoncodeccapability = 0; 07492 int tpeercapability = 0, tpeernoncodeccapability = 0; 07493 07494 struct ast_rtp *newaudiortp, *newvideortp, *newtextrtp; 07495 int newjointcapability; /* Negotiated capability */ 07496 int newpeercapability; 07497 int newnoncodeccapability; 07498 07499 const char *codecs; 07500 int codec; 07501 07502 /* Others */ 07503 int sendonly = -1; 07504 int vsendonly = -1; 07505 int numberofports; 07506 int numberofmediastreams = 0; 07507 int last_rtpmap_codec = 0; 07508 int red_data_pt[10]; /* For T.140 red */ 07509 int red_num_gen = 0; /* For T.140 red */ 07510 char red_fmtp[100] = "empty"; /* For T.140 red */ 07511 int debug = sip_debug_test_pvt(p); 07512 07513 /* START UNKNOWN */ 07514 char buf[SIPBUFSIZE]; 07515 /* END UNKNOWN */ 07516 07517 /* Initial check */ 07518 if (!p->rtp) { 07519 ast_log(LOG_ERROR, "Got SDP but have no RTP session allocated.\n"); 07520 return -1; 07521 } 07522 07523 /* Initialize the temporary RTP structures we use to evaluate the offer from the peer */ 07524 #ifdef LOW_MEMORY 07525 newaudiortp = ast_threadstorage_get(&ts_audio_rtp, ast_rtp_alloc_size()); 07526 #else 07527 newaudiortp = alloca(ast_rtp_alloc_size()); 07528 #endif 07529 memset(newaudiortp, 0, ast_rtp_alloc_size()); 07530 ast_rtp_new_init(newaudiortp); 07531 ast_rtp_pt_clear(newaudiortp); 07532 07533 #ifdef LOW_MEMORY 07534 newvideortp = ast_threadstorage_get(&ts_video_rtp, ast_rtp_alloc_size()); 07535 #else 07536 newvideortp = alloca(ast_rtp_alloc_size()); 07537 #endif 07538 memset(newvideortp, 0, ast_rtp_alloc_size()); 07539 ast_rtp_new_init(newvideortp); 07540 ast_rtp_pt_clear(newvideortp); 07541 07542 #ifdef LOW_MEMORY 07543 newtextrtp = ast_threadstorage_get(&ts_text_rtp, ast_rtp_alloc_size()); 07544 #else 07545 newtextrtp = alloca(ast_rtp_alloc_size()); 07546 #endif 07547 memset(newtextrtp, 0, ast_rtp_alloc_size()); 07548 ast_rtp_new_init(newtextrtp); 07549 ast_rtp_pt_clear(newtextrtp); 07550 07551 /* Update our last rtprx when we receive an SDP, too */ 07552 p->lastrtprx = p->lastrtptx = time(NULL); /* XXX why both ? */ 07553 07554 memset(p->offered_media, 0, sizeof(p->offered_media)); 07555 07556 07557 /* default: novideo and notext set */ 07558 p->novideo = TRUE; 07559 p->notext = TRUE; 07560 07561 if (p->vrtp) 07562 ast_rtp_pt_clear(newvideortp); /* Must be cleared in case no m=video line exists */ 07563 07564 if (p->trtp) 07565 ast_rtp_pt_clear(newtextrtp); /* Must be cleared in case no m=text line exists */ 07566 07567 /* Scan for the first media stream (m=) line to limit scanning of globals */ 07568 nextm = get_sdp_iterate(&next, req, "m"); 07569 if (ast_strlen_zero(nextm)) { 07570 ast_log(LOG_WARNING, "Insufficient information for SDP (m= not found)\n"); 07571 return -1; 07572 } 07573 07574 /* Scan session level SDP parameters (lines before first media stream) */ 07575 while ((type = get_sdp_line(&iterator, next - 1, req, &value)) != '\0') { 07576 int processed = FALSE; 07577 switch (type) { 07578 case 'o': 07579 /* If we end up receiving SDP that doesn't actually modify the session we don't want to treat this as a fatal 07580 * error. We just want to ignore the SDP and let the rest of the packet be handled as normal. 07581 */ 07582 if (!process_sdp_o(value, p)) 07583 return (p->session_modify == FALSE) ? 0 : -1; 07584 break; 07585 case 'c': 07586 if (process_sdp_c(value, &sessionhp)) { 07587 processed = TRUE; 07588 hp = &sessionhp.hp; 07589 vhp = hp; 07590 thp = hp; 07591 ihp = hp; 07592 } 07593 break; 07594 case 'a': 07595 if (process_sdp_a_sendonly(value, &sendonly)) { 07596 processed = TRUE; 07597 vsendonly = sendonly; 07598 } 07599 else if (process_sdp_a_audio(value, p, newaudiortp, &last_rtpmap_codec)) 07600 processed = TRUE; 07601 else if (process_sdp_a_video(value, p, newvideortp, &last_rtpmap_codec)) 07602 processed = TRUE; 07603 else if (process_sdp_a_text(value, p, newtextrtp, red_fmtp, &red_num_gen, red_data_pt, &last_rtpmap_codec)) 07604 processed = TRUE; 07605 else if (process_sdp_a_image(value, p)) 07606 processed = TRUE; 07607 break; 07608 } 07609 07610 if (option_debug > 2) 07611 ast_log(LOG_DEBUG, "Processing session-level SDP %c=%s... %s\n", type, value, (processed == TRUE)? "OK." : "UNSUPPORTED."); 07612 } 07613 07614 07615 07616 /* Scan media stream (m=) specific parameters loop */ 07617 while (!ast_strlen_zero(nextm)) { 07618 int audio = FALSE; 07619 int video = FALSE; 07620 int image = FALSE; 07621 int text = FALSE; 07622 int x; 07623 07624 numberofports = 1; 07625 len = -1; 07626 start = next; 07627 m = nextm; 07628 iterator = next; 07629 nextm = get_sdp_iterate(&next, req, "m"); 07630 07631 /* Search for audio media definition */ 07632 if ((sscanf(m, "audio %30u/%30u RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) || 07633 (sscanf(m, "audio %30u RTP/AVP %n", &x, &len) == 1 && len > 0)) { 07634 audio = TRUE; 07635 p->offered_media[SDP_AUDIO].offered = TRUE; 07636 numberofmediastreams++; 07637 portno = x; 07638 07639 /* Scan through the RTP payload types specified in a "m=" line: */ 07640 codecs = m + len; 07641 ast_copy_string(p->offered_media[SDP_AUDIO].text, codecs, sizeof(p->offered_media[SDP_AUDIO].text)); 07642 for (; !ast_strlen_zero(codecs); codecs = ast_skip_blanks(codecs + len)) { 07643 if (sscanf(codecs, "%30u%n", &codec, &len) != 1) { 07644 ast_log(LOG_WARNING, "Error in codec string '%s'\n", codecs); 07645 return -1; 07646 } 07647 if (debug) 07648 ast_verbose("Found RTP audio format %d\n", codec); 07649 07650 ast_rtp_set_m_type(newaudiortp, codec); 07651 } 07652 /* Search for video media definition */ 07653 } else if ((sscanf(m, "video %30u/%30u RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) || 07654 (sscanf(m, "video %30u RTP/AVP %n", &x, &len) == 1 && len >= 0)) { 07655 video = TRUE; 07656 p->novideo = FALSE; 07657 p->offered_media[SDP_VIDEO].offered = TRUE; 07658 numberofmediastreams++; 07659 vportno = x; 07660 07661 /* Scan through the RTP payload types specified in a "m=" line: */ 07662 codecs = m + len; 07663 ast_copy_string(p->offered_media[SDP_VIDEO].text, codecs, sizeof(p->offered_media[SDP_VIDEO].text)); 07664 for (; !ast_strlen_zero(codecs); codecs = ast_skip_blanks(codecs + len)) { 07665 if (sscanf(codecs, "%30u%n", &codec, &len) != 1) { 07666 ast_log(LOG_WARNING, "Error in codec string '%s'\n", codecs); 07667 return -1; 07668 } 07669 if (debug) 07670 ast_verbose("Found RTP video format %d\n", codec); 07671 ast_rtp_set_m_type(newvideortp, codec); 07672 } 07673 /* Search for text media definition */ 07674 } else if ((sscanf(m, "text %30u/%30u RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) || 07675 (sscanf(m, "text %30u RTP/AVP %n", &x, &len) == 1 && len > 0)) { 07676 text = TRUE; 07677 p->notext = FALSE; 07678 p->offered_media[SDP_TEXT].offered = TRUE; 07679 numberofmediastreams++; 07680 tportno = x; 07681 07682 /* Scan through the RTP payload types specified in a "m=" line: */ 07683 codecs = m + len; 07684 ast_copy_string(p->offered_media[SDP_TEXT].text, codecs, sizeof(p->offered_media[SDP_TEXT].text)); 07685 for (; !ast_strlen_zero(codecs); codecs = ast_skip_blanks(codecs + len)) { 07686 if (sscanf(codecs, "%30u%n", &codec, &len) != 1) { 07687 ast_log(LOG_WARNING, "Error in codec string '%s'\n", codecs); 07688 return -1; 07689 } 07690 if (debug) 07691 ast_verbose("Found RTP text format %d\n", codec); 07692 ast_rtp_set_m_type(newtextrtp, codec); 07693 } 07694 /* Search for image media definition */ 07695 } else if (p->udptl && ((sscanf(m, "image %30u udptl t38%n", &x, &len) == 1 && len > 0) || 07696 (sscanf(m, "image %30u UDPTL t38%n", &x, &len) == 1 && len > 0) )) { 07697 image = TRUE; 07698 if (debug) 07699 ast_verbose("Got T.38 offer in SDP in dialog %s\n", p->callid); 07700 p->offered_media[SDP_IMAGE].offered = TRUE; 07701 udptlportno = x; 07702 numberofmediastreams++; 07703 07704 if (p->t38.state != T38_ENABLED) { 07705 memset(&p->t38.their_parms, 0, sizeof(p->t38.their_parms)); 07706 } 07707 } else { 07708 ast_log(LOG_WARNING, "Unsupported SDP media type in offer: %s\n", m); 07709 continue; 07710 } 07711 07712 /* Check for number of ports */ 07713 if (numberofports > 1) 07714 ast_log(LOG_WARNING, "SDP offered %d ports for media, not supported by Asterisk. Will try anyway...\n", numberofports); 07715 07716 07717 07718 /* Media stream specific parameters */ 07719 while ((type = get_sdp_line(&iterator, next - 1, req, &value)) != '\0') { 07720 int processed = FALSE; 07721 07722 switch (type) { 07723 case 'c': 07724 if (audio) { 07725 if (process_sdp_c(value, &audiohp)) { 07726 processed = TRUE; 07727 hp = &audiohp.hp; 07728 } 07729 } else if (video) { 07730 if (process_sdp_c(value, &videohp)) { 07731 processed = TRUE; 07732 vhp = &videohp.hp; 07733 } 07734 } else if (text) { 07735 if (process_sdp_c(value, &texthp)) { 07736 processed = TRUE; 07737 thp = &texthp.hp; 07738 } 07739 } else if (image) { 07740 if (process_sdp_c(value, &imagehp)) { 07741 processed = TRUE; 07742 ihp = &imagehp.hp; 07743 } 07744 } 07745 break; 07746 case 'a': 07747 /* Audio specific scanning */ 07748 if (audio) { 07749 if (process_sdp_a_sendonly(value, &sendonly)) 07750 processed = TRUE; 07751 else if (process_sdp_a_audio(value, p, newaudiortp, &last_rtpmap_codec)) 07752 processed = TRUE; 07753 } 07754 /* Video specific scanning */ 07755 else if (video) { 07756 if (process_sdp_a_sendonly(value, &vsendonly)) 07757 processed = TRUE; 07758 else if (process_sdp_a_video(value, p, newvideortp, &last_rtpmap_codec)) 07759 processed = TRUE; 07760 } 07761 /* Text (T.140) specific scanning */ 07762 else if (text) { 07763 if (process_sdp_a_text(value, p, newtextrtp, red_fmtp, &red_num_gen, red_data_pt, &last_rtpmap_codec)) 07764 processed = TRUE; 07765 } 07766 /* Image (T.38 FAX) specific scanning */ 07767 else if (image) { 07768 if (process_sdp_a_image(value, p)) 07769 processed = TRUE; 07770 } 07771 break; 07772 } 07773 07774 if (option_debug > 2) 07775 ast_log(LOG_DEBUG, "Processing media-level (%s) SDP %c=%s... %s\n", 07776 (audio == TRUE)? "audio" : (video == TRUE)? "video" : "image", 07777 type, value, 07778 (processed == TRUE)? "OK." : "UNSUPPORTED."); 07779 } 07780 } 07781 07782 07783 /* Sanity checks */ 07784 if (!hp && !vhp && !thp && !ihp) { 07785 ast_log(LOG_WARNING, "Insufficient information in SDP (c=)...\n"); 07786 return -1; 07787 } 07788 07789 if (portno == -1 && vportno == -1 && udptlportno == -1 && tportno == -1) 07790 /* No acceptable offer found in SDP - we have no ports */ 07791 /* Do not change RTP or VRTP if this is a re-invite */ 07792 return -2; 07793 07794 if (numberofmediastreams > 3) 07795 /* We have too many fax, audio and/or video and/or text media streams, fail this offer */ 07796 return -3; 07797 07798 if (udptlportno == -1) { 07799 change_t38_state(p, T38_DISABLED); 07800 } 07801 07802 /* Now gather all of the codecs that we are asked for: */ 07803 ast_rtp_get_current_formats(newaudiortp, &peercapability, &peernoncodeccapability); 07804 ast_rtp_get_current_formats(newvideortp, &vpeercapability, &vpeernoncodeccapability); 07805 ast_rtp_get_current_formats(newtextrtp, &tpeercapability, &tpeernoncodeccapability); 07806 07807 newjointcapability = p->capability & (peercapability | vpeercapability | tpeercapability); 07808 newpeercapability = (peercapability | vpeercapability | tpeercapability); 07809 newnoncodeccapability = p->noncodeccapability & peernoncodeccapability; 07810 07811 07812 if (debug) { 07813 /* shame on whoever coded this.... */ 07814 char s1[SIPBUFSIZE], s2[SIPBUFSIZE], s3[SIPBUFSIZE], s4[SIPBUFSIZE], s5[SIPBUFSIZE]; 07815 07816 ast_verbose("Capabilities: us - %s, peer - audio=%s/video=%s/text=%s, combined - %s\n", 07817 ast_getformatname_multiple(s1, SIPBUFSIZE, p->capability), 07818 ast_getformatname_multiple(s2, SIPBUFSIZE, peercapability), 07819 ast_getformatname_multiple(s3, SIPBUFSIZE, vpeercapability), 07820 ast_getformatname_multiple(s4, SIPBUFSIZE, tpeercapability), 07821 ast_getformatname_multiple(s5, SIPBUFSIZE, newjointcapability)); 07822 07823 ast_verbose("Non-codec capabilities (dtmf): us - %s, peer - %s, combined - %s\n", 07824 ast_rtp_lookup_mime_multiple(s1, SIPBUFSIZE, p->noncodeccapability, 0, 0), 07825 ast_rtp_lookup_mime_multiple(s2, SIPBUFSIZE, peernoncodeccapability, 0, 0), 07826 ast_rtp_lookup_mime_multiple(s3, SIPBUFSIZE, newnoncodeccapability, 0, 0)); 07827 } 07828 if (!newjointcapability && (portno != -1)) { 07829 ast_log(LOG_NOTICE, "No compatible codecs, not accepting this offer!\n"); 07830 /* Do NOT Change current setting */ 07831 return -1; 07832 } 07833 07834 /* Setup audio address and port */ 07835 if (p->rtp) { 07836 if (portno > 0) { 07837 sin.sin_family = AF_INET; 07838 sin.sin_port = htons(portno); 07839 memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr)); 07840 ast_rtp_set_peer(p->rtp, &sin); 07841 if (debug) 07842 ast_verbose("Peer audio RTP is at port %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 07843 /* We are now ready to change the sip session and p->rtp and p->vrtp with the offered codecs, since 07844 they are acceptable */ 07845 p->jointcapability = newjointcapability; /* Our joint codec profile for this call */ 07846 p->peercapability = newpeercapability; /* The other sides capability in latest offer */ 07847 p->jointnoncodeccapability = newnoncodeccapability; /* DTMF capabilities */ 07848 07849 ast_rtp_pt_copy(p->rtp, newaudiortp); 07850 07851 if (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO) { 07852 ast_clear_flag(&p->flags[0], SIP_DTMF); 07853 if (newnoncodeccapability & AST_RTP_DTMF) { 07854 /* XXX Would it be reasonable to drop the DSP at this point? XXX */ 07855 ast_set_flag(&p->flags[0], SIP_DTMF_RFC2833); 07856 /* Since RFC2833 is now negotiated we need to change some properties of the RTP stream */ 07857 ast_rtp_setdtmf(p->rtp, 1); 07858 ast_rtp_setdtmfcompensate(p->rtp, ast_test_flag(&p->flags[1], SIP_PAGE2_RFC2833_COMPENSATE)); 07859 } else { 07860 ast_set_flag(&p->flags[0], SIP_DTMF_INBAND); 07861 } 07862 } 07863 } else if (udptlportno > 0) { 07864 if (debug) 07865 ast_verbose("Got T.38 Re-invite without audio. Keeping RTP active during T.38 session.\n"); 07866 } else { 07867 ast_rtp_stop(p->rtp); 07868 if (debug) 07869 ast_verbose("Peer doesn't provide audio\n"); 07870 } 07871 } 07872 07873 /* Setup video address and port */ 07874 if (p->vrtp) { 07875 if (vportno > 0) { 07876 vsin.sin_family = AF_INET; 07877 vsin.sin_port = htons(vportno); 07878 memcpy(&vsin.sin_addr, vhp->h_addr, sizeof(vsin.sin_addr)); 07879 ast_rtp_set_peer(p->vrtp, &vsin); 07880 if (debug) 07881 ast_verbose("Peer video RTP is at port %s:%d\n", ast_inet_ntoa(vsin.sin_addr), ntohs(vsin.sin_port)); 07882 ast_rtp_pt_copy(p->vrtp, newvideortp); 07883 } else { 07884 ast_rtp_stop(p->vrtp); 07885 if (debug) 07886 ast_verbose("Peer doesn't provide video\n"); 07887 } 07888 } 07889 07890 /* Setup text address and port */ 07891 if (p->trtp) { 07892 if (tportno > 0) { 07893 tsin.sin_family = AF_INET; 07894 tsin.sin_port = htons(tportno); 07895 memcpy(&tsin.sin_addr, thp->h_addr, sizeof(tsin.sin_addr)); 07896 ast_rtp_set_peer(p->trtp, &tsin); 07897 if (debug) 07898 ast_verbose("Peer T.140 RTP is at port %s:%d\n", ast_inet_ntoa(vsin.sin_addr), ntohs(vsin.sin_port)); 07899 if ((p->jointcapability & AST_FORMAT_T140RED)) { 07900 p->red = 1; 07901 rtp_red_init(p->trtp, 300, red_data_pt, 2); 07902 } else { 07903 p->red = 0; 07904 } 07905 ast_rtp_pt_copy(p->trtp, newtextrtp); 07906 } else { 07907 ast_rtp_stop(p->trtp); 07908 if (debug) 07909 ast_verbose("Peer doesn't provide T.140\n"); 07910 } 07911 } 07912 /* Setup image address and port */ 07913 if (p->udptl) { 07914 if (udptlportno > 0) { 07915 isin.sin_family = AF_INET; 07916 isin.sin_port = htons(udptlportno); 07917 if (ast_test_flag(&p->flags[0], SIP_NAT) && ast_test_flag(&p->flags[1], SIP_PAGE2_UDPTL_DESTINATION)) { 07918 struct sockaddr_in remote_address = { 0, }; 07919 ast_rtp_get_peer(p->rtp, &remote_address); 07920 if (remote_address.sin_addr.s_addr) { 07921 memcpy(&isin, &remote_address, sizeof(isin)); 07922 if (debug) { 07923 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)); 07924 } 07925 } 07926 } else { 07927 memcpy(&isin.sin_addr, ihp->h_addr, sizeof(sin.sin_addr)); 07928 } 07929 ast_udptl_set_peer(p->udptl, &isin); 07930 if (debug) 07931 ast_debug(1,"Peer T.38 UDPTL is at port %s:%d\n", ast_inet_ntoa(isin.sin_addr), ntohs(isin.sin_port)); 07932 07933 /* verify the far max ifp can be calculated. this requires far max datagram to be set. */ 07934 if (!ast_udptl_get_far_max_datagram(p->udptl)) { 07935 /* setting to zero will force a default if none was provided by the SDP */ 07936 ast_udptl_set_far_max_datagram(p->udptl, 0); 07937 } 07938 07939 /* Remote party offers T38, we need to update state */ 07940 if ((t38action == SDP_T38_ACCEPT) && 07941 (p->t38.state == T38_LOCAL_REINVITE)) { 07942 change_t38_state(p, T38_ENABLED); 07943 } else if ((t38action == SDP_T38_INITIATE) && 07944 p->owner && p->lastinvite) { 07945 change_t38_state(p, T38_PEER_REINVITE); /* T38 Offered in re-invite from remote party */ 07946 } 07947 } else { 07948 ast_udptl_stop(p->udptl); 07949 if (debug) 07950 ast_debug(1, "Peer doesn't provide T.38 UDPTL\n"); 07951 } 07952 } 07953 07954 if ((portno == -1) && (p->t38.state != T38_DISABLED)) { 07955 ast_debug(3, "Have T.38 but no audio, accepting offer anyway\n"); 07956 return 0; 07957 } 07958 07959 /* Ok, we're going with this offer */ 07960 ast_debug(2, "We're settling with these formats: %s\n", ast_getformatname_multiple(buf, SIPBUFSIZE, p->jointcapability)); 07961 07962 if (!p->owner) /* There's no open channel owning us so we can return here. For a re-invite or so, we proceed */ 07963 return 0; 07964 07965 ast_debug(4, "We have an owner, now see if we need to change this call\n"); 07966 07967 if (!(p->owner->nativeformats & p->jointcapability) && (p->jointcapability & AST_FORMAT_AUDIO_MASK)) { 07968 if (debug) { 07969 char s1[SIPBUFSIZE], s2[SIPBUFSIZE]; 07970 ast_debug(1, "Oooh, we need to change our audio formats since our peer supports only %s and not %s\n", 07971 ast_getformatname_multiple(s1, SIPBUFSIZE, p->jointcapability), 07972 ast_getformatname_multiple(s2, SIPBUFSIZE, p->owner->nativeformats)); 07973 } 07974 p->owner->nativeformats = ast_codec_choose(&p->prefs, p->jointcapability, 1) | (p->capability & vpeercapability) | (p->capability & tpeercapability); 07975 ast_set_read_format(p->owner, p->owner->readformat); 07976 ast_set_write_format(p->owner, p->owner->writeformat); 07977 } 07978 07979 if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD) && sin.sin_addr.s_addr && (!sendonly || sendonly == -1)) { 07980 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 07981 /* Activate a re-invite */ 07982 ast_queue_frame(p->owner, &ast_null_frame); 07983 /* Queue Manager Unhold event */ 07984 append_history(p, "Unhold", "%s", req->data->str); 07985 if (global_callevents) 07986 manager_event(EVENT_FLAG_CALL, "Hold", 07987 "Status: Off\r\n" 07988 "Channel: %s\r\n" 07989 "Uniqueid: %s\r\n", 07990 p->owner->name, 07991 p->owner->uniqueid); 07992 if (global_notifyhold) 07993 sip_peer_hold(p, FALSE); 07994 ast_clear_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD); /* Clear both flags */ 07995 } else if (!sin.sin_addr.s_addr || (sendonly && sendonly != -1)) { 07996 int already_on_hold = ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD); 07997 ast_queue_control_data(p->owner, AST_CONTROL_HOLD, 07998 S_OR(p->mohsuggest, NULL), 07999 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 08000 if (sendonly) 08001 ast_rtp_stop(p->rtp); 08002 /* RTCP needs to go ahead, even if we're on hold!!! */ 08003 /* Activate a re-invite */ 08004 ast_queue_frame(p->owner, &ast_null_frame); 08005 /* Queue Manager Hold event */ 08006 append_history(p, "Hold", "%s", req->data->str); 08007 if (global_callevents && !ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD)) { 08008 manager_event(EVENT_FLAG_CALL, "Hold", 08009 "Status: On\r\n" 08010 "Channel: %s\r\n" 08011 "Uniqueid: %s\r\n", 08012 p->owner->name, 08013 p->owner->uniqueid); 08014 } 08015 if (sendonly == 1) /* One directional hold (sendonly/recvonly) */ 08016 ast_set_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD_ONEDIR); 08017 else if (sendonly == 2) /* Inactive stream */ 08018 ast_set_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD_INACTIVE); 08019 else 08020 ast_set_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD_ACTIVE); 08021 if (global_notifyhold && !already_on_hold) 08022 sip_peer_hold(p, TRUE); 08023 } 08024 08025 return 0; 08026 }
| 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 8146 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, LONG_MAX, LONG_MIN, 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().
08147 { 08148 int found = FALSE; 08149 int codec; 08150 char mimeSubtype[128]; 08151 int debug = sip_debug_test_pvt(p); 08152 08153 if (!strncasecmp(a, "ptime", 5)) { 08154 char *tmp = strrchr(a, ':'); 08155 long int framing = 0; 08156 if (tmp) { 08157 tmp++; 08158 framing = strtol(tmp, NULL, 10); 08159 if (framing == LONG_MIN || framing == LONG_MAX) { 08160 framing = 0; 08161 ast_debug(1, "Can't read framing from SDP: %s\n", a); 08162 } 08163 } 08164 if (framing && p->autoframing) { 08165 struct ast_codec_pref *pref = ast_rtp_codec_getpref(p->rtp); 08166 int codec_n; 08167 int format = 0; 08168 for (codec_n = 0; codec_n < MAX_RTP_PT; codec_n++) { 08169 format = ast_rtp_codec_getformat(codec_n); 08170 if (!format) /* non-codec or not found */ 08171 continue; 08172 if (option_debug) 08173 ast_log(LOG_DEBUG, "Setting framing for %d to %ld\n", format, framing); 08174 ast_codec_pref_setsize(pref, format, framing); 08175 } 08176 ast_rtp_codec_setpref(p->rtp, pref); 08177 } 08178 found = TRUE; 08179 } else if (sscanf(a, "rtpmap: %30u %127[^/]/", &codec, mimeSubtype) == 2) { 08180 /* We have a rtpmap to handle */ 08181 if (*last_rtpmap_codec < SDP_MAX_RTPMAP_CODECS) { 08182 if (ast_rtp_set_rtpmap_type(newaudiortp, codec, "audio", mimeSubtype, 08183 ast_test_flag(&p->flags[0], SIP_G726_NONSTANDARD) ? AST_RTP_OPT_G726_NONSTANDARD : 0) != -1) { 08184 if (debug) 08185 ast_verbose("Found audio description format %s for ID %d\n", mimeSubtype, codec); 08186 //found_rtpmap_codecs[last_rtpmap_codec] = codec; 08187 (*last_rtpmap_codec)++; 08188 found = TRUE; 08189 } else { 08190 ast_rtp_unset_m_type(newaudiortp, codec); 08191 if (debug) 08192 ast_verbose("Found unknown media description format %s for ID %d\n", mimeSubtype, codec); 08193 } 08194 } else { 08195 if (debug) 08196 ast_verbose("Discarded description format %s for ID %d\n", mimeSubtype, codec); 08197 } 08198 } 08199 08200 return found; 08201 }
| static int process_sdp_a_image | ( | const char * | a, | |
| struct sip_pvt * | p | |||
| ) | [static] |
Definition at line 8284 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().
08285 { 08286 int found = FALSE; 08287 char s[256]; 08288 unsigned int x; 08289 08290 if ((sscanf(a, "T38FaxMaxBuffer:%30u", &x) == 1)) { 08291 ast_debug(3, "MaxBufferSize:%d\n", x); 08292 found = TRUE; 08293 } else if ((sscanf(a, "T38MaxBitRate:%30u", &x) == 1) || (sscanf(a, "T38FaxMaxRate:%30u", &x) == 1)) { 08294 ast_debug(3, "T38MaxBitRate: %d\n", x); 08295 switch (x) { 08296 case 14400: 08297 p->t38.their_parms.rate = AST_T38_RATE_14400; 08298 break; 08299 case 12000: 08300 p->t38.their_parms.rate = AST_T38_RATE_12000; 08301 break; 08302 case 9600: 08303 p->t38.their_parms.rate = AST_T38_RATE_9600; 08304 break; 08305 case 7200: 08306 p->t38.their_parms.rate = AST_T38_RATE_7200; 08307 break; 08308 case 4800: 08309 p->t38.their_parms.rate = AST_T38_RATE_4800; 08310 break; 08311 case 2400: 08312 p->t38.their_parms.rate = AST_T38_RATE_2400; 08313 break; 08314 } 08315 found = TRUE; 08316 } else if ((sscanf(a, "T38FaxVersion:%30u", &x) == 1)) { 08317 ast_debug(3, "FaxVersion: %u\n", x); 08318 p->t38.their_parms.version = x; 08319 found = TRUE; 08320 } else if ((sscanf(a, "T38FaxMaxDatagram:%30u", &x) == 1) || (sscanf(a, "T38MaxDatagram:%30u", &x) == 1)) { 08321 /* override the supplied value if the configuration requests it */ 08322 if (((signed int) p->t38_maxdatagram >= 0) && ((unsigned int) p->t38_maxdatagram > x)) { 08323 ast_debug(1, "Overriding T38FaxMaxDatagram '%d' with '%d'\n", x, p->t38_maxdatagram); 08324 x = p->t38_maxdatagram; 08325 } 08326 ast_debug(3, "FaxMaxDatagram: %u\n", x); 08327 ast_udptl_set_far_max_datagram(p->udptl, x); 08328 found = TRUE; 08329 } else if ((strncmp(a, "T38FaxFillBitRemoval", 20) == 0)) { 08330 if (sscanf(a, "T38FaxFillBitRemoval:%30u", &x) == 1) { 08331 ast_debug(3, "FillBitRemoval: %d\n", x); 08332 if (x == 1) { 08333 p->t38.their_parms.fill_bit_removal = TRUE; 08334 } 08335 } else { 08336 ast_debug(3, "FillBitRemoval\n"); 08337 p->t38.their_parms.fill_bit_removal = TRUE; 08338 } 08339 found = TRUE; 08340 } else if ((strncmp(a, "T38FaxTranscodingMMR", 20) == 0)) { 08341 if (sscanf(a, "T38FaxTranscodingMMR:%30u", &x) == 1) { 08342 ast_debug(3, "Transcoding MMR: %d\n", x); 08343 if (x == 1) { 08344 p->t38.their_parms.transcoding_mmr = TRUE; 08345 } 08346 } else { 08347 ast_debug(3, "Transcoding MMR\n"); 08348 p->t38.their_parms.transcoding_mmr = TRUE; 08349 } 08350 found = TRUE; 08351 } else if ((strncmp(a, "T38FaxTranscodingJBIG", 21) == 0)) { 08352 if (sscanf(a, "T38FaxTranscodingJBIG:%30u", &x) == 1) { 08353 ast_debug(3, "Transcoding JBIG: %d\n", x); 08354 if (x == 1) { 08355 p->t38.their_parms.transcoding_jbig = TRUE; 08356 } 08357 } else { 08358 ast_debug(3, "Transcoding JBIG\n"); 08359 p->t38.their_parms.transcoding_jbig = TRUE; 08360 } 08361 found = TRUE; 08362 } else if ((sscanf(a, "T38FaxRateManagement:%255s", s) == 1)) { 08363 ast_debug(3, "RateManagement: %s\n", s); 08364 if (!strcasecmp(s, "localTCF")) 08365 p->t38.their_parms.rate_management = AST_T38_RATE_MANAGEMENT_LOCAL_TCF; 08366 else if (!strcasecmp(s, "transferredTCF")) 08367 p->t38.their_parms.rate_management = AST_T38_RATE_MANAGEMENT_TRANSFERRED_TCF; 08368 found = TRUE; 08369 } else if ((sscanf(a, "T38FaxUdpEC:%255s", s) == 1)) { 08370 ast_debug(3, "UDP EC: %s\n", s); 08371 if (!strcasecmp(s, "t38UDPRedundancy")) { 08372 ast_udptl_set_error_correction_scheme(p->udptl, UDPTL_ERROR_CORRECTION_REDUNDANCY); 08373 } else if (!strcasecmp(s, "t38UDPFEC")) { 08374 ast_udptl_set_error_correction_scheme(p->udptl, UDPTL_ERROR_CORRECTION_FEC); 08375 } else { 08376 ast_udptl_set_error_correction_scheme(p->udptl, UDPTL_ERROR_CORRECTION_NONE); 08377 } 08378 found = TRUE; 08379 } 08380 08381 return found; 08382 }
| static int process_sdp_a_sendonly | ( | const char * | a, | |
| int * | sendonly | |||
| ) | [static] |
Definition at line 8126 of file chan_sip.c.
Referenced by process_sdp().
08127 { 08128 int found = FALSE; 08129 08130 if (!strcasecmp(a, "sendonly")) { 08131 if (*sendonly == -1) 08132 *sendonly = 1; 08133 found = TRUE; 08134 } else if (!strcasecmp(a, "inactive")) { 08135 if (*sendonly == -1) 08136 *sendonly = 2; 08137 found = TRUE; 08138 } else if (!strcasecmp(a, "sendrecv")) { 08139 if (*sendonly == -1) 08140 *sendonly = 0; 08141 found = TRUE; 08142 } 08143 return found; 08144 }
| 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 8236 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().
08237 { 08238 int found = FALSE; 08239 int codec; 08240 char mimeSubtype[128]; 08241 char *red_cp; 08242 int debug = sip_debug_test_pvt(p); 08243 08244 if (sscanf(a, "rtpmap: %30u %127[^/]/", &codec, mimeSubtype) == 2) { 08245 /* We have a rtpmap to handle */ 08246 if (*last_rtpmap_codec < SDP_MAX_RTPMAP_CODECS) { 08247 if (!strncasecmp(mimeSubtype, "T140", 4)) { /* Text */ 08248 if (p->trtp) { 08249 /* ast_verbose("Adding t140 mimeSubtype to textrtp struct\n"); */ 08250 ast_rtp_set_rtpmap_type(newtextrtp, codec, "text", mimeSubtype, 0); 08251 found = TRUE; 08252 } 08253 } else if (!strncasecmp(mimeSubtype, "RED", 3)) { /* Text with Redudancy */ 08254 if (p->trtp) { 08255 ast_rtp_set_rtpmap_type(newtextrtp, codec, "text", mimeSubtype, 0); 08256 sprintf(red_fmtp, "fmtp:%d ", codec); 08257 if (debug) 08258 ast_verbose("RED submimetype has payload type: %d\n", codec); 08259 found = TRUE; 08260 } 08261 } 08262 } else { 08263 if (debug) 08264 ast_verbose("Discarded description format %s for ID %d\n", mimeSubtype, codec); 08265 } 08266 } else if (!strncmp(a, red_fmtp, strlen(red_fmtp))) { 08267 /* count numbers of generations in fmtp */ 08268 red_cp = &red_fmtp[strlen(red_fmtp)]; 08269 strncpy(red_fmtp, a, 100); 08270 08271 sscanf(red_cp, "%30u", &red_data_pt[*red_num_gen]); 08272 red_cp = strtok(red_cp, "/"); 08273 while (red_cp && (*red_num_gen)++ < RED_MAX_GENERATION) { 08274 sscanf(red_cp, "%30u", &red_data_pt[*red_num_gen]); 08275 red_cp = strtok(NULL, "/"); 08276 } 08277 red_cp = red_fmtp; 08278 found = TRUE; 08279 } 08280 08281 return found; 08282 }
| 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 8203 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().
08204 { 08205 int found = FALSE; 08206 int codec; 08207 char mimeSubtype[128]; 08208 int debug = sip_debug_test_pvt(p); 08209 08210 if (sscanf(a, "rtpmap: %30u %127[^/]/", &codec, mimeSubtype) == 2) { 08211 /* We have a rtpmap to handle */ 08212 if (*last_rtpmap_codec < SDP_MAX_RTPMAP_CODECS) { 08213 /* Note: should really look at the '#chans' params too */ 08214 if (!strncasecmp(mimeSubtype, "H26", 3) || !strncasecmp(mimeSubtype, "MP4", 3)) { 08215 if (ast_rtp_set_rtpmap_type(newvideortp, codec, "video", mimeSubtype, 0) != -1) { 08216 if (debug) 08217 ast_verbose("Found video description format %s for ID %d\n", mimeSubtype, codec); 08218 //found_rtpmap_codecs[last_rtpmap_codec] = codec; 08219 (*last_rtpmap_codec)++; 08220 found = TRUE; 08221 } else { 08222 ast_rtp_unset_m_type(newvideortp, codec); 08223 if (debug) 08224 ast_verbose("Found unknown media description format %s for ID %d\n", mimeSubtype, codec); 08225 } 08226 } 08227 } else { 08228 if (debug) 08229 ast_verbose("Discarded description format %s for ID %d\n", mimeSubtype, codec); 08230 } 08231 } 08232 08233 return found; 08234 }
| static int process_sdp_c | ( | const char * | c, | |
| struct ast_hostent * | hp | |||
| ) | [static] |
Definition at line 8107 of file chan_sip.c.
References ast_gethostbyname(), ast_log(), FALSE, hp, LOG_WARNING, and TRUE.
Referenced by process_sdp().
08108 { 08109 char host[258]; 08110 struct hostent *hp; 08111 08112 /* Check for Media-description-level-address */ 08113 if (sscanf(c, "IN IP4 %255s", host) != 1) { 08114 ast_log(LOG_WARNING, "Invalid host in c= line, '%s'\n", c); 08115 return FALSE; 08116 } else { 08117 if (!(hp = ast_gethostbyname(host, ast_hp))) { 08118 ast_log(LOG_WARNING, "Unable to lookup RTP Audio host in c= line, '%s'\n", c); 08119 return FALSE; 08120 } 08121 return TRUE; 08122 } 08123 return FALSE; 08124 }
| static int process_sdp_o | ( | const char * | o, | |
| struct sip_pvt * | p | |||
| ) | [static] |
Definition at line 8028 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().
08029 { 08030 char *o_copy; 08031 char *token; 08032 int64_t rua_version; 08033 08034 /* Store the SDP version number of remote UA. This will allow us to 08035 distinguish between session modifications and session refreshes. If 08036 the remote UA does not send an incremented SDP version number in a 08037 subsequent RE-INVITE then that means its not changing media session. 08038 The RE-INVITE may have been sent to update connected party, remote 08039 target or to refresh the session (Session-Timers). Asterisk must not 08040 change media session and increment its own version number in answer 08041 SDP in this case. */ 08042 08043 p->session_modify = TRUE; 08044 08045 if (ast_strlen_zero(o)) { 08046 ast_log(LOG_WARNING, "SDP syntax error. SDP without an o= line\n"); 08047 return FALSE; 08048 } 08049 08050 o_copy = ast_strdupa(o); 08051 token = strsep(&o_copy, " "); /* Skip username */ 08052 if (!o_copy) { 08053 ast_log(LOG_WARNING, "SDP syntax error in o= line username\n"); 08054 return FALSE; 08055 } 08056 token = strsep(&o_copy, " "); /* Skip session-id */ 08057 if (!o_copy) { 08058 ast_log(LOG_WARNING, "SDP syntax error in o= line session-id\n"); 08059 return FALSE; 08060 } 08061 token = strsep(&o_copy, " "); /* Version */ 08062 if (!o_copy) { 08063 ast_log(LOG_WARNING, "SDP syntax error in o= line\n"); 08064 return FALSE; 08065 } 08066 if (!sscanf(token, "%30" SCNd64, &rua_version)) { 08067 ast_log(LOG_WARNING, "SDP syntax error in o= line version\n"); 08068 return FALSE; 08069 } 08070 08071 /* we need to check the SDP version number the other end sent us; 08072 * our rules for deciding what to accept are a bit complex. 08073 * 08074 * 1) if 'ignoresdpversion' has been set for this dialog, then 08075 * we will just accept whatever they sent and assume it is 08076 * a modification of the session, even if it is not 08077 * 2) otherwise, if this is the first SDP we've seen from them 08078 * we accept it 08079 * 3) otherwise, if the new SDP version number is higher than the 08080 * old one, we accept it 08081 * 4) otherwise, if this SDP is in response to us requesting a switch 08082 * to T.38, we accept the SDP, but also generate a warning message 08083 * that this peer should have the 'ignoresdpversion' option set, 08084 * because it is not following the SDP offer/answer RFC; if we did 08085 * not request a switch to T.38, then we stop parsing the SDP, as it 08086 * has not changed from the previous version 08087 */ 08088 08089 if (ast_test_flag(&p->flags[1], SIP_PAGE2_IGNORESDPVERSION) || 08090 (p->sessionversion_remote < 0) || 08091 (p->sessionversion_remote < rua_version)) { 08092 p->sessionversion_remote = rua_version; 08093 } else { 08094 if (p->t38.state == T38_LOCAL_REINVITE) { 08095 p->sessionversion_remote = rua_version; 08096 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); 08097 } else { 08098 p->session_modify = FALSE; 08099 ast_debug(2, "Call %s responded to our reinvite without changing SDP version; ignoring SDP.\n", p->callid); 08100 return FALSE; 08101 } 08102 } 08103 08104 return TRUE; 08105 }
| static struct sip_proxy* proxy_allocate | ( | char * | name, | |
| char * | port, | |||
| int | force | |||
| ) | [static, read] |
Allocate and initialize sip proxy.
Definition at line 2943 of file chan_sip.c.
References ao2_alloc, ast_copy_string(), ast_strlen_zero(), sip_proxy::force, sip_proxy::ip, sip_proxy::name, port_str2int(), proxy_update(), and STANDARD_SIP_PORT.
Referenced by build_peer().
02944 { 02945 struct sip_proxy *proxy; 02946 02947 if (ast_strlen_zero(name)) { 02948 return NULL; 02949 } 02950 02951 proxy = ao2_alloc(sizeof(*proxy), NULL); 02952 if (!proxy) 02953 return NULL; 02954 proxy->force = force; 02955 ast_copy_string(proxy->name, name, sizeof(proxy->name)); 02956 proxy->ip.sin_port = htons(port_str2int(port, STANDARD_SIP_PORT)); 02957 proxy_update(proxy); 02958 return proxy; 02959 }
| static int proxy_update | ( | struct sip_proxy * | proxy | ) | [static] |
Resolve DNS srv name or host name in a sip_proxy structure
Definition at line 2912 of file chan_sip.c.
References ast_get_ip_or_srv(), ast_log(), FALSE, sip_proxy::ip, sip_proxy::last_dnsupdate, LOG_WARNING, sip_proxy::name, and TRUE.
Referenced by proxy_allocate(), and reload_config().
02913 { 02914 /* if it's actually an IP address and not a name, 02915 there's no need for a managed lookup */ 02916 if (!inet_aton(proxy->name, &proxy->ip.sin_addr)) { 02917 /* Ok, not an IP address, then let's check if it's a domain or host */ 02918 /* XXX Todo - if we have proxy port, don't do SRV */ 02919 if (ast_get_ip_or_srv(&proxy->ip, proxy->name, global_srvlookup ? "_sip._udp" : NULL) < 0) { 02920 ast_log(LOG_WARNING, "Unable to locate host '%s'\n", proxy->name); 02921 return FALSE; 02922 } 02923 } 02924 proxy->last_dnsupdate = time(NULL); 02925 return TRUE; 02926 }
| static int queue_request | ( | struct sip_pvt * | p, | |
| const struct sip_request * | req | |||
| ) | [static] |
Definition at line 20909 of file chan_sip.c.
References ast_calloc, AST_LIST_INSERT_TAIL, ast_sched_add(), copy_request(), dialog_ref(), dialog_unref(), sip_pvt::request_queue, sip_pvt::request_queue_sched_id, and scheduler_process_request_queue().
Referenced by handle_request_do().
20910 { 20911 struct sip_request *newreq; 20912 20913 if (!(newreq = ast_calloc(1, sizeof(*newreq)))) { 20914 return -1; 20915 } 20916 20917 copy_request(newreq, req); 20918 AST_LIST_INSERT_TAIL(&p->request_queue, newreq, next); 20919 if (p->request_queue_sched_id == -1) { 20920 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) { 20921 dialog_unref(p, "Decrement refcount due to sched_add failure"); 20922 } 20923 } 20924 20925 return 0; 20926 }
| static struct sip_peer * realtime_peer | ( | const char * | peername, | |
| struct sockaddr_in * | sin, | |||
| int | devstate_only | |||
| ) | [static, read] |
realtime_peer: Get peer from realtime storage Checks the "sippeers" realtime family from extconfig.conf Checks the "sipregs" realtime family from extconfig.conf if it's configured. This returns a pointer to a peer and because we use build_peer, we can rest assured that the refcount is bumped.
Definition at line 4351 of file chan_sip.c.
References sip_peer::addr, ao2_t_link, ast_check_realtime(), ast_config_destroy(), ast_copy_flags, ast_copy_string(), ast_debug, ast_gethostbyname(), ast_inet_ntoa(), ast_load_realtime(), ast_load_realtime_multientry(), ast_log(), AST_SCHED_REPLACE_UNREF, ast_test_flag, ast_variables_destroy(), build_peer(), sip_peer::expire, expire_register(), sip_peer::flags, get_insecure_variable_from_config(), get_name_from_variable(), hp, ipaddr, sip_peer::is_realtime, LOG_WARNING, sip_peer::name, ast_variable::name, ast_variable::next, ref_peer(), SENTINEL, SIP_PAGE2_RTAUTOCLEAR, SIP_PAGE2_RTCACHEFRIENDS, TRUE, unref_peer(), ast_variable::value, and var.
Referenced by find_peer().
04352 { 04353 struct sip_peer *peer; 04354 struct ast_variable *var = NULL; 04355 struct ast_variable *varregs = NULL; 04356 struct ast_variable *tmp; 04357 struct ast_config *peerlist = NULL; 04358 char ipaddr[INET_ADDRSTRLEN]; 04359 char portstring[6]; /*up to 5 digits plus null terminator*/ 04360 char *cat = NULL; 04361 unsigned short portnum; 04362 int realtimeregs = ast_check_realtime("sipregs"); 04363 04364 /* First check on peer name */ 04365 if (newpeername) { 04366 if (realtimeregs) 04367 varregs = ast_load_realtime("sipregs", "name", newpeername, SENTINEL); 04368 04369 var = ast_load_realtime("sippeers", "name", newpeername, "host", "dynamic", SENTINEL); 04370 if (!var && sin) 04371 var = ast_load_realtime("sippeers", "name", newpeername, "host", ast_inet_ntoa(sin->sin_addr), SENTINEL); 04372 if (!var) { 04373 var = ast_load_realtime("sippeers", "name", newpeername, SENTINEL); 04374 /*!\note 04375 * If this one loaded something, then we need to ensure that the host 04376 * field matched. The only reason why we can't have this as a criteria 04377 * is because we only have the IP address and the host field might be 04378 * set as a name (and the reverse PTR might not match). 04379 */ 04380 if (var && sin) { 04381 for (tmp = var; tmp; tmp = tmp->next) { 04382 if (!strcasecmp(tmp->name, "host")) { 04383 struct hostent *hp; 04384 struct ast_hostent ahp; 04385 if (!(hp = ast_gethostbyname(tmp->value, &ahp)) || (memcmp(hp->h_addr, &sin->sin_addr, sizeof(hp->h_addr)))) { 04386 /* No match */ 04387 ast_variables_destroy(var); 04388 var = NULL; 04389 } 04390 break; 04391 } 04392 } 04393 } 04394 } 04395 } 04396 04397 if (!var && sin) { /* Then check on IP address for dynamic peers */ 04398 ast_copy_string(ipaddr, ast_inet_ntoa(sin->sin_addr), sizeof(ipaddr)); 04399 portnum = ntohs(sin->sin_port); 04400 sprintf(portstring, "%u", portnum); 04401 var = ast_load_realtime("sippeers", "host", ipaddr, "port", portstring, SENTINEL); /* First check for fixed IP hosts */ 04402 if (var) { 04403 if (realtimeregs) { 04404 newpeername = get_name_from_variable(var, newpeername); 04405 varregs = ast_load_realtime("sipregs", "name", newpeername, SENTINEL); 04406 } 04407 } else { 04408 if (realtimeregs) 04409 varregs = ast_load_realtime("sipregs", "ipaddr", ipaddr, "port", portstring, SENTINEL); /* Then check for registered hosts */ 04410 else 04411 var = ast_load_realtime("sippeers", "ipaddr", ipaddr, "port", portstring, SENTINEL); /* Then check for registered hosts */ 04412 if (varregs) { 04413 newpeername = get_name_from_variable(varregs, newpeername); 04414 var = ast_load_realtime("sippeers", "name", newpeername, SENTINEL); 04415 } 04416 } 04417 if (!var) { /*We couldn't match on ipaddress and port, so we need to check if port is insecure*/ 04418 peerlist = ast_load_realtime_multientry("sippeers", "host", ipaddr, SENTINEL); 04419 if (peerlist) { 04420 var = get_insecure_variable_from_config(peerlist); 04421 if(var) { 04422 if (realtimeregs) { 04423 newpeername = get_name_from_variable(var, newpeername); 04424 varregs = ast_load_realtime("sipregs", "name", newpeername, SENTINEL); 04425 } 04426 } else { /*var wasn't found in the list of "hosts", so try "ipaddr"*/ 04427 peerlist = NULL; 04428 cat = NULL; 04429 peerlist = ast_load_realtime_multientry("sippeers", "ipaddr", ipaddr, SENTINEL); 04430 if(peerlist) { 04431 var = get_insecure_variable_from_config(peerlist); 04432 if(var) { 04433 if (realtimeregs) { 04434 newpeername = get_name_from_variable(var, newpeername); 04435 varregs = ast_load_realtime("sipregs", "name", newpeername, SENTINEL); 04436 } 04437 } 04438 } 04439 } 04440 } else { 04441 if (realtimeregs) { 04442 peerlist = ast_load_realtime_multientry("sipregs", "ipaddr", ipaddr, SENTINEL); 04443 if (peerlist) { 04444 varregs = get_insecure_variable_from_config(peerlist); 04445 if (varregs) { 04446 newpeername = get_name_from_variable(varregs, newpeername); 04447 var = ast_load_realtime("sippeers", "name", newpeername, SENTINEL); 04448 } 04449 } 04450 } else { 04451 peerlist = ast_load_realtime_multientry("sippeers", "ipaddr", ipaddr, SENTINEL); 04452 if (peerlist) { 04453 var = get_insecure_variable_from_config(peerlist); 04454 if (var) { 04455 newpeername = get_name_from_variable(var, newpeername); 04456 varregs = ast_load_realtime("sipregs", "name", newpeername, SENTINEL); 04457 } 04458 } 04459 } 04460 } 04461 } 04462 } 04463 04464 if (!var) { 04465 if (peerlist) 04466 ast_config_destroy(peerlist); 04467 return NULL; 04468 } 04469 04470 for (tmp = var; tmp; tmp = tmp->next) { 04471 /* If this is type=user, then skip this object. */ 04472 if (!strcasecmp(tmp->name, "type") && 04473 !strcasecmp(tmp->value, "user")) { 04474 if(peerlist) 04475 ast_config_destroy(peerlist); 04476 else { 04477 ast_variables_destroy(var); 04478 ast_variables_destroy(varregs); 04479 } 04480 return NULL; 04481 } else if (!newpeername && !strcasecmp(tmp->name, "name")) { 04482 newpeername = tmp->value; 04483 } 04484 } 04485 04486 if (!newpeername) { /* Did not find peer in realtime */ 04487 ast_log(LOG_WARNING, "Cannot Determine peer name ip=%s\n", ipaddr); 04488 if(peerlist) 04489 ast_config_destroy(peerlist); 04490 else 04491 ast_variables_destroy(var); 04492 return NULL; 04493 } 04494 04495 04496 /* Peer found in realtime, now build it in memory */ 04497 peer = build_peer(newpeername, var, varregs, TRUE, devstate_only); 04498 if (!peer) { 04499 if(peerlist) 04500 ast_config_destroy(peerlist); 04501 else { 04502 ast_variables_destroy(var); 04503 ast_variables_destroy(varregs); 04504 } 04505 return NULL; 04506 } 04507 04508 ast_debug(3, "-REALTIME- loading peer from database to memory. Name: %s. Peer objects: %d\n", peer->name, rpeerobjs); 04509 04510 if (ast_test_flag(&global_flags[1], SIP_PAGE2_RTCACHEFRIENDS) && !devstate_only) { 04511 /* Cache peer */ 04512 ast_copy_flags(&peer->flags[1], &global_flags[1], SIP_PAGE2_RTAUTOCLEAR|SIP_PAGE2_RTCACHEFRIENDS); 04513 if (ast_test_flag(&global_flags[1], SIP_PAGE2_RTAUTOCLEAR)) { 04514 AST_SCHED_REPLACE_UNREF(peer->expire, sched, global_rtautoclear * 1000, expire_register, peer, 04515 unref_peer(_data, "remove registration ref"), 04516 unref_peer(peer, "remove registration ref"), 04517 ref_peer(peer, "add registration ref")); 04518 } 04519 ao2_t_link(peers, peer, "link peer into peers table"); 04520 if (peer->addr.sin_addr.s_addr) { 04521 ao2_t_link(peers_by_ip, peer, "link peer into peers_by_ip table"); 04522 } 04523 } 04524 peer->is_realtime = 1; 04525 if (peerlist) 04526 ast_config_destroy(peerlist); 04527 else { 04528 ast_variables_destroy(var); 04529 ast_variables_destroy(varregs); 04530 } 04531 04532 return peer; 04533 }
| 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 4155 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.
Referenced by update_peer().
04156 { 04157 char port[10]; 04158 char ipaddr[INET_ADDRSTRLEN]; 04159 char regseconds[20]; 04160 char *tablename = NULL; 04161 char str_lastms[20]; 04162 04163 const char *sysname = ast_config_AST_SYSTEM_NAME; 04164 char *syslabel = NULL; 04165 04166 time_t nowtime = time(NULL) + expirey; 04167 const char *fc = fullcontact ? "fullcontact" : NULL; 04168 04169 int realtimeregs = ast_check_realtime("sipregs"); 04170 04171 tablename = realtimeregs ? "sipregs" : "sippeers"; 04172 04173 04174 snprintf(str_lastms, sizeof(str_lastms), "%d", lastms); 04175 snprintf(regseconds, sizeof(regseconds), "%d", (int)nowtime); /* Expiration time */ 04176 ast_copy_string(ipaddr, ast_inet_ntoa(sin->sin_addr), sizeof(ipaddr)); 04177 snprintf(port, sizeof(port), "%d", ntohs(sin->sin_port)); 04178 04179 if (ast_strlen_zero(sysname)) /* No system name, disable this */ 04180 sysname = NULL; 04181 else if (sip_cfg.rtsave_sysname) 04182 syslabel = "regserver"; 04183 04184 if (fc) { 04185 ast_update_realtime(tablename, "name", peername, "ipaddr", ipaddr, 04186 "port", port, "regseconds", regseconds, 04187 deprecated_username ? "username" : "defaultuser", defaultuser, 04188 "useragent", useragent, "lastms", str_lastms, 04189 fc, fullcontact, syslabel, sysname, SENTINEL); /* note fc and syslabel _can_ be NULL */ 04190 } else { 04191 ast_update_realtime(tablename, "name", peername, "ipaddr", ipaddr, 04192 "port", port, "regseconds", regseconds, 04193 "useragent", useragent, "lastms", str_lastms, 04194 deprecated_username ? "username" : "defaultuser", defaultuser, 04195 syslabel, sysname, SENTINEL); /* note syslabel _can_ be NULL */ 04196 } 04197 }
| static void receive_message | ( | struct sip_pvt * | p, | |
| struct sip_request * | req | |||
| ) | [static] |
Receive SIP MESSAGE method messages.
Definition at line 13429 of file chan_sip.c.
References AST_FRAME_TEXT, ast_log(), ast_queue_frame(), ast_verbose, buf, sip_pvt::callid, ast_frame::data, ast_frame::datalen, DEFAULT_TRANS_TIMEOUT, FALSE, ast_frame::frametype, get_header(), get_msg_text(), LOG_WARNING, ast_frame::offset, sip_pvt::owner, ast_frame::ptr, sip_debug_test_pvt(), sip_scheddestroy(), ast_frame::subclass, and transmit_response().
Referenced by handle_request_message().
13430 { 13431 char buf[1400]; 13432 struct ast_frame f; 13433 const char *content_type = get_header(req, "Content-Type"); 13434 13435 if (strncmp(content_type, "text/plain", strlen("text/plain"))) { /* No text/plain attachment */ 13436 transmit_response(p, "415 Unsupported Media Type", req); /* Good enough, or? */ 13437 if (!p->owner) 13438 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 13439 return; 13440 } 13441 13442 if (get_msg_text(buf, sizeof(buf), req, FALSE)) { 13443 ast_log(LOG_WARNING, "Unable to retrieve text from %s\n", p->callid); 13444 transmit_response(p, "202 Accepted", req); 13445 if (!p->owner) 13446 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 13447 return; 13448 } 13449 13450 if (p->owner) { 13451 if (sip_debug_test_pvt(p)) 13452 ast_verbose("SIP Text message received: '%s'\n", buf); 13453 memset(&f, 0, sizeof(f)); 13454 f.frametype = AST_FRAME_TEXT; 13455 f.subclass = 0; 13456 f.offset = 0; 13457 f.data.ptr = buf; 13458 f.datalen = strlen(buf); 13459 ast_queue_frame(p->owner, &f); 13460 transmit_response(p, "202 Accepted", req); /* We respond 202 accepted, since we relay the message */ 13461 return; 13462 } 13463 13464 /* Message outside of a call, we do not support that */ 13465 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); 13466 transmit_response(p, "405 Method Not Allowed", req); 13467 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 13468 return; 13469 }
Definition at line 2754 of file chan_sip.c.
References ao2_t_ref.
Referenced by build_peer(), handle_request_subscribe(), handle_response_peerpoke(), parse_register_contact(), realtime_peer(), reg_source_db(), sip_poke_all_peers(), sip_poke_noanswer(), sip_poke_peer(), and sip_unregister().
02755 { 02756 ao2_t_ref(peer, 1, tag); 02757 return peer; 02758 }
| static struct sip_proxy* ref_proxy | ( | struct sip_pvt * | pvt, | |
| struct sip_proxy * | proxy | |||
| ) | [static, read] |
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 2771 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().
02772 { 02773 struct sip_proxy *old_obproxy = pvt->outboundproxy; 02774 /* Cool, now get the refs correct */ 02775 if (proxy && proxy != &global_outboundproxy) { 02776 ao2_ref(proxy, +1); 02777 } 02778 pvt->outboundproxy = proxy; 02779 if (old_obproxy && old_obproxy != &global_outboundproxy) { 02780 ao2_ref(old_obproxy, -1); 02781 } 02782 return proxy; 02783 }
| static const char * referstatus2str | ( | enum referstatus | rstatus | ) | [static] |
Convert transfer status to string.
Definition at line 2883 of file chan_sip.c.
References map_x_s().
Referenced by show_channels_cb().
02884 { 02885 return map_x_s(referstatusstrings, rstatus, ""); 02886 }
| static void reg_source_db | ( | struct sip_peer * | peer | ) | [static] |
Get registration details from Asterisk DB.
Definition at line 11287 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_peer::expire, expire_register(), sip_peer::fullcontact, sip_peer::name, sip_peer::pokeexpire, ref_peer(), register_peer_exten(), sip_peer::rt_fromcontact, sip_poke_peer(), sip_poke_peer_s(), strsep(), TRUE, unref_peer(), and sip_peer::username.
Referenced by build_peer(), and temp_peer().
11288 { 11289 char data[256]; 11290 struct in_addr in; 11291 int expire; 11292 int port; 11293 char *scan, *addr, *port_str, *expiry_str, *username, *contact; 11294 11295 if (peer->rt_fromcontact) 11296 return; 11297 if (ast_db_get("SIP/Registry", peer->name, data, sizeof(data))) 11298 return; 11299 11300 scan = data; 11301 addr = strsep(&scan, ":"); 11302 port_str = strsep(&scan, ":"); 11303 expiry_str = strsep(&scan, ":"); 11304 username = strsep(&scan, ":"); 11305 contact = scan; /* Contact include sip: and has to be the last part of the database entry as long as we use : as a separator */ 11306 11307 if (!inet_aton(addr, &in)) 11308 return; 11309 11310 if (port_str) 11311 port = atoi(port_str); 11312 else 11313 return; 11314 11315 if (expiry_str) 11316 expire = atoi(expiry_str); 11317 else 11318 return; 11319 11320 if (username) 11321 ast_copy_string(peer->username, username, sizeof(peer->username)); 11322 if (contact) 11323 ast_copy_string(peer->fullcontact, contact, sizeof(peer->fullcontact)); 11324 11325 ast_debug(2, "SIP Seeding peer from astdb: '%s' at %s@%s:%d for %d\n", 11326 peer->name, peer->username, ast_inet_ntoa(in), port, expire); 11327 11328 memset(&peer->addr, 0, sizeof(peer->addr)); 11329 peer->addr.sin_family = AF_INET; 11330 peer->addr.sin_addr = in; 11331 peer->addr.sin_port = htons(port); 11332 if (sipsock < 0) { 11333 /* SIP isn't up yet, so schedule a poke only, pretty soon */ 11334 AST_SCHED_REPLACE_UNREF(peer->pokeexpire, sched, ast_random() % 5000 + 1, sip_poke_peer_s, peer, 11335 unref_peer(_data, "removing poke peer ref"), 11336 unref_peer(peer, "removing poke peer ref"), 11337 ref_peer(peer, "adding poke peer ref")); 11338 } else { 11339 sip_poke_peer(peer, 0); 11340 } 11341 AST_SCHED_REPLACE_UNREF(peer->expire, sched, (expire + 10) * 1000, expire_register, peer, 11342 unref_peer(_data, "remove registration ref"), 11343 unref_peer(peer, "remove registration ref"), 11344 ref_peer(peer, "add registration ref")); 11345 register_peer_exten(peer, TRUE); 11346 }
| static void register_peer_exten | ( | struct sip_peer * | peer, | |
| int | onoff | |||
| ) | [static] |
Automatically add peer extension to dial plan.
Definition at line 4200 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().
Referenced by expire_register(), handle_response_peerpoke(), parse_register_contact(), reg_source_db(), sip_destroy_peer(), and sip_poke_noanswer().
04201 { 04202 char multi[256]; 04203 char *stringp, *ext, *context; 04204 struct pbx_find_info q = { .stacklen = 0 }; 04205 04206 /* XXX note that global_regcontext is both a global 'enable' flag and 04207 * the name of the global regexten context, if not specified 04208 * individually. 04209 */ 04210 if (ast_strlen_zero(global_regcontext)) 04211 return; 04212 04213 ast_copy_string(multi, S_OR(peer->regexten, peer->name), sizeof(multi)); 04214 stringp = multi; 04215 while ((ext = strsep(&stringp, "&"))) { 04216 if ((context = strchr(ext, '@'))) { 04217 *context++ = '\0'; /* split ext@context */ 04218 if (!ast_context_find(context)) { 04219 ast_log(LOG_WARNING, "Context %s must exist in regcontext= in sip.conf!\n", context); 04220 continue; 04221 } 04222 } else { 04223 context = global_regcontext; 04224 } 04225 if (onoff) { 04226 if (!ast_exists_extension(NULL, context, ext, 1, NULL)) { 04227 ast_add_extension(context, 1, ext, 1, NULL, NULL, "Noop", 04228 ast_strdup(peer->name), ast_free_ptr, "SIP"); 04229 } 04230 } else if (pbx_find_extension(NULL, NULL, &q, context, ext, 1, NULL, "", E_MATCH)) { 04231 ast_context_remove_extension(context, ext, 1, NULL); 04232 } 04233 } 04234 }
| 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 12142 of file chan_sip.c.
References sip_peer::addr, ao2_t_link, ast_apply_ha(), ast_copy_flags, ast_copy_string(), AST_DEVICE_UNKNOWN, ast_devstate_changed(), ast_inet_ntoa(), AST_LIST_EMPTY, ast_log(), ast_rtp_codec_setpref(), ast_set_flag, ast_string_field_set, ast_test_flag, ast_uri_decode(), AUTH_ACL_FAILED, AUTH_BAD_TRANSPORT, AUTH_NOT_FOUND, AUTH_PEER_NOT_DYNAMIC, AUTH_SECRET_FAILED, AUTH_UNKNOWN_DOMAIN, AUTH_USERNAME_MISMATCH, sip_peer::autoframing, sip_pvt::autoframing, build_contact(), check_auth(), check_request_transport, check_sip_domain(), EVENT_FLAG_SYSTEM, sip_pvt::expiry, 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, sip_peer::prefs, remove_uri_parameters(), sip_pvt::rtp, sip_peer::secret, sip_cancel_destroy(), SIP_NAT, SIP_PAGE2_REGISTERTRYING, SIP_PAGE2_SUBSCRIBEMWIONLY, SIP_PENDINGBYE, SIP_REGISTER, temp_peer(), terminate_uri(), transmit_fake_auth_response(), transmit_response(), transmit_response_with_date(), TRUE, unref_peer(), update_peer(), and XMIT_UNRELIABLE.
Referenced by handle_request_register().
12144 { 12145 enum check_auth_result res = AUTH_NOT_FOUND; 12146 struct sip_peer *peer; 12147 char tmp[256]; 12148 char *name, *c; 12149 char *domain; 12150 12151 terminate_uri(uri); /* warning, overwrite the string */ 12152 12153 ast_copy_string(tmp, get_header(req, "To"), sizeof(tmp)); 12154 if (pedanticsipchecking) 12155 ast_uri_decode(tmp); 12156 12157 c = get_in_brackets(tmp); 12158 c = remove_uri_parameters(c); 12159 12160 if (!strncasecmp(c, "sip:", 4)) { 12161 name = c + 4; 12162 } else if (!strncasecmp(c, "sips:", 5)) { 12163 name = c + 5; 12164 } else { 12165 name = c; 12166 ast_log(LOG_NOTICE, "Invalid to address: '%s' from %s (missing sip:) trying to use anyway...\n", c, ast_inet_ntoa(sin->sin_addr)); 12167 } 12168 12169 /* XXX here too we interpret a missing @domain as a name-only 12170 * URI, whereas the RFC says this is a domain-only uri. 12171 */ 12172 /* Strip off the domain name */ 12173 if ((c = strchr(name, '@'))) { 12174 *c++ = '\0'; 12175 domain = c; 12176 if ((c = strchr(domain, ':'))) /* Remove :port */ 12177 *c = '\0'; 12178 if (!AST_LIST_EMPTY(&domain_list)) { 12179 if (!check_sip_domain(domain, NULL, 0)) { 12180 transmit_response(p, "404 Not found (unknown domain)", &p->initreq); 12181 return AUTH_UNKNOWN_DOMAIN; 12182 } 12183 } 12184 } 12185 c = strchr(name, ';'); /* Remove any Username parameters */ 12186 if (c) 12187 *c = '\0'; 12188 12189 ast_string_field_set(p, exten, name); 12190 build_contact(p); 12191 peer = find_peer(name, NULL, TRUE, FINDPEERS, FALSE, 0); 12192 if (!(peer && ast_apply_ha(peer->ha, sin))) { 12193 /* Peer fails ACL check */ 12194 if (peer) { 12195 unref_peer(peer, "register_verify: unref_peer: from find_peer operation"); 12196 peer = NULL; 12197 res = AUTH_ACL_FAILED; 12198 } else 12199 res = AUTH_NOT_FOUND; 12200 } 12201 12202 if (peer) { 12203 /* Set Frame packetization */ 12204 if (p->rtp) { 12205 ast_rtp_codec_setpref(p->rtp, &peer->prefs); 12206 p->autoframing = peer->autoframing; 12207 } 12208 if (!peer->host_dynamic) { 12209 ast_log(LOG_ERROR, "Peer '%s' is trying to register, but not configured as host=dynamic\n", peer->name); 12210 res = AUTH_PEER_NOT_DYNAMIC; 12211 } else { 12212 ast_copy_flags(&p->flags[0], &peer->flags[0], SIP_NAT); 12213 if (ast_test_flag(&p->flags[1], SIP_PAGE2_REGISTERTRYING)) 12214 transmit_response(p, "100 Trying", req); 12215 if (!(res = check_auth(p, req, peer->name, peer->secret, peer->md5secret, SIP_REGISTER, uri, XMIT_UNRELIABLE, req->ignore))) { 12216 if (sip_cancel_destroy(p)) 12217 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 12218 12219 if (check_request_transport(peer, req)) { 12220 ast_set_flag(&p->flags[0], SIP_PENDINGBYE); 12221 transmit_response_with_date(p, "403 Forbidden", req); 12222 res = AUTH_BAD_TRANSPORT; 12223 } else { 12224 12225 /* We have a successful registration attempt with proper authentication, 12226 now, update the peer */ 12227 switch (parse_register_contact(p, peer, req)) { 12228 case PARSE_REGISTER_DENIED: 12229 transmit_response_with_date(p, "603 Denied", req); 12230 peer->lastmsgssent = -1; 12231 res = 0; 12232 break; 12233 case PARSE_REGISTER_FAILED: 12234 ast_log(LOG_WARNING, "Failed to parse contact info\n"); 12235 transmit_response_with_date(p, "400 Bad Request", req); 12236 peer->lastmsgssent = -1; 12237 res = 0; 12238 break; 12239 case PARSE_REGISTER_QUERY: 12240 ast_string_field_set(p, fullcontact, peer->fullcontact); 12241 transmit_response_with_date(p, "200 OK", req); 12242 peer->lastmsgssent = -1; 12243 res = 0; 12244 break; 12245 case PARSE_REGISTER_UPDATE: 12246 ast_string_field_set(p, fullcontact, peer->fullcontact); 12247 update_peer(peer, p->expiry); 12248 /* Say OK and ask subsystem to retransmit msg counter */ 12249 transmit_response_with_date(p, "200 OK", req); 12250 if (!ast_test_flag((&peer->flags[1]), SIP_PAGE2_SUBSCRIBEMWIONLY)) 12251 peer->lastmsgssent = -1; 12252 res = 0; 12253 break; 12254 } 12255 } 12256 12257 } 12258 } 12259 } 12260 if (!peer && autocreatepeer) { 12261 /* Create peer if we have autocreate mode enabled */ 12262 peer = temp_peer(name); 12263 if (peer) { 12264 ao2_t_link(peers, peer, "link peer into peer table"); 12265 if (peer->addr.sin_addr.s_addr) { 12266 ao2_t_link(peers_by_ip, peer, "link peer into peers-by-ip table"); 12267 } 12268 12269 if (sip_cancel_destroy(p)) 12270 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 12271 switch (parse_register_contact(p, peer, req)) { 12272 case PARSE_REGISTER_DENIED: 12273 transmit_response_with_date(p, "403 Forbidden (ACL)", req); 12274 peer->lastmsgssent = -1; 12275 res = 0; 12276 break; 12277 case PARSE_REGISTER_FAILED: 12278 ast_log(LOG_WARNING, "Failed to parse contact info\n"); 12279 transmit_response_with_date(p, "400 Bad Request", req); 12280 peer->lastmsgssent = -1; 12281 res = 0; 12282 break; 12283 case PARSE_REGISTER_QUERY: 12284 ast_string_field_set(p, fullcontact, peer->fullcontact); 12285 transmit_response_with_date(p, "200 OK", req); 12286 peer->lastmsgssent = -1; 12287 res = 0; 12288 break; 12289 case PARSE_REGISTER_UPDATE: 12290 ast_string_field_set(p, fullcontact, peer->fullcontact); 12291 /* Say OK and ask subsystem to retransmit msg counter */ 12292 transmit_response_with_date(p, "200 OK", req); 12293 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)); 12294 peer->lastmsgssent = -1; 12295 res = 0; 12296 break; 12297 } 12298 } 12299 } 12300 if (!peer && global_alwaysauthreject) { 12301 /* If we found a peer, we transmit a 100 Trying. Therefore, if we're 12302 * trying to avoid leaking information, we MUST also transmit the same 12303 * response when we DON'T find a peer. */ 12304 transmit_response(p, "100 Trying", req); 12305 /* Insert a fake delay between the 100 and the subsequent failure. */ 12306 sched_yield(); 12307 } 12308 if (!res) { 12309 ast_devstate_changed(AST_DEVICE_UNKNOWN, "SIP/%s", peer->name); 12310 } 12311 if (res < 0) { 12312 switch (res) { 12313 case AUTH_SECRET_FAILED: 12314 /* Wrong password in authentication. Go away, don't try again until you fixed it */ 12315 transmit_response(p, "403 Forbidden (Bad auth)", &p->initreq); 12316 if (global_authfailureevents) 12317 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", 12318 name, ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port)); 12319 break; 12320 case AUTH_USERNAME_MISMATCH: 12321 /* Username and digest username does not match. 12322 Asterisk uses the From: username for authentication. We need the 12323 devices to use the same authentication user name until we support 12324 proper authentication by digest auth name */ 12325 case AUTH_NOT_FOUND: 12326 case AUTH_PEER_NOT_DYNAMIC: 12327 case AUTH_ACL_FAILED: 12328 if (global_alwaysauthreject) { 12329 transmit_fake_auth_response(p, SIP_REGISTER, &p->initreq, XMIT_UNRELIABLE); 12330 } else { 12331 /* URI not found */ 12332 if (res == AUTH_PEER_NOT_DYNAMIC) { 12333 transmit_response(p, "403 Forbidden", &p->initreq); 12334 if (global_authfailureevents) 12335 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: SIP\r\nPeer: SIP/%s\r\nPeerStatus: Rejected\r\nCause: AUTH_PEER_NOT_DYNAMIC\r\nAddress: %s\r\nPort: %d\r\n", 12336 name, ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port)); 12337 } 12338 else 12339 transmit_response(p, "404 Not found", &p->initreq); 12340 if (global_authfailureevents) 12341 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: SIP\r\nPeer: SIP/%s\r\nPeerStatus: Rejected\r\nCause: %s\r\nAddress: %s\r\nPort: %d\r\n", 12342 (res == AUTH_USERNAME_MISMATCH) ? "AUTH_USERNAME_MISMATCH" : "URI_NOT_FOUND", name, ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port)); 12343 } 12344 break; 12345 case AUTH_BAD_TRANSPORT: 12346 default: 12347 break; 12348 } 12349 } 12350 if (peer) 12351 unref_peer(peer, "register_verify: unref_peer: tossing stack peer pointer at end of func"); 12352 12353 return res; 12354 }
| static struct sip_registry* registry_addref | ( | struct sip_registry * | reg, | |
| char * | tag | |||
| ) | [static, read] |
Add object reference to SIP registry.
Definition at line 2865 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().
02866 { 02867 ast_debug(3, "SIP Registry %s: refcount now %d\n", reg->hostname, reg->refcount + 1); 02868 return ASTOBJ_REF(reg); /* Add pointer to registry in packet */ 02869 }
| static void * registry_unref | ( | struct sip_registry * | reg, | |
| char * | tag | |||
| ) | [static] |
Definition at line 2857 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().
02858 { 02859 ast_debug(3, "SIP Registry %s: refcount now %d\n", reg->hostname, reg->refcount - 1); 02860 ASTOBJ_UNREF(reg, sip_registry_destroy); 02861 return NULL; 02862 }
| static const char * regstate2str | ( | enum sipregistrystate | regstate | ) | [static] |
Convert registration state status to string.
Definition at line 10668 of file chan_sip.c.
References map_x_s().
Referenced by handle_response_register(), manager_show_registry(), sip_reg_timeout(), and sip_show_registry().
10669 { 10670 return map_x_s(regstatestrings, regstate, "Unknown"); 10671 }
| static int reload | ( | void | ) | [static] |
Part of Asterisk module interface.
Definition at line 24618 of file chan_sip.c.
References sip_reload().
24619 { 24620 if (sip_reload(0, 0, NULL)) 24621 return 0; 24622 return 1; 24623 }
| 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 23282 of file chan_sip.c.
References add_realm_authentication(), add_sip_domain(), sip_peer::addr, ao2_t_callback, ao2_t_link, ast_append_ha(), ast_category_browse(), AST_CERTFILE, ast_clear_flag, ast_config_AST_SYSTEM_NAME, ast_config_destroy(), ast_config_load, ast_context_find_or_create(), ast_copy_string(), ast_debug, ast_enable_packet_fragmentation(), ast_false(), ast_find_ourip(), AST_FLAGS_ALL, ast_free, ast_free_ha(), ast_get_version(), ast_inet_ntoa(), ast_jb_read_conf(), AST_LIST_EMPTY, ast_log(), AST_MAX_CONTEXT, ast_mutex_lock(), ast_mutex_unlock(), ast_netsock_set_qos(), ast_parse_allow_disallow(), ast_parse_arg(), AST_SCHED_DEL_UNREF, ast_set2_flag, ast_set_flag, ast_skip_blanks(), AST_SSL_DONT_VERIFY_SERVER, ast_ssl_setup(), AST_SSL_VERIFY_CLIENT, ast_str2cos(), ast_str2tos(), ast_strdup, ast_strdupa, ast_strip(), ast_strlen_zero(), ast_stun_request(), ast_tcptls_server_start(), ast_test_flag, ast_true(), ast_unload_realtime(), ast_variable_browse(), ast_variable_retrieve(), ast_verb, ASTOBJ_CONTAINER_DESTROYALL, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_RDLOCK, ASTOBJ_UNLOCK, bindaddr, build_peer(), ast_tls_config::cafile, ast_tls_config::capath, ast_tls_config::certfile, CHANNEL_MODULE_LOAD, channelreloadreason2txt(), ast_tls_config::cipher, cleanup_stale_contexts(), clear_realm_authentication(), clear_sip_domains(), CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEUNCHANGED, context, DEFAULT_ALLOW_EXT_DOM, DEFAULT_ALLOWGUEST, DEFAULT_AUTOCREATEPEER, DEFAULT_CALLCOUNTER, DEFAULT_CALLERID, DEFAULT_COMPACTHEADERS, DEFAULT_CONTEXT, DEFAULT_COS_AUDIO, DEFAULT_COS_SIP, DEFAULT_COS_TEXT, DEFAULT_COS_VIDEO, DEFAULT_DEFAULT_EXPIRY, DEFAULT_MAX_CALL_BITRATE, DEFAULT_MAX_EXPIRY, DEFAULT_MAX_SE, DEFAULT_MAXMS, DEFAULT_MIN_EXPIRY, DEFAULT_MIN_SE, DEFAULT_MOHINTERPRET, DEFAULT_MOHSUGGEST, DEFAULT_NOTIFYMIME, DEFAULT_NOTIFYRINGING, DEFAULT_PEDANTIC, default_prefs, DEFAULT_QUALIFY, DEFAULT_QUALIFYFREQ, DEFAULT_REALM, DEFAULT_REGEXTENONQUALIFY, DEFAULT_REGISTRATION_TIMEOUT, DEFAULT_SDPOWNER, DEFAULT_SDPSESSION, DEFAULT_SRVLOOKUP, DEFAULT_T1MIN, default_tls_cfg, DEFAULT_TOS_AUDIO, DEFAULT_TOS_SIP, DEFAULT_TOS_TEXT, DEFAULT_TOS_VIDEO, DEFAULT_USERAGENT, DEFAULT_VMEXTEN, dialog_unlink_all(), dialog_unref(), ast_tls_config::enabled, errno, EVENT_FLAG_SYSTEM, externip, FALSE, ast_tls_config::flags, sip_proxy::force, gen, global_jbconf, global_outboundproxy, handle_common_options(), handle_t38_options(), sip_settings::ignore_regexpire, inaddrcmp(), internip, sip_proxy::ip, ast_variable::lineno, ast_tcptls_session_args::local_address, LOG_ERROR, LOG_NOTICE, LOG_WARNING, manager_event, MAXHOSTNAMELEN, sip_proxy::name, ast_variable::name, netlock, ast_variable::next, OBJ_NODATA, PARSE_INADDR, peer_markall_func(), sip_settings::peer_rtupdate, proxy_update(), registry_unref(), regl, sip_settings::rtsave_sysname, S_OR, secret, SESSION_TIMER_MODE_ACCEPT, SESSION_TIMER_REFRESHER_UAS, SIP_CAN_REINVITE, sip_cfg, sip_debug_config, sip_debug_console, SIP_DOMAIN_AUTO, SIP_DOMAIN_CONFIG, SIP_DTMF_RFC2833, SIP_NAT_RFC3581, SIP_PAGE2_ALLOWOVERLAP, SIP_PAGE2_ALLOWSUBSCRIBE, SIP_PAGE2_CONSTANT_SSRC, SIP_PAGE2_FAX_DETECT, SIP_PAGE2_IGNORESDPVERSION, SIP_PAGE2_RTAUTOCLEAR, SIP_PAGE2_RTCACHEFRIENDS, SIP_PAGE2_TEXTSUPPORT, SIP_PAGE2_VIDEOSUPPORT, SIP_PAGE2_VIDEOSUPPORT_ALWAYS, sip_parse_host(), sip_register(), sip_registry_destroy(), SIP_TIMER_T1, SIP_TYPE_PEER, SIP_TYPE_USER, SIP_USEREQPHONE, sip_request::socket, STANDARD_SIP_PORT, STANDARD_TLS_PORT, str2stmode(), str2strefresher(), strsep(), stunaddr, ast_tcptls_session_args::tls_cfg, TRANSFER_CLOSED, TRANSFER_OPENFORALL, sip_proxy::transport, TRUE, sip_peer::type, unref_peer(), and ast_variable::value.
Referenced by load_module(), and sip_do_reload().
23283 { 23284 struct ast_config *cfg, *ucfg; 23285 struct ast_variable *v; 23286 struct sip_peer *peer; 23287 char *cat, *stringp, *context, *oldregcontext; 23288 char newcontexts[AST_MAX_CONTEXT], oldcontexts[AST_MAX_CONTEXT]; 23289 struct ast_flags dummy[2]; 23290 struct ast_flags config_flags = { reason == CHANNEL_MODULE_LOAD ? 0 : ast_test_flag(&global_flags[1], SIP_PAGE2_RTCACHEFRIENDS) ? 0 : CONFIG_FLAG_FILEUNCHANGED }; 23291 int auto_sip_domains = FALSE; 23292 struct sockaddr_in old_bindaddr = bindaddr; 23293 int registry_count = 0, peer_count = 0; 23294 time_t run_start, run_end; 23295 23296 run_start = time(0); 23297 ast_unload_realtime("sipregs"); 23298 ast_unload_realtime("sippeers"); 23299 cfg = ast_config_load(config, config_flags); 23300 23301 /* We *must* have a config file otherwise stop immediately */ 23302 if (!cfg) { 23303 ast_log(LOG_NOTICE, "Unable to load config %s\n", config); 23304 return -1; 23305 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) { 23306 ucfg = ast_config_load("users.conf", config_flags); 23307 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) 23308 return 1; 23309 /* Must reread both files, because one changed */ 23310 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); 23311 cfg = ast_config_load(config, config_flags); 23312 } else { 23313 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); 23314 ucfg = ast_config_load("users.conf", config_flags); 23315 } 23316 23317 /* Initialize tcp sockets */ 23318 memset(&sip_tcp_desc.local_address, 0, sizeof(sip_tcp_desc.local_address)); 23319 memset(&sip_tls_desc.local_address, 0, sizeof(sip_tls_desc.local_address)); 23320 23321 ast_free_ha(global_contact_ha); 23322 global_contact_ha = NULL; 23323 23324 default_tls_cfg.enabled = FALSE; /* Default: Disable TLS */ 23325 23326 sip_tcp_desc.local_address.sin_port = htons(STANDARD_SIP_PORT); 23327 sip_tls_desc.local_address.sin_port = htons(STANDARD_TLS_PORT); 23328 23329 if (reason != CHANNEL_MODULE_LOAD) { 23330 ast_debug(4, "--------------- SIP reload started\n"); 23331 23332 clear_realm_authentication(authl); 23333 clear_sip_domains(); 23334 authl = NULL; 23335 23336 /* First, destroy all outstanding registry calls */ 23337 /* This is needed, since otherwise active registry entries will not be destroyed */ 23338 ASTOBJ_CONTAINER_TRAVERSE(®l, 1, do { /* regl is locked */ 23339 23340 ASTOBJ_RDLOCK(iterator); /* now regl is locked, and the object is also locked */ 23341 if (iterator->call) { 23342 ast_debug(3, "Destroying active SIP dialog for registry %s@%s\n", iterator->username, iterator->hostname); 23343 /* This will also remove references to the registry */ 23344 dialog_unlink_all(iterator->call, TRUE, TRUE); 23345 iterator->call = dialog_unref(iterator->call, "remove iterator->call from registry traversal"); 23346 } 23347 if (iterator->expire > -1) { 23348 AST_SCHED_DEL_UNREF(sched, iterator->expire, registry_unref(iterator, "reg ptr unref from reload config")); 23349 } 23350 if (iterator->timeout > -1) { 23351 AST_SCHED_DEL_UNREF(sched, iterator->timeout, registry_unref(iterator, "reg ptr unref from reload config")); 23352 } 23353 ASTOBJ_UNLOCK(iterator); 23354 23355 } while(0)); 23356 23357 /* Then, actually destroy users and registry */ 23358 ASTOBJ_CONTAINER_DESTROYALL(®l, sip_registry_destroy); 23359 ast_debug(4, "--------------- Done destroying registry list\n"); 23360 ao2_t_callback(peers, OBJ_NODATA, peer_markall_func, 0, "callback to mark all peers"); 23361 } 23362 23363 /* Reset certificate handling for TLS sessions */ 23364 if (reason != CHANNEL_MODULE_LOAD) { 23365 ast_free(default_tls_cfg.certfile); 23366 ast_free(default_tls_cfg.cipher); 23367 ast_free(default_tls_cfg.cafile); 23368 ast_free(default_tls_cfg.capath); 23369 } 23370 default_tls_cfg.certfile = ast_strdup(AST_CERTFILE); /*XXX Not sure if this is useful */ 23371 default_tls_cfg.cipher = ast_strdup(""); 23372 default_tls_cfg.cafile = ast_strdup(""); 23373 default_tls_cfg.capath = ast_strdup(""); 23374 23375 /* Initialize copy of current global_regcontext for later use in removing stale contexts */ 23376 ast_copy_string(oldcontexts, global_regcontext, sizeof(oldcontexts)); 23377 oldregcontext = oldcontexts; 23378 23379 /* Clear all flags before setting default values */ 23380 /* Preserve debugging settings for console */ 23381 sipdebug &= sip_debug_console; 23382 ast_clear_flag(&global_flags[0], AST_FLAGS_ALL); 23383 ast_clear_flag(&global_flags[1], AST_FLAGS_ALL); 23384 23385 /* Reset IP addresses */ 23386 memset(&bindaddr, 0, sizeof(bindaddr)); 23387 memset(&stunaddr, 0, sizeof(stunaddr)); 23388 memset(&internip, 0, sizeof(internip)); 23389 23390 /* Free memory for local network address mask */ 23391 ast_free_ha(localaddr); 23392 memset(&localaddr, 0, sizeof(localaddr)); 23393 memset(&externip, 0, sizeof(externip)); 23394 memset(&default_prefs, 0 , sizeof(default_prefs)); 23395 memset(&global_outboundproxy, 0, sizeof(struct sip_proxy)); 23396 global_outboundproxy.ip.sin_port = htons(STANDARD_SIP_PORT); 23397 global_outboundproxy.ip.sin_family = AF_INET; /*!< Type of address: IPv4 */ 23398 global_outboundproxy.force = FALSE; /*!< Don't force proxy usage, use route: headers */ 23399 ourport_tcp = STANDARD_SIP_PORT; 23400 ourport_tls = STANDARD_TLS_PORT; 23401 bindaddr.sin_port = htons(STANDARD_SIP_PORT); 23402 global_srvlookup = DEFAULT_SRVLOOKUP; 23403 global_tos_sip = DEFAULT_TOS_SIP; 23404 global_tos_audio = DEFAULT_TOS_AUDIO; 23405 global_tos_video = DEFAULT_TOS_VIDEO; 23406 global_tos_text = DEFAULT_TOS_TEXT; 23407 global_cos_sip = DEFAULT_COS_SIP; 23408 global_cos_audio = DEFAULT_COS_AUDIO; 23409 global_cos_video = DEFAULT_COS_VIDEO; 23410 global_cos_text = DEFAULT_COS_TEXT; 23411 23412 externhost[0] = '\0'; /* External host name (for behind NAT DynDNS support) */ 23413 externexpire = 0; /* Expiration for DNS re-issuing */ 23414 externrefresh = 10; 23415 23416 /* Reset channel settings to default before re-configuring */ 23417 allow_external_domains = DEFAULT_ALLOW_EXT_DOM; /* Allow external invites */ 23418 global_regcontext[0] = '\0'; 23419 global_regextenonqualify = DEFAULT_REGEXTENONQUALIFY; 23420 global_notifyringing = DEFAULT_NOTIFYRINGING; 23421 global_notifyhold = FALSE; /*!< Keep track of hold status for a peer */ 23422 global_directrtpsetup = FALSE; /* Experimental feature, disabled by default */ 23423 global_alwaysauthreject = 0; 23424 global_allowsubscribe = FALSE; 23425 snprintf(global_useragent, sizeof(global_useragent), "%s %s", DEFAULT_USERAGENT, ast_get_version()); 23426 snprintf(global_sdpsession, sizeof(global_sdpsession), "%s %s", DEFAULT_SDPSESSION, ast_get_version()); 23427 snprintf(global_sdpowner, sizeof(global_sdpowner), "%s", DEFAULT_SDPOWNER); 23428 global_prematuremediafilter = FALSE; 23429 ast_copy_string(default_notifymime, DEFAULT_NOTIFYMIME, sizeof(default_notifymime)); 23430 ast_copy_string(global_realm, S_OR(ast_config_AST_SYSTEM_NAME, DEFAULT_REALM), sizeof(global_realm)); 23431 ast_copy_string(default_callerid, DEFAULT_CALLERID, sizeof(default_callerid)); 23432 compactheaders = DEFAULT_COMPACTHEADERS; 23433 global_reg_timeout = DEFAULT_REGISTRATION_TIMEOUT; 23434 global_regattempts_max = 0; 23435 pedanticsipchecking = DEFAULT_PEDANTIC; 23436 autocreatepeer = DEFAULT_AUTOCREATEPEER; 23437 global_autoframing = 0; 23438 global_allowguest = DEFAULT_ALLOWGUEST; 23439 global_callcounter = DEFAULT_CALLCOUNTER; 23440 global_match_auth_username = FALSE; /*!< Match auth username if available instead of From: Default off. */ 23441 global_rtptimeout = 0; 23442 global_rtpholdtimeout = 0; 23443 global_rtpkeepalive = 0; 23444 global_allowtransfer = TRANSFER_OPENFORALL; /* Merrily accept all transfers by default */ 23445 global_rtautoclear = 120; 23446 ast_set_flag(&global_flags[1], SIP_PAGE2_ALLOWSUBSCRIBE); /* Default for all devices: TRUE */ 23447 ast_set_flag(&global_flags[1], SIP_PAGE2_ALLOWOVERLAP); /* Default for all devices: TRUE */ 23448 sip_cfg.peer_rtupdate = TRUE; 23449 global_dynamic_exclude_static = 0; /* Exclude static peers */ 23450 23451 /* Session-Timers */ 23452 global_st_mode = SESSION_TIMER_MODE_ACCEPT; 23453 global_st_refresher = SESSION_TIMER_REFRESHER_UAS; 23454 global_min_se = DEFAULT_MIN_SE; 23455 global_max_se = DEFAULT_MAX_SE; 23456 23457 /* Initialize some reasonable defaults at SIP reload (used both for channel and as default for devices */ 23458 ast_copy_string(default_context, DEFAULT_CONTEXT, sizeof(default_context)); 23459 default_subscribecontext[0] = '\0'; 23460 default_language[0] = '\0'; 23461 default_fromdomain[0] = '\0'; 23462 default_qualify = DEFAULT_QUALIFY; 23463 default_maxcallbitrate = DEFAULT_MAX_CALL_BITRATE; 23464 ast_copy_string(default_mohinterpret, DEFAULT_MOHINTERPRET, sizeof(default_mohinterpret)); 23465 ast_copy_string(default_mohsuggest, DEFAULT_MOHSUGGEST, sizeof(default_mohsuggest)); 23466 ast_copy_string(default_vmexten, DEFAULT_VMEXTEN, sizeof(default_vmexten)); 23467 ast_set_flag(&global_flags[0], SIP_DTMF_RFC2833); /*!< Default DTMF setting: RFC2833 */ 23468 ast_set_flag(&global_flags[0], SIP_NAT_RFC3581); /*!< NAT support if requested by device with rport */ 23469 ast_set_flag(&global_flags[0], SIP_CAN_REINVITE); /*!< Allow re-invites */ 23470 23471 /* Debugging settings, always default to off */ 23472 dumphistory = FALSE; 23473 recordhistory = FALSE; 23474 sipdebug &= ~sip_debug_config; 23475 23476 /* Misc settings for the channel */ 23477 global_relaxdtmf = FALSE; 23478 global_callevents = FALSE; 23479 global_authfailureevents = FALSE; 23480 global_t1 = SIP_TIMER_T1; 23481 global_timer_b = 64 * SIP_TIMER_T1; 23482 global_t1min = DEFAULT_T1MIN; 23483 global_qualifyfreq = DEFAULT_QUALIFYFREQ; 23484 global_t38_maxdatagram = -1; 23485 global_shrinkcallerid = 1; 23486 23487 global_matchexterniplocally = FALSE; 23488 23489 /* Copy the default jb config over global_jbconf */ 23490 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf)); 23491 23492 ast_clear_flag(&global_flags[1], SIP_PAGE2_VIDEOSUPPORT | SIP_PAGE2_VIDEOSUPPORT_ALWAYS); 23493 ast_clear_flag(&global_flags[1], SIP_PAGE2_TEXTSUPPORT); 23494 ast_clear_flag(&global_flags[1], SIP_PAGE2_IGNORESDPVERSION); 23495 ast_clear_flag(&global_flags[1], SIP_PAGE2_FAX_DETECT); 23496 23497 23498 /* Read the [general] config section of sip.conf (or from realtime config) */ 23499 for (v = ast_variable_browse(cfg, "general"); v; v = v->next) { 23500 if (handle_common_options(&global_flags[0], &dummy[0], v)) 23501 continue; 23502 if (handle_t38_options(&global_flags[0], &dummy[0], v, &global_t38_maxdatagram)) { 23503 continue; 23504 } 23505 /* handle jb conf */ 23506 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) 23507 continue; 23508 23509 if (!strcasecmp(v->name, "context")) { 23510 ast_copy_string(default_context, v->value, sizeof(default_context)); 23511 } else if (!strcasecmp(v->name, "subscribecontext")) { 23512 ast_copy_string(default_subscribecontext, v->value, sizeof(default_subscribecontext)); 23513 } else if (!strcasecmp(v->name, "callcounter")) { 23514 global_callcounter = ast_true(v->value) ? 1 : 0; 23515 } else if (!strcasecmp(v->name, "allowguest")) { 23516 global_allowguest = ast_true(v->value) ? 1 : 0; 23517 } else if (!strcasecmp(v->name, "realm")) { 23518 ast_copy_string(global_realm, v->value, sizeof(global_realm)); 23519 } else if (!strcasecmp(v->name, "useragent")) { 23520 ast_copy_string(global_useragent, v->value, sizeof(global_useragent)); 23521 ast_debug(1, "Setting SIP channel User-Agent Name to %s\n", global_useragent); 23522 } else if (!strcasecmp(v->name, "sdpsession")) { 23523 ast_copy_string(global_sdpsession, v->value, sizeof(global_sdpsession)); 23524 } else if (!strcasecmp(v->name, "sdpowner")) { 23525 /* Field cannot contain spaces */ 23526 if (!strstr(v->value, " ")) 23527 ast_copy_string(global_sdpowner, v->value, sizeof(global_sdpowner)); 23528 else 23529 ast_log(LOG_WARNING, "'%s' must not contain spaces at line %d. Using default.\n", v->value, v->lineno); 23530 } else if (!strcasecmp(v->name, "allowtransfer")) { 23531 global_allowtransfer = ast_true(v->value) ? TRANSFER_OPENFORALL : TRANSFER_CLOSED; 23532 } else if (!strcasecmp(v->name, "rtcachefriends")) { 23533 ast_set2_flag(&global_flags[1], ast_true(v->value), SIP_PAGE2_RTCACHEFRIENDS); 23534 } else if (!strcasecmp(v->name, "rtsavesysname")) { 23535 sip_cfg.rtsave_sysname = ast_true(v->value); 23536 } else if (!strcasecmp(v->name, "rtupdate")) { 23537 sip_cfg.peer_rtupdate = ast_true(v->value); 23538 } else if (!strcasecmp(v->name, "ignoreregexpire")) { 23539 sip_cfg.ignore_regexpire = ast_true(v->value); 23540 } else if (!strcasecmp(v->name, "timert1")) { 23541 /* Defaults to 500ms, but RFC 3261 states that it is recommended 23542 * for the value to be set higher, though a lower value is only 23543 * allowed on private networks unconnected to the Internet. */ 23544 global_t1 = atoi(v->value); 23545 /* Note that timer B is dependent on the value of T1 */ 23546 global_timer_b = global_t1 * 64; 23547 } else if (!strcasecmp(v->name, "t1min")) { 23548 global_t1min = atoi(v->value); 23549 } else if (!strcasecmp(v->name, "tcpenable")) { 23550 sip_tcp_desc.local_address.sin_family = ast_false(v->value) ? 0 : AF_INET; 23551 ast_debug(2, "Enabling TCP socket for listening\n"); 23552 } else if (!strcasecmp(v->name, "tcpbindaddr")) { 23553 int family = sip_tcp_desc.local_address.sin_family; 23554 if (ast_parse_arg(v->value, PARSE_INADDR, &sip_tcp_desc.local_address)) 23555 ast_log(LOG_WARNING, "Invalid %s '%s' at line %d of %s\n", v->name, v->value, v->lineno, config); 23556 sip_tcp_desc.local_address.sin_family = family; 23557 ast_debug(2, "Setting TCP socket address to %s\n", v->value); 23558 } else if (!strcasecmp(v->name, "tlsenable")) { 23559 default_tls_cfg.enabled = ast_true(v->value) ? TRUE : FALSE; 23560 sip_tls_desc.local_address.sin_family = AF_INET; 23561 } else if (!strcasecmp(v->name, "tlscertfile")) { 23562 ast_free(default_tls_cfg.certfile); 23563 default_tls_cfg.certfile = ast_strdup(v->value); 23564 } else if (!strcasecmp(v->name, "tlscipher")) { 23565 ast_free(default_tls_cfg.cipher); 23566 default_tls_cfg.cipher = ast_strdup(v->value); 23567 } else if (!strcasecmp(v->name, "tlscafile")) { 23568 ast_free(default_tls_cfg.cafile); 23569 default_tls_cfg.cafile = ast_strdup(v->value); 23570 } else if (!strcasecmp(v->name, "tlscapath")) { 23571 ast_free(default_tls_cfg.capath); 23572 default_tls_cfg.capath = ast_strdup(v->value); 23573 } else if (!strcasecmp(v->name, "tlsverifyclient")) { 23574 ast_set2_flag(&default_tls_cfg.flags, ast_true(v->value), AST_SSL_VERIFY_CLIENT); 23575 } else if (!strcasecmp(v->name, "tlsdontverifyserver")) { 23576 ast_set2_flag(&default_tls_cfg.flags, ast_true(v->value), AST_SSL_DONT_VERIFY_SERVER); 23577 } else if (!strcasecmp(v->name, "tlsbindaddr")) { 23578 if (ast_parse_arg(v->value, PARSE_INADDR, &sip_tls_desc.local_address)) 23579 ast_log(LOG_WARNING, "Invalid %s '%s' at line %d of %s\n", v->name, v->value, v->lineno, config); 23580 } else if (!strcasecmp(v->name, "dynamic_exclude_static") || !strcasecmp(v->name, "dynamic_excludes_static")) { 23581 global_dynamic_exclude_static = ast_true(v->value); 23582 } else if (!strcasecmp(v->name, "contactpermit") || !strcasecmp(v->name, "contactdeny")) { 23583 int ha_error = 0; 23584 global_contact_ha = ast_append_ha(v->name + 7, v->value, global_contact_ha, &ha_error); 23585 if (ha_error) { 23586 ast_log(LOG_ERROR, "Bad ACL entry in configuration line %d : %s\n", v->lineno, v->value); 23587 } 23588 } else if (!strcasecmp(v->name, "rtautoclear")) { 23589 int i = atoi(v->value); 23590 if (i > 0) 23591 global_rtautoclear = i; 23592 else 23593 i = 0; 23594 ast_set2_flag(&global_flags[1], i || ast_true(v->value), SIP_PAGE2_RTAUTOCLEAR); 23595 } else if (!strcasecmp(v->name, "usereqphone")) { 23596 ast_set2_flag(&global_flags[0], ast_true(v->value), SIP_USEREQPHONE); 23597 } else if (!strcasecmp(v->name, "prematuremedia")) { 23598 global_prematuremediafilter = ast_true(v->value); 23599 } else if (!strcasecmp(v->name, "relaxdtmf")) { 23600 global_relaxdtmf = ast_true(v->value); 23601 } else if (!strcasecmp(v->name, "vmexten")) { 23602 ast_copy_string(default_vmexten, v->value, sizeof(default_vmexten)); 23603 } else if (!strcasecmp(v->name, "rtptimeout")) { 23604 if ((sscanf(v->value, "%30d", &global_rtptimeout) != 1) || (global_rtptimeout < 0)) { 23605 ast_log(LOG_WARNING, "'%s' is not a valid RTP hold time at line %d. Using default.\n", v->value, v->lineno); 23606 global_rtptimeout = 0; 23607 } 23608 } else if (!strcasecmp(v->name, "rtpholdtimeout")) { 23609 if ((sscanf(v->value, "%30d", &global_rtpholdtimeout) != 1) || (global_rtpholdtimeout < 0)) { 23610 ast_log(LOG_WARNING, "'%s' is not a valid RTP hold time at line %d. Using default.\n", v->value, v->lineno); 23611 global_rtpholdtimeout = 0; 23612 } 23613 } else if (!strcasecmp(v->name, "rtpkeepalive")) { 23614 if ((sscanf(v->value, "%30d", &global_rtpkeepalive) != 1) || (global_rtpkeepalive < 0)) { 23615 ast_log(LOG_WARNING, "'%s' is not a valid RTP keepalive time at line %d. Using default.\n", v->value, v->lineno); 23616 global_rtpkeepalive = 0; 23617 } 23618 } else if (!strcasecmp(v->name, "compactheaders")) { 23619 compactheaders = ast_true(v->value); 23620 } else if (!strcasecmp(v->name, "notifymimetype")) { 23621 ast_copy_string(default_notifymime, v->value, sizeof(default_notifymime)); 23622 } else if (!strcasecmp(v->name, "directrtpsetup")) { 23623 global_directrtpsetup = ast_true(v->value); 23624 } else if (!strcasecmp(v->name, "notifyringing")) { 23625 global_notifyringing = ast_true(v->value); 23626 } else if (!strcasecmp(v->name, "notifyhold")) { 23627 global_notifyhold = ast_true(v->value); 23628 } else if (!strcasecmp(v->name, "alwaysauthreject")) { 23629 global_alwaysauthreject = ast_true(v->value); 23630 } else if (!strcasecmp(v->name, "mohinterpret")) { 23631 ast_copy_string(default_mohinterpret, v->value, sizeof(default_mohinterpret)); 23632 } else if (!strcasecmp(v->name, "mohsuggest")) { 23633 ast_copy_string(default_mohsuggest, v->value, sizeof(default_mohsuggest)); 23634 } else if (!strcasecmp(v->name, "language")) { 23635 ast_copy_string(default_language, v->value, sizeof(default_language)); 23636 } else if (!strcasecmp(v->name, "regcontext")) { 23637 ast_copy_string(newcontexts, v->value, sizeof(newcontexts)); 23638 stringp = newcontexts; 23639 /* Let's remove any contexts that are no longer defined in regcontext */ 23640 cleanup_stale_contexts(stringp, oldregcontext); 23641 /* Create contexts if they don't exist already */ 23642 while ((context = strsep(&stringp, "&"))) { 23643 ast_copy_string(used_context, context, sizeof(used_context)); 23644 ast_context_find_or_create(NULL, NULL, context, "SIP"); 23645 } 23646 ast_copy_string(global_regcontext, v->value, sizeof(global_regcontext)); 23647 } else if (!strcasecmp(v->name, "regextenonqualify")) { 23648 global_regextenonqualify = ast_true(v->value); 23649 } else if (!strcasecmp(v->name, "callerid")) { 23650 ast_copy_string(default_callerid, v->value, sizeof(default_callerid)); 23651 } else if (!strcasecmp(v->name, "fromdomain")) { 23652 ast_copy_string(default_fromdomain, v->value, sizeof(default_fromdomain)); 23653 } else if (!strcasecmp(v->name, "outboundproxy")) { 23654 int portnum; 23655 char *tok, *proxyname; 23656 23657 if (ast_strlen_zero(v->value)) { 23658 ast_log(LOG_WARNING, "no value given for outbound proxy on line %d of sip.conf.", v->lineno); 23659 continue; 23660 } 23661 23662 tok = ast_skip_blanks(strtok(ast_strdupa(v->value), ",")); 23663 23664 sip_parse_host(tok, v->lineno, &proxyname, &portnum, &global_outboundproxy.transport); 23665 23666 global_outboundproxy.ip.sin_port = htons(portnum); 23667 23668 if ((tok = strtok(NULL, ","))) { 23669 global_outboundproxy.force = !strncasecmp(ast_skip_blanks(tok), "force", 5); 23670 } else { 23671 global_outboundproxy.force = FALSE; 23672 } 23673 23674 if (ast_strlen_zero(proxyname)) { 23675 ast_log(LOG_WARNING, "you must specify a name for the outboundproxy on line %d of sip.conf.", v->lineno); 23676 global_outboundproxy.name[0] = '\0'; 23677 continue; 23678 } 23679 23680 ast_copy_string(global_outboundproxy.name, proxyname, sizeof(global_outboundproxy.name)); 23681 23682 proxy_update(&global_outboundproxy); 23683 } else if (!strcasecmp(v->name, "autocreatepeer")) { 23684 autocreatepeer = ast_true(v->value); 23685 } else if (!strcasecmp(v->name, "match_auth_username")) { 23686 global_match_auth_username = ast_true(v->value); 23687 } else if (!strcasecmp(v->name, "srvlookup")) { 23688 global_srvlookup = ast_true(v->value); 23689 } else if (!strcasecmp(v->name, "pedantic")) { 23690 pedanticsipchecking = ast_true(v->value); 23691 } else if (!strcasecmp(v->name, "maxexpirey") || !strcasecmp(v->name, "maxexpiry")) { 23692 max_expiry = atoi(v->value); 23693 if (max_expiry < 1) 23694 max_expiry = DEFAULT_MAX_EXPIRY; 23695 } else if (!strcasecmp(v->name, "minexpirey") || !strcasecmp(v->name, "minexpiry")) { 23696 min_expiry = atoi(v->value); 23697 if (min_expiry < 1) 23698 min_expiry = DEFAULT_MIN_EXPIRY; 23699 } else if (!strcasecmp(v->name, "defaultexpiry") || !strcasecmp(v->name, "defaultexpirey")) { 23700 default_expiry = atoi(v->value); 23701 if (default_expiry < 1) 23702 default_expiry = DEFAULT_DEFAULT_EXPIRY; 23703 } else if (!strcasecmp(v->name, "sipdebug")) { 23704 if (ast_true(v->value)) 23705 sipdebug |= sip_debug_config; 23706 } else if (!strcasecmp(v->name, "dumphistory")) { 23707 dumphistory = ast_true(v->value); 23708 } else if (!strcasecmp(v->name, "recordhistory")) { 23709 recordhistory = ast_true(v->value); 23710 } else if (!strcasecmp(v->name, "registertimeout")) { 23711 global_reg_timeout = atoi(v->value); 23712 if (global_reg_timeout < 1) 23713 global_reg_timeout = DEFAULT_REGISTRATION_TIMEOUT; 23714 } else if (!strcasecmp(v->name, "registerattempts")) { 23715 global_regattempts_max = atoi(v->value); 23716 } else if (!strcasecmp(v->name, "stunaddr")) { 23717 stunaddr.sin_port = htons(3478); 23718 if (ast_parse_arg(v->value, PARSE_INADDR, &stunaddr)) 23719 ast_log(LOG_WARNING, "Invalid STUN server address: %s\n", v->value); 23720 externexpire = time(NULL); 23721 } else if (!strcasecmp(v->name, "bindaddr") || !strcasecmp(v->name, "udpbindaddr")) { 23722 if (ast_parse_arg(v->value, PARSE_INADDR, &bindaddr)) 23723 ast_log(LOG_WARNING, "Invalid address: %s\n", v->value); 23724 } else if (!strcasecmp(v->name, "localnet")) { 23725 struct ast_ha *na; 23726 int ha_error = 0; 23727 23728 if (!(na = ast_append_ha("d", v->value, localaddr, &ha_error))) 23729 ast_log(LOG_WARNING, "Invalid localnet value: %s\n", v->value); 23730 else 23731 localaddr = na; 23732 if (ha_error) 23733 ast_log(LOG_ERROR, "Bad localnet configuration value line %d : %s\n", v->lineno, v->value); 23734 } else if (!strcasecmp(v->name, "externip")) { 23735 if (ast_parse_arg(v->value, PARSE_INADDR, &externip)) 23736 ast_log(LOG_WARNING, "Invalid address for externip keyword: %s\n", v->value); 23737 externexpire = 0; 23738 /* If no port was specified use the value of bindport */ 23739 if (!externip.sin_port) 23740 externip.sin_port = bindaddr.sin_port; 23741 } else if (!strcasecmp(v->name, "externhost")) { 23742 ast_copy_string(externhost, v->value, sizeof(externhost)); 23743 if (ast_parse_arg(externhost, PARSE_INADDR, &externip)) 23744 ast_log(LOG_WARNING, "Invalid address for externhost keyword: %s\n", externhost); 23745 externexpire = time(NULL); 23746 /* If no port was specified use the value of bindport */ 23747 if (!externip.sin_port) 23748 externip.sin_port = bindaddr.sin_port; 23749 } else if (!strcasecmp(v->name, "externrefresh")) { 23750 if (sscanf(v->value, "%30d", &externrefresh) != 1) { 23751 ast_log(LOG_WARNING, "Invalid externrefresh value '%s', must be an integer >0 at line %d\n", v->value, v->lineno); 23752 externrefresh = 10; 23753 } 23754 } else if (!strcasecmp(v->name, "allow")) { 23755 int error = ast_parse_allow_disallow(&default_prefs, &global_capability, v->value, TRUE); 23756 if (error) 23757 ast_log(LOG_WARNING, "Codec configuration errors found in line %d : %s = %s\n", v->lineno, v->name, v->value); 23758 } else if (!strcasecmp(v->name, "disallow")) { 23759 int error = ast_parse_allow_disallow(&default_prefs, &global_capability, v->value, FALSE); 23760 if (error) 23761 ast_log(LOG_WARNING, "Codec configuration errors found in line %d : %s = %s\n", v->lineno, v->name, v->value); 23762 } else if (!strcasecmp(v->name, "autoframing")) { 23763 global_autoframing = ast_true(v->value); 23764 } else if (!strcasecmp(v->name, "allowexternaldomains")) { 23765 allow_external_domains = ast_true(v->value); 23766 } else if (!strcasecmp(v->name, "autodomain")) { 23767 auto_sip_domains = ast_true(v->value); 23768 } else if (!strcasecmp(v->name, "domain")) { 23769 char *domain = ast_strdupa(v->value); 23770 char *cntx = strchr(domain, ','); 23771 23772 if (cntx) 23773 *cntx++ = '\0'; 23774 23775 if (ast_strlen_zero(cntx)) 23776 ast_debug(1, "No context specified at line %d for domain '%s'\n", v->lineno, domain); 23777 if (ast_strlen_zero(domain)) 23778 ast_log(LOG_WARNING, "Empty domain specified at line %d\n", v->lineno); 23779 else 23780 add_sip_domain(ast_strip(domain), SIP_DOMAIN_CONFIG, cntx ? ast_strip(cntx) : ""); 23781 } else if (!strcasecmp(v->name, "register")) { 23782 if (sip_register(v->value, v->lineno) == 0) 23783 registry_count++; 23784 } else if (!strcasecmp(v->name, "tos_sip")) { 23785 if (ast_str2tos(v->value, &global_tos_sip)) 23786 ast_log(LOG_WARNING, "Invalid tos_sip value at line %d, refer to QoS documentation\n", v->lineno); 23787 } else if (!strcasecmp(v->name, "tos_audio")) { 23788 if (ast_str2tos(v->value, &global_tos_audio)) 23789 ast_log(LOG_WARNING, "Invalid tos_audio value at line %d, refer to QoS documentation\n", v->lineno); 23790 } else if (!strcasecmp(v->name, "tos_video")) { 23791 if (ast_str2tos(v->value, &global_tos_video)) 23792 ast_log(LOG_WARNING, "Invalid tos_video value at line %d, refer to QoS documentation\n", v->lineno); 23793 } else if (!strcasecmp(v->name, "tos_text")) { 23794 if (ast_str2tos(v->value, &global_tos_text)) 23795 ast_log(LOG_WARNING, "Invalid tos_text value at line %d, refer to QoS documentation\n", v->lineno); 23796 } else if (!strcasecmp(v->name, "cos_sip")) { 23797 if (ast_str2cos(v->value, &global_cos_sip)) 23798 ast_log(LOG_WARNING, "Invalid cos_sip value at line %d, refer to QoS documentation\n", v->lineno); 23799 } else if (!strcasecmp(v->name, "cos_audio")) { 23800 if (ast_str2cos(v->value, &global_cos_audio)) 23801 ast_log(LOG_WARNING, "Invalid cos_audio value at line %d, refer to QoS documentation\n", v->lineno); 23802 } else if (!strcasecmp(v->name, "cos_video")) { 23803 if (ast_str2cos(v->value, &global_cos_video)) 23804 ast_log(LOG_WARNING, "Invalid cos_video value at line %d, refer to QoS documentation\n", v->lineno); 23805 } else if (!strcasecmp(v->name, "cos_text")) { 23806 if (ast_str2cos(v->value, &global_cos_text)) 23807 ast_log(LOG_WARNING, "Invalid cos_text value at line %d, refer to QoS documentation\n", v->lineno); 23808 } else if (!strcasecmp(v->name, "bindport")) { 23809 int i; 23810 if (sscanf(v->value, "%5d", &i) == 1) { 23811 bindaddr.sin_port = htons(i); 23812 } else { 23813 ast_log(LOG_WARNING, "Invalid port number '%s' at line %d of %s\n", v->value, v->lineno, config); 23814 } 23815 } else if (!strcasecmp(v->name, "hash_user")) { 23816 int i; 23817 if (sscanf(v->value, "%30d", &i) == 1 && i > 2) { 23818 hash_user_size = i; 23819 } else { 23820 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); 23821 } 23822 } else if (!strcasecmp(v->name, "hash_peer")) { 23823 int i; 23824 if (sscanf(v->value, "%30d", &i) == 1 && i > 2) { 23825 hash_peer_size = i; 23826 } else { 23827 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); 23828 } 23829 } else if (!strcasecmp(v->name, "hash_dialog")) { 23830 int i; 23831 if (sscanf(v->value, "%30d", &i) == 1 && i > 2) { 23832 hash_dialog_size = i; 23833 } else { 23834 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); 23835 } 23836 } else if (!strcasecmp(v->name, "qualify")) { 23837 if (!strcasecmp(v->value, "no")) { 23838 default_qualify = 0; 23839 } else if (!strcasecmp(v->value, "yes")) { 23840 default_qualify = DEFAULT_MAXMS; 23841 } else if (sscanf(v->value, "%30d", &default_qualify) != 1) { 23842 ast_log(LOG_WARNING, "Qualification default should be 'yes', 'no', or a number of milliseconds at line %d of sip.conf\n", v->lineno); 23843 default_qualify = 0; 23844 } 23845 } else if (!strcasecmp(v->name, "qualifyfreq")) { 23846 int i; 23847 if (sscanf(v->value, "%30d", &i) == 1) 23848 global_qualifyfreq = i * 1000; 23849 else { 23850 ast_log(LOG_WARNING, "Invalid qualifyfreq number '%s' at line %d of %s\n", v->value, v->lineno, config); 23851 global_qualifyfreq = DEFAULT_QUALIFYFREQ; 23852 } 23853 } else if (!strcasecmp(v->name, "callevents")) { 23854 global_callevents = ast_true(v->value); 23855 } else if (!strcasecmp(v->name, "authfailureevents")) { 23856 global_authfailureevents = ast_true(v->value); 23857 } else if (!strcasecmp(v->name, "maxcallbitrate")) { 23858 default_maxcallbitrate = atoi(v->value); 23859 if (default_maxcallbitrate < 0) 23860 default_maxcallbitrate = DEFAULT_MAX_CALL_BITRATE; 23861 } else if (!strcasecmp(v->name, "matchexterniplocally")) { 23862 global_matchexterniplocally = ast_true(v->value); 23863 } else if (!strcasecmp(v->name, "constantssrc")) { 23864 ast_set2_flag(&global_flags[1], ast_true(v->value), SIP_PAGE2_CONSTANT_SSRC); 23865 } else if (!strcasecmp(v->name, "session-timers")) { 23866 int i = (int) str2stmode(v->value); 23867 if (i < 0) { 23868 ast_log(LOG_WARNING, "Invalid session-timers '%s' at line %d of %s\n", v->value, v->lineno, config); 23869 global_st_mode = SESSION_TIMER_MODE_ACCEPT; 23870 } else { 23871 global_st_mode = i; 23872 } 23873 } else if (!strcasecmp(v->name, "session-expires")) { 23874 if (sscanf(v->value, "%30d", &global_max_se) != 1) { 23875 ast_log(LOG_WARNING, "Invalid session-expires '%s' at line %d of %s\n", v->value, v->lineno, config); 23876 global_max_se = DEFAULT_MAX_SE; 23877 } 23878 } else if (!strcasecmp(v->name, "session-minse")) { 23879 if (sscanf(v->value, "%30d", &global_min_se) != 1) { 23880 ast_log(LOG_WARNING, "Invalid session-minse '%s' at line %d of %s\n", v->value, v->lineno, config); 23881 global_min_se = DEFAULT_MIN_SE; 23882 } 23883 if (global_min_se < 90) { 23884 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); 23885 global_min_se = DEFAULT_MIN_SE; 23886 } 23887 } else if (!strcasecmp(v->name, "session-refresher")) { 23888 int i = (int) str2strefresher(v->value); 23889 if (i < 0) { 23890 ast_log(LOG_WARNING, "Invalid session-refresher '%s' at line %d of %s\n", v->value, v->lineno, config); 23891 global_st_refresher = SESSION_TIMER_REFRESHER_UAS; 23892 } else { 23893 global_st_refresher = i; 23894 } 23895 } else if (!strcasecmp(v->name, "shrinkcallerid")) { 23896 if (ast_true(v->value)) { 23897 global_shrinkcallerid = 1; 23898 } else if (ast_false(v->value)) { 23899 global_shrinkcallerid = 0; 23900 } else { 23901 ast_log(LOG_WARNING, "shrinkcallerid value %s is not valid at line %d.\n", v->value, v->lineno); 23902 } 23903 } 23904 } 23905 23906 if (!allow_external_domains && AST_LIST_EMPTY(&domain_list)) { 23907 ast_log(LOG_WARNING, "To disallow external domains, you need to configure local SIP domains.\n"); 23908 allow_external_domains = 1; 23909 } 23910 23911 /* Build list of authentication to various SIP realms, i.e. service providers */ 23912 for (v = ast_variable_browse(cfg, "authentication"); v ; v = v->next) { 23913 /* Format for authentication is auth = username:password@realm */ 23914 if (!strcasecmp(v->name, "auth")) 23915 authl = add_realm_authentication(authl, v->value, v->lineno); 23916 } 23917 23918 if (ucfg) { 23919 struct ast_variable *gen; 23920 int genhassip, genregistersip; 23921 const char *hassip, *registersip; 23922 23923 genhassip = ast_true(ast_variable_retrieve(ucfg, "general", "hassip")); 23924 genregistersip = ast_true(ast_variable_retrieve(ucfg, "general", "registersip")); 23925 gen = ast_variable_browse(ucfg, "general"); 23926 cat = ast_category_browse(ucfg, NULL); 23927 while (cat) { 23928 if (strcasecmp(cat, "general")) { 23929 hassip = ast_variable_retrieve(ucfg, cat, "hassip"); 23930 registersip = ast_variable_retrieve(ucfg, cat, "registersip"); 23931 if (ast_true(hassip) || (!hassip && genhassip)) { 23932 peer = build_peer(cat, gen, ast_variable_browse(ucfg, cat), 0, 0); 23933 if (peer) { 23934 /* user.conf entries are always of type friend */ 23935 peer->type = SIP_TYPE_USER | SIP_TYPE_PEER; 23936 ao2_t_link(peers, peer, "link peer into peer table"); 23937 if ((peer->type & SIP_TYPE_PEER) && peer->addr.sin_addr.s_addr) { 23938 ao2_t_link(peers_by_ip, peer, "link peer into peers_by_ip table"); 23939 } 23940 23941 unref_peer(peer, "unref_peer: from reload_config"); 23942 peer_count++; 23943 } 23944 } 23945 if (ast_true(registersip) || (!registersip && genregistersip)) { 23946 char tmp[256]; 23947 const char *host = ast_variable_retrieve(ucfg, cat, "host"); 23948 const char *username = ast_variable_retrieve(ucfg, cat, "username"); 23949 const char *secret = ast_variable_retrieve(ucfg, cat, "secret"); 23950 const char *contact = ast_variable_retrieve(ucfg, cat, "contact"); 23951 const char *authuser = ast_variable_retrieve(ucfg, cat, "authuser"); 23952 if (!host) 23953 host = ast_variable_retrieve(ucfg, "general", "host"); 23954 if (!username) 23955 username = ast_variable_retrieve(ucfg, "general", "username"); 23956 if (!secret) 23957 secret = ast_variable_retrieve(ucfg, "general", "secret"); 23958 if (!contact) 23959 contact = "s"; 23960 if (!ast_strlen_zero(username) && !ast_strlen_zero(host)) { 23961 if (!ast_strlen_zero(secret)) { 23962 if (!ast_strlen_zero(authuser)) { 23963 snprintf(tmp, sizeof(tmp), "%s:%s:%s@%s/%s", username, secret, authuser, host, contact); 23964 } else { 23965 snprintf(tmp, sizeof(tmp), "%s:%s@%s/%s", username, secret, host, contact); 23966 } 23967 } else if (!ast_strlen_zero(authuser)) { 23968 snprintf(tmp, sizeof(tmp), "%s::%s@%s/%s", username, authuser, host, contact); 23969 } else { 23970 snprintf(tmp, sizeof(tmp), "%s@%s/%s", username, host, contact); 23971 } 23972 if (sip_register(tmp, 0) == 0) 23973 registry_count++; 23974 } 23975 } 23976 } 23977 cat = ast_category_browse(ucfg, cat); 23978 } 23979 ast_config_destroy(ucfg); 23980 } 23981 23982 23983 /* Load peers, users and friends */ 23984 cat = NULL; 23985 while ( (cat = ast_category_browse(cfg, cat)) ) { 23986 const char *utype; 23987 if (!strcasecmp(cat, "general") || !strcasecmp(cat, "authentication")) 23988 continue; 23989 utype = ast_variable_retrieve(cfg, cat, "type"); 23990 if (!utype) { 23991 ast_log(LOG_WARNING, "Section '%s' lacks type\n", cat); 23992 continue; 23993 } else { 23994 if (!strcasecmp(utype, "user")) { 23995 ; 23996 } else if (!strcasecmp(utype, "friend")) { 23997 ; 23998 } else if (!strcasecmp(utype, "peer")) { 23999 ; 24000 } else { 24001 ast_log(LOG_WARNING, "Unknown type '%s' for '%s' in %s\n", utype, cat, "sip.conf"); 24002 continue; 24003 } 24004 peer = build_peer(cat, ast_variable_browse(cfg, cat), NULL, 0, 0); 24005 if (peer) { 24006 ao2_t_link(peers, peer, "link peer into peers table"); 24007 if ((peer->type & SIP_TYPE_PEER) && peer->addr.sin_addr.s_addr) { 24008 ao2_t_link(peers_by_ip, peer, "link peer into peers_by_ip table"); 24009 } 24010 unref_peer(peer, "unref the result of the build_peer call. Now, the links from the tables are the only ones left."); 24011 peer_count++; 24012 } 24013 } 24014 } 24015 24016 /* Set UDP address and open socket */ 24017 bindaddr.sin_family = AF_INET; 24018 internip = bindaddr; 24019 if (ast_find_ourip(&internip.sin_addr, bindaddr)) { 24020 ast_log(LOG_WARNING, "Unable to get own IP address, SIP disabled\n"); 24021 ast_config_destroy(cfg); 24022 return 0; 24023 } 24024 ast_mutex_lock(&netlock); 24025 if ((sipsock > -1) && (memcmp(&old_bindaddr, &bindaddr, sizeof(struct sockaddr_in)))) { 24026 close(sipsock); 24027 sipsock = -1; 24028 } 24029 if (sipsock < 0) { 24030 sipsock = socket(AF_INET, SOCK_DGRAM, 0); 24031 if (sipsock < 0) { 24032 ast_log(LOG_WARNING, "Unable to create SIP socket: %s\n", strerror(errno)); 24033 ast_config_destroy(cfg); 24034 return -1; 24035 } else { 24036 /* Allow SIP clients on the same host to access us: */ 24037 const int reuseFlag = 1; 24038 24039 setsockopt(sipsock, SOL_SOCKET, SO_REUSEADDR, 24040 (const char*)&reuseFlag, 24041 sizeof reuseFlag); 24042 24043 ast_enable_packet_fragmentation(sipsock); 24044 24045 if (bind(sipsock, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) < 0) { 24046 ast_log(LOG_WARNING, "Failed to bind to %s:%d: %s\n", 24047 ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port), 24048 strerror(errno)); 24049 close(sipsock); 24050 sipsock = -1; 24051 } else { 24052 ast_verb(2, "SIP Listening on %s:%d\n", 24053 ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port)); 24054 ast_netsock_set_qos(sipsock, global_tos_sip, global_cos_sip, "SIP"); 24055 } 24056 } 24057 } 24058 if (stunaddr.sin_addr.s_addr != 0) { 24059 ast_debug(1, "stun to %s:%d\n", 24060 ast_inet_ntoa(stunaddr.sin_addr) , ntohs(stunaddr.sin_port)); 24061 ast_stun_request(sipsock, &stunaddr, 24062 NULL, &externip); 24063 ast_debug(1, "STUN sees us at %s:%d\n", 24064 ast_inet_ntoa(externip.sin_addr) , ntohs(externip.sin_port)); 24065 } 24066 ast_mutex_unlock(&netlock); 24067 24068 /* Start TCP server */ 24069 ast_tcptls_server_start(&sip_tcp_desc); 24070 24071 /* Start TLS server if needed */ 24072 memcpy(sip_tls_desc.tls_cfg, &default_tls_cfg, sizeof(default_tls_cfg)); 24073 24074 if (ast_ssl_setup(sip_tls_desc.tls_cfg)) 24075 ast_tcptls_server_start(&sip_tls_desc); 24076 else if (sip_tls_desc.tls_cfg->enabled) { 24077 sip_tls_desc.tls_cfg = NULL; 24078 ast_log(LOG_WARNING, "SIP TLS server did not load because of errors.\n"); 24079 } 24080 24081 24082 /* Add default domains - host name, IP address and IP:port 24083 * Only do this if user added any sip domain with "localdomains" 24084 * In order to *not* break backwards compatibility 24085 * Some phones address us at IP only, some with additional port number 24086 */ 24087 if (auto_sip_domains) { 24088 char temp[MAXHOSTNAMELEN]; 24089 24090 /* First our default IP address */ 24091 if (bindaddr.sin_addr.s_addr) { 24092 add_sip_domain(ast_inet_ntoa(bindaddr.sin_addr), SIP_DOMAIN_AUTO, NULL); 24093 } else if (internip.sin_addr.s_addr) { 24094 /* Our internal IP address, if configured */ 24095 add_sip_domain(ast_inet_ntoa(internip.sin_addr), SIP_DOMAIN_AUTO, NULL); 24096 } else { 24097 ast_log(LOG_NOTICE, "Can't add wildcard IP address to domain list, please add IP address to domain manually.\n"); 24098 } 24099 24100 /* If TCP is running on a different IP than UDP, then add it too */ 24101 if (sip_tcp_desc.local_address.sin_addr.s_addr && !inaddrcmp(&bindaddr, &sip_tcp_desc.local_address)) 24102 add_sip_domain(ast_inet_ntoa(sip_tcp_desc.local_address.sin_addr), SIP_DOMAIN_AUTO, NULL); 24103 24104 /* If TLS is running on a differen IP than UDP and TCP, then add that too */ 24105 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)) 24106 add_sip_domain(ast_inet_ntoa(sip_tls_desc.local_address.sin_addr), SIP_DOMAIN_AUTO, NULL); 24107 24108 /* Our extern IP address, if configured */ 24109 if (externip.sin_addr.s_addr) 24110 add_sip_domain(ast_inet_ntoa(externip.sin_addr), SIP_DOMAIN_AUTO, NULL); 24111 24112 /* Extern host name (NAT traversal support) */ 24113 if (!ast_strlen_zero(externhost)) 24114 add_sip_domain(externhost, SIP_DOMAIN_AUTO, NULL); 24115 24116 /* Our host name */ 24117 if (!gethostname(temp, sizeof(temp))) 24118 add_sip_domain(temp, SIP_DOMAIN_AUTO, NULL); 24119 } 24120 24121 /* Release configuration from memory */ 24122 ast_config_destroy(cfg); 24123 24124 /* Load the list of manual NOTIFY types to support */ 24125 if (notify_types) 24126 ast_config_destroy(notify_types); 24127 notify_types = ast_config_load(notify_config, config_flags); 24128 24129 /* Done, tell the manager */ 24130 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); 24131 run_end = time(0); 24132 ast_debug(4, "SIP reload_config done...Runtime= %d sec\n", (int)(run_end-run_start)); 24133 24134 return 0; 24135 }
| static char * remove_uri_parameters | ( | char * | uri | ) | [static] |
Definition at line 9900 of file chan_sip.c.
Referenced by extract_uri(), parse_moved_contact(), register_verify(), reqprep(), and transmit_state_notify().
09901 { 09902 char *atsign; 09903 atsign = strchr(uri, '@'); /* First, locate the at sign */ 09904 if (!atsign) 09905 atsign = uri; /* Ok hostname only, let's stick with the rest */ 09906 atsign = strchr(atsign, ';'); /* Locate semi colon */ 09907 if (atsign) 09908 *atsign = '\0'; /* Kill at the semi colon */ 09909 return uri; 09910 }
| 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 13101 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().
13102 { 13103 /* replace callerid if rpid found, and not restricted */ 13104 if (!ast_strlen_zero(rpid_num) && ast_test_flag(&p->flags[0], SIP_TRUSTRPID)) { 13105 char *tmp = ast_strdupa(rpid_num); /* XXX the copy can be done later */ 13106 if (!ast_strlen_zero(calleridname)) 13107 ast_string_field_set(p, cid_name, calleridname); 13108 if (global_shrinkcallerid && ast_is_shrinkable_phonenumber(tmp)) 13109 ast_shrink_phone_number(tmp); 13110 ast_string_field_set(p, cid_num, tmp); 13111 } 13112 }
| 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 16231 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().
16232 { 16233 char tmp[512]; 16234 char *c; 16235 char oldnonce[256]; 16236 16237 /* table of recognised keywords, and places where they should be copied */ 16238 const struct x { 16239 const char *key; 16240 const ast_string_field *field; 16241 } *i, keys[] = { 16242 { "realm=", &p->realm }, 16243 { "nonce=", &p->nonce }, 16244 { "opaque=", &p->opaque }, 16245 { "qop=", &p->qop }, 16246 { "domain=", &p->domain }, 16247 { NULL, 0 }, 16248 }; 16249 16250 ast_copy_string(tmp, get_header(req, header), sizeof(tmp)); 16251 if (ast_strlen_zero(tmp)) 16252 return -1; 16253 if (strncasecmp(tmp, "Digest ", strlen("Digest "))) { 16254 ast_log(LOG_WARNING, "missing Digest.\n"); 16255 return -1; 16256 } 16257 c = tmp + strlen("Digest "); 16258 ast_copy_string(oldnonce, p->nonce, sizeof(oldnonce)); 16259 while (c && *(c = ast_skip_blanks(c))) { /* lookup for keys */ 16260 for (i = keys; i->key != NULL; i++) { 16261 char *src, *separator; 16262 if (strncasecmp(c, i->key, strlen(i->key)) != 0) 16263 continue; 16264 /* Found. Skip keyword, take text in quotes or up to the separator. */ 16265 c += strlen(i->key); 16266 if (*c == '"') { 16267 src = ++c; 16268 separator = "\""; 16269 } else { 16270 src = c; 16271 separator = ","; 16272 } 16273 strsep(&c, separator); /* clear separator and move ptr */ 16274 ast_string_field_ptr_set(p, i->field, src); 16275 break; 16276 } 16277 if (i->key == NULL) /* not found, try ',' */ 16278 strsep(&c, ","); 16279 } 16280 /* Reset nonce count */ 16281 if (strcmp(p->nonce, oldnonce)) 16282 p->noncecount = 0; 16283 16284 /* Save auth data for following registrations */ 16285 if (p->registry) { 16286 struct sip_registry *r = p->registry; 16287 16288 if (strcmp(r->nonce, p->nonce)) { 16289 ast_string_field_set(r, realm, p->realm); 16290 ast_string_field_set(r, nonce, p->nonce); 16291 ast_string_field_set(r, domain, p->domain); 16292 ast_string_field_set(r, opaque, p->opaque); 16293 ast_string_field_set(r, qop, p->qop); 16294 r->noncecount = 0; 16295 } 16296 } 16297 return build_reply_digest(p, sipmethod, digest, digest_len); 16298 }
| 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 8793 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.
Referenced by transmit_info_with_digit(), transmit_info_with_vidupdate(), transmit_invite(), transmit_message_with_text(), transmit_notify_with_sipfrag(), transmit_refer(), transmit_reinvite_with_sdp(), transmit_request(), transmit_request_with_auth(), and transmit_state_notify().
08794 { 08795 struct sip_request *orig = &p->initreq; 08796 char stripped[80]; 08797 char tmp[80]; 08798 char newto[256]; 08799 const char *c; 08800 const char *ot, *of; 08801 int is_strict = FALSE; /*!< Strict routing flag */ 08802 int is_outbound = ast_test_flag(&p->flags[0], SIP_OUTGOING); /* Session direction */ 08803 08804 memset(req, 0, sizeof(struct sip_request)); 08805 08806 snprintf(p->lastmsg, sizeof(p->lastmsg), "Tx: %s", sip_methods[sipmethod].text); 08807 08808 if (!seqno) { 08809 p->ocseq++; 08810 seqno = p->ocseq; 08811 } 08812 08813 /* A CANCEL must have the same branch as the INVITE that it is canceling. */ 08814 if (sipmethod == SIP_CANCEL) { 08815 p->branch = p->invite_branch; 08816 build_via(p); 08817 } else if (newbranch && (sipmethod == SIP_INVITE)) { 08818 p->branch ^= ast_random(); 08819 p->invite_branch = p->branch; 08820 build_via(p); 08821 } else if (newbranch) { 08822 p->branch ^= ast_random(); 08823 build_via(p); 08824 } 08825 08826 /* Check for strict or loose router */ 08827 if (p->route && !ast_strlen_zero(p->route->hop) && strstr(p->route->hop, ";lr") == NULL) { 08828 is_strict = TRUE; 08829 if (sipdebug) 08830 ast_debug(1, "Strict routing enforced for session %s\n", p->callid); 08831 } 08832 08833 if (sipmethod == SIP_CANCEL) 08834 c = REQ_OFFSET_TO_STR(&p->initreq, rlPart2); /* Use original URI */ 08835 else if (sipmethod == SIP_ACK) { 08836 /* Use URI from Contact: in 200 OK (if INVITE) 08837 (we only have the contacturi on INVITEs) */ 08838 if (!ast_strlen_zero(p->okcontacturi)) 08839 c = is_strict ? p->route->hop : p->okcontacturi; 08840 else 08841 c = REQ_OFFSET_TO_STR(&p->initreq, rlPart2); 08842 } else if (!ast_strlen_zero(p->okcontacturi)) 08843 c = is_strict ? p->route->hop : p->okcontacturi; /* Use for BYE or REINVITE */ 08844 else if (!ast_strlen_zero(p->uri)) 08845 c = p->uri; 08846 else { 08847 char *n; 08848 /* We have no URI, use To: or From: header as URI (depending on direction) */ 08849 ast_copy_string(stripped, get_header(orig, is_outbound ? "To" : "From"), 08850 sizeof(stripped)); 08851 n = get_in_brackets(stripped); 08852 c = remove_uri_parameters(n); 08853 } 08854 init_req(req, sipmethod, c); 08855 08856 snprintf(tmp, sizeof(tmp), "%d %s", seqno, sip_methods[sipmethod].text); 08857 08858 add_header(req, "Via", p->via); 08859 if (p->route) { 08860 set_destination(p, p->route->hop); 08861 add_route(req, is_strict ? p->route->next : p->route); 08862 } 08863 add_header(req, "Max-Forwards", DEFAULT_MAX_FORWARDS); 08864 08865 ot = get_header(orig, "To"); 08866 of = get_header(orig, "From"); 08867 08868 /* Add tag *unless* this is a CANCEL, in which case we need to send it exactly 08869 as our original request, including tag (or presumably lack thereof) */ 08870 if (!strcasestr(ot, "tag=") && sipmethod != SIP_CANCEL) { 08871 /* Add the proper tag if we don't have it already. If they have specified 08872 their tag, use it. Otherwise, use our own tag */ 08873 if (is_outbound && !ast_strlen_zero(p->theirtag)) 08874 snprintf(newto, sizeof(newto), "%s;tag=%s", ot, p->theirtag); 08875 else if (!is_outbound) 08876 snprintf(newto, sizeof(newto), "%s;tag=%s", ot, p->tag); 08877 else 08878 snprintf(newto, sizeof(newto), "%s", ot); 08879 ot = newto; 08880 } 08881 08882 if (is_outbound) { 08883 add_header(req, "From", of); 08884 add_header(req, "To", ot); 08885 } else { 08886 add_header(req, "From", ot); 08887 add_header(req, "To", of); 08888 } 08889 /* Do not add Contact for MESSAGE, BYE and Cancel requests */ 08890 if (sipmethod != SIP_BYE && sipmethod != SIP_CANCEL && sipmethod != SIP_MESSAGE) 08891 add_header(req, "Contact", p->our_contact); 08892 08893 copy_header(req, orig, "Call-ID"); 08894 add_header(req, "CSeq", tmp); 08895 08896 if (!ast_strlen_zero(global_useragent)) 08897 add_header(req, "User-Agent", global_useragent); 08898 08899 if (!ast_strlen_zero(p->rpid)) 08900 add_header(req, "Remote-Party-ID", p->rpid); 08901 08902 if (!ast_strlen_zero(p->url)) { 08903 add_header(req, "Access-URL", p->url); 08904 ast_string_field_set(p, url, NULL); 08905 } 08906 08907 /* Add Session-Timers related headers if the feature is active for this session. 08908 An exception to this behavior is the ACK request. Since Asterisk never requires 08909 session-timers support from a remote end-point (UAS) in an INVITE, it must 08910 not send 'Require: timer' header in the ACK request. 08911 This should only be added in the INVITE transactions, not MESSAGE or REFER or other 08912 in-dialog messages. 08913 */ 08914 if (p->stimer && p->stimer->st_active == TRUE && p->stimer->st_active_peer_ua == TRUE 08915 && sipmethod == SIP_INVITE) { 08916 char se_hdr[256]; 08917 snprintf(se_hdr, sizeof(se_hdr), "%d;refresher=%s", p->stimer->st_interval, 08918 strefresher2str(p->stimer->st_ref)); 08919 add_header(req, "Require", "timer"); 08920 add_header(req, "Session-Expires", se_hdr); 08921 snprintf(se_hdr, sizeof(se_hdr), "%d", st_get_se(p, FALSE)); 08922 add_header(req, "Min-SE", se_hdr); 08923 } 08924 08925 return 0; 08926 }
| static int resp_needs_contact | ( | const char * | msg, | |
| enum sipmethod | method | |||
| ) | [inline, static] |
Test if this response needs a contact header.
Definition at line 8667 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().
08667 { 08668 /* Requirements for Contact header inclusion in responses generated 08669 * from the header tables found in the following RFCs. Where the 08670 * Contact header was marked mandatory (m) or optional (o) this 08671 * function returns 1. 08672 * 08673 * - RFC 3261 (ACK, BYE, CANCEL, INVITE, OPTIONS, REGISTER) 08674 * - RFC 2976 (INFO) 08675 * - RFC 3262 (PRACK) 08676 * - RFC 3265 (SUBSCRIBE, NOTIFY) 08677 * - RFC 3311 (UPDATE) 08678 * - RFC 3428 (MESSAGE) 08679 * - RFC 3515 (REFER) 08680 * - RFC 3903 (PUBLISH) 08681 */ 08682 08683 switch (method) { 08684 /* 1xx, 2xx, 3xx, 485 */ 08685 case SIP_INVITE: 08686 case SIP_UPDATE: 08687 case SIP_SUBSCRIBE: 08688 case SIP_NOTIFY: 08689 if ((msg[0] >= '1' && msg[0] <= '3') || !strncmp(msg, "485", 3)) 08690 return 1; 08691 break; 08692 08693 /* 2xx, 3xx, 485 */ 08694 case SIP_REGISTER: 08695 case SIP_OPTIONS: 08696 if (msg[0] == '2' || msg[0] == '3' || !strncmp(msg, "485", 3)) 08697 return 1; 08698 break; 08699 08700 /* 3xx, 485 */ 08701 case SIP_BYE: 08702 case SIP_PRACK: 08703 case SIP_MESSAGE: 08704 case SIP_PUBLISH: 08705 if (msg[0] == '3' || !strncmp(msg, "485", 3)) 08706 return 1; 08707 break; 08708 08709 /* 2xx, 3xx, 4xx, 5xx, 6xx */ 08710 case SIP_REFER: 08711 if (msg[0] >= '2' && msg[0] <= '6') 08712 return 1; 08713 break; 08714 08715 /* contact will not be included for everything else */ 08716 case SIP_ACK: 08717 case SIP_CANCEL: 08718 case SIP_INFO: 08719 case SIP_PING: 08720 default: 08721 return 0; 08722 } 08723 return 0; 08724 }
| 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 8727 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.
Referenced by __transmit_response(), transmit_response_with_allow(), transmit_response_with_auth(), transmit_response_with_date(), transmit_response_with_minse(), transmit_response_with_sdp(), transmit_response_with_t38_sdp(), and transmit_response_with_unsupported().
08728 { 08729 char newto[256]; 08730 const char *ot; 08731 08732 init_resp(resp, msg); 08733 copy_via_headers(p, resp, req, "Via"); 08734 if (msg[0] == '1' || msg[0] == '2') 08735 copy_all_header(resp, req, "Record-Route"); 08736 copy_header(resp, req, "From"); 08737 ot = get_header(req, "To"); 08738 if (!strcasestr(ot, "tag=") && strncmp(msg, "100", 3)) { 08739 /* Add the proper tag if we don't have it already. If they have specified 08740 their tag, use it. Otherwise, use our own tag */ 08741 if (!ast_strlen_zero(p->theirtag) && ast_test_flag(&p->flags[0], SIP_OUTGOING)) 08742 snprintf(newto, sizeof(newto), "%s;tag=%s", ot, p->theirtag); 08743 else if (p->tag && !ast_test_flag(&p->flags[0], SIP_OUTGOING)) 08744 snprintf(newto, sizeof(newto), "%s;tag=%s", ot, p->tag); 08745 else 08746 ast_copy_string(newto, ot, sizeof(newto)); 08747 ot = newto; 08748 } 08749 add_header(resp, "To", ot); 08750 copy_header(resp, req, "Call-ID"); 08751 copy_header(resp, req, "CSeq"); 08752 if (!ast_strlen_zero(global_useragent)) 08753 add_header(resp, "Server", global_useragent); 08754 add_header(resp, "Allow", ALLOWED_METHODS); 08755 add_header(resp, "Supported", SUPPORTED_EXTENSIONS); 08756 08757 /* If this is an invite, add Session-Timers related headers if the feature is active for this session */ 08758 if (p->method == SIP_INVITE && p->stimer && p->stimer->st_active == TRUE && p->stimer->st_active_peer_ua == TRUE) { 08759 char se_hdr[256]; 08760 snprintf(se_hdr, sizeof(se_hdr), "%d;refresher=%s", p->stimer->st_interval, 08761 strefresher2str(p->stimer->st_ref)); 08762 add_header(resp, "Require", "timer"); 08763 add_header(resp, "Session-Expires", se_hdr); 08764 } 08765 08766 if (msg[0] == '2' && (p->method == SIP_SUBSCRIBE || p->method == SIP_REGISTER)) { 08767 /* For registration responses, we also need expiry and 08768 contact info */ 08769 char tmp[256]; 08770 08771 snprintf(tmp, sizeof(tmp), "%d", p->expiry); 08772 add_header(resp, "Expires", tmp); 08773 if (p->expiry) { /* Only add contact if we have an expiry time */ 08774 char contact[SIPBUFSIZE]; 08775 const char *contact_uri = p->method == SIP_SUBSCRIBE ? p->our_contact : p->fullcontact; 08776 char *brackets = strchr(contact_uri, '<'); 08777 snprintf(contact, sizeof(contact), "%s%s%s;expires=%d", brackets ? "" : "<", contact_uri, brackets ? "" : ">", p->expiry); 08778 add_header(resp, "Contact", contact); /* Not when we unregister */ 08779 } 08780 } else if (!ast_strlen_zero(p->our_contact) && resp_needs_contact(msg, p->method)) { 08781 add_header(resp, "Contact", p->our_contact); 08782 } 08783 08784 if (!ast_strlen_zero(p->url)) { 08785 add_header(resp, "Access-URL", p->url); 08786 ast_string_field_set(p, url, NULL); 08787 } 08788 08789 return 0; 08790 }
| static int restart_monitor | ( | void | ) | [static] |
Start the channel monitor thread.
Definition at line 21542 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.
Referenced by load_module(), sip_reload(), and sip_request_call().
21543 { 21544 /* If we're supposed to be stopped -- stay stopped */ 21545 if (monitor_thread == AST_PTHREADT_STOP) 21546 return 0; 21547 ast_mutex_lock(&monlock); 21548 if (monitor_thread == pthread_self()) { 21549 ast_mutex_unlock(&monlock); 21550 ast_log(LOG_WARNING, "Cannot kill myself\n"); 21551 return -1; 21552 } 21553 if (monitor_thread != AST_PTHREADT_NULL) { 21554 /* Wake up the thread */ 21555 pthread_kill(monitor_thread, SIGURG); 21556 } else { 21557 /* Start a new monitor */ 21558 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) { 21559 ast_mutex_unlock(&monlock); 21560 ast_log(LOG_ERROR, "Unable to start monitor thread.\n"); 21561 return -1; 21562 } 21563 } 21564 ast_mutex_unlock(&monlock); 21565 return 0; 21566 }
| static void restart_session_timer | ( | struct sip_pvt * | p | ) | [static] |
Session-Timers: Restart session timer.
Definition at line 21570 of file chan_sip.c.
References ast_debug, ast_log(), AST_SCHED_DEL_UNREF, sip_pvt::callid, dialog_unref(), LOG_WARNING, sip_st_dlg::st_active, sip_st_dlg::st_schedid, start_session_timer(), sip_pvt::stimer, and TRUE.
Referenced by handle_request_invite().
21571 { 21572 if (!p->stimer) { 21573 ast_log(LOG_WARNING, "Null stimer in restart_session_timer - %s\n", p->callid); 21574 return; 21575 } 21576 21577 if (p->stimer->st_active == TRUE) { 21578 AST_SCHED_DEL_UNREF(sched, p->stimer->st_schedid, 21579 dialog_unref(p, "Removing session timer ref")); 21580 ast_debug(2, "Session timer stopped: %d - %s\n", p->stimer->st_schedid, p->callid); 21581 start_session_timer(p); 21582 } 21583 }
| static int retrans_pkt | ( | const void * | data | ) | [static] |
Retransmit SIP message if no answer (Called from scheduler).
Definition at line 3343 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, cfsip_methods::text, sip_pkt::timer_a, sip_pkt::timer_t1, UNLINK, and XMIT_ERROR.
Referenced by __sip_reliable_xmit(), and sip_show_sched().
03344 { 03345 struct sip_pkt *pkt = (struct sip_pkt *)data, *prev, *cur = NULL; 03346 int reschedule = DEFAULT_RETRANS; 03347 int xmitres = 0; 03348 03349 /* Lock channel PVT */ 03350 sip_pvt_lock(pkt->owner); 03351 03352 if (pkt->retrans < MAX_RETRANS) { 03353 pkt->retrans++; 03354 if (!pkt->timer_t1) { /* Re-schedule using timer_a and timer_t1 */ 03355 if (sipdebug) 03356 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); 03357 } else { 03358 int siptimer_a; 03359 03360 if (sipdebug) 03361 ast_debug(4, "SIP TIMER: Rescheduling retransmission #%d (%d) %s - %d\n", pkt->retransid, pkt->retrans, sip_methods[pkt->method].text, pkt->method); 03362 if (!pkt->timer_a) 03363 pkt->timer_a = 2 ; 03364 else 03365 pkt->timer_a = 2 * pkt->timer_a; 03366 03367 /* For non-invites, a maximum of 4 secs */ 03368 siptimer_a = pkt->timer_t1 * pkt->timer_a; /* Double each time */ 03369 if (pkt->method != SIP_INVITE && siptimer_a > 4000) 03370 siptimer_a = 4000; 03371 03372 /* Reschedule re-transmit */ 03373 reschedule = siptimer_a; 03374 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); 03375 } 03376 03377 if (sip_debug_test_pvt(pkt->owner)) { 03378 const struct sockaddr_in *dst = sip_real_dst(pkt->owner); 03379 ast_verbose("Retransmitting #%d (%s) to %s:%d:\n%s\n---\n", 03380 pkt->retrans, sip_nat_mode(pkt->owner), 03381 ast_inet_ntoa(dst->sin_addr), 03382 ntohs(dst->sin_port), pkt->data->str); 03383 } 03384 03385 append_history(pkt->owner, "ReTx", "%d %s", reschedule, pkt->data->str); 03386 xmitres = __sip_xmit(pkt->owner, pkt->data, pkt->packetlen); 03387 sip_pvt_unlock(pkt->owner); 03388 if (xmitres == XMIT_ERROR) 03389 ast_log(LOG_WARNING, "Network error on retransmit in dialog %s\n", pkt->owner->callid); 03390 else 03391 return reschedule; 03392 } 03393 /* Too many retries */ 03394 if (pkt->owner && pkt->method != SIP_OPTIONS && xmitres == 0) { 03395 if (pkt->is_fatal || sipdebug) /* Tell us if it's critical or if we're debugging */ 03396 ast_log(LOG_WARNING, "Maximum retries exceeded on transmission %s for seqno %d (%s %s) -- See doc/sip-retransmit.txt.\n", 03397 pkt->owner->callid, pkt->seqno, 03398 pkt->is_fatal ? "Critical" : "Non-critical", pkt->is_resp ? "Response" : "Request"); 03399 } else if (pkt->method == SIP_OPTIONS && sipdebug) { 03400 ast_log(LOG_WARNING, "Cancelling retransmit of OPTIONs (call id %s) -- See doc/sip-retransmit.txt.\n", pkt->owner->callid); 03401 03402 } 03403 if (xmitres == XMIT_ERROR) { 03404 ast_log(LOG_WARNING, "Transmit error :: Cancelling transmission on Call ID %s\n", pkt->owner->callid); 03405 append_history(pkt->owner, "XmitErr", "%s", pkt->is_fatal ? "(Critical)" : "(Non-critical)"); 03406 } else 03407 append_history(pkt->owner, "MaxRetries", "%s", pkt->is_fatal ? "(Critical)" : "(Non-critical)"); 03408 03409 pkt->retransid = -1; 03410 03411 if (pkt->is_fatal) { 03412 while(pkt->owner->owner && ast_channel_trylock(pkt->owner->owner)) { 03413 sip_pvt_unlock(pkt->owner); /* SIP_PVT, not channel */ 03414 usleep(1); 03415 sip_pvt_lock(pkt->owner); 03416 } 03417 03418 if (pkt->owner->owner && !pkt->owner->owner->hangupcause) 03419 pkt->owner->owner->hangupcause = AST_CAUSE_NO_USER_RESPONSE; 03420 03421 if (pkt->owner->owner) { 03422 sip_alreadygone(pkt->owner); 03423 ast_log(LOG_WARNING, "Hanging up call %s - no reply to our critical packet (see doc/sip-retransmit.txt).\n", pkt->owner->callid); 03424 ast_queue_hangup_with_cause(pkt->owner->owner, AST_CAUSE_PROTOCOL_ERROR); 03425 ast_channel_unlock(pkt->owner->owner); 03426 } else { 03427 /* If no channel owner, destroy now */ 03428 03429 /* Let the peerpoke system expire packets when the timer expires for poke_noanswer */ 03430 if (pkt->method != SIP_OPTIONS && pkt->method != SIP_REGISTER) { 03431 pkt->owner->needdestroy = 1; 03432 sip_alreadygone(pkt->owner); 03433 append_history(pkt->owner, "DialogKill", "Killing this failed dialog immediately"); 03434 } 03435 } 03436 } 03437 03438 if (pkt->method == SIP_BYE) { 03439 /* We're not getting answers on SIP BYE's. Tear down the call anyway. */ 03440 if (pkt->owner->owner) 03441 ast_channel_unlock(pkt->owner->owner); 03442 append_history(pkt->owner, "ByeFailure", "Remote peer doesn't respond to bye. Destroying call anyway."); 03443 pkt->owner->needdestroy = 1; 03444 } 03445 03446 /* Remove the packet */ 03447 for (prev = NULL, cur = pkt->owner->packets; cur; prev = cur, cur = cur->next) { 03448 if (cur == pkt) { 03449 UNLINK(cur, pkt->owner->packets, prev); 03450 sip_pvt_unlock(pkt->owner); 03451 if (pkt->owner) 03452 pkt->owner = dialog_unref(pkt->owner,"pkt is being freed, its dialog ref is dead now"); 03453 if (pkt->data) 03454 ast_free(pkt->data); 03455 pkt->data = NULL; 03456 ast_free(pkt); 03457 return 0; 03458 } 03459 } 03460 /* error case */ 03461 ast_log(LOG_WARNING, "Weird, couldn't find packet owner!\n"); 03462 sip_pvt_unlock(pkt->owner); 03463 return 0; 03464 }
| static int scheduler_process_request_queue | ( | const void * | data | ) | [static] |
Definition at line 20854 of file chan_sip.c.
References ast_channel_trylock, ast_channel_unlock, AST_LIST_EMPTY, ast_update_use_count(), dialog_unref(), sip_pvt::owner, process_request_queue(), sip_pvt::request_queue, sip_pvt::request_queue_sched_id, sip_pvt_lock, and sip_pvt_unlock.
Referenced by queue_request().
20855 { 20856 struct sip_pvt *p = (struct sip_pvt *) data; 20857 int recount = 0; 20858 int nounlock = 0; 20859 int lockretry; 20860 20861 for (lockretry = 10; lockretry > 0; lockretry--) { 20862 sip_pvt_lock(p); 20863 20864 /* lock the owner if it has one -- we may need it */ 20865 /* because this is deadlock-prone, we need to try and unlock if failed */ 20866 if (!p->owner || !ast_channel_trylock(p->owner)) { 20867 break; /* locking succeeded */ 20868 } 20869 20870 if (lockretry != 1) { 20871 sip_pvt_unlock(p); 20872 /* Sleep for a very short amount of time */ 20873 usleep(1); 20874 } 20875 } 20876 20877 if (!lockretry) { 20878 int retry = !AST_LIST_EMPTY(&p->request_queue); 20879 20880 /* we couldn't get the owner lock, which is needed to process 20881 the queued requests, so return a non-zero value, which will 20882 cause the scheduler to run this request again later if there 20883 still requests to be processed 20884 */ 20885 sip_pvt_unlock(p); 20886 if (!retry) { 20887 dialog_unref(p, "The ref to a dialog passed to this sched callback is going out of scope; unref it."); 20888 } 20889 return retry; 20890 }; 20891 20892 process_request_queue(p, &recount, &nounlock); 20893 p->request_queue_sched_id = -1; 20894 20895 if (p->owner && !nounlock) { 20896 ast_channel_unlock(p->owner); 20897 } 20898 sip_pvt_unlock(p); 20899 20900 if (recount) { 20901 ast_update_use_count(); 20902 } 20903 20904 dialog_unref(p, "The ref to a dialog passed to this sched callback is going out of scope; unref it."); 20905 20906 return 0; 20907 }
| static int send_provisional_keepalive | ( | const void * | data | ) | [static] |
Definition at line 3791 of file chan_sip.c.
References send_provisional_keepalive_full().
Referenced by update_provisional_keepalive().
03791 { 03792 struct sip_pvt *pvt = (struct sip_pvt *) data; 03793 03794 return send_provisional_keepalive_full(pvt, 0); 03795 }
| static int send_provisional_keepalive_full | ( | struct sip_pvt * | pvt, | |
| int | with_sdp | |||
| ) | [static] |
Definition at line 3771 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().
03772 { 03773 const char *msg = NULL; 03774 03775 if (!pvt->last_provisional || !strncasecmp(pvt->last_provisional, "100", 3)) { 03776 msg = "183 Session Progress"; 03777 } 03778 03779 if (pvt->invitestate < INV_COMPLETED) { 03780 if (with_sdp) { 03781 transmit_response_with_sdp(pvt, S_OR(msg, pvt->last_provisional), &pvt->initreq, XMIT_UNRELIABLE, FALSE); 03782 } else { 03783 transmit_response(pvt, S_OR(msg, pvt->last_provisional), &pvt->initreq); 03784 } 03785 return PROVIS_KEEPALIVE_TIMEOUT; 03786 } 03787 03788 return 0; 03789 }
| static int send_provisional_keepalive_with_sdp | ( | const void * | data | ) | [static] |
Definition at line 3797 of file chan_sip.c.
References send_provisional_keepalive_full().
Referenced by update_provisional_keepalive().
03797 { 03798 struct sip_pvt *pvt = (void *)data; 03799 03800 return send_provisional_keepalive_full(pvt, 1); 03801 }
| 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 3849 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, cfsip_methods::text, and XMIT_CRITICAL.
Referenced by transmit_info_with_digit(), transmit_info_with_vidupdate(), transmit_invite(), transmit_message_with_text(), transmit_notify_custom(), transmit_notify_with_mwi(), transmit_notify_with_sipfrag(), transmit_refer(), transmit_register(), transmit_reinvite_with_sdp(), transmit_request(), transmit_request_with_auth(), and transmit_state_notify().
03850 { 03851 int res; 03852 03853 /* If we have an outbound proxy, reset peer address 03854 Only do this once. 03855 */ 03856 if (p->outboundproxy) { 03857 p->sa = p->outboundproxy->ip; 03858 } 03859 03860 add_blank(req); 03861 if (sip_debug_test_pvt(p)) { 03862 if (ast_test_flag(&p->flags[0], SIP_NAT_ROUTE)) 03863 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); 03864 else 03865 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); 03866 } 03867 if (p->do_history) { 03868 struct sip_request tmp = { .rlPart1 = 0, }; 03869 parse_copy(&tmp, req); 03870 append_history(p, reliable ? "TxReqRel" : "TxReq", "%s / %s - %s", tmp.data->str, get_header(&tmp, "CSeq"), sip_methods[tmp.method].text); 03871 ast_free(tmp.data); 03872 } 03873 res = (reliable) ? 03874 __sip_reliable_xmit(p, seqno, 0, req->data, req->len, (reliable == XMIT_CRITICAL), req->method) : 03875 __sip_xmit(p, req->data, req->len); 03876 if (req->data) { 03877 ast_free(req->data); 03878 req->data = NULL; 03879 } 03880 return res; 03881 }
| 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 3812 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, 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.
Referenced by __transmit_response(), transmit_response_with_allow(), transmit_response_with_auth(), transmit_response_with_date(), transmit_response_with_minse(), transmit_response_with_sdp(), transmit_response_with_t38_sdp(), and transmit_response_with_unsupported().
03813 { 03814 int res; 03815 03816 add_blank(req); 03817 if (sip_debug_test_pvt(p)) { 03818 const struct sockaddr_in *dst = sip_real_dst(p); 03819 03820 ast_verbose("\n<--- %sTransmitting (%s) to %s:%d --->\n%s\n<------------>\n", 03821 reliable ? "Reliably " : "", sip_nat_mode(p), 03822 ast_inet_ntoa(dst->sin_addr), 03823 ntohs(dst->sin_port), req->data->str); 03824 } 03825 if (p->do_history) { 03826 struct sip_request tmp = { .rlPart1 = 0, }; 03827 parse_copy(&tmp, req); 03828 append_history(p, reliable ? "TxRespRel" : "TxResp", "%s / %s - %s", tmp.data->str, get_header(&tmp, "CSeq"), 03829 (tmp.method == SIP_RESPONSE || tmp.method == SIP_UNKNOWN) ? REQ_OFFSET_TO_STR(&tmp, rlPart2) : sip_methods[tmp.method].text); 03830 ast_free(tmp.data); 03831 } 03832 03833 /* If we are sending a final response to an INVITE, stop retransmitting provisional responses */ 03834 if (p->initreq.method == SIP_INVITE && reliable == XMIT_CRITICAL) { 03835 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")); 03836 } 03837 03838 res = (reliable) ? 03839 __sip_reliable_xmit(p, seqno, 1, req->data, req->len, (reliable == XMIT_CRITICAL), req->method) : 03840 __sip_xmit(p, req->data, req->len); 03841 ast_free(req->data); 03842 req->data = NULL; 03843 if (res > 0) 03844 return 0; 03845 return res; 03846 }
| static int set_address_from_contact | ( | struct sip_pvt * | pvt | ) | [static] |
Change the other partys IP address based on given contact.
Definition at line 11415 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().
11416 { 11417 if (ast_test_flag(&pvt->flags[0], SIP_NAT_ROUTE)) { 11418 /* NAT: Don't trust the contact field. Just use what they came to us 11419 with. */ 11420 pvt->sa = pvt->recv; 11421 return 0; 11422 } 11423 11424 return __set_address_from_contact(pvt->fullcontact, &pvt->sa, pvt->socket.type == SIP_TRANSPORT_TLS ? 1 : 0); 11425 }
| static void set_destination | ( | struct sip_pvt * | p, | |
| char * | uri | |||
| ) | [static] |
Set destination from SIP URI.
Definition at line 8573 of file chan_sip.c.
References 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().
08574 { 08575 char *h, *maddr, hostname[256]; 08576 int port, hn; 08577 struct hostent *hp; 08578 struct ast_hostent ahp; 08579 int debug=sip_debug_test_pvt(p); 08580 08581 /* Parse uri to h (host) and port - uri is already just the part inside the <> */ 08582 /* general form we are expecting is sip[s]:username[:password][;parameter]@host[:port][;...] */ 08583 08584 if (debug) 08585 ast_verbose("set_destination: Parsing <%s> for address/port to send to\n", uri); 08586 08587 /* Find and parse hostname */ 08588 h = strchr(uri, '@'); 08589 if (h) 08590 ++h; 08591 else { 08592 h = uri; 08593 if (!strncasecmp(h, "sip:", 4)) 08594 h += 4; 08595 else if (!strncasecmp(h, "sips:", 5)) 08596 h += 5; 08597 } 08598 hn = strcspn(h, ":;>") + 1; 08599 if (hn > sizeof(hostname)) 08600 hn = sizeof(hostname); 08601 ast_copy_string(hostname, h, hn); 08602 /* XXX bug here if string has been trimmed to sizeof(hostname) */ 08603 h += hn - 1; 08604 08605 /* Is "port" present? if not default to STANDARD_SIP_PORT */ 08606 if (*h == ':') { 08607 /* Parse port */ 08608 ++h; 08609 port = strtol(h, &h, 10); 08610 } 08611 else 08612 port = STANDARD_SIP_PORT; 08613 08614 /* Got the hostname:port - but maybe there's a "maddr=" to override address? */ 08615 maddr = strstr(h, "maddr="); 08616 if (maddr) { 08617 maddr += 6; 08618 hn = strspn(maddr, "0123456789.") + 1; 08619 if (hn > sizeof(hostname)) 08620 hn = sizeof(hostname); 08621 ast_copy_string(hostname, maddr, hn); 08622 } 08623 08624 hp = ast_gethostbyname(hostname, &ahp); 08625 if (hp == NULL) { 08626 ast_log(LOG_WARNING, "Can't find address for host '%s'\n", hostname); 08627 return; 08628 } 08629 p->sa.sin_family = AF_INET; 08630 memcpy(&p->sa.sin_addr, hp->h_addr, sizeof(p->sa.sin_addr)); 08631 p->sa.sin_port = htons(port); 08632 if (debug) 08633 ast_verbose("set_destination: set destination to %s, port %d\n", ast_inet_ntoa(p->sa.sin_addr), port); 08634 }
| 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 22284 of file chan_sip.c.
References ast_copy_string(), ast_false(), ast_log(), ast_set_flag, ast_strlen_zero(), buf, LOG_WARNING, SIP_INSECURE_INVITE, SIP_INSECURE_PORT, and strsep().
Referenced by get_insecure_variable_from_config(), and handle_common_options().
22285 { 22286 if (ast_strlen_zero(value)) 22287 return; 22288 22289 if (!ast_false(value)) { 22290 char buf[64]; 22291 char *word, *next; 22292 22293 ast_copy_string(buf, value, sizeof(buf)); 22294 next = buf; 22295 while ((word = strsep(&next, ","))) { 22296 if (!strcasecmp(word, "port")) 22297 ast_set_flag(&flags[0], SIP_INSECURE_PORT); 22298 else if (!strcasecmp(word, "invite")) 22299 ast_set_flag(&flags[0], SIP_INSECURE_INVITE); 22300 else 22301 ast_log(LOG_WARNING, "Unknown insecure mode '%s' on line %d\n", value, lineno); 22302 } 22303 } 22304 }
| 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 11760 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().
11761 { 11762 if (p->stalenonce || forceupdate || ast_strlen_zero(p->randdata)) { 11763 ast_string_field_build(p, randdata, "%08lx", ast_random()); /* Create nonce for challenge */ 11764 p->stalenonce = 0; 11765 } 11766 }
| static void set_peer_defaults | ( | struct sip_peer * | peer | ) | [static] |
Set peer defaults before configuring specific configurations.
Definition at line 22639 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, 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().
22640 { 22641 if (peer->expire == 0) { 22642 /* Don't reset expire or port time during reload 22643 if we have an active registration 22644 */ 22645 peer->expire = -1; 22646 peer->pokeexpire = -1; 22647 peer->addr.sin_port = htons(STANDARD_SIP_PORT); 22648 set_socket_transport(&peer->socket, SIP_TRANSPORT_UDP); 22649 } 22650 peer->type = SIP_TYPE_PEER; 22651 ast_copy_flags(&peer->flags[0], &global_flags[0], SIP_FLAGS_TO_COPY); 22652 ast_copy_flags(&peer->flags[1], &global_flags[1], SIP_PAGE2_FLAGS_TO_COPY); 22653 strcpy(peer->context, default_context); 22654 strcpy(peer->subscribecontext, default_subscribecontext); 22655 strcpy(peer->language, default_language); 22656 strcpy(peer->mohinterpret, default_mohinterpret); 22657 strcpy(peer->mohsuggest, default_mohsuggest); 22658 peer->addr.sin_family = AF_INET; 22659 peer->defaddr.sin_family = AF_INET; 22660 peer->capability = global_capability; 22661 peer->maxcallbitrate = default_maxcallbitrate; 22662 peer->rtptimeout = global_rtptimeout; 22663 peer->rtpholdtimeout = global_rtpholdtimeout; 22664 peer->rtpkeepalive = global_rtpkeepalive; 22665 peer->allowtransfer = global_allowtransfer; 22666 peer->autoframing = global_autoframing; 22667 peer->t38_maxdatagram = global_t38_maxdatagram; 22668 peer->qualifyfreq = global_qualifyfreq; 22669 if (global_callcounter) 22670 peer->call_limit=999; 22671 strcpy(peer->vmexten, default_vmexten); 22672 peer->secret[0] = '\0'; 22673 peer->md5secret[0] = '\0'; 22674 peer->cid_num[0] = '\0'; 22675 peer->cid_name[0] = '\0'; 22676 peer->fromdomain[0] = '\0'; 22677 peer->fromuser[0] = '\0'; 22678 peer->regexten[0] = '\0'; 22679 peer->callgroup = 0; 22680 peer->pickupgroup = 0; 22681 peer->maxms = default_qualify; 22682 peer->prefs = default_prefs; 22683 peer->stimer.st_mode_oper = global_st_mode; /* Session-Timers */ 22684 peer->stimer.st_ref = global_st_refresher; 22685 peer->stimer.st_min_se = global_min_se; 22686 peer->stimer.st_max_se = global_max_se; 22687 peer->timer_t1 = global_t1; 22688 peer->timer_b = global_timer_b; 22689 clear_peer_mailboxes(peer); 22690 }
| static void set_socket_transport | ( | struct sip_socket * | socket, | |
| int | transport | |||
| ) | [static] |
Definition at line 11216 of file chan_sip.c.
References ao2_ref, sip_socket::fd, 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().
11217 { 11218 /* if the transport type changes, clear all socket data */ 11219 if (socket->type != transport) { 11220 socket->fd = -1; 11221 socket->type = transport; 11222 if (socket->tcptls_session) { 11223 ao2_ref(socket->tcptls_session, -1); 11224 socket->tcptls_session = NULL; 11225 } 11226 } 11227 }
| static void set_t38_capabilities | ( | struct sip_pvt * | p | ) | [static] |
Set the global T38 capabilities on a SIP dialog structure.
Definition at line 4692 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().
04693 { 04694 if (p->udptl) { 04695 if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT) == SIP_PAGE2_T38SUPPORT_UDPTL_REDUNDANCY) { 04696 ast_udptl_set_error_correction_scheme(p->udptl, UDPTL_ERROR_CORRECTION_REDUNDANCY); 04697 } else if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT) == SIP_PAGE2_T38SUPPORT_UDPTL_FEC) { 04698 ast_udptl_set_error_correction_scheme(p->udptl, UDPTL_ERROR_CORRECTION_FEC); 04699 } else if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT) == SIP_PAGE2_T38SUPPORT_UDPTL) { 04700 ast_udptl_set_error_correction_scheme(p->udptl, UDPTL_ERROR_CORRECTION_NONE); 04701 } 04702 } 04703 }
| static int show_channels_cb | ( | void * | __cur, | |
| void * | __arg, | |||
| int | flags | |||
| ) | [static] |
callback for show channel|subscription
Definition at line 15351 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, MWI_NOTIFICATION, 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().
15352 { 15353 struct sip_pvt *cur = __cur; 15354 struct __show_chan_arg *arg = __arg; 15355 const struct sockaddr_in *dst = sip_real_dst(cur); 15356 15357 /* XXX indentation preserved to reduce diff. Will be fixed later */ 15358 if (cur->subscribed == NONE && !arg->subscriptions) { 15359 /* set if SIP transfer in progress */ 15360 const char *referstatus = cur->refer ? referstatus2str(cur->refer->status) : ""; 15361 char formatbuf[SIPBUFSIZE/2]; 15362 15363 ast_cli(arg->fd, FORMAT, ast_inet_ntoa(dst->sin_addr), 15364 S_OR(cur->username, S_OR(cur->cid_num, "(None)")), 15365 cur->callid, 15366 ast_getformatname_multiple(formatbuf, sizeof(formatbuf), cur->owner ? cur->owner->nativeformats : 0), 15367 cli_yesno(ast_test_flag(&cur->flags[1], SIP_PAGE2_CALL_ONHOLD)), 15368 cur->needdestroy ? "(d)" : "", 15369 cur->lastmsg , 15370 referstatus 15371 ); 15372 arg->numchans++; 15373 } 15374 if (cur->subscribed != NONE && arg->subscriptions) { 15375 struct ast_str *mailbox_str = ast_str_alloca(512); 15376 if (cur->subscribed == MWI_NOTIFICATION && cur->relatedpeer) 15377 peer_mailboxes_to_str(&mailbox_str, cur->relatedpeer); 15378 ast_cli(arg->fd, FORMAT4, ast_inet_ntoa(dst->sin_addr), 15379 S_OR(cur->username, S_OR(cur->cid_num, "(None)")), 15380 cur->callid, 15381 /* the 'complete' exten/context is hidden in the refer_to field for subscriptions */ 15382 cur->subscribed == MWI_NOTIFICATION ? "--" : cur->subscribeuri, 15383 cur->subscribed == MWI_NOTIFICATION ? "<none>" : ast_extension_state2str(cur->laststate), 15384 subscription_type2str(cur->subscribed), 15385 cur->subscribed == MWI_NOTIFICATION ? S_OR(mailbox_str->str, "<none>") : "<none>", 15386 cur->expiry 15387 ); 15388 arg->numchans++; 15389 } 15390 return 0; /* don't care, we scan all channels */ 15391 }
| static int show_chanstats_cb | ( | void * | __cur, | |
| void * | __arg, | |||
| int | flags | |||
| ) | [static] |
Callback for show_chanstats.
Definition at line 15030 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, invstate2stringtable::desc, __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().
15031 { 15032 #define FORMAT2 "%-15.15s %-11.11s %-8.8s %-10.10s %-10.10s ( %%) %-6.6s %-10.10s %-10.10s ( %%) %-6.6s\n" 15033 #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" 15034 struct sip_pvt *cur = __cur; 15035 unsigned int rxcount, txcount, rxploss, txploss; 15036 char durbuf[10]; 15037 int duration; 15038 int durh, durm, durs; 15039 struct ast_channel *c = cur->owner; 15040 struct __show_chan_arg *arg = __arg; 15041 int fd = arg->fd; 15042 15043 15044 if (cur->subscribed != NONE) /* Subscriptions */ 15045 return 0; /* don't care, we scan all channels */ 15046 15047 if (!cur->rtp) { 15048 if (sipdebug) 15049 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"); 15050 return 0; /* don't care, we scan all channels */ 15051 } 15052 rxcount = ast_rtp_get_qosvalue(cur->rtp, AST_RTP_RXCOUNT); 15053 txcount = ast_rtp_get_qosvalue(cur->rtp, AST_RTP_TXCOUNT); 15054 rxploss = ast_rtp_get_qosvalue(cur->rtp, AST_RTP_RXPLOSS); 15055 txploss = ast_rtp_get_qosvalue(cur->rtp, AST_RTP_TXPLOSS); 15056 15057 /* Find the duration of this channel */ 15058 if (c && c->cdr && !ast_tvzero(c->cdr->start)) { 15059 duration = (int)(ast_tvdiff_ms(ast_tvnow(), c->cdr->start) / 1000); 15060 durh = duration / 3600; 15061 durm = (duration % 3600) / 60; 15062 durs = duration % 60; 15063 snprintf(durbuf, sizeof(durbuf), "%02d:%02d:%02d", durh, durm, durs); 15064 } else { 15065 durbuf[0] = '\0'; 15066 } 15067 /* Print stats for every call with RTP */ 15068 ast_cli(fd, FORMAT, 15069 ast_inet_ntoa(cur->sa.sin_addr), 15070 cur->callid, 15071 durbuf, 15072 rxcount > (unsigned int) 100000 ? (unsigned int) (rxcount)/(unsigned int) 1000 : rxcount, 15073 rxcount > (unsigned int) 100000 ? "K":" ", 15074 rxploss, 15075 (rxcount + rxploss) > 0 ? (double) rxploss / (rxcount + rxploss) * 100 : 0, 15076 ast_rtp_get_qosvalue(cur->rtp, AST_RTP_RXJITTER), 15077 txcount > (unsigned int) 100000 ? (unsigned int) (txcount)/(unsigned int) 1000 : txcount, 15078 txcount > (unsigned int) 100000 ? "K":" ", 15079 txploss, 15080 txcount > 0 ? (double) txploss / txcount * 100 : 0, 15081 ast_rtp_get_qosvalue(cur->rtp, AST_RTP_TXJITTER) 15082 ); 15083 arg->numchans++; 15084 15085 return 0; /* don't care, we scan all channels */ 15086 }
| static int sip_addheader | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Add a SIP header to an outbound INVITE.
Definition at line 24405 of file chan_sip.c.
References ast_channel_lock, ast_channel_unlock, ast_debug, ast_get_encoded_str(), ast_log(), ast_strlen_zero(), FALSE, inbuf(), LOG_WARNING, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), and TRUE.
Referenced by load_module().
24406 { 24407 int no = 0; 24408 int ok = FALSE; 24409 char varbuf[30]; 24410 char *inbuf = data, *subbuf; 24411 24412 if (ast_strlen_zero(inbuf)) { 24413 ast_log(LOG_WARNING, "This application requires the argument: Header\n"); 24414 return 0; 24415 } 24416 ast_channel_lock(chan); 24417 24418 /* Check for headers */ 24419 while (!ok && no <= 50) { 24420 no++; 24421 snprintf(varbuf, sizeof(varbuf), "__SIPADDHEADER%.2d", no); 24422 24423 /* Compare without the leading underscores */ 24424 if ((pbx_builtin_getvar_helper(chan, (const char *) varbuf + 2) == (const char *) NULL)) { 24425 ok = TRUE; 24426 } 24427 } 24428 if (ok) { 24429 size_t len = strlen(inbuf); 24430 subbuf = alloca(len + 1); 24431 ast_get_encoded_str(inbuf, subbuf, len + 1); 24432 pbx_builtin_setvar_helper(chan, varbuf, subbuf); 24433 if (sipdebug) { 24434 ast_debug(1, "SIP Header added \"%s\" as %s\n", inbuf, varbuf); 24435 } 24436 } else { 24437 ast_log(LOG_WARNING, "Too many SIP headers added, max 50\n"); 24438 } 24439 ast_channel_unlock(chan); 24440 return 0; 24441 }
| 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, read] |
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 6739 of file chan_sip.c.
References sip_pvt::allowtransfer, 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(), sip_pvt::autoframing, sip_pvt::autokillid, bindaddr, sip_pvt::branch, build_callid_pvt(), build_via(), sip_pvt::callid, sip_pvt::capability, sip_pvt::chanvars, context, default_prefs, dialogs, sip_pvt::do_history, do_setnat(), errno, sip_socket::fd, sip_pvt::flags, sip_pvt::fromdomain, INITIAL_CSEQ, sip_pvt::initid, internip, LOG_WARNING, make_our_tag(), sip_pvt::maxcallbitrate, sip_pvt::method, mohinterpret, mohsuggest, sip_pvt::noncodeccapability, NONE, sip_pvt::ocseq, sip_pvt::ourip, parkinglot, sip_pvt::prefs, sip_pvt::provisional_keepalive_sched_id, sip_pvt::recv, sip_pvt::request_queue, sip_pvt::request_queue_sched_id, sip_pvt::rtp, sip_pvt::sa, sip_pvt::session_modify, sip_pvt::sessionversion_remote, 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, sip_pvt::socket, sip_pvt::stateid, sip_pvt::stimer, sip_pvt::subscribed, sip_pvt::t38_maxdatagram, sip_pvt::t38id, sip_pvt::tag, cfsip_methods::text, sip_pvt::timer_b, sip_pvt::timer_t1, sip_pvt::trtp, TRUE, sip_socket::type, sip_pvt::udptl, sip_pvt::vrtp, and sip_pvt::waitid.
Referenced by find_call(), manager_sipnotify(), sip_cli_notify(), sip_poke_peer(), sip_request_call(), sip_send_mwi_to_peer(), and transmit_register().
06741 { 06742 struct sip_pvt *p; 06743 06744 if (!(p = ao2_t_alloc(sizeof(*p), sip_destroy_fn, "allocate a dialog(pvt) struct"))) 06745 return NULL; 06746 06747 if (ast_string_field_init(p, 512)) { 06748 ao2_t_ref(p, -1, "failed to string_field_init, drop p"); 06749 return NULL; 06750 } 06751 06752 if (req) { 06753 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 */ 06754 } else { 06755 set_socket_transport(&p->socket, SIP_TRANSPORT_UDP); 06756 } 06757 06758 p->socket.fd = -1; 06759 p->method = intended_method; 06760 p->initid = -1; 06761 p->waitid = -1; 06762 p->autokillid = -1; 06763 p->request_queue_sched_id = -1; 06764 p->provisional_keepalive_sched_id = -1; 06765 p->t38id = -1; 06766 p->subscribed = NONE; 06767 p->stateid = -1; 06768 p->sessionversion_remote = -1; 06769 p->session_modify = TRUE; 06770 p->stimer = NULL; 06771 p->prefs = default_prefs; /* Set default codecs for this call */ 06772 06773 if (intended_method != SIP_OPTIONS) { /* Peerpoke has it's own system */ 06774 p->timer_t1 = global_t1; /* Default SIP retransmission timer T1 (RFC 3261) */ 06775 p->timer_b = global_timer_b; /* Default SIP transaction timer B (RFC 3261) */ 06776 } 06777 06778 if (!sin) 06779 p->ourip = internip; 06780 else { 06781 p->sa = *sin; 06782 ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip, p); 06783 } 06784 06785 /* Copy global flags to this PVT at setup. */ 06786 ast_copy_flags(&p->flags[0], &global_flags[0], SIP_FLAGS_TO_COPY); 06787 ast_copy_flags(&p->flags[1], &global_flags[1], SIP_PAGE2_FLAGS_TO_COPY); 06788 06789 p->do_history = recordhistory; 06790 06791 p->branch = ast_random(); 06792 make_our_tag(p->tag, sizeof(p->tag)); 06793 p->ocseq = INITIAL_CSEQ; 06794 06795 if (sip_methods[intended_method].need_rtp) { 06796 p->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr); 06797 /* If the global videosupport flag is on, we always create a RTP interface for video */ 06798 if (ast_test_flag(&p->flags[1], SIP_PAGE2_VIDEOSUPPORT)) 06799 p->vrtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr); 06800 if (ast_test_flag(&p->flags[1], SIP_PAGE2_TEXTSUPPORT)) 06801 p->trtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr); 06802 if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT)) 06803 p->udptl = ast_udptl_new_with_bindaddr(sched, io, 0, bindaddr.sin_addr); 06804 if (!p->rtp|| (ast_test_flag(&p->flags[1], SIP_PAGE2_VIDEOSUPPORT) && !p->vrtp) 06805 || (ast_test_flag(&p->flags[1], SIP_PAGE2_TEXTSUPPORT) && !p->trtp)) { 06806 ast_log(LOG_WARNING, "Unable to create RTP audio %s%ssession: %s\n", 06807 ast_test_flag(&p->flags[1], SIP_PAGE2_VIDEOSUPPORT) ? "and video " : "", 06808 ast_test_flag(&p->flags[1], SIP_PAGE2_TEXTSUPPORT) ? "and text " : "", strerror(errno)); 06809 if (p->chanvars) { 06810 ast_variables_destroy(p->chanvars); 06811 p->chanvars = NULL; 06812 } 06813 ao2_t_ref(p, -1, "failed to create RTP audio session, drop p"); 06814 return NULL; 06815 p->t38_maxdatagram = global_t38_maxdatagram; 06816 } 06817 ast_rtp_setqos(p->rtp, global_tos_audio, global_cos_audio, "SIP RTP"); 06818 ast_rtp_setdtmf(p->rtp, ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833); 06819 ast_rtp_setdtmfcompensate(p->rtp, ast_test_flag(&p->flags[1], SIP_PAGE2_RFC2833_COMPENSATE)); 06820 ast_rtp_set_rtptimeout(p->rtp, global_rtptimeout); 06821 ast_rtp_set_rtpholdtimeout(p->rtp, global_rtpholdtimeout); 06822 ast_rtp_set_rtpkeepalive(p->rtp, global_rtpkeepalive); 06823 if (p->vrtp) { 06824 ast_rtp_setqos(p->vrtp, global_tos_video, global_cos_video, "SIP VRTP"); 06825 ast_rtp_setdtmf(p->vrtp, 0); 06826 ast_rtp_setdtmfcompensate(p->vrtp, 0); 06827 ast_rtp_set_rtptimeout(p->vrtp, global_rtptimeout); 06828 ast_rtp_set_rtpholdtimeout(p->vrtp, global_rtpholdtimeout); 06829 ast_rtp_set_rtpkeepalive(p->vrtp, global_rtpkeepalive); 06830 } 06831 if (p->trtp) { 06832 ast_rtp_setqos(p->trtp, global_tos_text, global_cos_text, "SIP TRTP"); 06833 ast_rtp_setdtmf(p->trtp, 0); 06834 ast_rtp_setdtmfcompensate(p->trtp, 0); 06835 } 06836 if (p->udptl) 06837 ast_udptl_setqos(p->udptl, global_tos_audio, global_cos_audio); 06838 p->maxcallbitrate = default_maxcallbitrate; 06839 p->autoframing = global_autoframing; 06840 ast_rtp_codec_setpref(p->rtp, &p->prefs); 06841 } 06842 06843 if (useglobal_nat && sin) { 06844 /* Setup NAT structure according to global settings if we have an address */ 06845 ast_copy_flags(&p->flags[0], &global_flags[0], SIP_NAT); 06846 p->recv = *sin; 06847 do_setnat(p, ast_test_flag(&p->flags[0], SIP_NAT) & SIP_NAT_ROUTE); 06848 } 06849 06850 if (p->method != SIP_REGISTER) 06851 ast_string_field_set(p, fromdomain, default_fromdomain); 06852 build_via(p); 06853 if (!callid) 06854 build_callid_pvt(p); 06855 else 06856 ast_string_field_set(p, callid, callid); 06857 /* Assign default music on hold class */ 06858 ast_string_field_set(p, mohinterpret, default_mohinterpret); 06859 ast_string_field_set(p, mohsuggest, default_mohsuggest); 06860 p->capability = global_capability; 06861 p->allowtransfer = global_allowtransfer; 06862 if ((ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833) || 06863 (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO)) 06864 p->noncodeccapability |= AST_RTP_DTMF; 06865 if (p->udptl) { 06866 p->t38_maxdatagram = global_t38_maxdatagram; 06867 set_t38_capabilities(p); 06868 } 06869 ast_string_field_set(p, context, default_context); 06870 ast_string_field_set(p, parkinglot, default_parkinglot); 06871 06872 AST_LIST_HEAD_INIT_NOLOCK(&p->request_queue); 06873 06874 /* Add to active dialog list */ 06875 06876 ao2_t_link(dialogs, p, "link pvt into dialogs table"); 06877 06878 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"); 06879 return p; 06880 }
| 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 2905 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().
02906 { 02907 ast_debug(3, "Setting SIP_ALREADYGONE on dialog %s\n", dialog->callid); 02908 dialog->alreadygone = 1; 02909 }
| 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 5784 of file chan_sip.c.
References ast_channel::_state, ast_debug, ast_rtp_new_source(), ast_set_flag, ast_setstate(), AST_STATE_UP, FALSE, sip_pvt::flags, sip_pvt::initreq, sip_pvt::rtp, 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.
05785 { 05786 int res = 0; 05787 struct sip_pvt *p = ast->tech_pvt; 05788 05789 sip_pvt_lock(p); 05790 if (ast->_state != AST_STATE_UP) { 05791 try_suggested_sip_codec(p); 05792 05793 ast_setstate(ast, AST_STATE_UP); 05794 ast_debug(1, "SIP answering channel: %s\n", ast->name); 05795 ast_rtp_new_source(p->rtp); 05796 res = transmit_response_with_sdp(p, "200 OK", &p->initreq, XMIT_CRITICAL, FALSE); 05797 ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED); 05798 } 05799 sip_pvt_unlock(p); 05800 return res; 05801 }
| 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 4994 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(), 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, sip_pvt::noncodeccapability, sip_pvt::options, sip_pvt::prefcodec, sip_invite_param::replaces, 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.
04995 { 04996 int res; 04997 struct sip_pvt *p = ast->tech_pvt; /* chan is locked, so the reference cannot go away */ 04998 struct varshead *headp; 04999 struct ast_var_t *current; 05000 const char *referer = NULL; /* SIP referrer */ 05001 05002 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) { 05003 ast_log(LOG_WARNING, "sip_call called on %s, neither down nor reserved\n", ast->name); 05004 return -1; 05005 } 05006 05007 /* Check whether there is vxml_url, distinctive ring variables */ 05008 headp=&ast->varshead; 05009 AST_LIST_TRAVERSE(headp, current, entries) { 05010 /* Check whether there is a VXML_URL variable */ 05011 if (!p->options->vxml_url && !strcasecmp(ast_var_name(current), "VXML_URL")) { 05012 p->options->vxml_url = ast_var_value(current); 05013 } else if (!p->options->uri_options && !strcasecmp(ast_var_name(current), "SIP_URI_OPTIONS")) { 05014 p->options->uri_options = ast_var_value(current); 05015 } else if (!p->options->addsipheaders && !strncasecmp(ast_var_name(current), "SIPADDHEADER", strlen("SIPADDHEADER"))) { 05016 /* Check whether there is a variable with a name starting with SIPADDHEADER */ 05017 p->options->addsipheaders = 1; 05018 } else if (!strcasecmp(ast_var_name(current), "SIPTRANSFER")) { 05019 /* This is a transfered call */ 05020 p->options->transfer = 1; 05021 } else if (!strcasecmp(ast_var_name(current), "SIPTRANSFER_REFERER")) { 05022 /* This is the referrer */ 05023 referer = ast_var_value(current); 05024 } else if (!strcasecmp(ast_var_name(current), "SIPTRANSFER_REPLACES")) { 05025 /* We're replacing a call. */ 05026 p->options->replaces = ast_var_value(current); 05027 } 05028 } 05029 05030 res = 0; 05031 ast_set_flag(&p->flags[0], SIP_OUTGOING); 05032 05033 if (p->options->transfer) { 05034 char buf[SIPBUFSIZE/2]; 05035 05036 if (referer) { 05037 if (sipdebug) 05038 ast_debug(3, "Call for %s transfered by %s\n", p->username, referer); 05039 snprintf(buf, sizeof(buf)-1, "-> %s (via %s)", p->cid_name, referer); 05040 } else 05041 snprintf(buf, sizeof(buf)-1, "-> %s", p->cid_name); 05042 ast_string_field_set(p, cid_name, buf); 05043 } 05044 ast_debug(1, "Outgoing Call for %s\n", p->username); 05045 05046 res = update_call_counter(p, INC_CALL_RINGING); 05047 05048 if (res == -1) { 05049 ast->hangupcause = AST_CAUSE_USER_BUSY; 05050 return res; 05051 } 05052 p->callingpres = ast->cid.cid_pres; 05053 p->jointcapability = ast_translate_available_formats(p->capability, p->prefcodec); 05054 p->jointnoncodeccapability = p->noncodeccapability; 05055 05056 /* If there are no audio formats left to offer, punt */ 05057 if (!(p->jointcapability & AST_FORMAT_AUDIO_MASK)) { 05058 ast_log(LOG_WARNING, "No audio format found to offer. Cancelling call to %s\n", p->username); 05059 res = -1; 05060 } else { 05061 int xmitres; 05062 05063 xmitres = transmit_invite(p, SIP_INVITE, 1, 2); 05064 if (xmitres == XMIT_ERROR) 05065 return -1; 05066 p->invitestate = INV_CALLING; 05067 05068 /* Initialize auto-congest time */ 05069 AST_SCHED_REPLACE_UNREF(p->initid, sched, p->timer_b, auto_congest, p, 05070 dialog_unref(_data, "dialog ptr dec when SCHED_REPLACE del op succeeded"), 05071 dialog_unref(p, "dialog ptr dec when SCHED_REPLACE add failed"), 05072 dialog_ref(p, "dialog ptr inc when SCHED_REPLACE add succeeded") ); 05073 } 05074 return res; 05075 }
| 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 3632 of file chan_sip.c.
References append_history, ast_sched_del(), sip_pvt::autokillid, and dialog_unref().
Referenced by cb_extensionstate(), handle_request_invite(), handle_request_subscribe(), handle_response(), handle_response_invite(), register_verify(), sip_hangup(), and sip_scheddestroy().
03633 { 03634 int res = 0; 03635 if (p->autokillid > -1) { 03636 int res3; 03637 03638 if (!(res3 = ast_sched_del(sched, p->autokillid))) { 03639 append_history(p, "CancelDestroy", ""); 03640 p->autokillid = -1; 03641 dialog_unref(p, "dialog unrefd because autokillid is de-sched'd"); 03642 } 03643 } 03644 return res; 03645 }
| 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 16053 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, CLI_SUCCESS, 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, 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.
16054 { 16055 struct ast_variable *varlist; 16056 int i; 16057 16058 switch (cmd) { 16059 case CLI_INIT: 16060 e->command = "sip notify"; 16061 e->usage = 16062 "Usage: sip notify <type> <peer> [<peer>...]\n" 16063 " Send a NOTIFY message to a SIP peer or peers\n" 16064 " Message types are defined in sip_notify.conf\n"; 16065 return NULL; 16066 case CLI_GENERATE: 16067 return complete_sipnotify(a->line, a->word, a->pos, a->n); 16068 } 16069 16070 if (a->argc < 4) 16071 return CLI_SHOWUSAGE; 16072 16073 if (!notify_types) { 16074 ast_cli(a->fd, "No %s file found, or no types listed there\n", notify_config); 16075 return CLI_FAILURE; 16076 } 16077 16078 varlist = ast_variable_browse(notify_types, a->argv[2]); 16079 16080 if (!varlist) { 16081 ast_cli(a->fd, "Unable to find notify type '%s'\n", a->argv[2]); 16082 return CLI_FAILURE; 16083 } 16084 16085 for (i = 3; i < a->argc; i++) { 16086 struct sip_pvt *p; 16087 16088 if (!(p = sip_alloc(NULL, NULL, 0, SIP_NOTIFY, NULL))) { 16089 ast_log(LOG_WARNING, "Unable to build sip pvt data for notify (memory/socket error)\n"); 16090 return CLI_FAILURE; 16091 } 16092 16093 if (create_addr(p, a->argv[i], NULL, 1)) { 16094 /* Maybe they're not registered, etc. */ 16095 dialog_unlink_all(p, TRUE, TRUE); 16096 dialog_unref(p, "unref dialog inside for loop" ); 16097 /* sip_destroy(p); */ 16098 ast_cli(a->fd, "Could not create address for '%s'\n", a->argv[i]); 16099 continue; 16100 } 16101 16102 /* Notify is outgoing call */ 16103 ast_set_flag(&p->flags[0], SIP_OUTGOING); 16104 16105 /* Recalculate our side, and recalculate Call ID */ 16106 ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip, p); 16107 build_via(p); 16108 ao2_t_unlink(dialogs, p, "About to change the callid -- remove the old name"); 16109 build_callid_pvt(p); 16110 ao2_t_link(dialogs, p, "Linking in new name"); 16111 ast_cli(a->fd, "Sending NOTIFY of type '%s' to '%s'\n", a->argv[2], a->argv[i]); 16112 dialog_ref(p, "bump the count of p, which transmit_sip_request will decrement."); 16113 sip_scheddestroy(p, SIP_TRANS_TIMEOUT); 16114 transmit_notify_custom(p, varlist); 16115 } 16116 16117 return CLI_SUCCESS; 16118 }
| static int sip_debug_test_addr | ( | const struct sockaddr_in * | addr | ) | [inline, static] |
See if we pass debug IP filter.
Definition at line 3063 of file chan_sip.c.
References debugaddr.
Referenced by check_peer_ok(), handle_request_do(), and sip_debug_test_pvt().
| static int sip_debug_test_pvt | ( | struct sip_pvt * | p | ) | [inline, static] |
Test PVT for debugging output.
Definition at line 3092 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().
03093 { 03094 if (!sipdebug) 03095 return 0; 03096 return sip_debug_test_addr(sip_real_dst(p)); 03097 }
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 5387 of file chan_sip.c.
References __sip_destroy(), ast_debug, sip_pvt::callid, and TRUE.
Referenced by sip_destroy_fn().
05388 { 05389 ast_debug(3, "Destroying SIP dialog %s\n", p->callid); 05390 __sip_destroy(p, TRUE, TRUE); 05391 return NULL; 05392 }
| static void sip_destroy_fn | ( | void * | p | ) | [static] |
Definition at line 5377 of file chan_sip.c.
References sip_destroy().
Referenced by sip_alloc().
05378 { 05379 sip_destroy(p); 05380 }
| static void sip_destroy_peer | ( | struct sip_peer * | peer | ) | [static] |
Destroy peer object from memory.
Definition at line 4263 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().
04264 { 04265 ast_debug(3, "Destroying SIP peer %s\n", peer->name); 04266 if (peer->outboundproxy) 04267 ao2_ref(peer->outboundproxy, -1); 04268 peer->outboundproxy = NULL; 04269 04270 /* Delete it, it needs to disappear */ 04271 if (peer->call) { 04272 dialog_unlink_all(peer->call, TRUE, TRUE); 04273 peer->call = dialog_unref(peer->call, "peer->call is being unset"); 04274 } 04275 04276 04277 if (peer->mwipvt) { /* We have an active subscription, delete it */ 04278 dialog_unlink_all(peer->mwipvt, TRUE, TRUE); 04279 peer->mwipvt = dialog_unref(peer->mwipvt, "unreffing peer->mwipvt"); 04280 } 04281 04282 if (peer->chanvars) { 04283 ast_variables_destroy(peer->chanvars); 04284 peer->chanvars = NULL; 04285 } 04286 04287 register_peer_exten(peer, FALSE); 04288 ast_free_ha(peer->ha); 04289 if (peer->selfdestruct) 04290 ast_atomic_fetchadd_int(&apeerobjs, -1); 04291 else if (peer->is_realtime) { 04292 ast_atomic_fetchadd_int(&rpeerobjs, -1); 04293 ast_debug(3, "-REALTIME- peer Destroyed. Name: %s. Realtime Peer objects: %d\n", peer->name, rpeerobjs); 04294 } else 04295 ast_atomic_fetchadd_int(&speerobjs, -1); 04296 clear_realm_authentication(peer->auth); 04297 peer->auth = NULL; 04298 if (peer->dnsmgr) 04299 ast_dnsmgr_release(peer->dnsmgr); 04300 clear_peer_mailboxes(peer); 04301 04302 if (peer->socket.tcptls_session) { 04303 ao2_ref(peer->socket.tcptls_session, -1); 04304 peer->socket.tcptls_session = NULL; 04305 } 04306 }
| static void sip_destroy_peer_fn | ( | void * | peer | ) | [static] |
Definition at line 4257 of file chan_sip.c.
References sip_destroy_peer().
Referenced by build_peer(), and temp_peer().
04258 { 04259 sip_destroy_peer(peer); 04260 }
| static int sip_devicestate | ( | void * | data | ) | [static] |
Part of PBX channel interface.
If we have qualify on and the device is not reachable, regardless of registration state we return AST_DEVICE_UNAVAILABLE
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 22042 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().
22043 { 22044 char *host; 22045 char *tmp; 22046 struct sip_peer *p; 22047 22048 int res = AST_DEVICE_INVALID; 22049 22050 /* make sure data is not null. Maybe unnecessary, but better be safe */ 22051 host = ast_strdupa(data ? data : ""); 22052 if ((tmp = strchr(host, '@'))) 22053 host = tmp + 1; 22054 22055 ast_debug(3, "Checking device state for peer %s\n", host); 22056 22057 /* If find_peer asks for a realtime peer, then this breaks rtautoclear. This 22058 * is because when a peer tries to autoexpire, the last thing it does is to 22059 * queue up an event telling the system that the devicestate has changed 22060 * (presumably to unavailable). If we ask for a realtime peer here, this would 22061 * load it BACK into memory, thus defeating the point of trying to clear dead 22062 * hosts out of memory. 22063 */ 22064 if ((p = find_peer(host, NULL, FALSE, FINDALLDEVICES, TRUE, 0))) { 22065 if (p->addr.sin_addr.s_addr || p->defaddr.sin_addr.s_addr) { 22066 /* we have an address for the peer */ 22067 22068 /* Check status in this order 22069 - Hold 22070 - Ringing 22071 - Busy (enforced only by call limit) 22072 - Inuse (we have a call) 22073 - Unreachable (qualify) 22074 If we don't find any of these state, report AST_DEVICE_NOT_INUSE 22075 for registered devices */ 22076 22077 if (p->onHold) 22078 /* First check for hold or ring states */ 22079 res = AST_DEVICE_ONHOLD; 22080 else if (p->inRinging) { 22081 if (p->inRinging == p->inUse) 22082 res = AST_DEVICE_RINGING; 22083 else 22084 res = AST_DEVICE_RINGINUSE; 22085 } else if (p->call_limit && (p->inUse == p->call_limit)) 22086 /* check call limit */ 22087 res = AST_DEVICE_BUSY; 22088 else if (p->call_limit && p->busy_level && p->inUse >= p->busy_level) 22089 /* We're forcing busy before we've reached the call limit */ 22090 res = AST_DEVICE_BUSY; 22091 else if (p->call_limit && p->inUse) 22092 /* Not busy, but we do have a call */ 22093 res = AST_DEVICE_INUSE; 22094 else if (p->maxms && ((p->lastms > p->maxms) || (p->lastms < 0))) 22095 /* We don't have a call. Are we reachable at all? Requires qualify= */ 22096 res = AST_DEVICE_UNAVAILABLE; 22097 else /* Default reply if we're registered and have no other data */ 22098 res = AST_DEVICE_NOT_INUSE; 22099 } else { 22100 /* there is no address, it's unavailable */ 22101 res = AST_DEVICE_UNAVAILABLE; 22102 } 22103 unref_peer(p, "unref_peer, from sip_devicestate, release ref from find_peer"); 22104 } else { 22105 res = AST_DEVICE_UNKNOWN; 22106 } 22107 22108 return res; 22109 }
| 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 16010 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(), debugaddr, 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.
16011 { 16012 int oldsipdebug = sipdebug & sip_debug_console; 16013 char *what; 16014 16015 if (cmd == CLI_INIT) { 16016 e->command = "sip set debug {on|off|ip|peer}"; 16017 e->usage = 16018 "Usage: sip set debug {off|on|ip addr[:port]|peer peername}\n" 16019 " Globally disables dumping of SIP packets,\n" 16020 " or enables it either globally or for a (single)\n" 16021 " IP address or registered peer.\n"; 16022 return NULL; 16023 } else if (cmd == CLI_GENERATE) { 16024 if (a->pos == 4 && strcasestr(a->line, " peer")) /* XXX should check on argv too */ 16025 return complete_sip_peer(a->word, a->n, 0); 16026 return NULL; 16027 } 16028 16029 what = a->argv[e->args-1]; /* guaranteed to exist */ 16030 if (a->argc == e->args) { /* on/off */ 16031 if (!strcasecmp(what, "on")) { 16032 sipdebug |= sip_debug_console; 16033 sipdebug_text = 1; /*! \note this can be a special debug command - "sip debug text" or something */ 16034 memset(&debugaddr, 0, sizeof(debugaddr)); 16035 ast_cli(a->fd, "SIP Debugging %senabled\n", oldsipdebug ? "re-" : ""); 16036 return CLI_SUCCESS; 16037 } else if (!strcasecmp(what, "off")) { 16038 sipdebug &= ~sip_debug_console; 16039 sipdebug_text = 0; 16040 ast_cli(a->fd, "SIP Debugging Disabled\n"); 16041 return CLI_SUCCESS; 16042 } 16043 } else if (a->argc == e->args +1) {/* ip/peer */ 16044 if (!strcasecmp(what, "ip")) 16045 return sip_do_debug_ip(a->fd, a->argv[e->args]); 16046 else if (!strcasecmp(what, "peer")) 16047 return sip_do_debug_peer(a->fd, a->argv[e->args]); 16048 } 16049 return CLI_SHOWUSAGE; /* default, failure */ 16050 }
| static char * sip_do_debug_ip | ( | int | fd, | |
| char * | arg | |||
| ) | [static] |
Enable SIP Debugging for a single IP.
Definition at line 15960 of file chan_sip.c.
References ast_cli(), ast_gethostbyname(), ast_inet_ntoa(), CLI_SHOWUSAGE, CLI_SUCCESS, debugaddr, hp, sip_debug_console, and strsep().
Referenced by sip_do_debug().
15961 { 15962 struct hostent *hp; 15963 struct ast_hostent ahp; 15964 int port = 0; 15965 char *p; 15966 15967 p = arg; 15968 strsep(&p, ":"); 15969 if (p) 15970 port = atoi(p); 15971 hp = ast_gethostbyname(arg, &ahp); 15972 if (hp == NULL) 15973 return CLI_SHOWUSAGE; 15974 15975 debugaddr.sin_family = AF_INET; 15976 memcpy(&debugaddr.sin_addr, hp->h_addr, sizeof(debugaddr.sin_addr)); 15977 debugaddr.sin_port = htons(port); 15978 if (port == 0) 15979 ast_cli(fd, "SIP Debugging Enabled for IP: %s\n", ast_inet_ntoa(debugaddr.sin_addr)); 15980 else 15981 ast_cli(fd, "SIP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(debugaddr.sin_addr), port); 15982 15983 sipdebug |= sip_debug_console; 15984 15985 return CLI_SUCCESS; 15986 }
| static char * sip_do_debug_peer | ( | int | fd, | |
| char * | arg | |||
| ) | [static] |
Turn on SIP debugging for a given peer.
Definition at line 15989 of file chan_sip.c.
References sip_peer::addr, ast_cli(), ast_inet_ntoa(), CLI_SUCCESS, debugaddr, FALSE, find_peer(), FINDPEERS, sip_debug_console, TRUE, and unref_peer().
Referenced by sip_do_debug().
15990 { 15991 struct sip_peer *peer = find_peer(arg, NULL, TRUE, FINDPEERS, FALSE, 0); 15992 if (!peer) 15993 ast_cli(fd, "No such peer '%s'\n", arg); 15994 else if (peer->addr.sin_addr.s_addr == 0) 15995 ast_cli(fd, "Unable to get IP address of peer '%s'\n", arg); 15996 else { 15997 debugaddr.sin_family = AF_INET; 15998 debugaddr.sin_addr = peer->addr.sin_addr; 15999 debugaddr.sin_port = peer->addr.sin_port; 16000 ast_cli(fd, "SIP Debugging Enabled for IP: %s:%d\n", 16001 ast_inet_ntoa(debugaddr.sin_addr), ntohs(debugaddr.sin_port)); 16002 sipdebug |= sip_debug_console; 16003 } 16004 if (peer) 16005 unref_peer(peer, "sip_do_debug_peer: unref_peer, from find_peer call"); 16006 return CLI_SUCCESS; 16007 }
| 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 16121 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.
16122 { 16123 switch (cmd) { 16124 case CLI_INIT: 16125 e->command = "sip history [off]"; 16126 e->usage = 16127 "Usage: sip history [off]\n" 16128 " Enables/Disables recording of SIP dialog history for debugging purposes.\n" 16129 " Use 'sip show history' to view the history of a call number.\n"; 16130 return NULL; 16131 case CLI_GENERATE: 16132 return NULL; 16133 } 16134 16135 if (a->argc < 2 || a->argc > 3) { 16136 return CLI_SHOWUSAGE; 16137 } 16138 if (a->argc == 2) { 16139 recordhistory = TRUE; 16140 ast_cli(a->fd, "SIP History Recording Enabled (use 'sip show history')\n"); 16141 } else { 16142 if (strncasecmp(a->argv[2], "off", 3)) 16143 return CLI_SHOWUSAGE; 16144 recordhistory = FALSE; 16145 ast_cli(a->fd, "SIP History Recording Disabled\n"); 16146 } 16147 return CLI_SUCCESS; 16148 }
| static int sip_do_reload | ( | enum channelreloadreason | reason | ) | [static] |
Reload module.
Definition at line 24561 of file chan_sip.c.
References ao2_t_callback, ast_debug, ast_sched_dump(), OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, peer_is_marked(), reload_config(), sip_poke_all_peers(), and sip_send_all_registers().
Referenced by do_monitor().
24562 { 24563 time_t start_poke, end_poke; 24564 24565 reload_config(reason); 24566 ast_sched_dump(sched); 24567 24568 start_poke = time(0); 24569 /* Prune peers who still are supposed to be deleted */ 24570 ao2_t_callback(peers, OBJ_NODATA | OBJ_UNLINK | OBJ_MULTIPLE, peer_is_marked, 0, 24571 "callback to remove marked peers"); 24572 24573 ast_debug(4, "--------------- Done destroying pruned peers\n"); 24574 24575 /* Send qualify (OPTIONS) to all peers */ 24576 sip_poke_all_peers(); 24577 24578 /* Register with all services */ 24579 sip_send_all_registers(); 24580 end_poke = time(0); 24581 24582 ast_debug(4, "do_reload finished. peer poke/prune reg contact time = %d sec.\n", (int)(end_poke-start_poke)); 24583 24584 ast_debug(4, "--------------- SIP reload done\n"); 24585 24586 return 0; 24587 }
| static int sip_dtmfmode | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Set the DTMFmode for an outbound SIP call (application).
Definition at line 24347 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, 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().
24348 { 24349 struct sip_pvt *p; 24350 char *mode = data; 24351 24352 if (!data) { 24353 ast_log(LOG_WARNING, "This application requires the argument: info, inband, rfc2833\n"); 24354 return 0; 24355 } 24356 ast_channel_lock(chan); 24357 if (!IS_SIP_TECH(chan->tech)) { 24358 ast_log(LOG_WARNING, "Call this application only on SIP incoming calls\n"); 24359 ast_channel_unlock(chan); 24360 return 0; 24361 } 24362 p = chan->tech_pvt; 24363 if (!p) { 24364 ast_channel_unlock(chan); 24365 return 0; 24366 } 24367 sip_pvt_lock(p); 24368 if (!strcasecmp(mode, "info")) { 24369 ast_clear_flag(&p->flags[0], SIP_DTMF); 24370 ast_set_flag(&p->flags[0], SIP_DTMF_INFO); 24371 p->jointnoncodeccapability &= ~AST_RTP_DTMF; 24372 } else if (!strcasecmp(mode, "shortinfo")) { 24373 ast_clear_flag(&p->flags[0], SIP_DTMF); 24374 ast_set_flag(&p->flags[0], SIP_DTMF_SHORTINFO); 24375 p->jointnoncodeccapability &= ~AST_RTP_DTMF; 24376 } else if (!strcasecmp(mode, "rfc2833")) { 24377 ast_clear_flag(&p->flags[0], SIP_DTMF); 24378 ast_set_flag(&p->flags[0], SIP_DTMF_RFC2833); 24379 p->jointnoncodeccapability |= AST_RTP_DTMF; 24380 } else if (!strcasecmp(mode, "inband")) { 24381 ast_clear_flag(&p->flags[0], SIP_DTMF); 24382 ast_set_flag(&p->flags[0], SIP_DTMF_INBAND); 24383 p->jointnoncodeccapability &= ~AST_RTP_DTMF; 24384 } else 24385 ast_log(LOG_WARNING, "I don't know about this dtmf mode: %s\n", mode); 24386 if (p->rtp) 24387 ast_rtp_setdtmf(p->rtp, ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833); 24388 if (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_INBAND) { 24389 if (!p->dsp) { 24390 p->dsp = ast_dsp_new(); 24391 ast_dsp_set_features(p->dsp, DSP_FEATURE_DIGIT_DETECT); 24392 } 24393 } else { 24394 if (p->dsp) { 24395 ast_dsp_free(p->dsp); 24396 p->dsp = NULL; 24397 } 24398 } 24399 sip_pvt_unlock(p); 24400 ast_channel_unlock(chan); 24401 return 0; 24402 }
| 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 15745 of file chan_sip.c.
References ast_debug, AST_LIST_TRAVERSE, ast_log(), sip_pvt::callid, sip_history::event, sip_pvt::history, LOG_NOTICE, option_debug, and sip_pvt::subscribed.
Referenced by __sip_destroy().
15746 { 15747 int x = 0; 15748 struct sip_history *hist; 15749 static int errmsg = 0; 15750 15751 if (!dialog) 15752 return; 15753 15754 if (!option_debug && !sipdebug) { 15755 if (!errmsg) { 15756 ast_log(LOG_NOTICE, "You must have debugging enabled (SIP or Asterisk) in order to dump SIP history.\n"); 15757 errmsg = 1; 15758 } 15759 return; 15760 } 15761 15762 ast_debug(1, "\n---------- SIP HISTORY for '%s' \n", dialog->callid); 15763 if (dialog->subscribed) 15764 ast_debug(1, " * Subscription\n"); 15765 else 15766 ast_debug(1, " * SIP Call\n"); 15767 if (dialog->history) 15768 AST_LIST_TRAVERSE(dialog->history, hist, list) 15769 ast_debug(1, " %-3.3d. %s\n", ++x, hist->event); 15770 if (!x) 15771 ast_debug(1, "Call '%s' has no history\n", dialog->callid); 15772 ast_debug(1, "\n---------- END SIP HISTORY for '%s' \n", dialog->callid); 15773 }
| 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 5914 of file chan_sip.c.
References append_history, ast_debug, AST_FLAG_ZOMBIE, ast_log(), ast_test_flag, sip_pvt::callid, LOG_WARNING, sip_pvt::owner, sip_pvt_lock, sip_pvt_unlock, sip_set_rtp_peer(), and ast_channel::tech_pvt.
05915 { 05916 int ret = -1; 05917 struct sip_pvt *p; 05918 05919 if (newchan && ast_test_flag(newchan, AST_FLAG_ZOMBIE)) 05920 ast_debug(1, "New channel is zombie\n"); 05921 if (oldchan && ast_test_flag(oldchan, AST_FLAG_ZOMBIE)) 05922 ast_debug(1, "Old channel is zombie\n"); 05923 05924 if (!newchan || !newchan->tech_pvt) { 05925 if (!newchan) 05926 ast_log(LOG_WARNING, "No new channel! Fixup of %s failed.\n", oldchan->name); 05927 else 05928 ast_log(LOG_WARNING, "No SIP tech_pvt! Fixup of %s failed.\n", oldchan->name); 05929 return -1; 05930 } 05931 p = newchan->tech_pvt; 05932 05933 sip_pvt_lock(p); 05934 append_history(p, "Masq", "Old channel: %s\n", oldchan->name); 05935 append_history(p, "Masq (cont)", "...new owner: %s\n", newchan->name); 05936 if (p->owner != oldchan) 05937 ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, p->owner); 05938 else { 05939 p->owner = newchan; 05940 /* Re-invite RTP back to Asterisk. Needed if channel is masqueraded out of a native 05941 RTP bridge (i.e., RTP not going through Asterisk): RTP bridge code might not be 05942 able to do this if the masquerade happens before the bridge breaks (e.g., AMI 05943 redirect of both channels). Note that a channel can not be masqueraded *into* 05944 a native bridge. So there is no danger that this breaks a native bridge that 05945 should stay up. */ 05946 sip_set_rtp_peer(newchan, NULL, NULL, 0, 0, 0); 05947 ret = 0; 05948 } 05949 ast_debug(3, "SIP Fixup: New owner for dialogue %s: %s (Old parent: %s)\n", p->callid, p->owner->name, oldchan->name); 05950 05951 sip_pvt_unlock(p); 05952 return ret; 05953 }
| static const char * sip_get_callid | ( | struct ast_channel * | chan | ) | [static] |
Deliver SIP call ID for the call.
Definition at line 4124 of file chan_sip.c.
References 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 24504 of file chan_sip.c.
References sip_pvt::capability, sip_pvt::jointcapability, and ast_channel::tech_pvt.
24505 { 24506 struct sip_pvt *p = chan->tech_pvt; 24507 return p->jointcapability ? p->jointcapability : p->capability; 24508 }
| 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 24181 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, 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.
24182 { 24183 struct sip_pvt *p = NULL; 24184 enum ast_rtp_get_result res = AST_RTP_TRY_PARTIAL; 24185 24186 if (!(p = chan->tech_pvt)) 24187 return AST_RTP_GET_FAILED; 24188 24189 sip_pvt_lock(p); 24190 if (!(p->rtp)) { 24191 sip_pvt_unlock(p); 24192 return AST_RTP_GET_FAILED; 24193 } 24194 24195 *rtp = p->rtp; 24196 24197 if (ast_rtp_getnat(*rtp) && !ast_test_flag(&p->flags[0], SIP_CAN_REINVITE_NAT)) 24198 res = AST_RTP_TRY_PARTIAL; 24199 else if (ast_test_flag(&p->flags[0], SIP_CAN_REINVITE)) 24200 res = AST_RTP_TRY_NATIVE; 24201 else if (ast_test_flag(&global_jbconf, AST_JB_FORCED)) 24202 res = AST_RTP_GET_FAILED; 24203 24204 sip_pvt_unlock(p); 24205 24206 return res; 24207 }
| 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 24235 of file chan_sip.c.
References AST_RTP_GET_FAILED, AST_RTP_TRY_NATIVE, AST_RTP_TRY_PARTIAL, ast_test_flag, sip_pvt::flags, SIP_CAN_REINVITE, sip_pvt_lock, sip_pvt_unlock, ast_channel::tech_pvt, and sip_pvt::trtp.
24236 { 24237 struct sip_pvt *p = NULL; 24238 enum ast_rtp_get_result res = AST_RTP_TRY_PARTIAL; 24239 24240 if (!(p = chan->tech_pvt)) 24241 return AST_RTP_GET_FAILED; 24242 24243 sip_pvt_lock(p); 24244 if (!(p->trtp)) { 24245 sip_pvt_unlock(p); 24246 return AST_RTP_GET_FAILED; 24247 } 24248 24249 *rtp = p->trtp; 24250 24251 if (ast_test_flag(&p->flags[0], SIP_CAN_REINVITE)) 24252 res = AST_RTP_TRY_NATIVE; 24253 24254 sip_pvt_unlock(p); 24255 24256 return res; 24257 }
| static struct ast_udptl * sip_get_udptl_peer | ( | struct ast_channel * | chan | ) | [static, read] |
Definition at line 24137 of file chan_sip.c.
References ast_test_flag, sip_pvt::flags, SIP_CAN_REINVITE, sip_pvt_lock, sip_pvt_unlock, ast_channel::tech_pvt, and sip_pvt::udptl.
24138 { 24139 struct sip_pvt *p; 24140 struct ast_udptl *udptl = NULL; 24141 24142 p = chan->tech_pvt; 24143 if (!p) 24144 return NULL; 24145 24146 sip_pvt_lock(p); 24147 if (p->udptl && ast_test_flag(&p->flags[0], SIP_CAN_REINVITE)) 24148 udptl = p->udptl; 24149 sip_pvt_unlock(p); 24150 return udptl; 24151 }
| 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 24210 of file chan_sip.c.
References AST_RTP_GET_FAILED, AST_RTP_TRY_NATIVE, AST_RTP_TRY_PARTIAL, ast_test_flag, sip_pvt::flags, SIP_CAN_REINVITE, sip_pvt_lock, sip_pvt_unlock, ast_channel::tech_pvt, and sip_pvt::vrtp.
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->vrtp)) { 24220 sip_pvt_unlock(p); 24221 return AST_RTP_GET_FAILED; 24222 } 24223 24224 *rtp = p->vrtp; 24225 24226 if (ast_test_flag(&p->flags[0], SIP_CAN_REINVITE)) 24227 res = AST_RTP_TRY_NATIVE; 24228 24229 sip_pvt_unlock(p); 24230 24231 return res; 24232 }
| 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 5557 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, 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, sip_request::data, DEC_CALL_LIMIT, DEFAULT_TRANS_TIMEOUT, dialog_unref(), sip_pvt::do_history, sip_pvt::dsp, FALSE, find_sip_method(), sip_pvt::flags, hangup_cause2sip(), ast_channel::hangupcause, sip_pvt::hangupcause, sip_pvt::initreq, INV_CALLING, INV_CANCELLED, INV_COMPLETED, INV_TERMINATED, sip_pvt::invitestate, sip_pkt::is_resp, IS_SIP_TECH, sip_pvt::lastinvite, LOG_WARNING, sip_pkt::method, sip_pvt::needdestroy, sip_pkt::next, sip_pvt::owner, sip_pvt::packets, pbx_builtin_setvar_helper(), sip_pvt::pendinginvite, sip_pvt::provisional_keepalive_sched_id, sip_pvt::refer, sip_pvt::rtp, RTPQOS_SUMMARY, 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(), sip_st_dlg::st_active, sip_pvt::stimer, 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(), sip_pvt::trtp, TRUE, update_call_counter(), sip_pvt::username, sip_pvt::vrtp, sip_pvt::waitid, and XMIT_RELIABLE.
05558 { 05559 struct sip_pvt *p = ast->tech_pvt; 05560 int needcancel = FALSE; 05561 int needdestroy = 0; 05562 struct ast_channel *oldowner = ast; 05563 05564 if (!p) { 05565 ast_debug(1, "Asked to hangup channel that was not connected\n"); 05566 return 0; 05567 } 05568 if (ast_test_flag(ast, AST_FLAG_ANSWERED_ELSEWHERE)) { 05569 ast_debug(1, "This call was answered elsewhere"); 05570 append_history(p, "Cancel", "Call answered elsewhere"); 05571 p->answered_elsewhere = TRUE; 05572 } 05573 05574 /* Store hangupcause locally in PVT so we still have it before disconnect */ 05575 if (p->owner) 05576 p->hangupcause = p->owner->hangupcause; 05577 05578 if (ast_test_flag(&p->flags[0], SIP_DEFER_BYE_ON_TRANSFER)) { 05579 if (ast_test_flag(&p->flags[0], SIP_INC_COUNT) || ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD)) { 05580 if (sipdebug) 05581 ast_debug(1, "update_call_counter(%s) - decrement call limit counter on hangup\n", p->username); 05582 update_call_counter(p, DEC_CALL_LIMIT); 05583 } 05584 ast_debug(4, "SIP Transfer: Not hanging up right now... Rescheduling hangup for %s.\n", p->callid); 05585 if (p->autokillid > -1 && sip_cancel_destroy(p)) 05586 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 05587 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 05588 ast_clear_flag(&p->flags[0], SIP_DEFER_BYE_ON_TRANSFER); /* Really hang up next time */ 05589 p->needdestroy = 0; 05590 p->owner->tech_pvt = dialog_unref(p->owner->tech_pvt, "unref p->owner->tech_pvt"); 05591 sip_pvt_lock(p); 05592 p->owner = NULL; /* Owner will be gone after we return, so take it away */ 05593 sip_pvt_unlock(p); 05594 return 0; 05595 } 05596 05597 if (ast_test_flag(ast, AST_FLAG_ZOMBIE)) { 05598 if (p->refer) 05599 ast_debug(1, "SIP Transfer: Hanging up Zombie channel %s after transfer ... Call-ID: %s\n", ast->name, p->callid); 05600 else 05601 ast_debug(1, "Hanging up zombie call. Be scared.\n"); 05602 } else 05603 ast_debug(1, "Hangup call %s, SIP callid %s\n", ast->name, p->callid); 05604 05605 sip_pvt_lock(p); 05606 if (ast_test_flag(&p->flags[0], SIP_INC_COUNT) || ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD)) { 05607 if (sipdebug) 05608 ast_debug(1, "update_call_counter(%s) - decrement call limit counter on hangup\n", p->username); 05609 update_call_counter(p, DEC_CALL_LIMIT); 05610 } 05611 05612 /* Determine how to disconnect */ 05613 if (p->owner != ast) { 05614 ast_log(LOG_WARNING, "Huh? We aren't the owner? Can't hangup call.\n"); 05615 sip_pvt_unlock(p); 05616 return 0; 05617 } 05618 /* If the call is not UP, we need to send CANCEL instead of BYE */ 05619 /* In case of re-invites, the call might be UP even though we have an incomplete invite transaction */ 05620 if (p->invitestate < INV_COMPLETED && p->owner->_state != AST_STATE_UP) { 05621 needcancel = TRUE; 05622 ast_debug(4, "Hanging up channel in state %s (not UP)\n", ast_state2str(ast->_state)); 05623 } 05624 05625 stop_media_flows(p); /* Immediately stop RTP, VRTP and UDPTL as applicable */ 05626 05627 append_history(p, needcancel ? "Cancel" : "Hangup", "Cause %s", p->owner ? ast_cause2str(p->hangupcause) : "Unknown"); 05628 05629 /* Disconnect */ 05630 if (p->dsp) 05631 ast_dsp_free(p->dsp); 05632 05633 p->owner = NULL; 05634 ast->tech_pvt = dialog_unref(ast->tech_pvt, "unref ast->tech_pvt"); 05635 05636 ast_module_unref(ast_module_info->self); 05637 /* Do not destroy this pvt until we have timeout or 05638 get an answer to the BYE or INVITE/CANCEL 05639 If we get no answer during retransmit period, drop the call anyway. 05640 (Sorry, mother-in-law, you can't deny a hangup by sending 05641 603 declined to BYE...) 05642 */ 05643 if (p->alreadygone) 05644 needdestroy = 1; /* Set destroy flag at end of this function */ 05645 else if (p->invitestate != INV_CALLING) 05646 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 05647 05648 /* Start the process if it's not already started */ 05649 if (!p->alreadygone && p->initreq.data && !ast_strlen_zero(p->initreq.data->str)) { 05650 if (needcancel) { /* Outgoing call, not up */ 05651 if (ast_test_flag(&p->flags[0], SIP_OUTGOING)) { 05652 /* stop retransmitting an INVITE that has not received a response */ 05653 /* if we can't send right now, mark it pending */ 05654 if (p->invitestate == INV_CALLING) { 05655 /* We can't send anything in CALLING state */ 05656 ast_set_flag(&p->flags[0], SIP_PENDINGBYE); 05657 __sip_pretend_ack(p); 05658 /* 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. */ 05659 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 05660 append_history(p, "DELAY", "Not sending cancel, waiting for timeout"); 05661 } else { 05662 struct sip_pkt *cur; 05663 05664 for (cur = p->packets; cur; cur = cur->next) { 05665 __sip_semi_ack(p, cur->seqno, cur->is_resp, cur->method ? cur->method : find_sip_method(cur->data->str)); 05666 } 05667 p->invitestate = INV_CANCELLED; 05668 /* Send a new request: CANCEL */ 05669 transmit_request(p, SIP_CANCEL, p->lastinvite, XMIT_RELIABLE, FALSE); 05670 /* Actually don't destroy us yet, wait for the 487 on our original 05671 INVITE, but do set an autodestruct just in case we never get it. */ 05672 needdestroy = 0; 05673 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 05674 } 05675 } else { /* Incoming call, not up */ 05676 const char *res; 05677 AST_SCHED_DEL(sched, p->provisional_keepalive_sched_id); 05678 if (p->hangupcause && (res = hangup_cause2sip(p->hangupcause))) 05679 transmit_response_reliable(p, res, &p->initreq); 05680 else 05681 transmit_response_reliable(p, "603 Declined", &p->initreq); 05682 p->invitestate = INV_TERMINATED; 05683 } 05684 } else { /* Call is in UP state, send BYE */ 05685 if (p->stimer->st_active == TRUE) { 05686 stop_session_timer(p); 05687 } 05688 05689 if (!p->pendinginvite) { 05690 struct ast_channel *bridge = ast_bridged_channel(oldowner); 05691 char *audioqos = ""; 05692 char *videoqos = ""; 05693 char *textqos = ""; 05694 05695 /* We need to get the lock on bridge because ast_rtp_set_vars will attempt 05696 * to lock the bridge. This may get hairy... 05697 */ 05698 while (bridge && ast_channel_trylock(bridge)) { 05699 sip_pvt_unlock(p); 05700 do { 05701 /* Use oldowner since p->owner is already NULL */ 05702 CHANNEL_DEADLOCK_AVOIDANCE(oldowner); 05703 } while (sip_pvt_trylock(p)); 05704 bridge = ast_bridged_channel(oldowner); 05705 } 05706 05707 if (p->rtp) 05708 ast_rtp_set_vars(oldowner, p->rtp); 05709 05710 if (bridge) { 05711 struct sip_pvt *q = bridge->tech_pvt; 05712 05713 if (IS_SIP_TECH(bridge->tech) && q && q->rtp) 05714 ast_rtp_set_vars(bridge, q->rtp); 05715 ast_channel_unlock(bridge); 05716 } 05717 05718 if (p->vrtp) 05719 videoqos = ast_rtp_get_quality(p->vrtp, NULL, RTPQOS_SUMMARY); 05720 if (p->trtp) 05721 textqos = ast_rtp_get_quality(p->trtp, NULL, RTPQOS_SUMMARY); 05722 /* Send a hangup */ 05723 if (oldowner->_state == AST_STATE_UP) { 05724 transmit_request_with_auth(p, SIP_BYE, 0, XMIT_RELIABLE, 1); 05725 } 05726 05727 /* Get RTCP quality before end of call */ 05728 if (p->do_history) { 05729 if (p->rtp) 05730 append_history(p, "RTCPaudio", "Quality:%s", audioqos); 05731 if (p->vrtp) 05732 append_history(p, "RTCPvideo", "Quality:%s", videoqos); 05733 if (p->trtp) 05734 append_history(p, "RTCPtext", "Quality:%s", textqos); 05735 } 05736 if (p->rtp && oldowner) 05737 pbx_builtin_setvar_helper(oldowner, "RTPAUDIOQOS", audioqos); 05738 if (p->vrtp && oldowner) 05739 pbx_builtin_setvar_helper(oldowner, "RTPVIDEOQOS", videoqos); 05740 if (p->trtp && oldowner) 05741 pbx_builtin_setvar_helper(oldowner, "RTPTEXTQOS", textqos); 05742 } else { 05743 /* Note we will need a BYE when this all settles out 05744 but we can't send one while we have "INVITE" outstanding. */ 05745 ast_set_flag(&p->flags[0], SIP_PENDINGBYE); 05746 ast_clear_flag(&p->flags[0], SIP_NEEDREINVITE); 05747 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")); 05748 if (sip_cancel_destroy(p)) 05749 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 05750 } 05751 } 05752 } 05753 if (needdestroy) 05754 p->needdestroy = 1; 05755 sip_pvt_unlock(p); 05756 return 0; 05757 }
| 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 6088 of file chan_sip.c.
References ast_channel::_state, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HOLD, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, AST_CONTROL_SRCUPDATE, AST_CONTROL_T38_PARAMETERS, AST_CONTROL_UNHOLD, AST_CONTROL_VIDUPDATE, ast_log(), ast_moh_start(), ast_moh_stop(), 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.
06089 { 06090 struct sip_pvt *p = ast->tech_pvt; 06091 int res = 0; 06092 06093 sip_pvt_lock(p); 06094 switch(condition) { 06095 case AST_CONTROL_RINGING: 06096 if (ast->_state == AST_STATE_RING) { 06097 p->invitestate = INV_EARLY_MEDIA; 06098 if (!ast_test_flag(&p->flags[0], SIP_PROGRESS_SENT) || 06099 (ast_test_flag(&p->flags[0], SIP_PROG_INBAND) == SIP_PROG_INBAND_NEVER)) { 06100 /* Send 180 ringing if out-of-band seems reasonable */ 06101 transmit_provisional_response(p, "180 Ringing", &p->initreq, 0); 06102 ast_set_flag(&p->flags[0], SIP_RINGING); 06103 if (ast_test_flag(&p->flags[0], SIP_PROG_INBAND) != SIP_PROG_INBAND_YES) 06104 break; 06105 } else { 06106 /* Well, if it's not reasonable, just send in-band */ 06107 } 06108 } 06109 res = -1; 06110 break; 06111 case AST_CONTROL_BUSY: 06112 if (ast->_state != AST_STATE_UP) { 06113 transmit_response_reliable(p, "486 Busy Here", &p->initreq); 06114 p->invitestate = INV_COMPLETED; 06115 sip_alreadygone(p); 06116 ast_softhangup_nolock(ast, AST_SOFTHANGUP_DEV); 06117 break; 06118 } 06119 res = -1; 06120 break; 06121 case AST_CONTROL_CONGESTION: 06122 if (ast->_state != AST_STATE_UP) { 06123 transmit_response_reliable(p, "503 Service Unavailable", &p->initreq); 06124 p->invitestate = INV_COMPLETED; 06125 sip_alreadygone(p); 06126 ast_softhangup_nolock(ast, AST_SOFTHANGUP_DEV); 06127 break; 06128 } 06129 res = -1; 06130 break; 06131 case AST_CONTROL_PROCEEDING: 06132 if ((ast->_state != AST_STATE_UP) && 06133 !ast_test_flag(&p->flags[0], SIP_PROGRESS_SENT) && 06134 !ast_test_flag(&p->flags[0], SIP_OUTGOING)) { 06135 transmit_response(p, "100 Trying", &p->initreq); 06136 p->invitestate = INV_PROCEEDING; 06137 break; 06138 } 06139 res = -1; 06140 break; 06141 case AST_CONTROL_PROGRESS: 06142 if ((ast->_state != AST_STATE_UP) && 06143 !ast_test_flag(&p->flags[0], SIP_PROGRESS_SENT) && 06144 !ast_test_flag(&p->flags[0], SIP_OUTGOING)) { 06145 p->invitestate = INV_EARLY_MEDIA; 06146 transmit_provisional_response(p, "183 Session Progress", &p->initreq, TRUE); 06147 ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT); 06148 break; 06149 } 06150 res = -1; 06151 break; 06152 case AST_CONTROL_HOLD: 06153 ast_rtp_new_source(p->rtp); 06154 ast_moh_start(ast, data, p->mohinterpret); 06155 break; 06156 case AST_CONTROL_UNHOLD: 06157 ast_rtp_new_source(p->rtp); 06158 ast_moh_stop(ast); 06159 break; 06160 case AST_CONTROL_VIDUPDATE: /* Request a video frame update */ 06161 if (p->vrtp && !p->novideo) { 06162 transmit_info_with_vidupdate(p); 06163 /* ast_rtcp_send_h261fur(p->vrtp); */ 06164 } else 06165 res = -1; 06166 break; 06167 case AST_CONTROL_T38_PARAMETERS: 06168 if (datalen != sizeof(struct ast_control_t38_parameters)) { 06169 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); 06170 } else { 06171 const struct ast_control_t38_parameters *parameters = data; 06172 interpret_t38_parameters(p, parameters); 06173 } 06174 break; 06175 case AST_CONTROL_SRCUPDATE: 06176 ast_rtp_new_source(p->rtp); 06177 break; 06178 case -1: 06179 res = -1; 06180 break; 06181 default: 06182 ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", condition); 06183 res = -1; 06184 break; 06185 } 06186 sip_pvt_unlock(p); 06187 return res; 06188 }
| static const char * sip_nat_mode | ( | const struct sip_pvt * | p | ) | [static] |
Display SIP nat mode.
Definition at line 3086 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().
03087 { 03088 return ast_test_flag(&p->flags[0], SIP_NAT) & SIP_NAT_ROUTE ? "NAT" : "no NAT"; 03089 }
| static struct ast_channel* sip_new | ( | struct sip_pvt * | i, | |
| int | state, | |||
| const char * | title | |||
| ) | [static, read] |
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 6196 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_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_info, SIPBUFSIZE, ast_channel::tech, ast_channel::tech_pvt, text, sip_pvt::trtp, sip_pvt::udptl, sip_pvt::uri, ast_variable::value, sip_pvt::vrtp, and ast_channel::writeformat.
Referenced by handle_request_invite(), and sip_request_call().
06197 { 06198 struct ast_channel *tmp; 06199 struct ast_variable *v = NULL; 06200 int fmt; 06201 int what; 06202 int video; 06203 int text; 06204 int needvideo = 0; 06205 int needtext = 0; 06206 char buf[SIPBUFSIZE]; 06207 char *decoded_exten; 06208 06209 { 06210 const char *my_name; /* pick a good name */ 06211 06212 if (title) 06213 my_name = title; 06214 else if ( (my_name = strchr(i->fromdomain, ':')) ) 06215 my_name++; /* skip ':' */ 06216 else 06217 my_name = i->fromdomain; 06218 06219 sip_pvt_unlock(i); 06220 /* Don't hold a sip pvt lock while we allocate a channel */ 06221 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)); 06222 06223 } 06224 if (!tmp) { 06225 ast_log(LOG_WARNING, "Unable to allocate AST channel structure for SIP channel\n"); 06226 sip_pvt_lock(i); 06227 return NULL; 06228 } 06229 sip_pvt_lock(i); 06230 06231 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; 06232 06233 /* Select our native format based on codec preference until we receive 06234 something from another device to the contrary. */ 06235 if (i->jointcapability) { /* The joint capabilities of us and peer */ 06236 what = i->jointcapability; 06237 video = i->jointcapability & AST_FORMAT_VIDEO_MASK; 06238 text = i->jointcapability & AST_FORMAT_TEXT_MASK; 06239 } else if (i->capability) { /* Our configured capability for this peer */ 06240 what = i->capability; 06241 video = i->capability & AST_FORMAT_VIDEO_MASK; 06242 text = i->capability & AST_FORMAT_TEXT_MASK; 06243 } else { 06244 what = global_capability; /* Global codec support */ 06245 video = global_capability & AST_FORMAT_VIDEO_MASK; 06246 text = global_capability & AST_FORMAT_TEXT_MASK; 06247 } 06248 06249 /* Set the native formats for audio and merge in video */ 06250 tmp->nativeformats = ast_codec_choose(&i->prefs, what, 1) | video | text; 06251 ast_debug(3, "*** Our native formats are %s \n", ast_getformatname_multiple(buf, SIPBUFSIZE, tmp->nativeformats)); 06252 ast_debug(3, "*** Joint capabilities are %s \n", ast_getformatname_multiple(buf, SIPBUFSIZE, i->jointcapability)); 06253 ast_debug(3, "*** Our capabilities are %s \n", ast_getformatname_multiple(buf, SIPBUFSIZE, i->capability)); 06254 ast_debug(3, "*** AST_CODEC_CHOOSE formats are %s \n", ast_getformatname_multiple(buf, SIPBUFSIZE, ast_codec_choose(&i->prefs, what, 1))); 06255 if (i->prefcodec) 06256 ast_debug(3, "*** Our preferred formats from the incoming channel are %s \n", ast_getformatname_multiple(buf, SIPBUFSIZE, i->prefcodec)); 06257 06258 /* XXX Why are we choosing a codec from the native formats?? */ 06259 fmt = ast_best_codec(tmp->nativeformats); 06260 06261 /* If we have a prefcodec setting, we have an inbound channel that set a 06262 preferred format for this call. Otherwise, we check the jointcapability 06263 We also check for vrtp. If it's not there, we are not allowed do any video anyway. 06264 */ 06265 if (i->vrtp) { 06266 if (ast_test_flag(&i->flags[1], SIP_PAGE2_VIDEOSUPPORT)) 06267 needvideo = AST_FORMAT_VIDEO_MASK; 06268 else if (i->prefcodec) 06269 needvideo = i->prefcodec & AST_FORMAT_VIDEO_MASK; /* Outbound call */ 06270 else 06271 needvideo = i->jointcapability & AST_FORMAT_VIDEO_MASK; /* Inbound call */ 06272 } 06273 06274 if (i->trtp) { 06275 if (i->prefcodec) 06276 needtext = i->prefcodec & AST_FORMAT_TEXT_MASK; /* Outbound call */ 06277 else 06278 needtext = i->jointcapability & AST_FORMAT_TEXT_MASK; /* Inbound call */ 06279 } 06280 06281 if (needvideo) 06282 ast_debug(3, "This channel can handle video! HOLLYWOOD next!\n"); 06283 else 06284 ast_debug(3, "This channel will not be able to handle video.\n"); 06285 06286 if ((ast_test_flag(&i->flags[0], SIP_DTMF) == SIP_DTMF_INBAND) || (ast_test_flag(&i->flags[0], SIP_DTMF) == SIP_DTMF_AUTO) || 06287 (ast_test_flag(&i->flags[1], SIP_PAGE2_FAX_DETECT))) { 06288 int features = DSP_FEATURE_DIGIT_DETECT; 06289 06290 if (ast_test_flag(&i->flags[1], SIP_PAGE2_FAX_DETECT)) { 06291 features |= DSP_FEATURE_FAX_DETECT; 06292 } 06293 06294 i->dsp = ast_dsp_new(); 06295 ast_dsp_set_features(i->dsp, features); 06296 if (global_relaxdtmf) 06297 ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | DSP_DIGITMODE_RELAXDTMF); 06298 } 06299 06300 /* Set file descriptors for audio, video, realtime text and UDPTL as needed */ 06301 if (i->rtp) { 06302 ast_channel_set_fd(tmp, 0, ast_rtp_fd(i->rtp)); 06303 ast_channel_set_fd(tmp, 1, ast_rtcp_fd(i->rtp)); 06304 } 06305 if (needvideo && i->vrtp) { 06306 ast_channel_set_fd(tmp, 2, ast_rtp_fd(i->vrtp)); 06307 ast_channel_set_fd(tmp, 3, ast_rtcp_fd(i->vrtp)); 06308 } 06309 if (needtext && i->trtp) 06310 ast_channel_set_fd(tmp, 4, ast_rtp_fd(i->trtp)); 06311 if (i->udptl) 06312 ast_channel_set_fd(tmp, 5, ast_udptl_fd(i->udptl)); 06313 06314 if (state == AST_STATE_RING) 06315 tmp->rings = 1; 06316 tmp->adsicpe = AST_ADSI_UNAVAILABLE; 06317 tmp->writeformat = fmt; 06318 tmp->rawwriteformat = fmt; 06319 tmp->readformat = fmt; 06320 tmp->rawreadformat = fmt; 06321 tmp->tech_pvt = dialog_ref(i, "sip_new: set chan->tech_pvt to i"); 06322 06323 tmp->callgroup = i->callgroup; 06324 tmp->pickupgroup = i->pickupgroup; 06325 tmp->cid.cid_pres = i->callingpres; 06326 if (!ast_strlen_zero(i->parkinglot)) 06327 ast_string_field_set(tmp, parkinglot, i->parkinglot); 06328 if (!ast_strlen_zero(i->accountcode)) 06329 ast_string_field_set(tmp, accountcode, i->accountcode); 06330 if (i->amaflags) 06331 tmp->amaflags = i->amaflags; 06332 if (!ast_strlen_zero(i->language)) 06333 ast_string_field_set(tmp, language, i->language); 06334 i->owner = tmp; 06335 ast_module_ref(ast_module_info->self); 06336 ast_copy_string(tmp->context, i->context, sizeof(tmp->context)); 06337 /*Since it is valid to have extensions in the dialplan that have unescaped characters in them 06338 * we should decode the uri before storing it in the channel, but leave it encoded in the sip_pvt 06339 * structure so that there aren't issues when forming URI's 06340 */ 06341 decoded_exten = ast_strdupa(i->exten); 06342 ast_uri_decode(decoded_exten); 06343 ast_copy_string(tmp->exten, decoded_exten, sizeof(tmp->exten)); 06344 06345 /* Don't use ast_set_callerid() here because it will 06346 * generate an unnecessary NewCallerID event */ 06347 tmp->cid.cid_ani = ast_strdup(i->cid_num); 06348 if (!ast_strlen_zero(i->rdnis)) 06349 tmp->cid.cid_rdnis = ast_strdup(i->rdnis); 06350 06351 if (!ast_strlen_zero(i->exten) && strcmp(i->exten, "s")) 06352 tmp->cid.cid_dnid = ast_strdup(i->exten); 06353 06354 tmp->priority = 1; 06355 if (!ast_strlen_zero(i->uri)) 06356 pbx_builtin_setvar_helper(tmp, "SIPURI", i->uri); 06357 if (!ast_strlen_zero(i->domain)) 06358 pbx_builtin_setvar_helper(tmp, "SIPDOMAIN", i->domain); 06359 if (!ast_strlen_zero(i->callid)) 06360 pbx_builtin_setvar_helper(tmp, "SIPCALLID", i->callid); 06361 if (i->rtp) 06362 ast_jb_configure(tmp, &global_jbconf); 06363 06364 /* Set channel variables for this call from configuration */ 06365 for (v = i->chanvars ; v ; v = v->next) 06366 pbx_builtin_setvar_helper(tmp, v->name, v->value); 06367 06368 if (state != AST_STATE_DOWN && ast_pbx_start(tmp)) { 06369 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name); 06370 tmp->hangupcause = AST_CAUSE_SWITCH_CONGESTION; 06371 ast_hangup(tmp); 06372 tmp = NULL; 06373 } 06374 06375 if (i->do_history) 06376 append_history(i, "NewChan", "Channel %s - from %s", tmp->name, i->callid); 06377 06378 /* Inform manager user about new channel and their SIP call ID */ 06379 if (global_callevents) 06380 manager_event(EVENT_FLAG_SYSTEM, "ChannelUpdate", 06381 "Channel: %s\r\nUniqueid: %s\r\nChanneltype: %s\r\nSIPcallid: %s\r\nSIPfullcontact: %s\r\n", 06382 tmp->name, tmp->uniqueid, "SIP", i->callid, i->fullcontact); 06383 06384 return tmp; 06385 }
| 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 17937 of file chan_sip.c.
References 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(), sip_dual::chan1, sip_dual::chan2, ast_channel::context, copy_request(), sip_request::data, ast_channel::exten, ast_channel::hangupcause, LOG_WARNING, parkinglot, ast_channel::priority, ast_channel::readformat, sip_dual::req, sip_dual::seqno, sip_park_thread(), sip_pvt_lock, sip_pvt_unlock, ast_channel::tech_pvt, and ast_channel::writeformat.
Referenced by handle_request_refer().
17938 { 17939 struct sip_dual *d; 17940 struct ast_channel *transferee, *transferer; 17941 /* Chan2m: The transferer, chan1m: The transferee */ 17942 pthread_t th; 17943 17944 transferee = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan1->accountcode, chan1->exten, chan1->context, chan1->amaflags, "Parking/%s", chan1->name); 17945 transferer = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, chan2->accountcode, chan2->exten, chan2->context, chan2->amaflags, "SIPPeer/%s", chan2->name); 17946 if ((!transferer) || (!transferee)) { 17947 if (transferee) { 17948 transferee->hangupcause = AST_CAUSE_SWITCH_CONGESTION; 17949 ast_hangup(transferee); 17950 } 17951 if (transferer) { 17952 transferer->hangupcause = AST_CAUSE_SWITCH_CONGESTION; 17953 ast_hangup(transferer); 17954 } 17955 return -1; 17956 } 17957 17958 /* Make formats okay */ 17959 transferee->readformat = chan1->readformat; 17960 transferee->writeformat = chan1->writeformat; 17961 17962 /* Prepare for taking over the channel */ 17963 ast_channel_masquerade(transferee, chan1); 17964 17965 /* Setup the extensions and such */ 17966 ast_copy_string(transferee->context, chan1->context, sizeof(transferee->context)); 17967 ast_copy_string(transferee->exten, chan1->exten, sizeof(transferee->exten)); 17968 transferee->priority = chan1->priority; 17969 17970 /* We make a clone of the peer channel too, so we can play 17971 back the announcement */ 17972 17973 /* Make formats okay */ 17974 transferer->readformat = chan2->readformat; 17975 transferer->writeformat = chan2->writeformat; 17976 if (!ast_strlen_zero(chan2->parkinglot)) 17977 ast_string_field_set(transferer, parkinglot, chan2->parkinglot); 17978 17979 /* Prepare for taking over the channel. Go ahead and grab this channel 17980 * lock here to avoid a deadlock with callbacks into the channel driver 17981 * that hold the channel lock and want the pvt lock. */ 17982 while (ast_channel_trylock(chan2)) { 17983 struct sip_pvt *pvt = chan2->tech_pvt; 17984 sip_pvt_unlock(pvt); 17985 usleep(1); 17986 sip_pvt_lock(pvt); 17987 } 17988 ast_channel_masquerade(transferer, chan2); 17989 ast_channel_unlock(chan2); 17990 17991 /* Setup the extensions and such */ 17992 ast_copy_string(transferer->context, chan2->context, sizeof(transferer->context)); 17993 ast_copy_string(transferer->exten, chan2->exten, sizeof(transferer->exten)); 17994 transferer->priority = chan2->priority; 17995 17996 ast_channel_lock(transferer); 17997 if (ast_do_masquerade(transferer)) { 17998 ast_log(LOG_WARNING, "Masquerade failed :(\n"); 17999 ast_channel_unlock(transferer); 18000 transferer->hangupcause = AST_CAUSE_SWITCH_CONGESTION; 18001 ast_hangup(transferer); 18002 return -1; 18003 } 18004 ast_channel_unlock(transferer); 18005 if (!transferer || !transferee) { 18006 if (!transferer) { 18007 ast_debug(1, "No transferer channel, giving up parking\n"); 18008 } 18009 if (!transferee) { 18010 ast_debug(1, "No transferee channel, giving up parking\n"); 18011 } 18012 return -1; 18013 } 18014 if ((d = ast_calloc(1, sizeof(*d)))) { 18015 18016 /* Save original request for followup */ 18017 copy_request(&d->req, req); 18018 d->chan1 = transferee; /* Transferee */ 18019 d->chan2 = transferer; /* Transferer */ 18020 d->seqno = seqno; 18021 if (ast_pthread_create_detached_background(&th, NULL, sip_park_thread, d) < 0) { 18022 /* Could not start thread */ 18023 if (d->req.data) 18024 ast_free(d->req.data); 18025 ast_free(d); /* We don't need it anymore. If thread is created, d will be free'd 18026 by sip_park_thread() */ 18027 return 0; 18028 } 18029 } 18030 return -1; 18031 }
| 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 17865 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, 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().
17866 { 17867 struct ast_channel *transferee, *transferer; /* Chan1: The transferee, Chan2: The transferer */ 17868 struct sip_dual *d; 17869 struct sip_request req = {0,}; 17870 int ext; 17871 int res; 17872 17873 d = stuff; 17874 transferee = d->chan1; 17875 transferer = d->chan2; 17876 copy_request(&req, &d->req); 17877 17878 if (!transferee || !transferer) { 17879 ast_log(LOG_ERROR, "Missing channels for parking! Transferer %s Transferee %s\n", transferer ? "<available>" : "<missing>", transferee ? "<available>" : "<missing>" ); 17880 if (d->req.data) 17881 ast_free(d->req.data); 17882 free(d); 17883 return NULL; 17884 } 17885 ast_debug(4, "SIP Park: Transferer channel %s, Transferee %s\n", transferer->name, transferee->name); 17886 17887 ast_channel_lock(transferee); 17888 if (ast_do_masquerade(transferee)) { 17889 ast_log(LOG_WARNING, "Masquerade failed.\n"); 17890 transmit_response(transferer->tech_pvt, "503 Internal error", &req); 17891 ast_channel_unlock(transferee); 17892 if (d->req.data) 17893 ast_free(d->req.data); 17894 free(d); 17895 return NULL; 17896 } 17897 ast_channel_unlock(transferee); 17898 17899 res = ast_park_call(transferee, transferer, 0, &ext); 17900 17901 17902 #ifdef WHEN_WE_KNOW_THAT_THE_CLIENT_SUPPORTS_MESSAGE 17903 if (!res) { 17904 transmit_message_with_text(transferer->tech_pvt, "Unable to park call.\n"); 17905 } else { 17906 /* Then tell the transferer what happened */ 17907 sprintf(buf, "Call parked on extension '%d'", ext); 17908 transmit_message_with_text(transferer->tech_pvt, buf); 17909 } 17910 #endif 17911 17912 /* Any way back to the current call??? */ 17913 /* Transmit response to the REFER request */ 17914 transmit_response(transferer->tech_pvt, "202 Accepted", &req); 17915 if (!res) { 17916 /* Transfer succeeded */ 17917 append_history(transferer->tech_pvt, "SIPpark", "Parked call on %d", ext); 17918 transmit_notify_with_sipfrag(transferer->tech_pvt, d->seqno, "200 OK", TRUE); 17919 transferer->hangupcause = AST_CAUSE_NORMAL_CLEARING; 17920 ast_hangup(transferer); /* This will cause a BYE */ 17921 ast_debug(1, "SIP Call parked on extension '%d'\n", ext); 17922 } else { 17923 transmit_notify_with_sipfrag(transferer->tech_pvt, d->seqno, "503 Service Unavailable", TRUE); 17924 append_history(transferer->tech_pvt, "SIPpark", "Parking failed\n"); 17925 ast_debug(1, "SIP Call parked failed \n"); 17926 /* Do not hangup call */ 17927 } 17928 if (d->req.data) 17929 ast_free(d->req.data); 17930 free(d); 17931 return NULL; 17932 }
| 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 21263 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 reload_config(), and sip_register().
21264 { 21265 char *port; 21266 21267 if ((*hostname = strstr(line, "://"))) { 21268 *hostname += 3; 21269 21270 if (!strncasecmp(line, "tcp", 3)) 21271 *transport = SIP_TRANSPORT_TCP; 21272 else if (!strncasecmp(line, "tls", 3)) 21273 *transport = SIP_TRANSPORT_TLS; 21274 else if (!strncasecmp(line, "udp", 3)) 21275 *transport = SIP_TRANSPORT_UDP; 21276 else 21277 ast_log(LOG_NOTICE, "'%.3s' is not a valid transport type on line %d of sip.conf. defaulting to udp.\n", line, lineno); 21278 } else { 21279 *hostname = line; 21280 *transport = SIP_TRANSPORT_UDP; 21281 } 21282 21283 if ((line = strrchr(*hostname, '@'))) 21284 line++; 21285 else 21286 line = *hostname; 21287 21288 if ((port = strrchr(line, ':'))) { 21289 *port++ = '\0'; 21290 21291 if (!sscanf(port, "%5u", portnum)) { 21292 ast_log(LOG_NOTICE, "'%s' is not a valid port number on line %d of sip.conf. using default.\n", port, lineno); 21293 port = NULL; 21294 } 21295 } 21296 21297 if (!port) { 21298 if (*transport & SIP_TRANSPORT_TLS) { 21299 *portnum = STANDARD_TLS_PORT; 21300 } else { 21301 *portnum = STANDARD_SIP_PORT; 21302 } 21303 } 21304 21305 return 0; 21306 }
| 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 11954 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().
11955 { 11956 struct sip_peer *peer = find_peer(p->peername, NULL, 1, FINDALLDEVICES, FALSE, 0); 11957 11958 if (!peer) 11959 return; 11960 11961 /* If they put someone on hold, increment the value... otherwise decrement it */ 11962 ast_atomic_fetchadd_int(&peer->onHold, (hold ? +1 : -1)); 11963 11964 /* Request device state update */ 11965 ast_devstate_changed(AST_DEVICE_UNKNOWN, "SIP/%s", peer->name); 11966 unref_peer(peer, "sip_peer_hold: from find_peer operation"); 11967 11968 return; 11969 }
| 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 24514 of file chan_sip.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_lock(), ao2_t_iterator_next, ao2_unlock(), AST_SCHED_REPLACE_UNREF, sip_peer::pokeexpire, ref_peer(), sip_poke_peer_s(), and unref_peer().
Referenced by load_module(), and sip_do_reload().
24515 { 24516 int ms = 0; 24517 struct ao2_iterator i; 24518 struct sip_peer *peer; 24519 24520 if (!speerobjs) /* No peers, just give up */ 24521 return; 24522 24523 i = ao2_iterator_init(peers, 0); 24524 while ((peer = ao2_t_iterator_next(&i, "iterate thru peers table"))) { 24525 ao2_lock(peer); 24526 ms += 100; 24527 AST_SCHED_REPLACE_UNREF(peer->pokeexpire, sched, ms, sip_poke_peer_s, peer, 24528 unref_peer(_data, "removing poke peer ref"), 24529 unref_peer(peer, "removing poke peer ref"), 24530 ref_peer(peer, "adding poke peer ref")); 24531 ao2_unlock(peer); 24532 unref_peer(peer, "toss iterator peer ptr"); 24533 } 24534 ao2_iterator_destroy(&i); 24535 }
| static int sip_poke_noanswer | ( | const void * | data | ) | [static] |
React to lack of answer to Qualify poke.
Definition at line 21887 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(), SENTINEL, sip_cfg, sip_poke_peer_s(), TRUE, and unref_peer().
Referenced by sip_poke_peer(), and sip_show_sched().
21888 { 21889 struct sip_peer *peer = (struct sip_peer *)data; 21890 21891 peer->pokeexpire = -1; 21892 21893 if (peer->lastms > -1) { 21894 ast_log(LOG_NOTICE, "Peer '%s' is now UNREACHABLE! Last qualify: %d\n", peer->name, peer->lastms); 21895 if (sip_cfg.peer_rtupdate) { 21896 ast_update_realtime(ast_check_realtime("sipregs") ? "sipregs" : "sippeers", "name", peer->name, "lastms", "-1", SENTINEL); 21897 } 21898 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: SIP\r\nPeer: SIP/%s\r\nPeerStatus: Unreachable\r\nTime: %d\r\n", peer->name, -1); 21899 if (global_regextenonqualify) { 21900 register_peer_exten(peer, FALSE); 21901 } 21902 } 21903 21904 if (peer->call) { 21905 dialog_unlink_all(peer->call, TRUE, TRUE); 21906 peer->call = dialog_unref(peer->call, "unref dialog peer->call"); 21907 /* peer->call = sip_destroy(peer->call);*/ 21908 } 21909 21910 peer->lastms = -1; 21911 ast_devstate_changed(AST_DEVICE_UNKNOWN, "SIP/%s", peer->name); 21912 21913 /* Try again quickly */ 21914 AST_SCHED_REPLACE_UNREF(peer->pokeexpire, sched, 21915 DEFAULT_FREQ_NOTOK, sip_poke_peer_s, peer, 21916 unref_peer(_data, "removing poke peer ref"), 21917 unref_peer(peer, "removing poke peer ref"), 21918 ref_peer(peer, "adding poke peer ref")); 21919 21920 /* Release the ref held by the running scheduler entry */ 21921 unref_peer(peer, "release peer poke noanswer ref"); 21922 21923 return 0; 21924 }
| static int sip_poke_peer | ( | struct sip_peer * | peer, | |
| int | force | |||
| ) | [static] |
Check availability of peer, also keep NAT open.
Definition at line 21931 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, 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().
21932 { 21933 struct sip_pvt *p; 21934 int xmitres = 0; 21935 21936 if ((!peer->maxms && !force) || !peer->addr.sin_addr.s_addr) { 21937 /* IF we have no IP, or this isn't to be monitored, return 21938 immediately after clearing things out */ 21939 AST_SCHED_DEL_UNREF(sched, peer->pokeexpire, 21940 unref_peer(peer, "removing poke peer ref")); 21941 21942 peer->lastms = 0; 21943 if (peer->call) { 21944 peer->call = dialog_unref(peer->call, "unref dialog peer->call"); 21945 } 21946 return 0; 21947 } 21948 if (peer->call) { 21949 if (sipdebug) { 21950 ast_log(LOG_NOTICE, "Still have a QUALIFY dialog active, deleting\n"); 21951 } 21952 dialog_unlink_all(peer->call, TRUE, TRUE); 21953 peer->call = dialog_unref(peer->call, "unref dialog peer->call"); 21954 /* peer->call = sip_destroy(peer->call); */ 21955 } 21956 if (!(p = sip_alloc(NULL, NULL, 0, SIP_OPTIONS, NULL))) { 21957 return -1; 21958 } 21959 peer->call = dialog_ref(p, "copy sip alloc from p to peer->call"); 21960 21961 p->sa = peer->addr; 21962 p->recv = peer->addr; 21963 copy_socket_data(&p->socket, &peer->socket); 21964 ast_copy_flags(&p->flags[0], &peer->flags[0], SIP_FLAGS_TO_COPY); 21965 ast_copy_flags(&p->flags[1], &peer->flags[1], SIP_PAGE2_FLAGS_TO_COPY); 21966 21967 /* Send OPTIONs to peer's fullcontact */ 21968 if (!ast_strlen_zero(peer->fullcontact)) 21969 ast_string_field_set(p, fullcontact, peer->fullcontact); 21970 21971 if (!ast_strlen_zero(peer->tohost)) 21972 ast_string_field_set(p, tohost, peer->tohost); 21973 else 21974 ast_string_field_set(p, tohost, ast_inet_ntoa(peer->addr.sin_addr)); 21975 21976 /* Recalculate our side, and recalculate Call ID */ 21977 ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip, p); 21978 build_via(p); 21979 ao2_t_unlink(dialogs, p, "About to change the callid -- remove the old name"); 21980 build_callid_pvt(p); 21981 ao2_t_link(dialogs, p, "Linking in under new name"); 21982 21983 AST_SCHED_DEL_UNREF(sched, peer->pokeexpire, 21984 unref_peer(peer, "removing poke peer ref")); 21985 21986 if (p->relatedpeer) 21987 p->relatedpeer = unref_peer(p->relatedpeer,"unsetting the relatedpeer field in the dialog, before it is set to something else."); 21988 p->relatedpeer = ref_peer(peer, "setting the relatedpeer field in the dialog"); 21989 ast_set_flag(&p->flags[0], SIP_OUTGOING); 21990 #ifdef VOCAL_DATA_HACK 21991 ast_copy_string(p->username, "__VOCAL_DATA_SHOULD_READ_THE_SIP_SPEC__", sizeof(p->username)); 21992 xmitres = transmit_invite(p, SIP_INVITE, 0, 2); /* sinks the p refcount */ 21993 #else 21994 xmitres = transmit_invite(p, SIP_OPTIONS, 0, 2); /* sinks the p refcount */ 21995 #endif 21996 peer->ps = ast_tvnow(); 21997 if (xmitres == XMIT_ERROR) { 21998 sip_poke_noanswer(peer); /* Immediately unreachable, network problems */ 21999 } else if (!force) { 22000 AST_SCHED_REPLACE_UNREF(peer->pokeexpire, sched, peer->maxms * 2, sip_poke_noanswer, peer, 22001 unref_peer(_data, "removing poke peer ref"), 22002 unref_peer(peer, "removing poke peer ref"), 22003 ref_peer(peer, "adding poke peer ref")); 22004 } 22005 dialog_unref(p, "unref dialog at end of sip_poke_peer, obtained from sip_alloc, just before it goes out of scope"); 22006 return 0; 22007 }
| 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 11273 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().
11274 { 11275 struct sip_peer *peer = (struct sip_peer *)data; 11276 11277 peer->pokeexpire = -1; 11278 11279 sip_poke_peer(peer, 0); 11280 11281 unref_peer(peer, "removing poke peer ref"); 11282 11283 return 0; 11284 }
| static int sip_prepare_socket | ( | struct sip_pvt * | p | ) | [static] |
Definition at line 21132 of file chan_sip.c.
References ast_tcptls_session_args::accept_fd, 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, sip_socket::fd, ast_tcptls_session_args::hostname, ast_tcptls_session_args::master, ast_tcptls_session_args::name, name, sip_pvt::outboundproxy, ast_tcptls_session_args::remote_address, s, sip_real_dst(), sip_tcp_locate(), sip_tcp_worker_fn(), sip_tcptls_client_args_destructor(), sip_threadinfo_create(), SIP_TRANSPORT_TCP, SIP_TRANSPORT_TLS, SIP_TRANSPORT_UDP, sip_pvt::socket, sip_socket::tcptls_session, ast_tcptls_session_args::tls_cfg, sip_pvt::tohost, sip_proxy::transport, and sip_socket::type.
Referenced by __sip_xmit().
21133 { 21134 struct sip_socket *s = &p->socket; 21135 static const char name[] = "SIP socket"; 21136 struct sip_threadinfo *th = NULL; 21137 struct ast_tcptls_session_instance *tcptls_session; 21138 struct ast_tcptls_session_args tmp_ca = { 21139 .name = name, 21140 .accept_fd = -1, 21141 }; 21142 struct ast_tcptls_session_args *ca; 21143 21144 /* check to see if a socket is already active */ 21145 if ((s->fd != -1) && (s->type == SIP_TRANSPORT_UDP)) { 21146 return s->fd; 21147 } 21148 if ((s->type & (SIP_TRANSPORT_TCP | SIP_TRANSPORT_TLS)) && 21149 (s->tcptls_session) && 21150 (s->tcptls_session->fd != -1)) { 21151 return s->tcptls_session->fd; 21152 } 21153 21154 if (p->outboundproxy && p->outboundproxy->transport) { 21155 s->type = p->outboundproxy->transport; 21156 } 21157 21158 if (s->type == SIP_TRANSPORT_UDP) { 21159 s->fd = sipsock; 21160 return s->fd; 21161 } 21162 21163 /* At this point we are dealing with a TCP/TLS connection 21164 * 1. We need to check to see if a connectin thread exists 21165 * for this address, if so use that. 21166 * 2. If a thread does not exist for this address, but the tcptls_session 21167 * exists on the socket, the connection was closed. 21168 * 3. If no tcptls_session thread exists for the address, and no tcptls_session 21169 * already exists on the socket, create a new one and launch a new thread. 21170 */ 21171 21172 /* 1. check for existing threads */ 21173 tmp_ca.remote_address = *(sip_real_dst(p)); 21174 if ((tcptls_session = sip_tcp_locate(&tmp_ca.remote_address))) { 21175 s->fd = tcptls_session->fd; 21176 if (s->tcptls_session) { 21177 ao2_ref(s->tcptls_session, -1); 21178 s->tcptls_session = NULL; 21179 } 21180 s->tcptls_session = tcptls_session; 21181 return s->fd; 21182 /* 2. Thread not found, if tcptls_session already exists, it once had a thread and is now terminated */ 21183 } else if (s->tcptls_session) { 21184 return s->fd; /* XXX whether reconnection is ever necessary here needs to be investigated further */ 21185 } 21186 21187 /* 3. Create a new TCP/TLS client connection */ 21188 /* create new session arguments for the client connection */ 21189 if (!(ca = ao2_alloc(sizeof(*ca), sip_tcptls_client_args_destructor)) || 21190 !(ca->name = ast_strdup(name))) { 21191 goto create_tcptls_session_fail; 21192 } 21193 ca->accept_fd = -1; 21194 ca->remote_address = *(sip_real_dst(p)); 21195 /* if type is TLS, we need to create a tls cfg for this session arg */ 21196 if (s->type == SIP_TRANSPORT_TLS) { 21197 if (!(ca->tls_cfg = ast_calloc(1, sizeof(*ca->tls_cfg)))) { 21198 goto create_tcptls_session_fail; 21199 } 21200 memcpy(ca->tls_cfg, &default_tls_cfg, sizeof(*ca->tls_cfg)); 21201 21202 if (!(ca->tls_cfg->certfile = ast_strdup(default_tls_cfg.certfile)) || 21203 !(ca->tls_cfg->cipher = ast_strdup(default_tls_cfg.cipher)) || 21204 !(ca->tls_cfg->cafile = ast_strdup(default_tls_cfg.cafile)) || 21205 !(ca->tls_cfg->capath = ast_strdup(default_tls_cfg.capath))) { 21206 21207 goto create_tcptls_session_fail; 21208 } 21209 21210 /* this host is used as the common name in ssl/tls */ 21211 if (!ast_strlen_zero(p->tohost)) { 21212 ast_copy_string(ca->hostname, p->tohost, sizeof(ca->hostname)); 21213 } 21214 } 21215 /* Create a client connection for address, this does not start the connection, just sets it up. */ 21216 if (!(s->tcptls_session = ast_tcptls_client_create(ca))) { 21217 goto create_tcptls_session_fail; 21218 } 21219 21220 s->fd = s->tcptls_session->fd; 21221 21222 /* client connections need to have the sip_threadinfo object created before 21223 * the thread is detached. This ensures the alert_pipe is up before it will 21224 * be used. Note that this function links the new threadinfo object into the 21225 * threadt container. */ 21226 if (!(th = sip_threadinfo_create(s->tcptls_session, s->type))) { 21227 goto create_tcptls_session_fail; 21228 21229 } 21230 21231 /* Give the new thread a reference to the tcptls_session */ 21232 ao2_ref(s->tcptls_session, +1); 21233 21234 if (ast_pthread_create_background(&ca->master, NULL, sip_tcp_worker_fn, s->tcptls_session)) { 21235 ast_debug(1, "Unable to launch '%s'.", ca->name); 21236 ao2_ref(s->tcptls_session, -1); /* take away the thread ref we just gave it */ 21237 goto create_tcptls_session_fail; 21238 } 21239 21240 return s->fd; 21241 21242 create_tcptls_session_fail: 21243 if (ca) { 21244 ao2_t_ref(ca, -1, "failed to create client, getting rid of client tcptls_session arguments"); 21245 } 21246 if (s->tcptls_session) { 21247 close(tcptls_session->fd); 21248 s->fd = tcptls_session->fd = -1; 21249 ao2_ref(s->tcptls_session, -1); 21250 s->tcptls_session = NULL; 21251 } 21252 if (th) { 21253 ao2_t_unlink(threadt, th, "Removing tcptls thread info object, thread failed to open"); 21254 } 21255 21256 return -1; 21257 }
| 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 14229 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(), ast_cli_args::pos, SIP_PAGE2_RTCACHEFRIENDS, strcasestr(), sip_peer::the_mark, TRUE, unref_peer(), ast_cli_entry::usage, and ast_cli_args::word.
14230 { 14231 struct sip_peer *peer, *pi; 14232 int prunepeer = FALSE; 14233 int multi = FALSE; 14234 char *name = NULL; 14235 regex_t regexbuf; 14236 struct ao2_iterator i; 14237 14238 if (cmd == CLI_INIT) { 14239 e->command = "sip prune realtime [peer|all] [all|like]"; 14240 e->usage = 14241 "Usage: sip prune realtime [peer [<name>|all|like <pattern>]|all]\n" 14242 " Prunes object(s) from the cache.\n" 14243 " Optional regular expression pattern is used to filter the objects.\n"; 14244 return NULL; 14245 } else if (cmd == CLI_GENERATE) { 14246 if (a->pos == 4) { 14247 if (strcasestr(a->line, "realtime peer")) 14248 return complete_sip_peer(a->word, a->n, SIP_PAGE2_RTCACHEFRIENDS); 14249 } 14250 return NULL; 14251 } 14252 switch (a->argc) { 14253 case 4: 14254 name = a->argv[3]; 14255 /* we accept a name in position 3, but keywords are not good. */ 14256 if (!strcasecmp(name, "peer") || !strcasecmp(name, "like")) 14257 return CLI_SHOWUSAGE; 14258 prunepeer = TRUE; 14259 if (!strcasecmp(name, "all")) { 14260 multi = TRUE; 14261 name = NULL; 14262 } 14263 /* else a single name, already set */ 14264 break; 14265 case 5: 14266 /* sip prune realtime {peer|like} name */ 14267 name = a->argv[4]; 14268 if (!strcasecmp(a->argv[3], "peer")) 14269 prunepeer = TRUE; 14270 else if (!strcasecmp(a->argv[3], "like")) { 14271 prunepeer = TRUE; 14272 multi = TRUE; 14273 } else 14274 return CLI_SHOWUSAGE; 14275 if (!strcasecmp(a->argv[4], "like")) 14276 return CLI_SHOWUSAGE; 14277 if (!multi && !strcasecmp(a->argv[4], "all")) { 14278 multi = TRUE; 14279 name = NULL; 14280 } 14281 break; 14282 case 6: 14283 name = a->argv[5]; 14284 multi = TRUE; 14285 /* sip prune realtime {peer} like name */ 14286 if (strcasecmp(a->argv[4], "like")) 14287 return CLI_SHOWUSAGE; 14288 if (!strcasecmp(a->argv[3], "peer")) { 14289 prunepeer = TRUE; 14290 } else 14291 return CLI_SHOWUSAGE; 14292 break; 14293 default: 14294 return CLI_SHOWUSAGE; 14295 } 14296 14297 if (multi && name) { 14298 if (regcomp(®exbuf, name, REG_EXTENDED | REG_NOSUB)) 14299 return CLI_SHOWUSAGE; 14300 } 14301 14302 if (multi) { 14303 if (prunepeer) { 14304 int pruned = 0; 14305 14306 i = ao2_iterator_init(peers, 0); 14307 while ((pi = ao2_t_iterator_next(&i, "iterate thru peers table"))) { 14308 ao2_lock(pi); 14309 if (name && regexec(®exbuf, pi->name, 0, NULL, 0)) { 14310 unref_peer(pi, "toss iterator peer ptr before continue"); 14311 ao2_unlock(pi); 14312 continue; 14313 }; 14314 if (ast_test_flag(&pi->flags[1], SIP_PAGE2_RTCACHEFRIENDS)) { 14315 pi->the_mark = 1; 14316 pruned++; 14317 } 14318 ao2_unlock(pi); 14319 unref_peer(pi, "toss iterator peer ptr"); 14320 } 14321 ao2_iterator_destroy(&i); 14322 if (pruned) { 14323 ao2_t_callback(peers, OBJ_NODATA | OBJ_UNLINK | OBJ_MULTIPLE, peer_is_marked, 0, 14324 "initiating callback to remove marked peers"); 14325 ast_cli(a->fd, "%d peers pruned.\n", pruned); 14326 } else 14327 ast_cli(a->fd, "No peers found to prune.\n"); 14328 } 14329 } else { 14330 if (prunepeer) { 14331 struct sip_peer tmp; 14332 ast_copy_string(tmp.name, name, sizeof(tmp.name)); 14333 if ((peer = ao2_t_find(peers, &tmp, OBJ_POINTER | OBJ_UNLINK, "finding to unlink from peers"))) { 14334 if (peer->addr.sin_addr.s_addr) { 14335 ao2_t_unlink(peers_by_ip, peer, "unlinking peer from peers_by_ip also"); 14336 } 14337 if (!ast_test_flag(&peer->flags[1], SIP_PAGE2_RTCACHEFRIENDS)) { 14338 ast_cli(a->fd, "Peer '%s' is not a Realtime peer, cannot be pruned.\n", name); 14339 /* put it back! */ 14340 ao2_t_link(peers, peer, "link peer into peer table"); 14341 if (peer->addr.sin_addr.s_addr) { 14342 ao2_t_link(peers_by_ip, peer, "link peer into peers_by_ip table"); 14343 } 14344 14345 } else 14346 ast_cli(a->fd, "Peer '%s' pruned.\n", name); 14347 unref_peer(peer, "sip_prune_realtime: unref_peer: tossing temp peer ptr"); 14348 } else 14349 ast_cli(a->fd, "Peer '%s' not found.\n", name); 14350 } 14351 } 14352 14353 return CLI_SUCCESS; 14354 }
| 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 14508 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.
14509 { 14510 switch (cmd) { 14511 case CLI_INIT: 14512 e->command = "sip qualify peer"; 14513 e->usage = 14514 "Usage: sip qualify peer <name> [load]\n" 14515 " Requests a response from one SIP peer and the current status.\n" 14516 " Option \"load\" forces lookup of peer in realtime storage.\n"; 14517 return NULL; 14518 case CLI_GENERATE: 14519 return complete_sip_show_peer(a->line, a->word, a->pos, a->n); 14520 } 14521 return _sip_qualify_peer(0, a->fd, NULL, NULL, a->argc, (const char **) a->argv); 14522 }
| 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 3884 of file chan_sip.c.
References ast_log(), AST_OPTION_T38_STATE, ast_test_flag, 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.
03885 { 03886 int res = -1; 03887 enum ast_t38_state state = T38_STATE_UNAVAILABLE; 03888 struct sip_pvt *p = (struct sip_pvt *) chan->tech_pvt; 03889 03890 switch (option) { 03891 case AST_OPTION_T38_STATE: 03892 /* Make sure we got an ast_t38_state enum passed in */ 03893 if (*datalen != sizeof(enum ast_t38_state)) { 03894 ast_log(LOG_ERROR, "Invalid datalen for AST_OPTION_T38_STATE option. Expected %d, got %d\n", (int)sizeof(enum ast_t38_state), *datalen); 03895 return -1; 03896 } 03897 03898 sip_pvt_lock(p); 03899 03900 /* 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 */ 03901 if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT)) { 03902 switch (p->t38.state) { 03903 case T38_LOCAL_REINVITE: 03904 case T38_PEER_REINVITE: 03905 state = T38_STATE_NEGOTIATING; 03906 break; 03907 case T38_ENABLED: 03908 state = T38_STATE_NEGOTIATED; 03909 break; 03910 default: 03911 state = T38_STATE_UNKNOWN; 03912 } 03913 } 03914 03915 sip_pvt_unlock(p); 03916 03917 *((enum ast_t38_state *) data) = state; 03918 res = 0; 03919 03920 break; 03921 default: 03922 break; 03923 } 03924 03925 return res; 03926 }
| static struct ast_frame * sip_read | ( | struct ast_channel * | ast | ) | [static, read] |
Read SIP RTP from channel.
Definition at line 6633 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, ast_channel::cid, ast_callerid::cid_num, ast_channel::context, ast_channel::exten, FALSE, sip_pvt::flags, ast_frame::frametype, INV_EARLY_MEDIA, sip_pvt::invitestate, sip_pvt::lastrtprx, LOG_NOTICE, ast_channel::macrocontext, 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.
06634 { 06635 struct ast_frame *fr; 06636 struct sip_pvt *p = ast->tech_pvt; 06637 int faxdetected = FALSE; 06638 06639 sip_pvt_lock(p); 06640 fr = sip_rtp_read(ast, p, &faxdetected); 06641 p->lastrtprx = time(NULL); 06642 06643 /* If we detect a CNG tone and fax detection is enabled then send us off to the fax extension */ 06644 if (faxdetected && ast_test_flag(&p->flags[1], SIP_PAGE2_FAX_DETECT)) { 06645 ast_channel_lock(ast); 06646 if (strcmp(ast->exten, "fax")) { 06647 const char *target_context = S_OR(ast->macrocontext, ast->context); 06648 ast_channel_unlock(ast); 06649 if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) { 06650 ast_verbose(VERBOSE_PREFIX_2 "Redirecting '%s' to fax extension\n", ast->name); 06651 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten); 06652 if (ast_async_goto(ast, target_context, "fax", 1)) { 06653 ast_log(LOG_NOTICE, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context); 06654 } 06655 fr = &ast_null_frame; 06656 } else { 06657 ast_log(LOG_NOTICE, "Fax detected but no fax extension\n"); 06658 } 06659 } else { 06660 ast_channel_unlock(ast); 06661 } 06662 } 06663 06664 /* Only allow audio through if they sent progress with SDP, or if the channel is actually answered */ 06665 if (fr && fr->frametype == AST_FRAME_VOICE && p->invitestate != INV_EARLY_MEDIA && ast->_state != AST_STATE_UP) { 06666 fr = &ast_null_frame; 06667 } 06668 06669 sip_pvt_unlock(p); 06670 06671 return fr; 06672 }
| static struct sockaddr_in * sip_real_dst | ( | const struct sip_pvt * | p | ) | [static, read] |
The real destination address for a write.
Definition at line 3077 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().
03078 { 03079 if (p->outboundproxy) 03080 return &p->outboundproxy->ip; 03081 03082 return ast_test_flag(&p->flags[0], SIP_NAT) & SIP_NAT_ROUTE ? &p->recv : &p->sa; 03083 }
| static int sip_refer_allocate | ( | struct sip_pvt * | p | ) | [static] |
Allocate SIP refer structure.
Definition at line 11033 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().
11034 { 11035 p->refer = ast_calloc(1, sizeof(struct sip_refer)); 11036 return p->refer ? 1 : 0; 11037 }
| 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 10717 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().
10718 { 10719 10720 /* if we are here, our registration timed out, so we'll just do it over */ 10721 struct sip_registry *r = (struct sip_registry *)data; /* the ref count should have been bumped when the sched item was added */ 10722 struct sip_pvt *p; 10723 int res; 10724 10725 /* if we couldn't get a reference to the registry object, punt */ 10726 if (!r) 10727 return 0; 10728 10729 if (r->dnsmgr) { 10730 /* If the registration has timed out, maybe the IP changed. Force a refresh. */ 10731 ast_dnsmgr_refresh(r->dnsmgr); 10732 } 10733 10734 ast_log(LOG_NOTICE, " -- Registration for '%s@%s' timed out, trying again (Attempt #%d)\n", r->username, r->hostname, r->regattempts); 10735 /* If the initial tranmission failed, we may not have an existing dialog, 10736 * so it is possible that r->call == NULL. 10737 * Otherwise destroy it, as we have a timeout so we don't want it. 10738 */ 10739 if (r->call) { 10740 /* Unlink us, destroy old call. Locking is not relevant here because all this happens 10741 in the single SIP manager thread. */ 10742 p = r->call; 10743 sip_pvt_lock(p); 10744 p->needdestroy = 1; 10745 /* Pretend to ACK anything just in case */ 10746 __sip_pretend_ack(p); 10747 sip_pvt_unlock(p); 10748 10749 /* decouple the two objects */ 10750 /* p->registry == r, so r has 2 refs, and the unref won't take the object away */ 10751 if (p->registry) 10752 p->registry = registry_unref(p->registry, "p->registry unreffed"); 10753 r->call = dialog_unref(r->call, "unrefing r->call"); 10754 } 10755 /* If we have a limit, stop registration and give up */ 10756 r->timeout = -1; 10757 if (global_regattempts_max && r->regattempts > global_regattempts_max) { 10758 /* Ok, enough is enough. Don't try any more */ 10759 /* We could add an external notification here... 10760 steal it from app_voicemail :-) */ 10761 ast_log(LOG_NOTICE, " -- Giving up forever trying to register '%s@%s'\n", r->username, r->hostname); 10762 r->regstate = REG_STATE_FAILED; 10763 } else { 10764 r->regstate = REG_STATE_UNREGISTERED; 10765 res=transmit_register(r, SIP_REGISTER, NULL, NULL); 10766 } 10767 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)); 10768 registry_unref(r, "unreffing registry_unref r"); 10769 return 0; 10770 }
| static int sip_register | ( | const char * | value, | |
| int | lineno | |||
| ) | [static] |
Parse register=> line in sip.conf and add to registry.
Definition at line 7060 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, sip_registry::callid_valid, sip_registry::configured_expiry, sip_registry::expire, sip_registry::expiry, FALSE, hostname, INITIAL_CSEQ, LOG_ERROR, LOG_WARNING, sip_registry::ocseq, sip_registry::peername, sip_registry::portno, sip_registry::refresh, registry_unref(), regl, secret, sip_parse_host(), SIP_TRANSPORT_UDP, sip_registry::timeout, sip_registry::transport, and sip_registry::username.
Referenced by build_peer(), and reload_config().
07061 { 07062 struct sip_registry *reg; 07063 int portnum = 0; 07064 enum sip_transport transport = SIP_TRANSPORT_UDP; 07065 char buf[256] = ""; 07066 char *username = NULL; 07067 char *hostname=NULL, *secret=NULL, *authuser=NULL, *expire=NULL, *tmp=NULL; 07068 char *callback=NULL, *peername=NULL; 07069 07070 if (!value) 07071 return -1; 07072 ast_copy_string(buf, value, sizeof(buf)); 07073 tmp = strrchr(buf, '@'); 07074 07075 /* split [/extension][~expiry] */ 07076 expire = strchr(tmp, '~'); 07077 if (expire) 07078 *expire++ = '\0'; 07079 callback = strrchr(tmp, '/'); 07080 if (callback) 07081 *callback++ = '\0'; 07082 if (ast_strlen_zero(callback)) 07083 callback = "s"; 07084 07085 /* split [peername?][transport://] */ 07086 tmp = strchr(buf, '?'); 07087 if (tmp) { 07088 *tmp++ = '\0'; 07089 peername = buf; 07090 } else { 07091 tmp = buf; 07092 } 07093 /* tmp is set at the beginning of [transport://] */ 07094 sip_parse_host(tmp, lineno, &username, &portnum, &transport); 07095 07096 /* First split around the last '@' then parse the two components. */ 07097 hostname = strrchr(username, '@'); /* allow @ in the first part */ 07098 if (hostname) 07099 *hostname++ = '\0'; 07100 if (ast_strlen_zero(username) || ast_strlen_zero(hostname)) { 07101 ast_log(LOG_WARNING, "Format for registration is [transport://]user[@domain][:secret[:authuser]]@host[:port][/extension][~expiry] at line %d\n", lineno); 07102 return -1; 07103 } 07104 /* split user[:secret[:authuser]] */ 07105 secret = strchr(username, ':'); 07106 if (secret) { 07107 *secret++ = '\0'; 07108 authuser = strchr(secret, ':'); 07109 if (authuser) 07110 *authuser++ = '\0'; 07111 } 07112 07113 if (!(reg = ast_calloc(1, sizeof(*reg)))) { 07114 ast_log(LOG_ERROR, "Out of memory. Can't allocate SIP registry entry\n"); 07115 return -1; 07116 } 07117 07118 if (ast_string_field_init(reg, 256)) { 07119 ast_log(LOG_ERROR, "Out of memory. Can't allocate SIP registry strings\n"); 07120 ast_free(reg); 07121 return -1; 07122 } 07123 07124 ast_atomic_fetchadd_int(®objs, 1); 07125 ASTOBJ_INIT(reg); 07126 ast_string_field_set(reg, callback, callback); 07127 if (!ast_strlen_zero(username)) 07128 ast_string_field_set(reg, username, username); 07129 if (hostname) 07130 ast_string_field_set(reg, hostname, hostname); 07131 if (authuser) 07132 ast_string_field_set(reg, authuser, authuser); 07133 if (secret) 07134 ast_string_field_set(reg, secret, secret); 07135 if (peername) { 07136 ast_string_field_set(reg, peername, peername); 07137 } 07138 reg->transport = transport; 07139 reg->expire = -1; 07140 reg->configured_expiry = (expire ? atoi(expire) : default_expiry); 07141 reg->expiry = reg->configured_expiry; 07142 reg->timeout = -1; 07143 reg->refresh = reg->expiry; 07144 reg->portno = portnum; 07145 reg->callid_valid = FALSE; 07146 reg->ocseq = INITIAL_CSEQ; 07147 ASTOBJ_CONTAINER_LINK(®l, reg); /* Add the new registry entry to the list */ 07148 registry_unref(reg, "unref the reg pointer"); /* release the reference given by ASTOBJ_INIT. The container has another reference */ 07149 return 0; 07150 }
| 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 5079 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(), sip_registry::timeout, TRUE, and sip_registry::username.
Referenced by registry_unref(), reload_config(), and unload_module().
05080 { 05081 /* Really delete */ 05082 ast_debug(3, "Destroying registry entry for %s@%s\n", reg->username, reg->hostname); 05083 05084 if (reg->call) { 05085 /* Clear registry before destroying to ensure 05086 we don't get reentered trying to grab the registry lock */ 05087 reg->call->registry = registry_unref(reg->call->registry, "destroy reg->call->registry"); 05088 ast_debug(3, "Destroying active SIP dialog for registry %s@%s\n", reg->username, reg->hostname); 05089 dialog_unlink_all(reg->call, TRUE, TRUE); 05090 reg->call = dialog_unref(reg->call, "unref reg->call"); 05091 /* reg->call = sip_destroy(reg->call); */ 05092 } 05093 AST_SCHED_DEL(sched, reg->expire); 05094 AST_SCHED_DEL(sched, reg->timeout); 05095 05096 ast_string_field_free_memory(reg); 05097 ast_atomic_fetchadd_int(®objs, -1); 05098 ast_dnsmgr_release(reg->dnsmgr); 05099 ast_free(reg); 05100 }
| 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 16788 of file chan_sip.c.
References ast_set_flag, check_pendings(), dialog_unref(), sip_pvt::flags, SIP_NEEDREINVITE, sip_pvt_lock, sip_pvt_unlock, and sip_pvt::waitid.
Referenced by handle_response_invite(), and sip_show_sched().
16789 { 16790 struct sip_pvt *p = (struct sip_pvt *) data; 16791 16792 sip_pvt_lock(p); /* called from schedule thread which requires a lock */ 16793 ast_set_flag(&p->flags[0], SIP_NEEDREINVITE); 16794 p->waitid = -1; 16795 check_pendings(p); 16796 sip_pvt_unlock(p); 16797 dialog_unref(p, "unref the dialog ptr from sip_reinvite_retry, because it held a dialog ptr"); 16798 return 0; 16799 }
| 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 24590 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().
24591 { 24592 24593 switch (cmd) { 24594 case CLI_INIT: 24595 e->command = "sip reload"; 24596 e->usage = 24597 "Usage: sip reload\n" 24598 " Reloads SIP configuration from sip.conf\n"; 24599 return NULL; 24600 case CLI_GENERATE: 24601 return NULL; 24602 } 24603 24604 ast_mutex_lock(&sip_reload_lock); 24605 if (sip_reloading) 24606 ast_verbose("Previous SIP reload not yet done\n"); 24607 else { 24608 sip_reloading = TRUE; 24609 sip_reloadreason = (a && a->fd) ? CHANNEL_CLI_RELOAD : CHANNEL_MODULE_RELOAD; 24610 } 24611 ast_mutex_unlock(&sip_reload_lock); 24612 restart_monitor(); 24613 24614 return CLI_SUCCESS; 24615 }
| static struct ast_channel * sip_request_call | ( | const char * | type, | |
| int | format, | |||
| void * | data, | |||
| int * | cause | |||
| ) | [static, read] |
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 22121 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(), sip_pvt::callid, create_addr(), dialog_unlink_all(), dialog_unref(), dialogs, EVENT_FLAG_SYSTEM, ext, sip_pvt::fullcontact, sip_pvt::jointcapability, LOG_ERROR, LOG_NOTICE, LOG_WARNING, manager_event, sip_pvt::options, sip_pvt::ourip, sip_pvt::outgoing_call, sip_pvt::owner, sip_pvt::peername, sip_pvt::prefcodec, restart_monitor(), sip_pvt::sa, 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.
22122 { 22123 struct sip_pvt *p; 22124 struct ast_channel *tmpc = NULL; 22125 char *ext = NULL, *host; 22126 char tmp[256]; 22127 char *dest = data; 22128 char *dnid; 22129 char *secret = NULL; 22130 char *md5secret = NULL; 22131 char *authname = NULL; 22132 char *trans = NULL; 22133 enum sip_transport transport = 0; 22134 int oldformat = format; 22135 22136 /* mask request with some set of allowed formats. 22137 * XXX this needs to be fixed. 22138 * The original code uses AST_FORMAT_AUDIO_MASK, but it is 22139 * unclear what to use here. We have global_capabilities, which is 22140 * configured from sip.conf, and sip_tech.capabilities, which is 22141 * hardwired to all audio formats. 22142 */ 22143 format &= AST_FORMAT_AUDIO_MASK; 22144 if (!format) { 22145 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)); 22146 *cause = AST_CAUSE_BEARERCAPABILITY_NOTAVAIL; /* Can't find codec to connect to host */ 22147 return NULL; 22148 } 22149 ast_debug(1, "Asked to create a SIP channel with formats: %s\n", ast_getformatname_multiple(tmp, sizeof(tmp), oldformat)); 22150 22151 if (!(p = sip_alloc(NULL, NULL, 0, SIP_INVITE, NULL))) { 22152 ast_log(LOG_ERROR, "Unable to build sip pvt data for '%s' (Out of memory or socket error)\n", dest); 22153 *cause = AST_CAUSE_SWITCH_CONGESTION; 22154 return NULL; 22155 } 22156 22157 p->outgoing_call = TRUE; 22158 22159 if (!(p->options = ast_calloc(1, sizeof(*p->options)))) { 22160 dialog_unlink_all(p, TRUE, TRUE); 22161 dialog_unref(p, "unref dialog p from mem fail"); 22162 /* sip_destroy(p); */ 22163 ast_log(LOG_ERROR, "Unable to build option SIP data structure - Out of memory\n"); 22164 *cause = AST_CAUSE_SWITCH_CONGESTION; 22165 return NULL; 22166 } 22167 22168 /* Save the destination, the SIP dial string */ 22169 ast_copy_string(tmp, dest, sizeof(tmp)); 22170 22171 22172 /* Find DNID and take it away */ 22173 dnid = strchr(tmp, '!'); 22174 if (dnid != NULL) { 22175 *dnid++ = '\0'; 22176 ast_string_field_set(p, todnid, dnid); 22177 } 22178 22179 /* Find at sign - @ */ 22180 host = strchr(tmp, '@'); 22181 if (host) { 22182 *host++ = '\0'; 22183 ext = tmp; 22184 secret = strchr(ext, ':'); 22185 } 22186 if (secret) { 22187 *secret++ = '\0'; 22188 md5secret = strchr(secret, ':'); 22189 } 22190 if (md5secret) { 22191 *md5secret++ = '\0'; 22192 authname = strchr(md5secret, ':'); 22193 } 22194 if (authname) { 22195 *authname++ = '\0'; 22196 trans = strchr(authname, ':'); 22197 } 22198 if (trans) { 22199 *trans++ = '\0'; 22200 if (!strcasecmp(trans, "tcp")) 22201 transport = SIP_TRANSPORT_TCP; 22202 else if (!strcasecmp(trans, "tls")) 22203 transport = SIP_TRANSPORT_TLS; 22204 else { 22205 if (strcasecmp(trans, "udp")) 22206 ast_log(LOG_WARNING, "'%s' is not a valid transport option to Dial() for SIP calls, using udp by default.\n", trans); 22207 transport = SIP_TRANSPORT_UDP; 22208 } 22209 } else { /* use default */ 22210 transport = SIP_TRANSPORT_UDP; 22211 } 22212 22213 if (!host) { 22214 ext = strchr(tmp, '/'); 22215 if (ext) 22216 *ext++ = '\0'; 22217 host = tmp; 22218 } 22219 22220 set_socket_transport(&p->socket, transport); 22221 22222 /* We now have 22223 host = peer name, DNS host name or DNS domain (for SRV) 22224 ext = extension (user part of URI) 22225 dnid = destination of the call (applies to the To: header) 22226 */ 22227 if (create_addr(p, host, NULL, 1)) { 22228 *cause = AST_CAUSE_UNREGISTERED; 22229 ast_debug(3, "Cant create SIP call - target device not registered\n"); 22230 dialog_unlink_all(p, TRUE, TRUE); 22231 dialog_unref(p, "unref dialog p UNREGISTERED"); 22232 /* sip_destroy(p); */ 22233 return NULL; 22234 } 22235 if (ast_strlen_zero(p->peername) && ext) 22236 ast_string_field_set(p, peername, ext); 22237 /* Recalculate our side, and recalculate Call ID */ 22238 ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip, p); 22239 build_via(p); 22240 ao2_t_unlink(dialogs, p, "About to change the callid -- remove the old name"); 22241 build_callid_pvt(p); 22242 ao2_t_link(dialogs, p, "Linking in under new name"); 22243 22244 /* We have an extension to call, don't use the full contact here */ 22245 /* This to enable dialing registered peers with extension dialling, 22246 like SIP/peername/extension 22247 SIP/peername will still use the full contact 22248 */ 22249 if (ext) { 22250 ast_string_field_set(p, username, ext); 22251 ast_string_field_set(p, fullcontact, NULL); 22252 } 22253 if (secret && !ast_strlen_zero(secret)) 22254 ast_string_field_set(p, peersecret, secret); 22255 22256 if (md5secret && !ast_strlen_zero(md5secret)) 22257 ast_string_field_set(p, peermd5secret, md5secret); 22258 22259 if (authname && !ast_strlen_zero(authname)) 22260 ast_string_field_set(p, authname, authname); 22261 #if 0 22262 printf("Setting up to call extension '%s' at '%s'\n", ext ? ext : "<none>", host); 22263 #endif 22264 p->prefcodec = oldformat; /* Format for this call */ 22265 p->jointcapability = oldformat; 22266 sip_pvt_lock(p); 22267 tmpc = sip_new(p, AST_STATE_DOWN, host); /* Place the call */ 22268 if (global_callevents) 22269 manager_event(EVENT_FLAG_SYSTEM, "ChannelUpdate", 22270 "Channel: %s\r\nChanneltype: %s\r\nSIPcallid: %s\r\nSIPfullcontact: %s\r\nPeername: %s\r\n", 22271 p->owner? p->owner->name : "", "SIP", p->callid, p->fullcontact, p->peername); 22272 sip_pvt_unlock(p); 22273 if (!tmpc) { 22274 dialog_unlink_all(p, TRUE, TRUE); 22275 /* sip_destroy(p); */ 22276 } 22277 dialog_unref(p, "toss pvt ptr at end of sip_request_call"); 22278 ast_update_use_count(); 22279 restart_monitor(); 22280 return tmpc; 22281 }
| 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 10679 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().
10680 { 10681 /* if we are here, we know that we need to reregister. */ 10682 struct sip_registry *r= (struct sip_registry *) data; 10683 10684 /* if we couldn't get a reference to the registry object, punt */ 10685 if (!r) 10686 return 0; 10687 10688 if (r->call && r->call->do_history) 10689 append_history(r->call, "RegistryRenew", "Account: %s@%s", r->username, r->hostname); 10690 /* Since registry's are only added/removed by the the monitor thread, this 10691 may be overkill to reference/dereference at all here */ 10692 if (sipdebug) 10693 ast_log(LOG_NOTICE, " -- Re-registration for %s@%s\n", r->username, r->hostname); 10694 10695 r->expire = -1; 10696 r->expiry = r->configured_expiry; 10697 __sip_do_register(r); 10698 registry_unref(r, "unref the re-register scheduled event"); 10699 return 0; 10700 }
| static struct ast_frame * sip_rtp_read | ( | struct ast_channel * | ast, | |
| struct sip_pvt * | p, | |||
| int * | faxdetect | |||
| ) | [static, read] |
Read RTP from network.
Definition at line 6543 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, ast_frame::data, ast_frame::datalen, sip_pvt::dsp, DSP_FEATURE_DIGIT_DETECT, f, ast_channel::fdno, sip_pvt::flags, ast_frame::frametype, sip_pvt::jointcapability, LOG_DEBUG, ast_channel::nativeformats, option_debug, sip_pvt::owner, ast_frame::ptr, ast_channel::readformat, sip_pvt::rtp, SIP_DTMF, SIP_DTMF_INBAND, SIP_DTMF_RFC2833, SIP_PAGE2_FAX_DETECT, ast_frame::subclass, sip_pvt::trtp, sip_pvt::udptl, sip_pvt::vrtp, and ast_channel::writeformat.
Referenced by sip_read().
06544 { 06545 /* Retrieve audio/etc from channel. Assumes p->lock is already held. */ 06546 struct ast_frame *f; 06547 06548 if (!p->rtp) { 06549 /* We have no RTP allocated for this channel */ 06550 return &ast_null_frame; 06551 } 06552 06553 switch(ast->fdno) { 06554 case 0: 06555 f = ast_rtp_read(p->rtp); /* RTP Audio */ 06556 break; 06557 case 1: 06558 f = ast_rtcp_read(p->rtp); /* RTCP Control Channel */ 06559 break; 06560 case 2: 06561 f = ast_rtp_read(p->vrtp); /* RTP Video */ 06562 break; 06563 case 3: 06564 f = ast_rtcp_read(p->vrtp); /* RTCP Control Channel for video */ 06565 break; 06566 case 4: 06567 f = ast_rtp_read(p->trtp); /* RTP Text */ 06568 if (sipdebug_text) { 06569 int i; 06570 unsigned char* arr = f->data.ptr; 06571 for (i=0; i < f->datalen; i++) 06572 ast_verbose("%c", (arr[i] > ' ' && arr[i] < '}') ? arr[i] : '.'); 06573 ast_verbose(" -> "); 06574 for (i=0; i < f->datalen; i++) 06575 ast_verbose("%02X ", arr[i]); 06576 ast_verbose("\n"); 06577 } 06578 break; 06579 case 5: 06580 f = ast_udptl_read(p->udptl); /* UDPTL for T.38 */ 06581 break; 06582 default: 06583 f = &ast_null_frame; 06584 } 06585 /* Don't forward RFC2833 if we're not supposed to */ 06586 if (f && (f->frametype == AST_FRAME_DTMF_BEGIN || f->frametype == AST_FRAME_DTMF_END) && 06587 (ast_test_flag(&p->flags[0], SIP_DTMF) != SIP_DTMF_RFC2833)) { 06588 ast_debug(1, "Ignoring DTMF (%c) RTP frame because dtmfmode is not RFC2833\n", f->subclass); 06589 return &ast_null_frame; 06590 } 06591 06592 /* We already hold the channel lock */ 06593 if (!p->owner || (f && f->frametype != AST_FRAME_VOICE)) 06594 return f; 06595 06596 if (f && f->subclass != (p->owner->nativeformats & AST_FORMAT_AUDIO_MASK)) { 06597 if (!(f->subclass & p->jointcapability)) { 06598 ast_debug(1, "Bogus frame of format '%s' received from '%s'!\n", 06599 ast_getformatname(f->subclass), p->owner->name); 06600 return &ast_null_frame; 06601 } 06602 ast_debug(1, "Oooh, format changed to %d %s\n", 06603 f->subclass, ast_getformatname(f->subclass)); 06604 p->owner->nativeformats = (p->owner->nativeformats & (AST_FORMAT_VIDEO_MASK | AST_FORMAT_TEXT_MASK)) | f->subclass; 06605 ast_set_read_format(p->owner, p->owner->readformat); 06606 ast_set_write_format(p->owner, p->owner->writeformat); 06607 } 06608 06609 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) { 06610 f = ast_dsp_process(p->owner, p->dsp, f); 06611 if (f && f->frametype == AST_FRAME_DTMF) { 06612 if (f->subclass == 'f') { 06613 if (option_debug) 06614 ast_log(LOG_DEBUG, "Fax CNG detected on %s\n", ast->name); 06615 *faxdetect = 1; 06616 /* If we only needed this DSP for fax detection purposes we can just drop it now */ 06617 if (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_INBAND) { 06618 ast_dsp_set_features(p->dsp, DSP_FEATURE_DIGIT_DETECT); 06619 } else { 06620 ast_dsp_free(p->dsp); 06621 p->dsp = NULL; 06622 } 06623 } else { 06624 ast_debug(1, "* Detected inband DTMF '%c'\n", f->subclass); 06625 } 06626 } 06627 } 06628 06629 return f; 06630 }
| static void sip_scheddestroy | ( | struct sip_pvt * | p, | |
| int | ms | |||
| ) | [static] |
Schedule destruction of SIP dialog.
Definition at line 3606 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, 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(), cfsip_methods::text, 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().
03607 { 03608 if (ms < 0) { 03609 if (p->timer_t1 == 0) { 03610 p->timer_t1 = global_t1; /* Set timer T1 if not set (RFC 3261) */ 03611 p->timer_b = global_timer_b; /* Set timer B if not set (RFC 3261) */ 03612 } 03613 ms = p->timer_t1 * 64; 03614 } 03615 if (sip_debug_test_pvt(p)) 03616 ast_verbose("Scheduling destruction of SIP dialog '%s' in %d ms (Method: %s)\n", p->callid, ms, sip_methods[p->method].text); 03617 if (sip_cancel_destroy(p)) 03618 ast_log(LOG_WARNING, "Unable to cancel SIP destruction. Expect bad things.\n"); 03619 03620 if (p->do_history) 03621 append_history(p, "SchedDestroy", "%d ms", ms); 03622 p->autokillid = ast_sched_add(sched, ms, __sip_autodestruct, dialog_ref(p, "setting ref as passing into ast_sched_add for __sip_autodestruct")); 03623 03624 if (p->stimer && p->stimer->st_active == TRUE && p->stimer->st_schedid > 0) 03625 stop_session_timer(p); 03626 }
| static void sip_send_all_registers | ( | void | ) | [static] |
Send all known registrations.
Definition at line 24538 of file chan_sip.c.
References AST_SCHED_REPLACE_UNREF, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_UNLOCK, ASTOBJ_WRLOCK, registry_addref(), registry_unref(), regl, and sip_reregister().
Referenced by load_module(), and sip_do_reload().
24539 { 24540 int ms; 24541 int regspacing; 24542 if (!regobjs) 24543 return; 24544 regspacing = default_expiry * 1000/regobjs; 24545 if (regspacing > 100) 24546 regspacing = 100; 24547 ms = regspacing; 24548 ASTOBJ_CONTAINER_TRAVERSE(®l, 1, do { 24549 ASTOBJ_WRLOCK(iterator); 24550 ms += regspacing; 24551 AST_SCHED_REPLACE_UNREF(iterator->expire, sched, ms, sip_reregister, iterator, 24552 registry_unref(_data, "REPLACE sched del decs the refcount"), 24553 registry_unref(iterator, "REPLACE sched add failure decs the refcount"), 24554 registry_addref(iterator, "REPLACE sched add incs the refcount")); 24555 ASTOBJ_UNLOCK(iterator); 24556 } while (0) 24557 ); 24558 }
| 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 21334 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().
21335 { 21336 /* Called with peerl lock, but releases it */ 21337 struct sip_pvt *p; 21338 int newmsgs = 0, oldmsgs = 0; 21339 21340 if (ast_test_flag((&peer->flags[1]), SIP_PAGE2_SUBSCRIBEMWIONLY) && !peer->mwipvt) 21341 return 0; 21342 21343 /* Do we have an IP address? If not, skip this peer */ 21344 if (!peer->addr.sin_addr.s_addr && !peer->defaddr.sin_addr.s_addr) 21345 return 0; 21346 21347 if (event) { 21348 newmsgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS); 21349 oldmsgs = ast_event_get_ie_uint(event, AST_EVENT_IE_OLDMSGS); 21350 } else if (!get_cached_mwi(peer, &newmsgs, &oldmsgs)) { 21351 /* got it! Don't keep looking. */ 21352 } else if (cache_only) { 21353 return 0; 21354 } else { /* Fall back to manually checking the mailbox */ 21355 struct ast_str *mailbox_str = ast_str_alloca(512); 21356 peer_mailboxes_to_str(&mailbox_str, peer); 21357 ast_app_inboxcount(mailbox_str->str, &newmsgs, &oldmsgs); 21358 } 21359 21360 if (peer->mwipvt) { 21361 /* Base message on subscription */ 21362 p = dialog_ref(peer->mwipvt, "sip_send_mwi_to_peer: Setting dialog ptr p from peer->mwipvt-- should this be done?"); 21363 } else { 21364 /* Build temporary dialog for this message */ 21365 if (!(p = sip_alloc(NULL, NULL, 0, SIP_NOTIFY, NULL))) 21366 return -1; 21367 /* If we don't set the socket type to 0, then create_addr_from_peer will fail immediately if the peer 21368 * uses any transport other than UDP. We set the type to 0 here and then let create_addr_from_peer copy 21369 * the peer's socket information to the sip_pvt we just allocated 21370 */ 21371 set_socket_transport(&p->socket, 0); 21372 if (create_addr_from_peer(p, peer)) { 21373 /* Maybe they're not registered, etc. */ 21374 dialog_unlink_all(p, TRUE, TRUE); 21375 dialog_unref(p, "unref dialog p just created via sip_alloc"); 21376 /* sip_destroy(p); */ 21377 return 0; 21378 } 21379 /* Recalculate our side, and recalculate Call ID */ 21380 ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip, p); 21381 build_via(p); 21382 ao2_t_unlink(dialogs, p, "About to change the callid -- remove the old name"); 21383 build_callid_pvt(p); 21384 ao2_t_link(dialogs, p, "Linking in under new name"); 21385 /* Destroy this session after 32 secs */ 21386 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 21387 } 21388 21389 /* Send MWI */ 21390 ast_set_flag(&p->flags[0], SIP_OUTGOING); 21391 /* the following will decrement the refcount on p as it finishes */ 21392 transmit_notify_with_mwi(p, newmsgs, oldmsgs, peer->vmexten); 21393 dialog_unref(p, "unref dialog ptr p just before it goes out of scope at the end of sip_send_mwi_to_peer."); 21394 return 0; 21395 }
| static int sip_senddigit_begin | ( | struct ast_channel * | ast, | |
| char | digit | |||
| ) | [static] |
Definition at line 5955 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.
05956 { 05957 struct sip_pvt *p = ast->tech_pvt; 05958 int res = 0; 05959 05960 sip_pvt_lock(p); 05961 switch (ast_test_flag(&p->flags[0], SIP_DTMF)) { 05962 case SIP_DTMF_INBAND: 05963 res = -1; /* Tell Asterisk to generate inband indications */ 05964 break; 05965 case SIP_DTMF_RFC2833: 05966 if (p->rtp) 05967 ast_rtp_senddigit_begin(p->rtp, digit); 05968 break; 05969 default: 05970 break; 05971 } 05972 sip_pvt_unlock(p); 05973 05974 return res; 05975 }
| 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 5979 of file chan_sip.c.
References ast_rtp_senddigit_end(), ast_test_flag, sip_pvt::flags, 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_pvt, and transmit_info_with_digit().
05980 { 05981 struct sip_pvt *p = ast->tech_pvt; 05982 int res = 0; 05983 05984 sip_pvt_lock(p); 05985 switch (ast_test_flag(&p->flags[0], SIP_DTMF)) { 05986 case SIP_DTMF_INFO: 05987 case SIP_DTMF_SHORTINFO: 05988 transmit_info_with_digit(p, digit, duration); 05989 break; 05990 case SIP_DTMF_RFC2833: 05991 if (p->rtp) 05992 ast_rtp_senddigit_end(p->rtp, digit); 05993 break; 05994 case SIP_DTMF_INBAND: 05995 res = -1; /* Tell Asterisk to stop inband indications */ 05996 break; 05997 } 05998 sip_pvt_unlock(p); 05999 06000 return res; 06001 }
| 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 4090 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, 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.
04091 { 04092 struct sip_pvt *p = chan->tech_pvt; 04093 04094 if (subclass != AST_HTML_URL) 04095 return -1; 04096 04097 ast_string_field_build(p, url, "<%s>;mode=active", data); 04098 04099 if (sip_debug_test_pvt(p)) 04100 ast_debug(1, "Send URL %s, state = %d!\n", data, chan->_state); 04101 04102 switch (chan->_state) { 04103 case AST_STATE_RING: 04104 transmit_response(p, "100 Trying", &p->initreq); 04105 break; 04106 case AST_STATE_RINGING: 04107 transmit_response(p, "180 Ringing", &p->initreq); 04108 break; 04109 case AST_STATE_UP: 04110 if (!p->pendinginvite) { /* We are up, and have no outstanding invite */ 04111 transmit_reinvite_with_sdp(p, FALSE, FALSE); 04112 } else if (!ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) { 04113 ast_set_flag(&p->flags[0], SIP_NEEDREINVITE); 04114 } 04115 break; 04116 default: 04117 ast_log(LOG_WARNING, "Don't know how to send URI when state is %d!\n", chan->_state); 04118 } 04119 04120 return 0; 04121 }
| 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 4131 of file chan_sip.c.
References ast_verbose, sip_request::debug, sip_debug_test_pvt(), ast_channel::tech_pvt, and transmit_message_with_text().
04132 { 04133 struct sip_pvt *p = ast->tech_pvt; 04134 int debug = sip_debug_test_pvt(p); 04135 04136 if (debug) 04137 ast_verbose("Sending text %s on %s\n", text, ast->name); 04138 if (!p) 04139 return -1; 04140 /* NOT ast_strlen_zero, because a zero-length message is specifically 04141 * allowed by RFC 3428 (See section 10, Examples) */ 04142 if (!text) 04143 return 0; 04144 if (debug) 04145 ast_verbose("Really sending text %s on %s\n", text, ast->name); 04146 transmit_message_with_text(p, text); 04147 return 0; 04148 }
| 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 16151 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.
16152 { 16153 switch (cmd) { 16154 case CLI_INIT: 16155 e->command = "sip set history {on|off}"; 16156 e->usage = 16157 "Usage: sip set history {on|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 != e->args) 16166 return CLI_SHOWUSAGE; 16167 16168 if (!strncasecmp(a->argv[e->args - 1], "on", 2)) { 16169 recordhistory = TRUE; 16170 ast_cli(a->fd, "SIP History Recording Enabled (use 'sip show history')\n"); 16171 } else if (!strncasecmp(a->argv[e->args - 1], "off", 3)) { 16172 recordhistory = FALSE; 16173 ast_cli(a->fd, "SIP History Recording Disabled\n"); 16174 } else { 16175 return CLI_SHOWUSAGE; 16176 } 16177 return CLI_SUCCESS; 16178 }
| static void sip_set_redirstr | ( | struct sip_pvt * | p, | |
| char * | reason | |||
| ) | [static] |
Translate referring cause.
Definition at line 12357 of file chan_sip.c.
References ast_string_field_set.
Referenced by get_rdnis().
12357 { 12358 12359 if (!strcmp(reason, "unknown")) { 12360 ast_string_field_set(p, redircause, "UNKNOWN"); 12361 } else if (!strcmp(reason, "user-busy")) { 12362 ast_string_field_set(p, redircause, "BUSY"); 12363 } else if (!strcmp(reason, "no-answer")) { 12364 ast_string_field_set(p, redircause, "NOANSWER"); 12365 } else if (!strcmp(reason, "unavailable")) { 12366 ast_string_field_set(p, redircause, "UNREACHABLE"); 12367 } else if (!strcmp(reason, "unconditional")) { 12368 ast_string_field_set(p, redircause, "UNCONDITIONAL"); 12369 } else if (!strcmp(reason, "time-of-day")) { 12370 ast_string_field_set(p, redircause, "UNKNOWN"); 12371 } else if (!strcmp(reason, "do-not-disturb")) { 12372 ast_string_field_set(p, redircause, "UNKNOWN"); 12373 } else if (!strcmp(reason, "deflection")) { 12374 ast_string_field_set(p, redircause, "UNKNOWN"); 12375 } else if (!strcmp(reason, "follow-me")) { 12376 ast_string_field_set(p, redircause, "UNKNOWN"); 12377 } else if (!strcmp(reason, "out-of-service")) { 12378 ast_string_field_set(p, redircause, "UNREACHABLE"); 12379 } else if (!strcmp(reason, "away")) { 12380 ast_string_field_set(p, redircause, "UNREACHABLE"); 12381 } else { 12382 ast_string_field_set(p, redircause, "UNKNOWN"); 12383 } 12384 }
| 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 24260 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, 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_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, and sip_pvt::vredirip.
Referenced by sip_fixup().
24261 { 24262 struct sip_pvt *p; 24263 int changed = 0; 24264 24265 p = chan->tech_pvt; 24266 if (!p) 24267 return -1; 24268 24269 /* Disable early RTP bridge */ 24270 if (!ast_bridged_channel(chan) && !global_directrtpsetup) /* We are in early state */ 24271 return 0; 24272 24273 sip_pvt_lock(p); 24274 if (p->alreadygone) { 24275 /* If we're destroyed, don't bother */ 24276 sip_pvt_unlock(p); 24277 return 0; 24278 } 24279 24280 /* if this peer cannot handle reinvites of the media stream to devices 24281 that are known to be behind a NAT, then stop the process now 24282 */ 24283 if (nat_active && !ast_test_flag(&p->flags[0], SIP_CAN_REINVITE_NAT)) { 24284 sip_pvt_unlock(p); 24285 return 0; 24286 } 24287 24288 if (rtp) { 24289 changed |= ast_rtp_get_peer(rtp, &p->redirip); 24290 } else if (p->redirip.sin_addr.s_addr || ntohs(p->redirip.sin_port) != 0) { 24291 memset(&p->redirip, 0, sizeof(p->redirip)); 24292 changed = 1; 24293 } 24294 if (vrtp) { 24295 changed |= ast_rtp_get_peer(vrtp, &p->vredirip); 24296 } else if (p->vredirip.sin_addr.s_addr || ntohs(p->vredirip.sin_port) != 0) { 24297 memset(&p->vredirip, 0, sizeof(p->vredirip)); 24298 changed = 1; 24299 } 24300 if (trtp) { 24301 changed |= ast_rtp_get_peer(trtp, &p->tredirip); 24302 } else if (p->tredirip.sin_addr.s_addr || ntohs(p->tredirip.sin_port) != 0) { 24303 memset(&p->tredirip, 0, sizeof(p->tredirip)); 24304 changed = 1; 24305 } 24306 if (codecs && (p->redircodecs != codecs)) { 24307 p->redircodecs = codecs; 24308 changed = 1; 24309 } 24310 if (changed && !ast_test_flag(&p->flags[0], SIP_GOTREFER) && !ast_test_flag(&p->flags[0], SIP_DEFER_BYE_ON_TRANSFER)) { 24311 if (chan->_state != AST_STATE_UP) { /* We are in early state */ 24312 if (p->do_history) 24313 append_history(p, "ExtInv", "Initial invite sent with remote bridge proposal."); 24314 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)); 24315 } else if (!p->pendinginvite) { /* We are up, and have no outstanding invite */ 24316 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)); 24317 transmit_reinvite_with_sdp(p, FALSE, FALSE); 24318 } else if (!ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) { 24319 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)); 24320 /* We have a pending Invite. Send re-invite when we're done with the invite */ 24321 ast_set_flag(&p->flags[0], SIP_NEEDREINVITE); 24322 } 24323 } 24324 /* Reset lastrtprx timer */ 24325 p->lastrtprx = p->lastrtptx = time(NULL); 24326 sip_pvt_unlock(p); 24327 return 0; 24328 }
| static int sip_set_udptl_peer | ( | struct ast_channel * | chan, | |
| struct ast_udptl * | udptl | |||
| ) | [static] |
Definition at line 24153 of file chan_sip.c.
References ast_debug, ast_inet_ntoa(), ast_set_flag, ast_test_flag, ast_udptl_get_peer(), sip_pvt::callid, 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, and sip_pvt::udptlredirip.
24154 { 24155 struct sip_pvt *p; 24156 24157 p = chan->tech_pvt; 24158 if (!p) 24159 return -1; 24160 sip_pvt_lock(p); 24161 if (udptl) 24162 ast_udptl_get_peer(udptl, &p->udptlredirip); 24163 else 24164 memset(&p->udptlredirip, 0, sizeof(p->udptlredirip)); 24165 if (!ast_test_flag(&p->flags[0], SIP_GOTREFER)) { 24166 if (!p->pendinginvite) { 24167 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); 24168 transmit_reinvite_with_sdp(p, TRUE, FALSE); 24169 } else if (!ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) { 24170 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); 24171 ast_set_flag(&p->flags[0], SIP_NEEDREINVITE); 24172 } 24173 } 24174 /* Reset lastrtprx timer */ 24175 p->lastrtprx = p->lastrtptx = time(NULL); 24176 sip_pvt_unlock(p); 24177 return 0; 24178 }
| 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 15577 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, 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.
15578 { 15579 struct sip_pvt *cur; 15580 size_t len; 15581 int found = 0; 15582 struct ao2_iterator i; 15583 15584 switch (cmd) { 15585 case CLI_INIT: 15586 e->command = "sip show channel"; 15587 e->usage = 15588 "Usage: sip show channel <call-id>\n" 15589 " Provides detailed status on a given SIP dialog (identified by SIP call-id).\n"; 15590 return NULL; 15591 case CLI_GENERATE: 15592 return complete_sipch(a->line, a->word, a->pos, a->n); 15593 } 15594 15595 if (a->argc != 4) 15596 return CLI_SHOWUSAGE; 15597 len = strlen(a->argv[3]); 15598 15599 i = ao2_iterator_init(dialogs, 0); 15600 while ((cur = ao2_t_iterator_next(&i, "iterate thru dialogs"))) { 15601 sip_pvt_lock(cur); 15602 15603 if (!strncasecmp(cur->callid, a->argv[3], len)) { 15604 char formatbuf[SIPBUFSIZE/2]; 15605 ast_cli(a->fd, "\n"); 15606 if (cur->subscribed != NONE) 15607 ast_cli(a->fd, " * Subscription (type: %s)\n", subscription_type2str(cur->subscribed)); 15608 else 15609 ast_cli(a->fd, " * SIP Call\n"); 15610 ast_cli(a->fd, " Curr. trans. direction: %s\n", ast_test_flag(&cur->flags[0], SIP_OUTGOING) ? "Outgoing" : "Incoming"); 15611 ast_cli(a->fd, " Call-ID: %s\n", cur->callid); 15612 ast_cli(a->fd, " Owner channel ID: %s\n", cur->owner ? cur->owner->name : "<none>"); 15613 ast_cli(a->fd, " Our Codec Capability: %d\n", cur->capability); 15614 ast_cli(a->fd, " Non-Codec Capability (DTMF): %d\n", cur->noncodeccapability); 15615 ast_cli(a->fd, " Their Codec Capability: %d\n", cur->peercapability); 15616 ast_cli(a->fd, " Joint Codec Capability: %d\n", cur->jointcapability); 15617 ast_cli(a->fd, " Format: %s\n", ast_getformatname_multiple(formatbuf, sizeof(formatbuf), cur->owner ? cur->owner->nativeformats : 0) ); 15618 ast_cli(a->fd, " T.38 support %s\n", cli_yesno(cur->udptl != NULL)); 15619 ast_cli(a->fd, " Video support %s\n", cli_yesno(cur->vrtp != NULL)); 15620 ast_cli(a->fd, " MaxCallBR: %d kbps\n", cur->maxcallbitrate); 15621 ast_cli(a->fd, " Theoretical Address: %s:%d\n", ast_inet_ntoa(cur->sa.sin_addr), ntohs(cur->sa.sin_port)); 15622 ast_cli(a->fd, " Received Address: %s:%d\n", ast_inet_ntoa(cur->recv.sin_addr), ntohs(cur->recv.sin_port)); 15623 ast_cli(a->fd, " SIP Transfer mode: %s\n", transfermode2str(cur->allowtransfer)); 15624 ast_cli(a->fd, " NAT Support: %s\n", nat2str(ast_test_flag(&cur->flags[0], SIP_NAT))); 15625 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)" ); 15626 ast_cli(a->fd, " Our Tag: %s\n", cur->tag); 15627 ast_cli(a->fd, " Their Tag: %s\n", cur->theirtag); 15628 ast_cli(a->fd, " SIP User agent: %s\n", cur->useragent); 15629 if (!ast_strlen_zero(cur->username)) 15630 ast_cli(a->fd, " Username: %s\n", cur->username); 15631 if (!ast_strlen_zero(cur->peername)) 15632 ast_cli(a->fd, " Peername: %s\n", cur->peername); 15633 if (!ast_strlen_zero(cur->uri)) 15634 ast_cli(a->fd, " Original uri: %s\n", cur->uri); 15635 if (!ast_strlen_zero(cur->cid_num)) 15636 ast_cli(a->fd, " Caller-ID: %s\n", cur->cid_num); 15637 ast_cli(a->fd, " Need Destroy: %s\n", cli_yesno(cur->needdestroy)); 15638 ast_cli(a->fd, " Last Message: %s\n", cur->lastmsg); 15639 ast_cli(a->fd, " Promiscuous Redir: %s\n", cli_yesno(ast_test_flag(&cur->flags[0], SIP_PROMISCREDIR))); 15640 ast_cli(a->fd, " Route: %s\n", cur->route ? cur->route->hop : "N/A"); 15641 ast_cli(a->fd, " DTMF Mode: %s\n", dtmfmode2str(ast_test_flag(&cur->flags[0], SIP_DTMF))); 15642 ast_cli(a->fd, " SIP Options: "); 15643 if (cur->sipoptions) { 15644 int x; 15645 for (x = 0 ; x < ARRAY_LEN(sip_options); x++) { 15646 if (cur->sipoptions & sip_options[x].id) 15647 ast_cli(a->fd, "%s ", sip_options[x].text); 15648 } 15649 ast_cli(a->fd, "\n"); 15650 } else 15651 ast_cli(a->fd, "(none)\n"); 15652 15653 if (!cur->stimer) 15654 ast_cli(a->fd, " Session-Timer: Uninitiallized\n"); 15655 else { 15656 ast_cli(a->fd, " Session-Timer: %s\n", cur->stimer->st_active ? "Active" : "Inactive"); 15657 if (cur->stimer->st_active == TRUE) { 15658 ast_cli(a->fd, " S-Timer Interval: %d\n", cur->stimer->st_interval); 15659 ast_cli(a->fd, " S-Timer Refresher: %s\n", strefresher2str(cur->stimer->st_ref)); 15660 ast_cli(a->fd, " S-Timer Expirys: %d\n", cur->stimer->st_expirys); 15661 ast_cli(a->fd, " S-Timer Sched Id: %d\n", cur->stimer->st_schedid); 15662 ast_cli(a->fd, " S-Timer Peer Sts: %s\n", cur->stimer->st_active_peer_ua ? "Active" : "Inactive"); 15663 ast_cli(a->fd, " S-Timer Cached Min-SE: %d\n", cur->stimer->st_cached_min_se); 15664 ast_cli(a->fd, " S-Timer Cached SE: %d\n", cur->stimer->st_cached_max_se); 15665 ast_cli(a->fd, " S-Timer Cached Ref: %s\n", strefresher2str(cur->stimer->st_cached_ref)); 15666 ast_cli(a->fd, " S-Timer Cached Mode: %s\n", stmode2str(cur->stimer->st_cached_mode)); 15667 } 15668 } 15669 15670 ast_cli(a->fd, "\n\n"); 15671 15672 found++; 15673 } 15674 15675 sip_pvt_unlock(cur); 15676 15677 ao2_t_ref(cur, -1, "toss dialog ptr set by iterator_next"); 15678 } 15679 ao2_iterator_destroy(&i); 15680 15681 if (!found) 15682 ast_cli(a->fd, "No such SIP Call ID starting with '%s'\n", a->argv[3]); 15683 15684 return CLI_SUCCESS; 15685 }
| 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 15398 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.
15399 { 15400 struct __show_chan_arg arg = { .fd = a->fd, .numchans = 0 }; 15401 15402 15403 if (cmd == CLI_INIT) { 15404 e->command = "sip show {channels|subscriptions}"; 15405 e->usage = 15406 "Usage: sip show channels\n" 15407 " Lists all currently active SIP calls (dialogs).\n" 15408 "Usage: sip show subscriptions\n" 15409 " Lists active SIP subscriptions.\n"; 15410 return NULL; 15411 } else if (cmd == CLI_GENERATE) 15412 return NULL; 15413 15414 if (a->argc != e->args) 15415 return CLI_SHOWUSAGE; 15416 arg.subscriptions = !strcasecmp(a->argv[e->args - 1], "subscriptions"); 15417 if (!arg.subscriptions) 15418 ast_cli(arg.fd, FORMAT2, "Peer", "User/ANR", "Call ID", "Format", "Hold", "Last Message", "Expiry"); 15419 else 15420 ast_cli(arg.fd, FORMAT3, "Peer", "User", "Call ID", "Extension", "Last state", "Type", "Mailbox", "Expiry"); 15421 15422 /* iterate on the container and invoke the callback on each item */ 15423 ao2_t_callback(dialogs, OBJ_NODATA, show_channels_cb, &arg, "callback to show channels"); 15424 15425 /* print summary information */ 15426 ast_cli(arg.fd, "%d active SIP %s%s\n", arg.numchans, 15427 (arg.subscriptions ? "subscription" : "dialog"), 15428 ESS(arg.numchans)); /* ESS(n) returns an "s" if n>1 */ 15429 return CLI_SUCCESS; 15430 #undef FORMAT 15431 #undef FORMAT2 15432 #undef FORMAT3 15433 }
| 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 15089 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.
15090 { 15091 struct __show_chan_arg arg = { .fd = a->fd, .numchans = 0 }; 15092 15093 switch (cmd) { 15094 case CLI_INIT: 15095 e->command = "sip show channelstats"; 15096 e->usage = 15097 "Usage: sip show channelstats\n" 15098 " Lists all currently active SIP channel's RTCP statistics.\n" 15099 " Note that calls in the much optimized RTP P2P bridge mode will not show any packets here."; 15100 return NULL; 15101 case CLI_GENERATE: 15102 return NULL; 15103 } 15104 15105 if (a->argc != 3) 15106 return CLI_SHOWUSAGE; 15107 15108 ast_cli(a->fd, FORMAT2, "Peer", "Call ID", "Duration", "Recv: Pack", "Lost", "Jitter", "Send: Pack", "Lost", "Jitter"); 15109 /* iterate on the container and invoke the callback on each item */ 15110 ao2_t_callback(dialogs, OBJ_NODATA, show_chanstats_cb, &arg, "callback to sip show chanstats"); 15111 ast_cli(a->fd, "%d active SIP channel%s\n", arg.numchans, (arg.numchans != 1) ? "s" : ""); 15112 return CLI_SUCCESS; 15113 }
| 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 14388 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::mode, S_OR, and ast_cli_entry::usage.
14389 { 14390 struct domain *d; 14391 #define FORMAT "%-40.40s %-20.20s %-16.16s\n" 14392 14393 switch (cmd) { 14394 case CLI_INIT: 14395 e->command = "sip show domains"; 14396 e->usage = 14397 "Usage: sip show domains\n" 14398 " Lists all configured SIP local domains.\n" 14399 " Asterisk only responds to SIP messages to local domains.\n"; 14400 return NULL; 14401 case CLI_GENERATE: 14402 return NULL; 14403 } 14404 14405 if (AST_LIST_EMPTY(&domain_list)) { 14406 ast_cli(a->fd, "SIP Domain support not enabled.\n\n"); 14407 return CLI_SUCCESS; 14408 } else { 14409 ast_cli(a->fd, FORMAT, "Our local SIP domains:", "Context", "Set by"); 14410 AST_LIST_LOCK(&domain_list); 14411 AST_LIST_TRAVERSE(&domain_list, d, list) 14412 ast_cli(a->fd, FORMAT, d->domain, S_OR(d->context, "(default)"), 14413 domain_mode_to_text(d->mode)); 14414 AST_LIST_UNLOCK(&domain_list); 14415 ast_cli(a->fd, "\n"); 14416 return CLI_SUCCESS; 14417 } 14418 }
| 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 15688 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, 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.
15689 { 15690 struct sip_pvt *cur; 15691 size_t len; 15692 int found = 0; 15693 struct ao2_iterator i; 15694 15695 switch (cmd) { 15696 case CLI_INIT: 15697 e->command = "sip show history"; 15698 e->usage = 15699 "Usage: sip show history <call-id>\n" 15700 " Provides detailed dialog history on a given SIP call (specified by call-id).\n"; 15701 return NULL; 15702 case CLI_GENERATE: 15703 return complete_sip_show_history(a->line, a->word, a->pos, a->n); 15704 } 15705 15706 if (a->argc != 4) 15707 return CLI_SHOWUSAGE; 15708 15709 if (!recordhistory) 15710 ast_cli(a->fd, "\n***Note: History recording is currently DISABLED. Use 'sip set history on' to ENABLE.\n"); 15711 15712 len = strlen(a->argv[3]); 15713 15714 i = ao2_iterator_init(dialogs, 0); 15715 while ((cur = ao2_t_iterator_next(&i, "iterate thru dialogs"))) { 15716 sip_pvt_lock(cur); 15717 if (!strncasecmp(cur->callid, a->argv[3], len)) { 15718 struct sip_history *hist; 15719 int x = 0; 15720 15721 ast_cli(a->fd, "\n"); 15722 if (cur->subscribed != NONE) 15723 ast_cli(a->fd, " * Subscription\n"); 15724 else 15725 ast_cli(a->fd, " * SIP Call\n"); 15726 if (cur->history) 15727 AST_LIST_TRAVERSE(cur->history, hist, list) 15728 ast_cli(a->fd, "%d. %s\n", ++x, hist->event); 15729 if (x == 0) 15730 ast_cli(a->fd, "Call '%s' has no history\n", cur->callid); 15731 found++; 15732 } 15733 sip_pvt_unlock(cur); 15734 ao2_t_ref(cur, -1, "toss dialog ptr from iterator_next"); 15735 } 15736 ao2_iterator_destroy(&i); 15737 15738 if (!found) 15739 ast_cli(a->fd, "No such SIP Call ID starting with '%s'\n", a->argv[3]); 15740 15741 return CLI_SUCCESS; 15742 }
| 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 13472 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, TRUE, unref_peer(), and ast_cli_entry::usage.
13473 { 13474 #define FORMAT "%-25.25s %-15.15s %-15.15s \n" 13475 #define FORMAT2 "%-25.25s %-15.15s %-15.15s \n" 13476 char ilimits[40]; 13477 char iused[40]; 13478 int showall = FALSE; 13479 struct ao2_iterator i; 13480 struct sip_peer *peer; 13481 13482 switch (cmd) { 13483 case CLI_INIT: 13484 e->command = "sip show inuse"; 13485 e->usage = 13486 "Usage: sip show inuse [all]\n" 13487 " List all SIP devices usage counters and limits.\n" 13488 " Add option \"all\" to show all devices, not only those with a limit.\n"; 13489 return NULL; 13490 case CLI_GENERATE: 13491 return NULL; 13492 } 13493 13494 if (a->argc < 3) 13495 return CLI_SHOWUSAGE; 13496 13497 if (a->argc == 4 && !strcmp(a->argv[3], "all")) 13498 showall = TRUE; 13499 13500 ast_cli(a->fd, FORMAT, "* Peer name", "In use", "Limit"); 13501 13502 i = ao2_iterator_init(peers, 0); 13503 while ((peer = ao2_t_iterator_next(&i, "iterate thru peer table"))) { 13504 ao2_lock(peer); 13505 if (peer->call_limit) 13506 snprintf(ilimits, sizeof(ilimits), "%d", peer->call_limit); 13507 else 13508 ast_copy_string(ilimits, "N/A", sizeof(ilimits)); 13509 snprintf(iused, sizeof(iused), "%d/%d/%d", peer->inUse, peer->inRinging, peer->onHold); 13510 if (showall || peer->call_limit) 13511 ast_cli(a->fd, FORMAT2, peer->name, iused, ilimits); 13512 ao2_unlock(peer); 13513 unref_peer(peer, "toss iterator pointer"); 13514 } 13515 ao2_iterator_destroy(&i); 13516 13517 return CLI_SUCCESS; 13518 #undef FORMAT 13519 #undef FORMAT2 13520 }
| 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 14055 of file chan_sip.c.
References ao2_t_callback, ast_cli_args::argc, ast_cli(), ASTOBJ_CONTAINER_DUMP, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dialog_dump_func(), dialogs, ast_cli_args::fd, OBJ_NODATA, peer_dump_func(), regl, and ast_cli_entry::usage.
14056 { 14057 char tmp[256]; 14058 14059 switch (cmd) { 14060 case CLI_INIT: 14061 e->command = "sip show objects"; 14062 e->usage = 14063 "Usage: sip show objects\n" 14064 " Lists status of known SIP objects\n"; 14065 return NULL; 14066 case CLI_GENERATE: 14067 return NULL; 14068 } 14069 14070 if (a->argc != 3) 14071 return CLI_SHOWUSAGE; 14072 ast_cli(a->fd, "-= Peer objects: %d static, %d realtime, %d autocreate =-\n\n", speerobjs, rpeerobjs, apeerobjs); 14073 ao2_t_callback(peers, OBJ_NODATA, peer_dump_func, &a->fd, "initiate ao2_callback to dump peers"); 14074 ast_cli(a->fd, "-= Registry objects: %d =-\n\n", regobjs); 14075 ASTOBJ_CONTAINER_DUMP(a->fd, tmp, sizeof(tmp), ®l); 14076 ast_cli(a->fd, "-= Dialog objects:\n\n"); 14077 ao2_t_callback(dialogs, OBJ_NODATA, dialog_dump_func, &a->fd, "initiate ao2_callback to dump dialogs"); 14078 return CLI_SUCCESS; 14079 }
| 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 14449 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.
14450 { 14451 switch (cmd) { 14452 case CLI_INIT: 14453 e->command = "sip show peer"; 14454 e->usage = 14455 "Usage: sip show peer <name> [load]\n" 14456 " Shows all details on one SIP peer and the current status.\n" 14457 " Option \"load\" forces lookup of peer in realtime storage.\n"; 14458 return NULL; 14459 case CLI_GENERATE: 14460 return complete_sip_show_peer(a->line, a->word, a->pos, a->n); 14461 } 14462 return _sip_show_peer(0, a->fd, NULL, NULL, a->argc, (const char **) a->argv); 14463 }
| 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 13831 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.
13832 { 13833 switch (cmd) { 13834 case CLI_INIT: 13835 e->command = "sip show peers"; 13836 e->usage = 13837 "Usage: sip show peers [like <pattern>]\n" 13838 " Lists all known SIP peers.\n" 13839 " Optional regular expression pattern is used to filter the peer list.\n"; 13840 return NULL; 13841 case CLI_GENERATE: 13842 return NULL; 13843 } 13844 13845 return _sip_show_peers(a->fd, NULL, NULL, NULL, a->argc, (const char **) a->argv); 13846 }
| 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 14947 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.
14948 { 14949 #define FORMAT2 "%-30.30s %-6.6s %-12.12s %8.8s %-20.20s %-25.25s\n" 14950 #define FORMAT "%-30.30s %-6.6s %-12.12s %8d %-20.20s %-25.25s\n" 14951 char host[80]; 14952 char tmpdat[256]; 14953 struct ast_tm tm; 14954 int counter = 0; 14955 14956 switch (cmd) { 14957 case CLI_INIT: 14958 e->command = "sip show registry"; 14959 e->usage = 14960 "Usage: sip show registry\n" 14961 " Lists all registration requests and status.\n"; 14962 return NULL; 14963 case CLI_GENERATE: 14964 return NULL; 14965 } 14966 14967 if (a->argc != 3) 14968 return CLI_SHOWUSAGE; 14969 ast_cli(a->fd, FORMAT2, "Host", "dnsmgr", "Username", "Refresh", "State", "Reg.Time"); 14970 14971 ASTOBJ_CONTAINER_TRAVERSE(®l, 1, do { 14972 ASTOBJ_RDLOCK(iterator); 14973 snprintf(host, sizeof(host), "%s:%d", iterator->hostname, iterator->portno ? iterator->portno : STANDARD_SIP_PORT); 14974 if (iterator->regtime.tv_sec) { 14975 ast_localtime(&iterator->regtime, &tm, NULL); 14976 ast_strftime(tmpdat, sizeof(tmpdat), "%a, %d %b %Y %T", &tm); 14977 } else 14978 tmpdat[0] = '\0'; 14979 ast_cli(a->fd, FORMAT, host, (iterator->dnsmgr) ? "Y" : "N", iterator->username, iterator->refresh, regstate2str(iterator->regstate), tmpdat); 14980 ASTOBJ_UNLOCK(iterator); 14981 counter++; 14982 } while(0)); 14983 ast_cli(a->fd, "%d SIP registrations.\n", counter); 14984 return CLI_SUCCESS; 14985 #undef FORMAT 14986 #undef FORMAT2 14987 }
| static char * sip_show_sched | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 14904 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(), sip_poke_noanswer(), sip_poke_peer_s(), sip_reg_timeout(), sip_reinvite_retry(), sip_reregister(), ast_str::str, and ast_cli_entry::usage.
14905 { 14906 struct ast_str *cbuf; 14907 struct ast_cb_names cbnames = {9, { "retrans_pkt", 14908 "__sip_autodestruct", 14909 "expire_register", 14910 "auto_congest", 14911 "sip_reg_timeout", 14912 "sip_poke_peer_s", 14913 "sip_poke_noanswer", 14914 "sip_reregister", 14915 "sip_reinvite_retry"}, 14916 { retrans_pkt, 14917 __sip_autodestruct, 14918 expire_register, 14919 auto_congest, 14920 sip_reg_timeout, 14921 sip_poke_peer_s, 14922 sip_poke_noanswer, 14923 sip_reregister, 14924 sip_reinvite_retry}}; 14925 14926 switch (cmd) { 14927 case CLI_INIT: 14928 e->command = "sip show sched"; 14929 e->usage = 14930 "Usage: sip show sched\n" 14931 " Shows stats on what's in the sched queue at the moment\n"; 14932 return NULL; 14933 case CLI_GENERATE: 14934 return NULL; 14935 } 14936 14937 cbuf = ast_str_alloca(2048); 14938 14939 ast_cli(a->fd, "\n"); 14940 ast_sched_report(sched, &cbuf, &cbnames); 14941 ast_cli(a->fd, "%s", cbuf->str); 14942 14943 return CLI_SUCCESS; 14944 }
| 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 15118 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(), bindaddr, 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, externip, FALSE, faxec2str(), ast_cli_args::fd, sip_proxy::force, global_jbconf, global_outboundproxy, sip_settings::ignore_regexpire, ast_jb_conf::impl, internip, ast_tcptls_session_args::local_address, 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_USECLIENTCODE, SIP_USEREQPHONE, SIPBUFSIZE, stmode2str(), strefresher2str(), stunaddr, transfermode2str(), and ast_cli_entry::usage.
15119 { 15120 int realtimepeers; 15121 int realtimeregs; 15122 char codec_buf[SIPBUFSIZE]; 15123 const char *msg; /* temporary msg pointer */ 15124 15125 switch (cmd) { 15126 case CLI_INIT: 15127 e->command = "sip show settings"; 15128 e->usage = 15129 "Usage: sip show settings\n" 15130 " Provides detailed list of the configuration of the SIP channel.\n"; 15131 return NULL; 15132 case CLI_GENERATE: 15133 return NULL; 15134 } 15135 15136 15137 realtimepeers = ast_check_realtime("sippeers"); 15138 realtimeregs = ast_check_realtime("sipregs"); 15139 15140 if (a->argc != 3) 15141 return CLI_SHOWUSAGE; 15142 ast_cli(a->fd, "\n\nGlobal Settings:\n"); 15143 ast_cli(a->fd, "----------------\n"); 15144 ast_cli(a->fd, " UDP SIP Port: %d\n", ntohs(bindaddr.sin_port)); 15145 ast_cli(a->fd, " UDP Bindaddress: %s\n", ast_inet_ntoa(bindaddr.sin_addr)); 15146 ast_cli(a->fd, " TCP SIP Port: "); 15147 if (sip_tcp_desc.local_address.sin_family == AF_INET) { 15148 ast_cli(a->fd, "%d\n", ntohs(sip_tcp_desc.local_address.sin_port)); 15149 ast_cli(a->fd, " TCP Bindaddress: %s\n", ast_inet_ntoa(sip_tcp_desc.local_address.sin_addr)); 15150 } else { 15151 ast_cli(a->fd, "Disabled\n"); 15152 } 15153 ast_cli(a->fd, " TLS SIP Port: "); 15154 if (default_tls_cfg.enabled != FALSE) { 15155 ast_cli(a->fd, "%d\n", ntohs(sip_tls_desc.local_address.sin_port)); 15156 ast_cli(a->fd, " TLS Bindaddress: %s\n", ast_inet_ntoa(sip_tls_desc.local_address.sin_addr)); 15157 } else { 15158 ast_cli(a->fd, "Disabled\n"); 15159 } 15160 ast_cli(a->fd, " Videosupport: %s\n", cli_yesno(ast_test_flag(&global_flags[1], SIP_PAGE2_VIDEOSUPPORT))); 15161 ast_cli(a->fd, " Textsupport: %s\n", cli_yesno(ast_test_flag(&global_flags[1], SIP_PAGE2_TEXTSUPPORT))); 15162 ast_cli(a->fd, " AutoCreate Peer: %s\n", cli_yesno(autocreatepeer)); 15163 ast_cli(a->fd, " Ignore SDP sess. ver.: %s\n", cli_yesno(ast_test_flag(&global_flags[1], SIP_PAGE2_IGNORESDPVERSION))); 15164 ast_cli(a->fd, " Match Auth Username: %s\n", cli_yesno(global_match_auth_username)); 15165 ast_cli(a->fd, " Allow unknown access: %s\n", cli_yesno(global_allowguest)); 15166 ast_cli(a->fd, " Allow subscriptions: %s\n", cli_yesno(ast_test_flag(&global_flags[1], SIP_PAGE2_ALLOWSUBSCRIBE))); 15167 ast_cli(a->fd, " Allow overlap dialing: %s\n", cli_yesno(ast_test_flag(&global_flags[1], SIP_PAGE2_ALLOWOVERLAP))); 15168 ast_cli(a->fd, " Allow promsic. redir: %s\n", cli_yesno(ast_test_flag(&global_flags[0], SIP_PROMISCREDIR))); 15169 ast_cli(a->fd, " Enable call counters: %s\n", cli_yesno(global_callcounter)); 15170 ast_cli(a->fd, " SIP domain support: %s\n", cli_yesno(!AST_LIST_EMPTY(&domain_list))); 15171 ast_cli(a->fd, " Realm. auth: %s\n", cli_yesno(authl != NULL)); 15172 ast_cli(a->fd, " Our auth realm %s\n", global_realm); 15173 ast_cli(a->fd, " Call to non-local dom.: %s\n", cli_yesno(allow_external_domains)); 15174 ast_cli(a->fd, " URI user is phone no: %s\n", cli_yesno(ast_test_flag(&global_flags[0], SIP_USEREQPHONE))); 15175 ast_cli(a->fd, " Always auth rejects: %s\n", cli_yesno(global_alwaysauthreject)); 15176 ast_cli(a->fd, " Direct RTP setup: %s\n", cli_yesno(global_directrtpsetup)); 15177 ast_cli(a->fd, " User Agent: %s\n", global_useragent); 15178 ast_cli(a->fd, " SDP Session Name: %s\n", ast_strlen_zero(global_sdpsession) ? "-" : global_sdpsession); 15179 ast_cli(a->fd, " SDP Owner Name: %s\n", ast_strlen_zero(global_sdpowner) ? "-" : global_sdpowner); 15180 ast_cli(a->fd, " Reg. context: %s\n", S_OR(global_regcontext, "(not set)")); 15181 ast_cli(a->fd, " Regexten on Qualify: %s\n", cli_yesno(global_regextenonqualify)); 15182 ast_cli(a->fd, " Caller ID: %s\n", default_callerid); 15183 ast_cli(a->fd, " From: Domain: %s\n", default_fromdomain); 15184 ast_cli(a->fd, " Record SIP history: %s\n", recordhistory ? "On" : "Off"); 15185 ast_cli(a->fd, " Call Events: %s\n", global_callevents ? "On" : "Off"); 15186 ast_cli(a->fd, " Auth. Failure Events: %s\n", global_authfailureevents ? "On" : "Off"); 15187 15188 ast_cli(a->fd, " T.38 support: %s\n", cli_yesno(ast_test_flag(&global_flags[1], SIP_PAGE2_T38SUPPORT))); 15189 ast_cli(a->fd, " T.38 EC mode: %s\n", faxec2str(ast_test_flag(&global_flags[1], SIP_PAGE2_T38SUPPORT))); 15190 ast_cli(a->fd, " T.38 MaxDtgrm: %d\n", global_t38_maxdatagram); 15191 15192 if (!realtimepeers && !realtimeregs) 15193 ast_cli(a->fd, " SIP realtime: Disabled\n" ); 15194 else 15195 ast_cli(a->fd, " SIP realtime: Enabled\n" ); 15196 ast_cli(a->fd, " Qualify Freq : %d ms\n", global_qualifyfreq); 15197 ast_cli(a->fd, "\nNetwork QoS Settings:\n"); 15198 ast_cli(a->fd, "---------------------------\n"); 15199 ast_cli(a->fd, " IP ToS SIP: %s\n", ast_tos2str(global_tos_sip)); 15200 ast_cli(a->fd, " IP ToS RTP audio: %s\n", ast_tos2str(global_tos_audio)); 15201 ast_cli(a->fd, " IP ToS RTP video: %s\n", ast_tos2str(global_tos_video)); 15202 ast_cli(a->fd, " IP ToS RTP text: %s\n", ast_tos2str(global_tos_text)); 15203 ast_cli(a->fd, " 802.1p CoS SIP: %d\n", global_cos_sip); 15204 ast_cli(a->fd, " 802.1p CoS RTP audio: %d\n", global_cos_audio); 15205 ast_cli(a->fd, " 802.1p CoS RTP video: %d\n", global_cos_video); 15206 ast_cli(a->fd, " 802.1p CoS RTP text: %d\n", global_cos_text); 15207 ast_cli(a->fd, " Jitterbuffer enabled: %s\n", cli_yesno(ast_test_flag(&global_jbconf, AST_JB_ENABLED))); 15208 ast_cli(a->fd, " Jitterbuffer forced: %s\n", cli_yesno(ast_test_flag(&global_jbconf, AST_JB_FORCED))); 15209 ast_cli(a->fd, " Jitterbuffer max size: %ld\n", global_jbconf.max_size); 15210 ast_cli(a->fd, " Jitterbuffer resync: %ld\n", global_jbconf.resync_threshold); 15211 ast_cli(a->fd, " Jitterbuffer impl: %s\n", global_jbconf.impl); 15212 ast_cli(a->fd, " Jitterbuffer log: %s\n", cli_yesno(ast_test_flag(&global_jbconf, AST_JB_LOG))); 15213 15214 ast_cli(a->fd, "\nNetwork Settings:\n"); 15215 ast_cli(a->fd, "---------------------------\n"); 15216 /* determine if/how SIP address can be remapped */ 15217 if (localaddr == NULL) 15218 msg = "Disabled, no localnet list"; 15219 else if (externip.sin_addr.s_addr == 0) 15220 msg = "Disabled, externip is 0.0.0.0"; 15221 else if (stunaddr.sin_addr.s_addr != 0) 15222 msg = "Enabled using STUN"; 15223 else if (!ast_strlen_zero(externhost)) 15224 msg = "Enabled using externhost"; 15225 else 15226 msg = "Enabled using externip"; 15227 ast_cli(a->fd, " SIP address remapping: %s\n", msg); 15228 ast_cli(a->fd, " Externhost: %s\n", S_OR(externhost, "<none>")); 15229 ast_cli(a->fd, " Externip: %s:%d\n", ast_inet_ntoa(externip.sin_addr), ntohs(externip.sin_port)); 15230 ast_cli(a->fd, " Externrefresh: %d\n", externrefresh); 15231 ast_cli(a->fd, " Internal IP: %s:%d\n", ast_inet_ntoa(internip.sin_addr), ntohs(internip.sin_port)); 15232 { 15233 struct ast_ha *d; 15234 const char *prefix = "Localnet:"; 15235 char buf[INET_ADDRSTRLEN]; /* need to print two addresses */ 15236 15237 for (d = localaddr; d ; prefix = "", d = d->next) { 15238 ast_cli(a->fd, " %-24s%s/%s\n", 15239 prefix, ast_inet_ntoa(d->netaddr), 15240 inet_ntop(AF_INET, &d->netmask, buf, sizeof(buf)) ); 15241 } 15242 } 15243 ast_cli(a->fd, " STUN server: %s:%d\n", ast_inet_ntoa(stunaddr.sin_addr), ntohs(stunaddr.sin_port)); 15244 15245 ast_cli(a->fd, "\nGlobal Signalling Settings:\n"); 15246 ast_cli(a->fd, "---------------------------\n"); 15247 ast_cli(a->fd, " Codecs: "); 15248 ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, global_capability); 15249 ast_cli(a->fd, "%s\n", codec_buf); 15250 ast_cli(a->fd, " Codec Order: "); 15251 print_codec_to_cli(a->fd, &default_prefs); 15252 ast_cli(a->fd, "\n"); 15253 ast_cli(a->fd, " Relax DTMF: %s\n", cli_yesno(global_relaxdtmf)); 15254 ast_cli(a->fd, " RFC2833 Compensation: %s\n", cli_yesno(ast_test_flag(&global_flags[1], SIP_PAGE2_RFC2833_COMPENSATE))); 15255 ast_cli(a->fd, " Compact SIP headers: %s\n", cli_yesno(compactheaders)); 15256 ast_cli(a->fd, " RTP Keepalive: %d %s\n", global_rtpkeepalive, global_rtpkeepalive ? "" : "(Disabled)" ); 15257 ast_cli(a->fd, " RTP Timeout: %d %s\n", global_rtptimeout, global_rtptimeout ? "" : "(Disabled)" ); 15258 ast_cli(a->fd, " RTP Hold Timeout: %d %s\n", global_rtpholdtimeout, global_rtpholdtimeout ? "" : "(Disabled)"); 15259 ast_cli(a->fd, " MWI NOTIFY mime type: %s\n", default_notifymime); 15260 ast_cli(a->fd, " DNS SRV lookup: %s\n", cli_yesno(global_srvlookup)); 15261 ast_cli(a->fd, " Pedantic SIP support: %s\n", cli_yesno(pedanticsipchecking)); 15262 ast_cli(a->fd, " Reg. min duration %d secs\n", min_expiry); 15263 ast_cli(a->fd, " Reg. max duration: %d secs\n", max_expiry); 15264 ast_cli(a->fd, " Reg. default duration: %d secs\n", default_expiry); 15265 ast_cli(a->fd, " Outbound reg. timeout: %d secs\n", global_reg_timeout); 15266 ast_cli(a->fd, " Outbound reg. attempts: %d\n", global_regattempts_max); 15267 ast_cli(a->fd, " Notify ringing state: %s\n", cli_yesno(global_notifyringing)); 15268 ast_cli(a->fd, " Notify hold state: %s\n", cli_yesno(global_notifyhold)); 15269 ast_cli(a->fd, " SIP Transfer mode: %s\n", transfermode2str(global_allowtransfer)); 15270 ast_cli(a->fd, " Max Call Bitrate: %d kbps\n", default_maxcallbitrate); 15271 ast_cli(a->fd, " Auto-Framing: %s\n", cli_yesno(global_autoframing)); 15272 ast_cli(a->fd, " Outb. proxy: %s %s\n", ast_strlen_zero(global_outboundproxy.name) ? "<not set>" : global_outboundproxy.name, 15273 global_outboundproxy.force ? "(forced)" : ""); 15274 ast_cli(a->fd, " Session Timers: %s\n", stmode2str(global_st_mode)); 15275 ast_cli(a->fd, " Session Refresher: %s\n", strefresher2str (global_st_refresher)); 15276 ast_cli(a->fd, " Session Expires: %d secs\n", global_max_se); 15277 ast_cli(a->fd, " Session Min-SE: %d secs\n", global_min_se); 15278 ast_cli(a->fd, " Timer T1: %d\n", global_t1); 15279 ast_cli(a->fd, " Timer T1 minimum: %d\n", global_t1min); 15280 ast_cli(a->fd, " Timer B: %d\n", global_timer_b); 15281 ast_cli(a->fd, " No premature media: %s\n", global_prematuremediafilter ? "Yes" : "No"); 15282 15283 ast_cli(a->fd, "\nDefault Settings:\n"); 15284 ast_cli(a->fd, "-----------------\n"); 15285 ast_cli(a->fd, " Context: %s\n", default_context); 15286 ast_cli(a->fd, " Nat: %s\n", nat2str(ast_test_flag(&global_flags[0], SIP_NAT))); 15287 ast_cli(a->fd, " DTMF: %s\n", dtmfmode2str(ast_test_flag(&global_flags[0], SIP_DTMF))); 15288 ast_cli(a->fd, " Qualify: %d\n", default_qualify); 15289 ast_cli(a->fd, " Use ClientCode: %s\n", cli_yesno(ast_test_flag(&global_flags[0], SIP_USECLIENTCODE))); 15290 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" ); 15291 ast_cli(a->fd, " Language: %s\n", default_language); 15292 ast_cli(a->fd, " MOH Interpret: %s\n", default_mohinterpret); 15293 ast_cli(a->fd, " MOH Suggest: %s\n", default_mohsuggest); 15294 ast_cli(a->fd, " Voice Mail Extension: %s\n", default_vmexten); 15295 15296 15297 if (realtimepeers || realtimeregs) { 15298 ast_cli(a->fd, "\nRealtime SIP Settings:\n"); 15299 ast_cli(a->fd, "----------------------\n"); 15300 ast_cli(a->fd, " Realtime Peers: %s\n", cli_yesno(realtimepeers)); 15301 ast_cli(a->fd, " Realtime Regs: %s\n", cli_yesno(realtimeregs)); 15302 ast_cli(a->fd, " Cache Friends: %s\n", cli_yesno(ast_test_flag(&global_flags[1], SIP_PAGE2_RTCACHEFRIENDS))); 15303 ast_cli(a->fd, " Update: %s\n", cli_yesno(sip_cfg.peer_rtupdate)); 15304 ast_cli(a->fd, " Ignore Reg. Expire: %s\n", cli_yesno(sip_cfg.ignore_regexpire)); 15305 ast_cli(a->fd, " Save sys. name: %s\n", cli_yesno(sip_cfg.rtsave_sysname)); 15306 ast_cli(a->fd, " Auto Clear: %d\n", global_rtautoclear); 15307 } 15308 ast_cli(a->fd, "\n----\n"); 15309 return CLI_SUCCESS; 15310 }
| 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 13643 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, sip_threadinfo::type, and ast_cli_entry::usage.
13644 { 13645 struct sip_threadinfo *th; 13646 struct ao2_iterator i; 13647 13648 #define FORMAT2 "%-30.30s %3.6s %9.9s %6.6s\n" 13649 #define FORMAT "%-30.30s %-6d %-9.9s %-6.6s\n" 13650 13651 switch (cmd) { 13652 case CLI_INIT: 13653 e->command = "sip show tcp"; 13654 e->usage = 13655 "Usage: sip show tcp\n" 13656 " Lists all active TCP/TLS sessions.\n"; 13657 return NULL; 13658 case CLI_GENERATE: 13659 return NULL; 13660 } 13661 13662 if (a->argc != 3) 13663 return CLI_SHOWUSAGE; 13664 13665 ast_cli(a->fd, FORMAT2, "Host", "Port", "Transport", "Type"); 13666 i = ao2_iterator_init(threadt, 0); 13667 while ((th = ao2_t_iterator_next(&i, "iterate through tcp threads for 'sip show tcp'"))) { 13668 ast_cli(a->fd, FORMAT, ast_inet_ntoa(th->tcptls_session->remote_address.sin_addr), 13669 ntohs(th->tcptls_session->remote_address.sin_port), 13670 get_transport(th->type), 13671 (th->tcptls_session->client ? "Client" : "Server")); 13672 ao2_t_ref(th, -1, "decrement ref from iterator"); 13673 } 13674 ao2_iterator_destroy(&i); 13675 return CLI_SUCCESS; 13676 #undef FORMAT 13677 #undef FORMAT2 13678 }
| 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 14828 of file chan_sip.c.
References sip_peer::accountcode, sip_peer::allowtransfer, sip_peer::amaflags, 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, sip_peer::autoframing, sip_peer::call_limit, sip_peer::callgroup, sip_peer::callingpres, sip_peer::chanvars, sip_peer::cid_name, sip_peer::cid_num, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, cli_yesno(), ast_cli_entry::command, complete_sip_show_user(), sip_peer::context, FALSE, ast_cli_args::fd, find_peer(), FINDUSERS, sip_peer::flags, sip_peer::ha, sip_peer::language, ast_cli_args::line, sip_peer::maxcallbitrate, sip_peer::md5secret, ast_cli_args::n, ast_variable::name, sip_peer::name, ast_variable::next, sip_peer::pickupgroup, ast_cli_args::pos, sip_peer::prefs, print_codec_to_cli(), print_group(), sip_peer::secret, SIP_PAGE2_IGNORESDPVERSION, sip_st_cfg::st_max_se, sip_st_cfg::st_min_se, sip_st_cfg::st_mode_oper, sip_st_cfg::st_ref, sip_peer::stimer, stmode2str(), strefresher2str(), transfermode2str(), TRUE, unref_peer(), ast_cli_entry::usage, ast_variable::value, and ast_cli_args::word.
14829 { 14830 char cbuf[256]; 14831 struct sip_peer *user; 14832 struct ast_variable *v; 14833 int load_realtime; 14834 14835 switch (cmd) { 14836 case CLI_INIT: 14837 e->command = "sip show user"; 14838 e->usage = 14839 "Usage: sip show user <name> [load]\n" 14840 " Shows all details on one SIP user and the current status.\n" 14841 " Option \"load\" forces lookup of peer in realtime storage.\n"; 14842 return NULL; 14843 case CLI_GENERATE: 14844 return complete_sip_show_user(a->line, a->word, a->pos, a->n); 14845 } 14846 14847 if (a->argc < 4) 14848 return CLI_SHOWUSAGE; 14849 14850 /* Load from realtime storage? */ 14851 load_realtime = (a->argc == 5 && !strcmp(a->argv[4], "load")) ? TRUE : FALSE; 14852 14853 if ((user = find_peer(a->argv[3], NULL, load_realtime, FINDUSERS, FALSE, 0))) { 14854 ao2_lock(user); 14855 ast_cli(a->fd, "\n\n"); 14856 ast_cli(a->fd, " * Name : %s\n", user->name); 14857 ast_cli(a->fd, " Secret : %s\n", ast_strlen_zero(user->secret)?"<Not set>":"<Set>"); 14858 ast_cli(a->fd, " MD5Secret : %s\n", ast_strlen_zero(user->md5secret)?"<Not set>":"<Set>"); 14859 ast_cli(a->fd, " Context : %s\n", user->context); 14860 ast_cli(a->fd, " Language : %s\n", user->language); 14861 if (!ast_strlen_zero(user->accountcode)) 14862 ast_cli(a->fd, " Accountcode : %s\n", user->accountcode); 14863 ast_cli(a->fd, " AMA flags : %s\n", ast_cdr_flags2str(user->amaflags)); 14864 ast_cli(a->fd, " Transfer mode: %s\n", transfermode2str(user->allowtransfer)); 14865 ast_cli(a->fd, " MaxCallBR : %d kbps\n", user->maxcallbitrate); 14866 ast_cli(a->fd, " CallingPres : %s\n", ast_describe_caller_presentation(user->callingpres)); 14867 ast_cli(a->fd, " Call limit : %d\n", user->call_limit); 14868 ast_cli(a->fd, " Callgroup : "); 14869 print_group(a->fd, user->callgroup, 0); 14870 ast_cli(a->fd, " Pickupgroup : "); 14871 print_group(a->fd, user->pickupgroup, 0); 14872 ast_cli(a->fd, " Callerid : %s\n", ast_callerid_merge(cbuf, sizeof(cbuf), user->cid_name, user->cid_num, "<unspecified>")); 14873 ast_cli(a->fd, " ACL : %s\n", cli_yesno(user->ha != NULL)); 14874 ast_cli(a->fd, " Sess-Timers : %s\n", stmode2str(user->stimer.st_mode_oper)); 14875 ast_cli(a->fd, " Sess-Refresh : %s\n", strefresher2str(user->stimer.st_ref)); 14876 ast_cli(a->fd, " Sess-Expires : %d secs\n", user->stimer.st_max_se); 14877 ast_cli(a->fd, " Sess-Min-SE : %d secs\n", user->stimer.st_min_se); 14878 ast_cli(a->fd, " Ign SDP ver : %s\n", cli_yesno(ast_test_flag(&user->flags[1], SIP_PAGE2_IGNORESDPVERSION))); 14879 14880 ast_cli(a->fd, " Codec Order : ("); 14881 print_codec_to_cli(a->fd, &user->prefs); 14882 ast_cli(a->fd, ")\n"); 14883 14884 ast_cli(a->fd, " Auto-Framing: %s \n", cli_yesno(user->autoframing)); 14885 if (user->chanvars) { 14886 ast_cli(a->fd, " Variables :\n"); 14887 for (v = user->chanvars ; v ; v = v->next) 14888 ast_cli(a->fd, " %s = %s\n", v->name, v->value); 14889 } 14890 14891 ast_cli(a->fd, "\n"); 14892 14893 ao2_unlock(user); 14894 unref_peer(user, "sip show user"); 14895 } else { 14896 ast_cli(a->fd, "User %s not found.\n", a->argv[3]); 14897 ast_cli(a->fd, "\n"); 14898 } 14899 14900 return CLI_SUCCESS; 14901 }
| 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 13681 of file chan_sip.c.
References sip_peer::accountcode, 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, sip_peer::context, FALSE, ast_cli_args::fd, sip_peer::flags, FORMAT, sip_peer::ha, sip_peer::name, nat2str(), sip_peer::secret, SIP_NAT, SIP_TYPE_USER, TRUE, sip_peer::type, unref_peer(), and ast_cli_entry::usage.
13682 { 13683 regex_t regexbuf; 13684 int havepattern = FALSE; 13685 struct ao2_iterator user_iter; 13686 struct sip_peer *user; 13687 13688 #define FORMAT "%-25.25s %-15.15s %-15.15s %-15.15s %-5.5s%-10.10s\n" 13689 13690 switch (cmd) { 13691 case CLI_INIT: 13692 e->command = "sip show users"; 13693 e->usage = 13694 "Usage: sip show users [like <pattern>]\n" 13695 " Lists all known SIP users.\n" 13696 " Optional regular expression pattern is used to filter the user list.\n"; 13697 return NULL; 13698 case CLI_GENERATE: 13699 return NULL; 13700 } 13701 13702 switch (a->argc) { 13703 case 5: 13704 if (!strcasecmp(a->argv[3], "like")) { 13705 if (regcomp(®exbuf, a->argv[4], REG_EXTENDED | REG_NOSUB)) 13706 return CLI_SHOWUSAGE; 13707 havepattern = TRUE; 13708 } else 13709 return CLI_SHOWUSAGE; 13710 case 3: 13711 break; 13712 default: 13713 return CLI_SHOWUSAGE; 13714 } 13715 13716 ast_cli(a->fd, FORMAT, "Username", "Secret", "Accountcode", "Def.Context", "ACL", "NAT"); 13717 13718 user_iter = ao2_iterator_init(peers, 0); 13719 while ((user = ao2_iterator_next(&user_iter))) { 13720 ao2_lock(user); 13721 if (!(user->type & SIP_TYPE_USER)) { 13722 ao2_unlock(user); 13723 unref_peer(user, "sip show users"); 13724 continue; 13725 } 13726 13727 if (havepattern && regexec(®exbuf, user->name, 0, NULL, 0)) { 13728 ao2_unlock(user); 13729 unref_peer(user, "sip show users"); 13730 continue; 13731 } 13732 13733 ast_cli(a->fd, FORMAT, user->name, 13734 user->secret, 13735 user->accountcode, 13736 user->context, 13737 cli_yesno(user->ha != NULL), 13738 nat2str(ast_test_flag(&user->flags[0], SIP_NAT))); 13739 ao2_unlock(user); 13740 unref_peer(user, "sip show users"); 13741 } 13742 ao2_iterator_destroy(&user_iter); 13743 13744 if (havepattern) 13745 regfree(®exbuf); 13746 13747 return CLI_SUCCESS; 13748 #undef FORMAT 13749 }
| static int sip_sipredirect | ( | struct sip_pvt * | p, | |
| const char * | dest | |||
| ) | [static] |
Transfer call before connect with a 302 redirect.
Definition at line 24449 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().
24450 { 24451 char *cdest; 24452 char *extension, *host, *port; 24453 char tmp[80]; 24454 24455 cdest = ast_strdupa(dest); 24456 24457 extension = strsep(&cdest, "@"); 24458 host = strsep(&cdest, ":"); 24459 port = strsep(&cdest, ":"); 24460 if (ast_strlen_zero(extension)) { 24461 ast_log(LOG_ERROR, "Missing mandatory argument: extension\n"); 24462 return 0; 24463 } 24464 24465 /* we'll issue the redirect message here */ 24466 if (!host) { 24467 char *localtmp; 24468 24469 ast_copy_string(tmp, get_header(&p->initreq, "To"), sizeof(tmp)); 24470 if (ast_strlen_zero(tmp)) { 24471 ast_log(LOG_ERROR, "Cannot retrieve the 'To' header from the original SIP request!\n"); 24472 return 0; 24473 } 24474 if ( ( (localtmp = strcasestr(tmp, "sip:")) || (localtmp = strcasestr(tmp, "sips:")) ) 24475 && (localtmp = strchr(localtmp, '@'))) { 24476 char lhost[80], lport[80]; 24477 24478 memset(lhost, 0, sizeof(lhost)); 24479 memset(lport, 0, sizeof(lport)); 24480 localtmp++; 24481 /* This is okey because lhost and lport are as big as tmp */ 24482 sscanf(localtmp, "%80[^<>:; ]:%80[^<>:; ]", lhost, lport); 24483 if (ast_strlen_zero(lhost)) { 24484 ast_log(LOG_ERROR, "Can't find the host address\n"); 24485 return 0; 24486 } 24487 host = ast_strdupa(lhost); 24488 if (!ast_strlen_zero(lport)) { 24489 port = ast_strdupa(lport); 24490 } 24491 } 24492 } 24493 24494 ast_string_field_build(p, our_contact, "Transfer <sip:%s@%s%s%s>", extension, host, port ? ":" : "", port ? port : ""); 24495 transmit_response_reliable(p, "302 Moved Temporarily", &p->initreq); 24496 24497 sip_scheddestroy(p, SIP_TRANS_TIMEOUT); /* Make sure we stop send this reply. */ 24498 sip_alreadygone(p); 24499 /* hangup here */ 24500 return 0; 24501 }
| static struct sip_st_dlg * sip_st_alloc | ( | struct sip_pvt *const | p | ) | [static, read] |
Allocate Session-Timers struct w/in dialog.
Definition at line 6716 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().
06717 { 06718 struct sip_st_dlg *stp; 06719 06720 if (p->stimer) { 06721 ast_log(LOG_ERROR, "Session-Timer struct already allocated\n"); 06722 return p->stimer; 06723 } 06724 06725 if (!(stp = ast_calloc(1, sizeof(struct sip_st_dlg)))) 06726 return NULL; 06727 06728 p->stimer = stp; 06729 06730 stp->st_schedid = -1; /* Session-Timers ast_sched scheduler id */ 06731 06732 return p->stimer; 06733 }
| 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 21094 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().
21095 { 21096 if (type & SIP_TRANSPORT_TLS) 21097 return port == STANDARD_TLS_PORT; 21098 else 21099 return port == STANDARD_SIP_PORT; 21100 }
| static int sip_t38_abort | ( | const void * | data | ) | [static] |
Definition at line 18739 of file chan_sip.c.
References change_t38_state(), dialog_unref(), sip_pvt::initreq, T38_DISABLED, sip_pvt::t38id, and transmit_response_reliable().
Referenced by handle_request_invite().
18740 { 18741 struct sip_pvt *p = (struct sip_pvt *) data; 18742 18743 change_t38_state(p, T38_DISABLED); 18744 transmit_response_reliable(p, "488 Not acceptable here", &p->initreq); 18745 p->t38id = -1; 18746 dialog_unref(p, "unref the dialog ptr from sip_t38_abort, because it held a dialog ptr"); 18747 18748 return 0; 18749 }
| static struct ast_tcptls_session_instance* sip_tcp_locate | ( | struct sockaddr_in * | s | ) | [static, read] |
Find thread for TCP/TLS session (based on IP/Port.
Definition at line 21119 of file chan_sip.c.
References ao2_callback, ao2_ref, ao2_t_ref, sip_threadinfo::tcptls_session, and threadinfo_locate_cb().
Referenced by sip_prepare_socket().
21120 { 21121 struct sip_threadinfo *th; 21122 struct ast_tcptls_session_instance *tcptls_instance = NULL; 21123 21124 if ((th = ao2_callback(threadt, 0, threadinfo_locate_cb, s))) { 21125 tcptls_instance = (ao2_ref(th->tcptls_session, +1), th->tcptls_session); 21126 ao2_t_ref(th, -1, "decrement ref from callback"); 21127 } 21128 return tcptls_instance; 21129 }
| static void * sip_tcp_worker_fn | ( | void * | data | ) | [static] |
SIP TCP connection handler.
Definition at line 2535 of file chan_sip.c.
References _sip_tcp_helper_thread().
Referenced by sip_prepare_socket().
02536 { 02537 struct ast_tcptls_session_instance *tcptls_session = data; 02538 02539 return _sip_tcp_helper_thread(NULL, tcptls_session); 02540 }
| static void sip_tcptls_client_args_destructor | ( | void * | obj | ) | [static] |
Definition at line 2418 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().
02419 { 02420 struct ast_tcptls_session_args *args = obj; 02421 if (args->tls_cfg) { 02422 ast_free(args->tls_cfg->certfile); 02423 ast_free(args->tls_cfg->cipher); 02424 ast_free(args->tls_cfg->cafile); 02425 ast_free(args->tls_cfg->capath); 02426 } 02427 ast_free(args->tls_cfg); 02428 ast_free((char *) args->name); 02429 }
| 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 2477 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(), tcptls_packet::data, errno, ast_tcptls_session_instance::fd, tcptls_packet::len, ast_tcptls_session_instance::lock, LOG_ERROR, OBJ_POINTER, sip_threadinfo::packet_q, TCPTLS_ALERT_DATA, tcptls_packet_destructor(), sip_threadinfo::tcptls_session, and XMIT_ERROR.
Referenced by __sip_xmit().
02478 { 02479 int res = len; 02480 struct sip_threadinfo *th = NULL; 02481 struct tcptls_packet *packet = NULL; 02482 struct sip_threadinfo tmp = { 02483 .tcptls_session = tcptls_session, 02484 }; 02485 enum sip_tcptls_alert alert = TCPTLS_ALERT_DATA; 02486 02487 if (!tcptls_session) { 02488 return XMIT_ERROR; 02489 } 02490 02491 ast_mutex_lock(&tcptls_session->lock); 02492 02493 if ((tcptls_session->fd == -1) || 02494 !(th = ao2_t_find(threadt, &tmp, OBJ_POINTER, "ao2_find, getting sip_threadinfo in tcp helper thread")) || 02495 !(packet = ao2_alloc(sizeof(*packet), tcptls_packet_destructor)) || 02496 !(packet->data = ast_str_create(len))) { 02497 goto tcptls_write_setup_error; 02498 } 02499 02500 /* goto tcptls_write_error should _NOT_ be used beyond this point */ 02501 ast_str_set(&packet->data, 0, "%s", (char *) buf); 02502 packet->len = len; 02503 02504 /* alert tcptls thread handler that there is a packet to be sent. 02505 * must lock the thread info object to guarantee control of the 02506 * packet queue */ 02507 ao2_lock(th); 02508 if (write(th->alert_pipe[1], &alert, sizeof(alert)) == -1) { 02509 ast_log(LOG_ERROR, "write() to alert pipe failed: %s\n", strerror(errno)); 02510 ao2_t_ref(packet, -1, "could not write to alert pipe, remove packet"); 02511 packet = NULL; 02512 res = XMIT_ERROR; 02513 } else { /* it is safe to queue the frame after issuing the alert when we hold the threadinfo lock */ 02514 AST_LIST_INSERT_TAIL(&th->packet_q, packet, entry); 02515 } 02516 ao2_unlock(th); 02517 02518 ast_mutex_unlock(&tcptls_session->lock); 02519 ao2_t_ref(th, -1, "In sip_tcptls_write, unref threadinfo object after finding it"); 02520 return res; 02521 02522 tcptls_write_setup_error: 02523 if (th) { 02524 ao2_t_ref(th, -1, "In sip_tcptls_write, unref threadinfo obj, could not create packet"); 02525 } 02526 if (packet) { 02527 ao2_t_ref(packet, -1, "could not allocate packet's data"); 02528 } 02529 ast_mutex_unlock(&tcptls_session->lock); 02530 02531 return XMIT_ERROR; 02532 }
| static struct sip_threadinfo* sip_threadinfo_create | ( | struct ast_tcptls_session_instance * | tcptls_session, | |
| int | transport | |||
| ) | [static, read] |
creates a sip_threadinfo object and links it into the threadt table.
Definition at line 2453 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 sip_threadinfo::type.
Referenced by _sip_tcp_helper_thread(), and sip_prepare_socket().
02454 { 02455 struct sip_threadinfo *th; 02456 02457 if (!tcptls_session || !(th = ao2_alloc(sizeof(*th), sip_threadinfo_destructor))) { 02458 return NULL; 02459 } 02460 02461 th->alert_pipe[0] = th->alert_pipe[1] = -1; 02462 02463 if (pipe(th->alert_pipe) == -1) { 02464 ao2_t_ref(th, -1, "Failed to open alert pipe on sip_threadinfo"); 02465 ast_log(LOG_ERROR, "Could not create sip alert pipe in tcptls thread, error %s\n", strerror(errno)); 02466 return NULL; 02467 } 02468 ao2_t_ref(tcptls_session, +1, "tcptls_session ref for sip_threadinfo object"); 02469 th->tcptls_session = tcptls_session; 02470 th->type = transport ? transport : (tcptls_session->ssl ? SIP_TRANSPORT_TLS: SIP_TRANSPORT_TCP); 02471 ao2_t_link(threadt, th, "Adding new tcptls helper thread"); 02472 ao2_t_ref(th, -1, "Decrementing threadinfo ref from alloc, only table ref remains"); 02473 return th; 02474 }
| static void sip_threadinfo_destructor | ( | void * | obj | ) | [static] |
Definition at line 2431 of file chan_sip.c.
References sip_threadinfo::alert_pipe, ao2_t_ref, AST_LIST_REMOVE_HEAD, sip_threadinfo::packet_q, and sip_threadinfo::tcptls_session.
Referenced by sip_threadinfo_create().
02432 { 02433 struct sip_threadinfo *th = obj; 02434 struct tcptls_packet *packet; 02435 if (th->alert_pipe[1] > -1) { 02436 close(th->alert_pipe[0]); 02437 } 02438 if (th->alert_pipe[1] > -1) { 02439 close(th->alert_pipe[1]); 02440 } 02441 th->alert_pipe[0] = th->alert_pipe[1] = -1; 02442 02443 while ((packet = AST_LIST_REMOVE_HEAD(&th->packet_q, entry))) { 02444 ao2_t_ref(packet, -1, "thread destruction, removing packet from frame queue"); 02445 } 02446 02447 if (th->tcptls_session) { 02448 ao2_t_ref(th->tcptls_session, -1, "remove tcptls_session for sip_threadinfo object"); 02449 } 02450 }
| static int sip_transfer | ( | struct ast_channel * | ast, | |
| const char * | dest | |||
| ) | [static] |
Transfer SIP call.
Definition at line 6004 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().
06005 { 06006 struct sip_pvt *p = ast->tech_pvt; 06007 int res; 06008 06009 if (dest == NULL) /* functions below do not take a NULL */ 06010 dest = ""; 06011 sip_pvt_lock(p); 06012 if (ast->_state == AST_STATE_RING) 06013 res = sip_sipredirect(p, dest); 06014 else 06015 res = transmit_refer(p, dest); 06016 sip_pvt_unlock(p); 06017 return res; 06018 }
| 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 14993 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(), TRUE, unref_peer(), ast_cli_entry::usage, and ast_cli_args::word.
14994 { 14995 struct sip_peer *peer; 14996 int load_realtime = 0; 14997 14998 switch (cmd) { 14999 case CLI_INIT: 15000 e->command = "sip unregister"; 15001 e->usage = 15002 "Usage: sip unregister <peer>\n" 15003 " Unregister (force expiration) a SIP peer from the registry\n"; 15004 return NULL; 15005 case CLI_GENERATE: 15006 return complete_sip_unregister(a->line, a->word, a->pos, a->n); 15007 } 15008 15009 if (a->argc != 3) 15010 return CLI_SHOWUSAGE; 15011 15012 if ((peer = find_peer(a->argv[2], NULL, load_realtime, FINDPEERS, TRUE, 0))) { 15013 if (peer->expire > 0) { 15014 AST_SCHED_DEL_UNREF(sched, peer->expire, 15015 unref_peer(peer, "remove register expire ref")); 15016 expire_register(ref_peer(peer, "ref for expire_register")); 15017 ast_cli(a->fd, "Unregistered peer \'%s\'\n\n", a->argv[2]); 15018 } else { 15019 ast_cli(a->fd, "Peer %s not registered\n", a->argv[2]); 15020 } 15021 unref_peer(peer, "sip_unregister: unref_peer via sip_unregister: done with peer from find_peer call"); 15022 } else { 15023 ast_cli(a->fd, "Peer unknown: \'%s\'. Not unregistered.\n", a->argv[2]); 15024 } 15025 15026 return CLI_SUCCESS; 15027 }
| static int sip_uri_cmp | ( | const char * | input1, | |
| const char * | input2 | |||
| ) | [static] |
Definition at line 18656 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().
18657 { 18658 char *uri1 = ast_strdupa(input1); 18659 char *uri2 = ast_strdupa(input2); 18660 char *host1; 18661 char *host2; 18662 char *params1; 18663 char *params2; 18664 char *headers1; 18665 char *headers2; 18666 18667 /* Strip off "sip:" from the URI. We know this is present 18668 * because it was checked back in parse_request() 18669 */ 18670 strsep(&uri1, ":"); 18671 strsep(&uri2, ":"); 18672 18673 if ((host1 = strchr(uri1, '@'))) { 18674 *host1++ = '\0'; 18675 } 18676 if ((host2 = strchr(uri2, '@'))) { 18677 *host2++ = '\0'; 18678 } 18679 18680 /* Check for mismatched username and passwords. This is the 18681 * only case-sensitive comparison of a SIP URI 18682 */ 18683 if ((host1 && !host2) || 18684 (host2 && !host1) || 18685 (host1 && host2 && strcmp(uri1, uri2))) { 18686 return 1; 18687 } 18688 18689 if (!host1) 18690 host1 = uri1; 18691 if (!host2) 18692 host2 = uri2; 18693 18694 /* Strip off the parameters and headers so we can compare 18695 * host and port 18696 */ 18697 18698 if ((params1 = strchr(host1, ';'))) { 18699 *params1++ = '\0'; 18700 } 18701 if ((params2 = strchr(host2, ';'))) { 18702 *params2++ = '\0'; 18703 } 18704 18705 /* Headers come after parameters, but there may be headers without 18706 * parameters, thus the S_OR 18707 */ 18708 if ((headers1 = strchr(S_OR(params1, host1), '?'))) { 18709 *headers1++ = '\0'; 18710 } 18711 if ((headers2 = strchr(S_OR(params2, host2), '?'))) { 18712 *headers2++ = '\0'; 18713 } 18714 18715 /* Now the host/port are properly isolated. We can get by with a string comparison 18716 * because the SIP URI checking rules have some interesting exceptions that make 18717 * this possible. I will note 2 in particular 18718 * 1. hostnames which resolve to the same IP address as well as a hostname and its 18719 * IP address are not considered a match with SIP URI's. 18720 * 2. If one URI specifies a port and the other does not, then the URIs do not match. 18721 * This includes if one URI explicitly contains port 5060 and the other implies it 18722 * by not having a port specified. 18723 */ 18724 18725 if (strcasecmp(host1, host2)) { 18726 return 1; 18727 } 18728 18729 /* Headers have easier rules to follow, so do those first */ 18730 if (sip_uri_headers_cmp(headers1, headers2)) { 18731 return 1; 18732 } 18733 18734 /* And now the parameters. Ugh */ 18735 return sip_uri_params_cmp(params1, params2); 18736 }
| 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 18610 of file chan_sip.c.
References ast_strdupa, ast_strlen_zero(), strcasestr(), and strsep().
Referenced by sip_uri_cmp().
18611 { 18612 char *headers1 = NULL; 18613 char *headers2 = NULL; 18614 int zerolength1 = 0; 18615 int zerolength2 = 0; 18616 int different = 0; 18617 char *header1; 18618 18619 if (ast_strlen_zero(input1)) { 18620 zerolength1 = 1; 18621 } else { 18622 headers1 = ast_strdupa(input1); 18623 } 18624 18625 if (ast_strlen_zero(input2)) { 18626 zerolength2 = 1; 18627 } else { 18628 headers2 = ast_strdupa(input2); 18629 } 18630 18631 if ((zerolength1 && !zerolength2) || 18632 (zerolength2 && !zerolength1)) 18633 return 1; 18634 18635 if (zerolength1 && zerolength2) 18636 return 0; 18637 18638 /* At this point, we can definitively state that both inputs are 18639 * not zero-length. First, one more optimization. If the length 18640 * of the headers is not equal, then we definitely have no match 18641 */ 18642 if (strlen(headers1) != strlen(headers2)) { 18643 return 1; 18644 } 18645 18646 for (header1 = strsep(&headers1, "&"); header1; header1 = strsep(&headers1, "&")) { 18647 if (!strcasestr(headers2, header1)) { 18648 different = 1; 18649 break; 18650 } 18651 } 18652 18653 return different; 18654 }
| 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 18470 of file chan_sip.c.
References ast_strdupa, and ast_strlen_zero().
Referenced by sip_uri_cmp().
18471 { 18472 char *params1 = NULL; 18473 char *params2 = NULL; 18474 char *pos1; 18475 char *pos2; 18476 int zerolength1 = 0; 18477 int zerolength2 = 0; 18478 int maddrmatch = 0; 18479 int ttlmatch = 0; 18480 int usermatch = 0; 18481 int methodmatch = 0; 18482 18483 if (ast_strlen_zero(input1)) { 18484 zerolength1 = 1; 18485 } else { 18486 params1 = ast_strdupa(input1); 18487 } 18488 if (ast_strlen_zero(input2)) { 18489 zerolength2 = 1; 18490 } else { 18491 params2 = ast_strdupa(input2); 18492 } 18493 18494 /*Quick optimization. If both params are zero-length, then 18495 * they match 18496 */ 18497 if (zerolength1 && zerolength2) { 18498 return 0; 18499 } 18500 18501 pos1 = params1; 18502 while (!ast_strlen_zero(pos1)) { 18503 char *name1 = pos1; 18504 char *value1 = strchr(pos1, '='); 18505 char *semicolon1 = strchr(pos1, ';'); 18506 int matched = 0; 18507 if (semicolon1) { 18508 *semicolon1++ = '\0'; 18509 } 18510 if (!value1) { 18511 goto fail; 18512 } 18513 *value1++ = '\0'; 18514 /* Checkpoint reached. We have the name and value parsed for param1 18515 * We have to duplicate params2 each time through the second loop 18516 * or else we can't search and replace the semicolons with \0 each 18517 * time 18518 */ 18519 pos2 = ast_strdupa(params2); 18520 while (!ast_strlen_zero(pos2)) { 18521 char *name2 = pos2; 18522 char *value2 = strchr(pos2, '='); 18523 char *semicolon2 = strchr(pos2, ';'); 18524 if (semicolon2) { 18525 *semicolon2++ = '\0'; 18526 } 18527 if (!value2) { 18528 goto fail; 18529 } 18530 *value2++ = '\0'; 18531 if (!strcasecmp(name1, name2)) { 18532 if (strcasecmp(value1, value2)) { 18533 goto fail; 18534 } else { 18535 matched = 1; 18536 break; 18537 } 18538 } 18539 pos2 = semicolon2; 18540 } 18541 /* Need to see if the parameter we're looking at is one of the 'must-match' parameters */ 18542 if (!strcasecmp(name1, "maddr")) { 18543 if (matched) { 18544 maddrmatch = 1; 18545 } else { 18546 goto fail; 18547 } 18548 } else if (!strcasecmp(name1, "ttl")) { 18549 if (matched) { 18550 ttlmatch = 1; 18551 } else { 18552 goto fail; 18553 } 18554 } else if (!strcasecmp(name1, "user")) { 18555 if (matched) { 18556 usermatch = 1; 18557 } else { 18558 goto fail; 18559 } 18560 } else if (!strcasecmp(name1, "method")) { 18561 if (matched) { 18562 methodmatch = 1; 18563 } else { 18564 goto fail; 18565 } 18566 } 18567 pos1 = semicolon1; 18568 } 18569 18570 /* We've made it out of that horrible O(m*n) construct and there are no 18571 * failures yet. We're not done yet, though, because params2 could have 18572 * an maddr, ttl, user, or method header and params1 did not. 18573 */ 18574 pos2 = params2; 18575 while (!ast_strlen_zero(pos2)) { 18576 char *name2 = pos2; 18577 char *value2 = strchr(pos2, '='); 18578 char *semicolon2 = strchr(pos2, ';'); 18579 if (semicolon2) { 18580 *semicolon2++ = '\0'; 18581 } 18582 if (!value2) { 18583 goto fail; 18584 } 18585 *value2++ = '\0'; 18586 if ((!strcasecmp(name2, "maddr") && !maddrmatch) || 18587 (!strcasecmp(name2, "ttl") && !ttlmatch) || 18588 (!strcasecmp(name2, "user") && !usermatch) || 18589 (!strcasecmp(name2, "method") && !methodmatch)) { 18590 goto fail; 18591 } 18592 } 18593 return 0; 18594 18595 fail: 18596 return 1; 18597 }
| static int sip_write | ( | struct ast_channel * | ast, | |
| struct ast_frame * | frame | |||
| ) | [static] |
Send frame to media channel (rtp).
Definition at line 5804 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(), sip_pvt::flags, ast_frame::frametype, sip_pvt::initreq, INV_EARLY_MEDIA, sip_pvt::invitestate, sip_pvt::lastrtptx, LOG_WARNING, ast_channel::nativeformats, ast_channel::readformat, sip_pvt::red, red_buffer_t140(), sip_pvt::rtp, SIP_OUTGOING, SIP_PROGRESS_SENT, sip_pvt_lock, sip_pvt_unlock, t38properties::state, ast_frame::subclass, sip_pvt::t38, T38_ENABLED, ast_channel::tech_pvt, transmit_provisional_response(), sip_pvt::trtp, TRUE, sip_pvt::udptl, sip_pvt::vrtp, and ast_channel::writeformat.
05805 { 05806 struct sip_pvt *p = ast->tech_pvt; 05807 int res = 0; 05808 05809 switch (frame->frametype) { 05810 case AST_FRAME_VOICE: 05811 if (!(frame->subclass & ast->nativeformats)) { 05812 char s1[512], s2[512], s3[512]; 05813 ast_log(LOG_WARNING, "Asked to transmit frame type %d, while native formats is %s(%d) read/write = %s(%d)/%s(%d)\n", 05814 frame->subclass, 05815 ast_getformatname_multiple(s1, sizeof(s1) - 1, ast->nativeformats & AST_FORMAT_AUDIO_MASK), 05816 ast->nativeformats & AST_FORMAT_AUDIO_MASK, 05817 ast_getformatname_multiple(s2, sizeof(s2) - 1, ast->readformat), 05818 ast->readformat, 05819 ast_getformatname_multiple(s3, sizeof(s3) - 1, ast->writeformat), 05820 ast->writeformat); 05821 return 0; 05822 } 05823 if (p) { 05824 sip_pvt_lock(p); 05825 if (p->rtp) { 05826 /* If channel is not up, activate early media session */ 05827 if ((ast->_state != AST_STATE_UP) && 05828 !ast_test_flag(&p->flags[0], SIP_PROGRESS_SENT) && 05829 !ast_test_flag(&p->flags[0], SIP_OUTGOING)) { 05830 ast_rtp_new_source(p->rtp); 05831 if (!global_prematuremediafilter) { 05832 p->invitestate = INV_EARLY_MEDIA; 05833 transmit_provisional_response(p, "183 Session Progress", &p->initreq, TRUE); 05834 ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT); 05835 } 05836 } else if (p->t38.state == T38_ENABLED) { 05837 /* drop frame, can't sent VOICE frames while in T.38 mode */ 05838 } else { 05839 p->lastrtptx = time(NULL); 05840 res = ast_rtp_write(p->rtp, frame); 05841 } 05842 } 05843 sip_pvt_unlock(p); 05844 } 05845 break; 05846 case AST_FRAME_VIDEO: 05847 if (p) { 05848 sip_pvt_lock(p); 05849 if (p->vrtp) { 05850 /* Activate video early media */ 05851 if ((ast->_state != AST_STATE_UP) && 05852 !ast_test_flag(&p->flags[0], SIP_PROGRESS_SENT) && 05853 !ast_test_flag(&p->flags[0], SIP_OUTGOING)) { 05854 p->invitestate = INV_EARLY_MEDIA; 05855 transmit_provisional_response(p, "183 Session Progress", &p->initreq, TRUE); 05856 ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT); 05857 } 05858 p->lastrtptx = time(NULL); 05859 res = ast_rtp_write(p->vrtp, frame); 05860 } 05861 sip_pvt_unlock(p); 05862 } 05863 break; 05864 case AST_FRAME_TEXT: 05865 if (p) { 05866 sip_pvt_lock(p); 05867 if (p->red) { 05868 red_buffer_t140(p->trtp, frame); 05869 } else { 05870 if (p->trtp) { 05871 /* Activate text early media */ 05872 if ((ast->_state != AST_STATE_UP) && 05873 !ast_test_flag(&p->flags[0], SIP_PROGRESS_SENT) && 05874 !ast_test_flag(&p->flags[0], SIP_OUTGOING)) { 05875 p->invitestate = INV_EARLY_MEDIA; 05876 transmit_provisional_response(p, "183 Session Progress", &p->initreq, TRUE); 05877 ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT); 05878 } 05879 p->lastrtptx = time(NULL); 05880 res = ast_rtp_write(p->trtp, frame); 05881 } 05882 } 05883 sip_pvt_unlock(p); 05884 } 05885 break; 05886 case AST_FRAME_IMAGE: 05887 return 0; 05888 break; 05889 case AST_FRAME_MODEM: 05890 if (p) { 05891 sip_pvt_lock(p); 05892 /* UDPTL requires two-way communication, so early media is not needed here. 05893 we simply forget the frames if we get modem frames before the bridge is up. 05894 Fax will re-transmit. 05895 */ 05896 if ((ast->_state == AST_STATE_UP) && 05897 p->udptl && 05898 (p->t38.state == T38_ENABLED)) { 05899 res = ast_udptl_write(p->udptl, frame); 05900 } 05901 sip_pvt_unlock(p); 05902 } 05903 break; 05904 default: 05905 ast_log(LOG_WARNING, "Can't send %d type frames with SIP write\n", frame->frametype); 05906 return 0; 05907 } 05908 05909 return res; 05910 }
| static int sipsock_read | ( | int * | id, | |
| int | fd, | |||
| short | events, | |||
| void * | ignore | |||
| ) | [static] |
Read data from SIP socket.
Definition at line 20933 of file chan_sip.c.
References AST_DYNSTR_BUILD_FAILED, ast_free, ast_log(), ast_str_create(), ast_str_set(), bindaddr, sip_request::data, errno, sip_socket::fd, handle_request_do(), sip_request::len, LOG_NOTICE, LOG_WARNING, sip_socket::port, set_socket_transport(), SIP_MIN_PACKET, SIP_TRANSPORT_UDP, sip_request::socket, and sip_socket::tcptls_session.
Referenced by do_monitor().
20934 { 20935 struct sip_request req; 20936 struct sockaddr_in sin = { 0, }; 20937 int res; 20938 socklen_t len = sizeof(sin); 20939 static char readbuf[65535]; 20940 20941 memset(&req, 0, sizeof(req)); 20942 res = recvfrom(fd, readbuf, sizeof(readbuf) - 1, 0, (struct sockaddr *)&sin, &len); 20943 if (res < 0) { 20944 #if !defined(__FreeBSD__) 20945 if (errno == EAGAIN) 20946 ast_log(LOG_NOTICE, "SIP: Received packet with bad UDP checksum\n"); 20947 else 20948 #endif 20949 if (errno != ECONNREFUSED) 20950 ast_log(LOG_WARNING, "Recv error: %s\n", strerror(errno)); 20951 return 1; 20952 } 20953 20954 readbuf[res] = '\0'; 20955 20956 if (!(req.data = ast_str_create(SIP_MIN_PACKET))) { 20957 return 1; 20958 } 20959 20960 if (ast_str_set(&req.data, 0, "%s", readbuf) == AST_DYNSTR_BUILD_FAILED) { 20961 return -1; 20962 } 20963 20964 req.len = res; 20965 req.socket.fd = sipsock; 20966 set_socket_transport(&req.socket, SIP_TRANSPORT_UDP); 20967 req.socket.tcptls_session = NULL; 20968 req.socket.port = bindaddr.sin_port; 20969 20970 handle_request_do(&req, &sin); 20971 if (req.data) { 20972 ast_free(req.data); 20973 req.data = NULL; 20974 } 20975 20976 return 1; 20977 }
Get the session-timer mode.
| p | pointer to the SIP dialog |
Definition at line 21864 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_st_cfg::st_mode_oper, sip_peer::stimer, sip_pvt::stimer, TRUE, and unref_peer().
Referenced by handle_request_invite(), handle_response_invite(), and transmit_invite().
21865 { 21866 if (!p->stimer) 21867 sip_st_alloc(p); 21868 21869 if (p->stimer->st_cached_mode != SESSION_TIMER_MODE_INVALID) 21870 return p->stimer->st_cached_mode; 21871 21872 if (p->peername) { 21873 struct sip_peer *pp = find_peer(p->peername, NULL, TRUE, FINDPEERS, FALSE, 0); 21874 if (pp) { 21875 p->stimer->st_cached_mode = pp->stimer.st_mode_oper; 21876 unref_peer(pp, "unref peer pointer from find_peer call in st_get_mode"); 21877 return pp->stimer.st_mode_oper; 21878 } 21879 } 21880 21881 p->stimer->st_cached_mode = global_st_mode; 21882 return global_st_mode; 21883 }
| 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 21842 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_st_cfg::st_ref, sip_peer::stimer, sip_pvt::stimer, TRUE, and unref_peer().
Referenced by handle_request_invite().
21843 { 21844 if (p->stimer->st_cached_ref != SESSION_TIMER_REFRESHER_AUTO) 21845 return p->stimer->st_cached_ref; 21846 21847 if (p->peername) { 21848 struct sip_peer *pp = find_peer(p->peername, NULL, TRUE, FINDPEERS, FALSE, 0); 21849 if (pp) { 21850 p->stimer->st_cached_ref = pp->stimer.st_ref; 21851 unref_peer(pp, "unref peer pointer from find_peer call in st_get_refresher"); 21852 return pp->stimer.st_ref; 21853 } 21854 } 21855 21856 p->stimer->st_cached_ref = global_st_refresher; 21857 return global_st_refresher; 21858 }
| 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 21807 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_st_cfg::st_max_se, sip_st_cfg::st_min_se, sip_peer::stimer, sip_pvt::stimer, TRUE, and unref_peer().
Referenced by handle_request_invite(), reqprep(), and transmit_invite().
21808 { 21809 if (max == TRUE) { 21810 if (p->stimer->st_cached_max_se) { 21811 return p->stimer->st_cached_max_se; 21812 } else if (p->peername) { 21813 struct sip_peer *pp = find_peer(p->peername, NULL, TRUE, FINDPEERS, FALSE, 0); 21814 if (pp) { 21815 p->stimer->st_cached_max_se = pp->stimer.st_max_se; 21816 unref_peer(pp, "unref peer pointer from find_peer call in st_get_se"); 21817 return (p->stimer->st_cached_max_se); 21818 } 21819 } 21820 p->stimer->st_cached_max_se = global_max_se; 21821 return (p->stimer->st_cached_max_se); 21822 } else { 21823 if (p->stimer->st_cached_min_se) { 21824 return p->stimer->st_cached_min_se; 21825 } else if (p->peername) { 21826 struct sip_peer *pp = find_peer(p->peername, NULL, TRUE, FINDPEERS, FALSE, 0); 21827 if (pp) { 21828 p->stimer->st_cached_min_se = pp->stimer.st_min_se; 21829 unref_peer(pp, "unref peer pointer from find_peer call in st_get_se (2)"); 21830 return (p->stimer->st_cached_min_se); 21831 } 21832 } 21833 p->stimer->st_cached_min_se = global_min_se; 21834 return (p->stimer->st_cached_min_se); 21835 } 21836 }
| static void start_session_timer | ( | struct sip_pvt * | p | ) | [static] |
Session-Timers: Start session timer.
Definition at line 21604 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(), 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().
21605 { 21606 if (!p->stimer) { 21607 ast_log(LOG_WARNING, "Null stimer in start_session_timer - %s\n", p->callid); 21608 return; 21609 } 21610 21611 p->stimer->st_schedid = ast_sched_add(sched, p->stimer->st_interval * 1000 / 2, proc_session_timer, 21612 dialog_ref(p, "adding session timer ref")); 21613 if (p->stimer->st_schedid < 0) { 21614 dialog_unref(p, "removing session timer ref"); 21615 ast_log(LOG_ERROR, "ast_sched_add failed.\n"); 21616 } 21617 ast_debug(2, "Session timer started: %d - %s\n", p->stimer->st_schedid, p->callid); 21618 }
| static const char* stmode2str | ( | enum st_mode | m | ) | [static] |
Definition at line 13580 of file chan_sip.c.
References map_x_s().
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 17415 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().
17416 { 17417 /* Immediately stop RTP, VRTP and UDPTL as applicable */ 17418 if (p->rtp) 17419 ast_rtp_stop(p->rtp); 17420 if (p->vrtp) 17421 ast_rtp_stop(p->vrtp); 17422 if (p->trtp) 17423 ast_rtp_stop(p->trtp); 17424 if (p->udptl) 17425 ast_udptl_stop(p->udptl); 17426 }
| static void stop_session_timer | ( | struct sip_pvt * | p | ) | [static] |
Session-Timers: Stop session timer.
Definition at line 21587 of file chan_sip.c.
References ast_debug, ast_log(), AST_SCHED_DEL_UNREF, sip_pvt::callid, dialog_unref(), FALSE, LOG_WARNING, 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().
21588 { 21589 if (!p->stimer) { 21590 ast_log(LOG_WARNING, "Null stimer in stop_session_timer - %s\n", p->callid); 21591 return; 21592 } 21593 21594 if (p->stimer->st_active == TRUE) { 21595 p->stimer->st_active = FALSE; 21596 AST_SCHED_DEL_UNREF(sched, p->stimer->st_schedid, 21597 dialog_unref(p, "removing session timer ref")); 21598 ast_debug(2, "Session timer stopped: %d - %s\n", p->stimer->st_schedid, p->callid); 21599 } 21600 }
| static int str2dtmfmode | ( | const char * | str | ) | [static] |
| static enum st_mode str2stmode | ( | const char * | s | ) | [static] |
Definition at line 13585 of file chan_sip.c.
References map_s_x().
Referenced by build_peer(), and reload_config().
| static enum st_refresher str2strefresher | ( | const char * | s | ) | [static] |
Definition at line 13603 of file chan_sip.c.
References map_s_x().
Referenced by build_peer(), and reload_config().
13604 { 13605 return map_s_x(strefreshers, s, -1); 13606 }
| static const char * strefresher2str | ( | enum st_refresher | r | ) | [static] |
Definition at line 13598 of file chan_sip.c.
References map_x_s().
Referenced by _sip_show_peer(), reqprep(), respprep(), sip_show_channel(), sip_show_settings(), and sip_show_user().
13599 { 13600 return map_x_s(strefreshers, r, "Unknown"); 13601 }
| static const char * subscription_type2str | ( | enum subscriptiontype | subtype | ) | [static] |
Show subscription type in string format.
Definition at line 15313 of file chan_sip.c.
References ARRAY_LEN, subscription_types, and cfsubscription_types::text.
Referenced by show_channels_cb(), and sip_show_channel().
15314 { 15315 int i; 15316 15317 for (i = 1; i < ARRAY_LEN(subscription_types); i++) { 15318 if (subscription_types[i].type == subtype) { 15319 return subscription_types[i].text; 15320 } 15321 } 15322 return subscription_types[0].text; 15323 }
| 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 9289 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().
09290 { 09291 switch (rate) { 09292 case AST_T38_RATE_2400: 09293 return 2400; 09294 case AST_T38_RATE_4800: 09295 return 4800; 09296 case AST_T38_RATE_7200: 09297 return 7200; 09298 case AST_T38_RATE_9600: 09299 return 9600; 09300 case AST_T38_RATE_12000: 09301 return 12000; 09302 case AST_T38_RATE_14400: 09303 return 14400; 09304 default: 09305 return 0; 09306 } 09307 }
| static void tcptls_packet_destructor | ( | void * | obj | ) | [static] |
Definition at line 2411 of file chan_sip.c.
References ast_free, and tcptls_packet::data.
Referenced by sip_tcptls_write().
02412 { 02413 struct tcptls_packet *packet = obj; 02414 02415 ast_free(packet->data); 02416 }
| static struct sip_peer * temp_peer | ( | const char * | name | ) | [static, read] |
Create temporary peer (used in autocreatepeer mode).
Definition at line 22693 of file chan_sip.c.
References ao2_t_alloc, ast_atomic_fetchadd_int(), ast_copy_string(), default_prefs, sip_peer::host_dynamic, sip_peer::name, sip_peer::prefs, reg_source_db(), sip_peer::selfdestruct, set_peer_defaults(), sip_destroy_peer_fn(), and TRUE.
Referenced by register_verify().
22694 { 22695 struct sip_peer *peer; 22696 22697 if (!(peer = ao2_t_alloc(sizeof(*peer), sip_destroy_peer_fn, "allocate a peer struct"))) 22698 return NULL; 22699 22700 ast_atomic_fetchadd_int(&apeerobjs, 1); 22701 set_peer_defaults(peer); 22702 22703 ast_copy_string(peer->name, name, sizeof(peer->name)); 22704 22705 peer->selfdestruct = TRUE; 22706 peer->host_dynamic = TRUE; 22707 peer->prefs = default_prefs; 22708 reg_source_db(peer); 22709 22710 return peer; 22711 }
| static void temp_pvt_cleanup | ( | void * | data | ) | [static] |
Definition at line 8960 of file chan_sip.c.
References ast_free, and ast_string_field_free_memory.
08961 { 08962 struct sip_pvt *p = data; 08963 08964 ast_string_field_free_memory(p); 08965 08966 ast_free(data); 08967 }
| static int temp_pvt_init | ( | void * | data | ) | [static] |
Definition at line 8952 of file chan_sip.c.
References ast_string_field_init, and sip_pvt::do_history.
08953 { 08954 struct sip_pvt *p = data; 08955 08956 p->do_history = 0; /* XXX do we need it ? isn't already all 0 ? */ 08957 return ast_string_field_init(p, 512); 08958 }
| 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 12128 of file chan_sip.c.
Referenced by check_user_full(), and register_verify().
| static int threadinfo_locate_cb | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 21102 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().
21103 { 21104 struct sip_threadinfo *th = obj; 21105 struct sockaddr_in *s = arg; 21106 21107 if (!inaddrcmp(&th->tcptls_session->remote_address, s)) { 21108 return CMP_MATCH | CMP_STOP; 21109 } 21110 21111 return 0; 21112 }
| static int threadt_cmp_cb | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 1772 of file chan_sip.c.
References CMP_MATCH, CMP_STOP, and sip_threadinfo::tcptls_session.
Referenced by load_module().
01773 { 01774 struct sip_threadinfo *th = obj, *th2 = arg; 01775 01776 return (th->tcptls_session == th2->tcptls_session) ? CMP_MATCH | CMP_STOP : 0; 01777 }
| static int threadt_hash_cb | ( | const void * | obj, | |
| const int | flags | |||
| ) | [static] |
Definition at line 1765 of file chan_sip.c.
References ast_tcptls_session_instance::remote_address, and sip_threadinfo::tcptls_session.
Referenced by load_module().
01766 { 01767 const struct sip_threadinfo *th = obj; 01768 01769 return (int) th->tcptls_session->remote_address.sin_addr.s_addr; 01770 }
| static char * transfermode2str | ( | enum transfermodes | mode | ) | [static] |
Convert transfer mode to text string.
Definition at line 13524 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().
13525 { 13526 if (mode == TRANSFER_OPENFORALL) 13527 return "open"; 13528 else if (mode == TRANSFER_CLOSED) 13529 return "closed"; 13530 return "strict"; 13531 }
| 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 12025 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, FALSE, get_header(), sip_request::ignore, sip_pvt::initreq, sip_pvt::randdata, s, set_nonce_randdata(), SIP_REGISTER, sip_scheddestroy(), SIP_SUBSCRIBE, ast_str::str, strsep(), transmit_response(), and transmit_response_with_auth().
Referenced by handle_request_invite(), handle_request_subscribe(), and register_verify().
12026 { 12027 /* We have to emulate EXACTLY what we'd get with a good peer 12028 * and a bad password, or else we leak information. */ 12029 const char *response = "407 Proxy Authentication Required"; 12030 const char *reqheader = "Proxy-Authorization"; 12031 const char *respheader = "Proxy-Authenticate"; 12032 const char *authtoken; 12033 struct ast_str *buf; 12034 char *c; 12035 12036 /* table of recognised keywords, and their value in the digest */ 12037 enum keys { K_NONCE, K_LAST }; 12038 struct x { 12039 const char *key; 12040 const char *s; 12041 } *i, keys[] = { 12042 [K_NONCE] = { "nonce=", "" }, 12043 [K_LAST] = { NULL, NULL} 12044 }; 12045 12046 if (sipmethod == SIP_REGISTER || sipmethod == SIP_SUBSCRIBE) { 12047 response = "401 Unauthorized"; 12048 reqheader = "Authorization"; 12049 respheader = "WWW-Authenticate"; 12050 } 12051 authtoken = get_header(req, reqheader); 12052 if (req->ignore && !ast_strlen_zero(p->randdata) && ast_strlen_zero(authtoken)) { 12053 /* This is a retransmitted invite/register/etc, don't reconstruct authentication 12054 * information */ 12055 transmit_response_with_auth(p, response, req, p->randdata, 0, respheader, 0); 12056 /* Schedule auto destroy in 32 seconds (according to RFC 3261) */ 12057 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 12058 return; 12059 } else if (ast_strlen_zero(p->randdata) || ast_strlen_zero(authtoken)) { 12060 /* We have no auth, so issue challenge and request authentication */ 12061 set_nonce_randdata(p, 1); 12062 transmit_response_with_auth(p, response, req, p->randdata, 0, respheader, 0); 12063 /* Schedule auto destroy in 32 seconds */ 12064 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 12065 return; 12066 } 12067 12068 if (!(buf = ast_str_thread_get(&check_auth_buf, CHECK_AUTH_BUF_INITLEN))) { 12069 transmit_response(p, "403 Forbidden (Bad auth)", &p->initreq); 12070 return; 12071 } 12072 12073 /* Make a copy of the response and parse it */ 12074 if (ast_str_set(&buf, 0, "%s", authtoken) == AST_DYNSTR_BUILD_FAILED) { 12075 transmit_response(p, "403 Forbidden (Bad auth)", &p->initreq); 12076 return; 12077 } 12078 12079 c = buf->str; 12080 12081 while (c && *(c = ast_skip_blanks(c))) { /* lookup for keys */ 12082 for (i = keys; i->key != NULL; i++) { 12083 const char *separator = ","; /* default */ 12084 12085 if (strncasecmp(c, i->key, strlen(i->key)) != 0) { 12086 continue; 12087 } 12088 /* Found. Skip keyword, take text in quotes or up to the separator. */ 12089 c += strlen(i->key); 12090 if (*c == '"') { /* in quotes. Skip first and look for last */ 12091 c++; 12092 separator = "\""; 12093 } 12094 i->s = c; 12095 strsep(&c, separator); 12096 break; 12097 } 12098 if (i->key == NULL) { /* not found, jump after space or comma */ 12099 strsep(&c, " ,"); 12100 } 12101 } 12102 12103 /* Verify nonce from request matches our nonce. If not, send 401 with new nonce */ 12104 if (strcasecmp(p->randdata, keys[K_NONCE].s)) { 12105 if (!req->ignore) { 12106 set_nonce_randdata(p, 1); 12107 } 12108 transmit_response_with_auth(p, response, req, p->randdata, reliable, respheader, FALSE); 12109 12110 /* Schedule auto destroy in 32 seconds */ 12111 sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); 12112 } else { 12113 transmit_response(p, "403 Forbidden (Bad auth)", &p->initreq); 12114 } 12115 }
| 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 11117 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().
11118 { 11119 struct sip_request req; 11120 11121 reqprep(&req, p, SIP_INFO, 0, 1); 11122 add_digit(&req, digit, duration, (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_SHORTINFO)); 11123 return send_request(p, &req, XMIT_RELIABLE, p->ocseq); 11124 }
| static int transmit_info_with_vidupdate | ( | struct sip_pvt * | p | ) | [static] |
Send SIP INFO with video update request.
Definition at line 11127 of file chan_sip.c.
References add_vidupdate(), sip_pvt::ocseq, reqprep(), send_request(), SIP_INFO, and XMIT_RELIABLE.
Referenced by sip_indicate().
11128 { 11129 struct sip_request req; 11130 11131 reqprep(&req, p, SIP_INFO, 0, 1); 11132 add_vidupdate(&req); 11133 return send_request(p, &req, XMIT_RELIABLE, p->ocseq); 11134 }
| 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 10187 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, 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_variable::name, ast_variable::next, 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, ast_variable::value, var, ast_channel::varshead, XMIT_CRITICAL, and XMIT_RELIABLE.
Referenced by do_proxy_auth(), proc_422_rsp(), sip_call(), and sip_poke_peer().
10188 { 10189 struct sip_request req; 10190 struct ast_variable *var; 10191 10192 req.method = sipmethod; 10193 if (init) {/* Bump branch even on initial requests */ 10194 p->branch ^= ast_random(); 10195 p->invite_branch = p->branch; 10196 build_via(p); 10197 } 10198 if (init > 1) 10199 initreqprep(&req, p, sipmethod); 10200 else 10201 /* If init=1, we should not generate a new branch. If it's 0, we need a new branch. */ 10202 reqprep(&req, p, sipmethod, 0, init ? 0 : 1); 10203 10204 if (p->options && p->options->auth) 10205 add_header(&req, p->options->authheader, p->options->auth); 10206 append_date(&req); 10207 if (sipmethod == SIP_REFER) { /* Call transfer */ 10208 if (p->refer) { 10209 char buf[SIPBUFSIZE]; 10210 if (!ast_strlen_zero(p->refer->refer_to)) 10211 add_header(&req, "Refer-To", p->refer->refer_to); 10212 if (!ast_strlen_zero(p->refer->referred_by)) { 10213 snprintf(buf, sizeof(buf), "%s <%s>", p->refer->referred_by_name, p->refer->referred_by); 10214 add_header(&req, "Referred-By", buf); 10215 } 10216 } 10217 } 10218 /* This new INVITE is part of an attended transfer. Make sure that the 10219 other end knows and replace the current call with this new call */ 10220 if (p->options && !ast_strlen_zero(p->options->replaces)) { 10221 add_header(&req, "Replaces", p->options->replaces); 10222 add_header(&req, "Require", "replaces"); 10223 } 10224 10225 /* Add Session-Timers related headers */ 10226 if (st_get_mode(p) == SESSION_TIMER_MODE_ORIGINATE) { 10227 char i2astr[10]; 10228 10229 if (!p->stimer->st_interval) 10230 p->stimer->st_interval = st_get_se(p, TRUE); 10231 10232 p->stimer->st_active = TRUE; 10233 10234 snprintf(i2astr, sizeof(i2astr), "%d", p->stimer->st_interval); 10235 add_header(&req, "Session-Expires", i2astr); 10236 snprintf(i2astr, sizeof(i2astr), "%d", st_get_se(p, FALSE)); 10237 add_header(&req, "Min-SE", i2astr); 10238 } 10239 10240 add_header(&req, "Allow", ALLOWED_METHODS); 10241 add_header(&req, "Supported", SUPPORTED_EXTENSIONS); 10242 10243 if(p->notify_headers) { 10244 char buf[512]; 10245 for (var = p->notify_headers; var; var = var->next) { 10246 ast_copy_string(buf, var->value, sizeof(buf)); 10247 add_header(&req, var->name, ast_unescape_semicolon(buf)); 10248 } 10249 } 10250 if (p->options && p->options->addsipheaders && p->owner) { 10251 struct ast_channel *chan = p->owner; /* The owner channel */ 10252 struct varshead *headp; 10253 10254 ast_channel_lock(chan); 10255 10256 headp = &chan->varshead; 10257 10258 if (!headp) 10259 ast_log(LOG_WARNING, "No Headp for the channel...ooops!\n"); 10260 else { 10261 const struct ast_var_t *current; 10262 AST_LIST_TRAVERSE(headp, current, entries) { 10263 /* SIPADDHEADER: Add SIP header to outgoing call */ 10264 if (!strncasecmp(ast_var_name(current), "SIPADDHEADER", strlen("SIPADDHEADER"))) { 10265 char *content, *end; 10266 const char *header = ast_var_value(current); 10267 char *headdup = ast_strdupa(header); 10268 10269 /* Strip of the starting " (if it's there) */ 10270 if (*headdup == '"') 10271 headdup++; 10272 if ((content = strchr(headdup, ':'))) { 10273 *content++ = '\0'; 10274 content = ast_skip_blanks(content); /* Skip white space */ 10275 /* Strip the ending " (if it's there) */ 10276 end = content + strlen(content) -1; 10277 if (*end == '"') 10278 *end = '\0'; 10279 10280 add_header(&req, headdup, content); 10281 if (sipdebug) 10282 ast_debug(1, "Adding SIP Header \"%s\" with content :%s: \n", headdup, content); 10283 } 10284 } 10285 } 10286 } 10287 10288 ast_channel_unlock(chan); 10289 } 10290 if (sdp) { 10291 memset(p->offered_media, 0, sizeof(p->offered_media)); 10292 if (p->udptl && p->t38.state == T38_LOCAL_REINVITE) { 10293 ast_debug(1, "T38 is in state %d on channel %s\n", p->t38.state, p->owner ? p->owner->name : "<none>"); 10294 add_sdp(&req, p, FALSE, FALSE, TRUE); 10295 } else if (p->rtp) 10296 add_sdp(&req, p, FALSE, TRUE, FALSE); 10297 } else { 10298 if (!p->notify_headers) { 10299 add_header_contentLength(&req, 0); 10300 } 10301 } 10302 10303 if (!p->initreq.headers || init > 2) 10304 initialize_initreq(p, &req); 10305 p->lastinvite = p->ocseq; 10306 return send_request(p, &req, init ? XMIT_CRITICAL : XMIT_RELIABLE, p->ocseq); 10307 }
| static int transmit_message_with_text | ( | struct sip_pvt * | p, | |
| const char * | text | |||
| ) | [static] |
Transmit text with SIP MESSAGE method.
Definition at line 11023 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().
11024 { 11025 struct sip_request req; 11026 11027 reqprep(&req, p, SIP_MESSAGE, 0, 1); 11028 add_text(&req, text); 11029 return send_request(p, &req, XMIT_RELIABLE, p->ocseq); 11030 }
| 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 10571 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().
10571 { 10572 struct sip_request req; 10573 struct ast_variable *var, *newvar; 10574 10575 initreqprep(&req, p, SIP_NOTIFY); 10576 10577 /* Copy notify vars and add headers */ 10578 p->notify_headers = newvar = ast_variable_new("Subscription-State", "terminated", ""); 10579 add_header(&req, newvar->name, newvar->value); 10580 for (var = vars; var; var = var->next) { 10581 char buf[512]; 10582 ast_debug(2, " Adding pair %s=%s\n", var->name, var->value); 10583 ast_copy_string(buf, var->value, sizeof(buf)); 10584 add_header(&req, var->name, ast_unescape_semicolon(buf)); 10585 newvar->next = ast_variable_new(var->name, var->value, ""); 10586 newvar = newvar->next; 10587 } 10588 10589 if (!p->initreq.headers) { /* Initialize first request before sending */ 10590 initialize_initreq(p, &req); 10591 } 10592 10593 return send_request(p, &req, XMIT_UNRELIABLE, p->ocseq); 10594 }
| 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 10498 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().
10499 { 10500 struct sip_request req; 10501 struct ast_str *out = ast_str_alloca(500); 10502 int ourport = ntohs(p->ourip.sin_port); 10503 const char *exten = S_OR(vmexten, default_vmexten); 10504 10505 initreqprep(&req, p, SIP_NOTIFY); 10506 add_header(&req, "Event", "message-summary"); 10507 add_header(&req, "Content-Type", default_notifymime); 10508 ast_str_append(&out, 0, "Messages-Waiting: %s\r\n", newmsgs ? "yes" : "no"); 10509 10510 if (!ast_strlen_zero(p->fromdomain)) { 10511 ast_str_append(&out, 0, "Message-Account: sip:%s@%s\r\n", exten, p->fromdomain); 10512 } else if (!sip_standard_port(p->socket.type, ourport)) { 10513 if (p->socket.type == SIP_TRANSPORT_UDP) { 10514 ast_str_append(&out, 0, "Message-Account: sip:%s@%s:%d\r\n", exten, ast_inet_ntoa(p->ourip.sin_addr), ourport); 10515 } else { 10516 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)); 10517 } 10518 } else { 10519 if (p->socket.type == SIP_TRANSPORT_UDP) { 10520 ast_str_append(&out, 0, "Message-Account: sip:%s@%s\r\n", exten, ast_inet_ntoa(p->ourip.sin_addr)); 10521 } else { 10522 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)); 10523 } 10524 } 10525 /* Cisco has a bug in the SIP stack where it can't accept the 10526 (0/0) notification. This can temporarily be disabled in 10527 sip.conf with the "buggymwi" option */ 10528 ast_str_append(&out, 0, "Voice-Message: %d/%d%s\r\n", 10529 newmsgs, oldmsgs, (ast_test_flag(&p->flags[1], SIP_PAGE2_BUGGY_MWI) ? "" : " (0/0)")); 10530 10531 if (p->subscribed) { 10532 if (p->expiry) 10533 add_header(&req, "Subscription-State", "active"); 10534 else /* Expired */ 10535 add_header(&req, "Subscription-State", "terminated;reason=timeout"); 10536 } 10537 10538 add_header_contentLength(&req, out->used); 10539 add_line(&req, out->str); 10540 10541 if (!p->initreq.headers) 10542 initialize_initreq(p, &req); 10543 return send_request(p, &req, XMIT_RELIABLE, p->ocseq); 10544 }
| 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 10547 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().
10548 { 10549 struct sip_request req; 10550 char tmp[SIPBUFSIZE/2]; 10551 10552 reqprep(&req, p, SIP_NOTIFY, 0, 1); 10553 snprintf(tmp, sizeof(tmp), "refer;id=%d", cseq); 10554 add_header(&req, "Event", tmp); 10555 add_header(&req, "Subscription-state", terminate ? "terminated;reason=noresource" : "active"); 10556 add_header(&req, "Content-Type", "message/sipfrag;version=2.0"); 10557 add_header(&req, "Allow", ALLOWED_METHODS); 10558 add_header(&req, "Supported", SUPPORTED_EXTENSIONS); 10559 10560 snprintf(tmp, sizeof(tmp), "SIP/2.0 %s\r\n", message); 10561 add_header_contentLength(&req, strlen(tmp)); 10562 add_line(&req, tmp); 10563 10564 if (!p->initreq.headers) 10565 initialize_initreq(p, &req); 10566 10567 return send_request(p, &req, XMIT_RELIABLE, p->ocseq); 10568 }
| static int transmit_provisional_response | ( | struct sip_pvt * | p, | |
| const char * | msg, | |||
| const struct sip_request * | req, | |||
| int | with_sdp | |||
| ) | [static] |
Definition at line 9117 of file chan_sip.c.
References FALSE, sip_pvt::last_provisional, transmit_response(), transmit_response_with_sdp(), update_provisional_keepalive(), and XMIT_UNRELIABLE.
Referenced by handle_request_invite(), sip_indicate(), and sip_write().
09118 { 09119 int res; 09120 09121 if (!(res = with_sdp ? transmit_response_with_sdp(p, msg, req, XMIT_UNRELIABLE, FALSE) : transmit_response(p, msg, req))) { 09122 p->last_provisional = msg; 09123 update_provisional_keepalive(p, with_sdp); 09124 } 09125 09126 return res; 09127 }
| 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 11044 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().
11045 { 11046 struct sip_request req = { 11047 .headers = 0, 11048 }; 11049 char from[256]; 11050 const char *of; 11051 char *c; 11052 char referto[256]; 11053 char *ttag, *ftag; 11054 char *theirtag = ast_strdupa(p->theirtag); 11055 11056 if (sipdebug) 11057 ast_debug(1, "SIP transfer of %s to %s\n", p->callid, dest); 11058 11059 /* Are we transfering an inbound or outbound call ? */ 11060 if (ast_test_flag(&p->flags[0], SIP_OUTGOING)) { 11061 of = get_header(&p->initreq, "To"); 11062 ttag = theirtag; 11063 ftag = p->tag; 11064 } else { 11065 of = get_header(&p->initreq, "From"); 11066 ftag = theirtag; 11067 ttag = p->tag; 11068 } 11069 11070 ast_copy_string(from, of, sizeof(from)); 11071 of = get_in_brackets(from); 11072 ast_string_field_set(p, from, of); 11073 if (!strncasecmp(of, "sip:", 4)) 11074 of += 4; 11075 else if (!strncasecmp(of, "sips:", 5)) 11076 of += 5; 11077 else 11078 ast_log(LOG_NOTICE, "From address missing 'sip(s):', using it anyway\n"); 11079 /* Get just the username part */ 11080 if ((c = strchr(dest, '@'))) 11081 c = NULL; 11082 else if ((c = strchr(of, '@'))) 11083 *c++ = '\0'; 11084 if (c) 11085 snprintf(referto, sizeof(referto), "<sip:%s@%s>", dest, c); 11086 else 11087 snprintf(referto, sizeof(referto), "<sip:%s>", dest); 11088 11089 /* save in case we get 407 challenge */ 11090 sip_refer_allocate(p); 11091 ast_copy_string(p->refer->refer_to, referto, sizeof(p->refer->refer_to)); 11092 ast_copy_string(p->refer->referred_by, p->our_contact, sizeof(p->refer->referred_by)); 11093 p->refer->status = REFER_SENT; /* Set refer status */ 11094 11095 reqprep(&req, p, SIP_REFER, 0, 1); 11096 11097 add_header(&req, "Refer-To", referto); 11098 add_header(&req, "Allow", ALLOWED_METHODS); 11099 add_header(&req, "Supported", SUPPORTED_EXTENSIONS); 11100 if (!ast_strlen_zero(p->our_contact)) 11101 add_header(&req, "Referred-By", p->our_contact); 11102 11103 return send_request(p, &req, XMIT_RELIABLE, p->ocseq); 11104 11105 /* We should propably wait for a NOTIFY here until we ack the transfer */ 11106 /* Maybe fork a new thread and wait for a STATUS of REFER_200OK on the refer status before returning to app_transfer */ 11107 11108 /*! \todo In theory, we should hang around and wait for a reply, before 11109 returning to the dial plan here. Don't know really how that would 11110 affect the transfer() app or the pbx, but, well, to make this 11111 useful we should have a STATUS code on transfer(). 11112 */ 11113 }
| 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 10775 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, internip, 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, sip_registry::secret, send_request(), set_socket_transport(), sip_alloc(), sip_debug_test_pvt(), sip_methods, SIP_OUTGOING, sip_reg_timeout(), SIP_REGISTER, 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().
10776 { 10777 struct sip_request req; 10778 char from[256]; 10779 char to[256]; 10780 char tmp[80]; 10781 char addr[80]; 10782 struct sip_pvt *p; 10783 struct sip_peer *peer = NULL; 10784 int res; 10785 char *fromdomain; 10786 10787 /* exit if we are already in process with this registrar ?*/ 10788 if (r == NULL || ((auth == NULL) && (r->regstate == REG_STATE_REGSENT || r->regstate == REG_STATE_AUTHSENT))) { 10789 if (r) { 10790 ast_log(LOG_NOTICE, "Strange, trying to register %s@%s when registration already pending\n", r->username, r->hostname); 10791 } 10792 return 0; 10793 } 10794 10795 if (r->dnsmgr == NULL) { 10796 char transport[MAXHOSTNAMELEN]; 10797 peer = find_peer(r->hostname, NULL, TRUE, FINDPEERS, FALSE, 0); 10798 snprintf(transport, sizeof(transport), "_sip._%s", get_transport(r->transport)); /* have to use static get_transport function */ 10799 ast_dnsmgr_lookup(peer ? peer->tohost : r->hostname, &r->us, &r->dnsmgr, global_srvlookup ? transport : NULL); 10800 if (peer) { 10801 peer = unref_peer(peer, "removing peer ref for dnsmgr_lookup"); 10802 } 10803 } 10804 10805 if (r->call) { /* We have a registration */ 10806 if (!auth) { 10807 ast_log(LOG_WARNING, "Already have a REGISTER going on to %s@%s?? \n", r->username, r->hostname); 10808 return 0; 10809 } else { 10810 p = dialog_ref(r->call, "getting a copy of the r->call dialog in transmit_register"); 10811 make_our_tag(p->tag, sizeof(p->tag)); /* create a new local tag for every register attempt */ 10812 ast_string_field_set(p, theirtag, NULL); /* forget their old tag, so we don't match tags when getting response */ 10813 } 10814 } else { 10815 /* Build callid for registration if we haven't registered before */ 10816 if (!r->callid_valid) { 10817 build_callid_registry(r, internip.sin_addr, default_fromdomain); 10818 r->callid_valid = TRUE; 10819 } 10820 /* Allocate SIP dialog for registration */ 10821 if (!(p = sip_alloc( r->callid, NULL, 0, SIP_REGISTER, NULL))) { 10822 ast_log(LOG_WARNING, "Unable to allocate registration transaction (memory or socket error)\n"); 10823 return 0; 10824 } 10825 10826 if (p->do_history) 10827 append_history(p, "RegistryInit", "Account: %s@%s", r->username, r->hostname); 10828 10829 if (!ast_strlen_zero(r->peername)) { 10830 if (!(peer = find_peer(r->peername, NULL, 1, FINDPEERS, FALSE, 0))) { 10831 ast_log(LOG_WARNING, "Could not find peer %s in transmit_register\n", r->peername); 10832 } else { 10833 p->peerauth = peer->auth; 10834 } 10835 } 10836 ref_proxy(p, obproxy_get(p, peer)); /* it is ok to pass a NULL peer into obproxy_get() */ 10837 if (peer) { 10838 unref_peer(peer, "transmit_registration: from find_peer operation"); 10839 } 10840 /* Use port number specified if no SRV record was found */ 10841 if (!r->us.sin_port && r->portno) 10842 r->us.sin_port = htons(r->portno); 10843 10844 /* Find address to hostname */ 10845 if (create_addr(p, r->hostname, &r->us, 0)) { 10846 /* we have what we hope is a temporary network error, 10847 * probably DNS. We need to reschedule a registration try */ 10848 dialog_unlink_all(p, TRUE, TRUE); 10849 p = dialog_unref(p, "unref dialog after unlink_all"); 10850 if (r->timeout > -1) { 10851 AST_SCHED_REPLACE_UNREF(r->timeout, sched, global_reg_timeout * 1000, sip_reg_timeout, r, 10852 registry_unref(_data, "del for REPLACE of registry ptr"), 10853 registry_unref(r, "object ptr dec when SCHED_REPLACE add failed"), 10854 registry_addref(r,"add for REPLACE registry ptr")); 10855 ast_log(LOG_WARNING, "Still have a registration timeout for %s@%s (create_addr() error), %d\n", r->username, r->hostname, r->timeout); 10856 } else { 10857 r->timeout = ast_sched_add(sched, global_reg_timeout * 1000, sip_reg_timeout, registry_addref(r, "add for REPLACE registry ptr")); 10858 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); 10859 } 10860 r->regattempts++; 10861 return 0; 10862 } 10863 10864 /* Copy back Call-ID in case create_addr changed it */ 10865 ast_string_field_set(r, callid, p->callid); 10866 if (!r->dnsmgr && r->portno) { 10867 p->sa.sin_port = htons(r->portno); 10868 p->recv.sin_port = htons(r->portno); 10869 } else { /* Set registry port to the port set from the peer definition/srv or default */ 10870 r->portno = ntohs(p->sa.sin_port); 10871 } 10872 ast_set_flag(&p->flags[0], SIP_OUTGOING); /* Registration is outgoing call */ 10873 r->call = dialog_ref(p, "copying dialog into registry r->call"); /* Save pointer to SIP dialog */ 10874 p->registry = registry_addref(r, "transmit_register: addref to p->registry in transmit_register"); /* Add pointer to registry in packet */ 10875 if (!ast_strlen_zero(r->secret)) /* Secret (password) */ 10876 ast_string_field_set(p, peersecret, r->secret); 10877 if (!ast_strlen_zero(r->md5secret)) 10878 ast_string_field_set(p, peermd5secret, r->md5secret); 10879 /* User name in this realm 10880 - if authuser is set, use that, otherwise use username */ 10881 if (!ast_strlen_zero(r->authuser)) { 10882 ast_string_field_set(p, peername, r->authuser); 10883 ast_string_field_set(p, authname, r->authuser); 10884 } else if (!ast_strlen_zero(r->username)) { 10885 ast_string_field_set(p, peername, r->username); 10886 ast_string_field_set(p, authname, r->username); 10887 ast_string_field_set(p, fromuser, r->username); 10888 } 10889 if (!ast_strlen_zero(r->username)) 10890 ast_string_field_set(p, username, r->username); 10891 /* Save extension in packet */ 10892 if (!ast_strlen_zero(r->callback)) 10893 ast_string_field_set(p, exten, r->callback); 10894 10895 /* Set transport and port so the correct contact is built */ 10896 set_socket_transport(&p->socket, r->transport); 10897 if (r->transport == SIP_TRANSPORT_TLS || r->transport == SIP_TRANSPORT_TCP) { 10898 p->socket.port = sip_tcp_desc.local_address.sin_port; 10899 } 10900 10901 /* 10902 check which address we should use in our contact header 10903 based on whether the remote host is on the external or 10904 internal network so we can register through nat 10905 */ 10906 ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip, p); 10907 build_contact(p); 10908 } 10909 10910 /* set up a timeout */ 10911 if (auth == NULL) { 10912 if (r->timeout > -1) 10913 ast_log(LOG_WARNING, "Still have a registration timeout, #%d - deleting it\n", r->timeout); 10914 AST_SCHED_REPLACE_UNREF(r->timeout, sched, global_reg_timeout * 1000, sip_reg_timeout, r, 10915 registry_unref(_data,"reg ptr unrefed from del in SCHED_REPLACE"), 10916 registry_unref(r,"reg ptr unrefed from add failure in SCHED_REPLACE"), 10917 registry_addref(r,"reg ptr reffed from add in SCHED_REPLACE")); 10918 ast_debug(1, "Scheduled a registration timeout for %s id #%d \n", r->hostname, r->timeout); 10919 } 10920 10921 if ((fromdomain = strchr(r->username, '@'))) { 10922 /* the domain name is just behind '@' */ 10923 fromdomain++ ; 10924 /* We have a domain in the username for registration */ 10925 snprintf(from, sizeof(from), "<sip:%s>;tag=%s", r->username, p->tag); 10926 if (!ast_strlen_zero(p->theirtag)) 10927 snprintf(to, sizeof(to), "<sip:%s>;tag=%s", r->username, p->theirtag); 10928 else 10929 snprintf(to, sizeof(to), "<sip:%s>", r->username); 10930 10931 /* If the registration username contains '@', then the domain should be used as 10932 the equivalent of "fromdomain" for the registration */ 10933 if (ast_strlen_zero(p->fromdomain)) { 10934 ast_string_field_set(p, fromdomain, fromdomain); 10935 } 10936 } else { 10937 snprintf(from, sizeof(from), "<sip:%s@%s>;tag=%s", r->username, p->tohost, p->tag); 10938 if (!ast_strlen_zero(p->theirtag)) 10939 snprintf(to, sizeof(to), "<sip:%s@%s>;tag=%s", r->username, p->tohost, p->theirtag); 10940 else 10941 snprintf(to, sizeof(to), "<sip:%s@%s>", r->username, p->tohost); 10942 } 10943 10944 /* Fromdomain is what we are registering to, regardless of actual 10945 host name from SRV */ 10946 if (!ast_strlen_zero(p->fromdomain)) { 10947 if (r->portno && r->portno != STANDARD_SIP_PORT) 10948 snprintf(addr, sizeof(addr), "sip:%s:%d", p->fromdomain, r->portno); 10949 else 10950 snprintf(addr, sizeof(addr), "sip:%s", p->fromdomain); 10951 } else { 10952 if (r->portno && r->portno != STANDARD_SIP_PORT) 10953 snprintf(addr, sizeof(addr), "sip:%s:%d", r->hostname, r->portno); 10954 else 10955 snprintf(addr, sizeof(addr), "sip:%s", r->hostname); 10956 } 10957 ast_string_field_set(p, uri, addr); 10958 10959 p->branch ^= ast_random(); 10960 10961 init_req(&req, sipmethod, addr); 10962 10963 /* Add to CSEQ */ 10964 snprintf(tmp, sizeof(tmp), "%u %s", ++r->ocseq, sip_methods[sipmethod].text); 10965 p->ocseq = r->ocseq; 10966 10967 build_via(p); 10968 add_header(&req, "Via", p->via); 10969 add_header(&req, "Max-Forwards", DEFAULT_MAX_FORWARDS); 10970 add_header(&req, "From", from); 10971 add_header(&req, "To", to); 10972 add_header(&req, "Call-ID", p->callid); 10973 add_header(&req, "CSeq", tmp); 10974 if (!ast_strlen_zero(global_useragent)) 10975 add_header(&req, "User-Agent", global_useragent); 10976 10977 10978 if (auth) /* Add auth header */ 10979 add_header(&req, authheader, auth); 10980 else if (!ast_strlen_zero(r->nonce)) { 10981 char digest[1024]; 10982 10983 /* We have auth data to reuse, build a digest header. 10984 * Note, this is not always useful because some parties do not 10985 * like nonces to be reused (for good reasons!) so they will 10986 * challenge us anyways. 10987 */ 10988 if (sipdebug) 10989 ast_debug(1, " >>> Re-using Auth data for %s@%s\n", r->username, r->hostname); 10990 ast_string_field_set(p, realm, r->realm); 10991 ast_string_field_set(p, nonce, r->nonce); 10992 ast_string_field_set(p, domain, r->domain); 10993 ast_string_field_set(p, opaque, r->opaque); 10994 ast_string_field_set(p, qop, r->qop); 10995 p->noncecount = ++r->noncecount; 10996 10997 memset(digest, 0, sizeof(digest)); 10998 if(!build_reply_digest(p, sipmethod, digest, sizeof(digest))) 10999 add_header(&req, "Authorization", digest); 11000 else 11001 ast_log(LOG_NOTICE, "No authorization available for authentication of registration to %s@%s\n", r->username, r->hostname); 11002 11003 } 11004 11005 snprintf(tmp, sizeof(tmp), "%d", r->expiry); 11006 add_header(&req, "Expires", tmp); 11007 add_header(&req, "Contact", p->our_contact); 11008 add_header_contentLength(&req, 0); 11009 11010 initialize_initreq(p, &req); 11011 if (sip_debug_test_pvt(p)) { 11012 ast_verbose("REGISTER %d headers, %d lines\n", p->initreq.headers, p->initreq.lines); 11013 } 11014 r->regstate = auth ? REG_STATE_AUTHSENT : REG_STATE_REGSENT; 11015 r->regattempts++; /* Another attempt */ 11016 ast_debug(4, "REGISTER attempt %d to %s@%s\n", r->regattempts, r->username, r->hostname); 11017 res = send_request(p, &req, XMIT_CRITICAL, p->ocseq); 11018 dialog_unref(p, "p is finished here at the end of transmit_register"); 11019 return res; 11020 }
| static int transmit_reinvite_with_sdp | ( | struct sip_pvt * | p, | |
| int | t38version, | |||
| int | oldsdp | |||
| ) | [static] |
Transmit reinvite with SDP.
If t38version is TRUE, we send T38 SDP for re-invite from audio/video to T38 UDPTL transmission on the channel
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 9867 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().
09868 { 09869 struct sip_request req; 09870 09871 reqprep(&req, p, ast_test_flag(&p->flags[0], SIP_REINVITE_UPDATE) ? SIP_UPDATE : SIP_INVITE, 0, 1); 09872 09873 add_header(&req, "Allow", ALLOWED_METHODS); 09874 add_header(&req, "Supported", SUPPORTED_EXTENSIONS); 09875 if (sipdebug) { 09876 if (oldsdp == TRUE) 09877 add_header(&req, "X-asterisk-Info", "SIP re-invite (Session-Timers)"); 09878 else 09879 add_header(&req, "X-asterisk-Info", "SIP re-invite (External RTP bridge)"); 09880 } 09881 09882 if (p->do_history) 09883 append_history(p, "ReInv", "Re-invite sent"); 09884 memset(p->offered_media, 0, sizeof(p->offered_media)); 09885 09886 if (t38version) 09887 add_sdp(&req, p, oldsdp, FALSE, TRUE); 09888 else 09889 add_sdp(&req, p, oldsdp, TRUE, FALSE); 09890 09891 /* Use this as the basis */ 09892 initialize_initreq(p, &req); 09893 p->lastinvite = p->ocseq; 09894 ast_set_flag(&p->flags[0], SIP_OUTGOING); /* Change direction of this dialog */ 09895 09896 return send_request(p, &req, XMIT_CRITICAL, p->ocseq); 09897 }
| 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 11139 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().
11140 { 11141 struct sip_request resp; 11142 11143 if (sipmethod == SIP_ACK) 11144 p->invitestate = INV_CONFIRMED; 11145 11146 reqprep(&resp, p, sipmethod, seqno, newbranch); 11147 if (sipmethod == SIP_CANCEL && p->answered_elsewhere) 11148 add_header(&resp, "Reason", "SIP;cause=200;text=\"Call completed elsewhere\""); 11149 11150 add_header_contentLength(&resp, 0); 11151 return send_request(p, &resp, reliable, seqno ? seqno : p->ocseq); 11152 }
| 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 11170 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().
11171 { 11172 struct sip_request resp; 11173 11174 reqprep(&resp, p, sipmethod, seqno, newbranch); 11175 if (!ast_strlen_zero(p->realm)) { 11176 char digest[1024]; 11177 11178 memset(digest, 0, sizeof(digest)); 11179 if(!build_reply_digest(p, sipmethod, digest, sizeof(digest))) { 11180 char *dummy, *response; 11181 enum sip_auth_type code = p->options ? p->options->auth_type : PROXY_AUTH; /* XXX force 407 if unknown */ 11182 auth_headers(code, &dummy, &response); 11183 add_header(&resp, response, digest); 11184 } else 11185 ast_log(LOG_WARNING, "No authentication available for call %s\n", p->callid); 11186 } 11187 /* If we are hanging up and know a cause for that, send it in clear text to make 11188 debugging easier. */ 11189 if (sipmethod == SIP_BYE) { 11190 char buf[10]; 11191 11192 add_header(&resp, "X-Asterisk-HangupCause", ast_cause2str(p->hangupcause)); 11193 snprintf(buf, sizeof(buf), "%d", p->hangupcause); 11194 add_header(&resp, "X-Asterisk-HangupCauseCode", buf); 11195 } 11196 11197 add_header_contentLength(&resp, 0); 11198 return send_request(p, &resp, reliable, seqno ? seqno : p->ocseq); 11199 }
| static int transmit_response | ( | struct sip_pvt * | p, | |
| const char * | msg, | |||
| const struct sip_request * | req | |||
| ) | [static] |
Transmit response, no retransmits.
Definition at line 9022 of file chan_sip.c.
References __transmit_response(), and XMIT_UNRELIABLE.
Referenced by handle_incoming(), handle_invite_replaces(), handle_request_bye(), handle_request_cancel(), handle_request_do(), handle_request_info(), handle_request_invite(), handle_request_message(), handle_request_notify(), handle_request_refer(), handle_request_subscribe(), local_attended_transfer(), receive_message(), register_verify(), send_provisional_keepalive_full(), sip_indicate(), sip_park_thread(), sip_sendhtml(), transmit_fake_auth_response(), and transmit_provisional_response().
09023 { 09024 return __transmit_response(p, msg, req, XMIT_UNRELIABLE); 09025 }
| 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 9058 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().
09059 { 09060 return __transmit_response(p, msg, req, req->ignore ? XMIT_UNRELIABLE : XMIT_CRITICAL); 09061 }
| 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 8970 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(), sip_pvt::branch, build_via(), copy_socket_data(), do_setnat(), sip_pvt::flags, sip_pvt::fromdomain, INITIAL_CSEQ, internip, LOG_ERROR, make_our_tag(), sip_pvt::method, sip_pvt::ocseq, sip_pvt::ourip, sip_pvt::recv, sip_pvt::sa, SIP_NAT, SIP_NAT_ROUTE, sip_request::socket, sip_pvt::socket, sip_pvt::tag, ts_temp_pvt, and XMIT_UNRELIABLE.
Referenced by find_call().
08971 { 08972 struct sip_pvt *p = NULL; 08973 08974 if (!(p = ast_threadstorage_get(&ts_temp_pvt, sizeof(*p)))) { 08975 ast_log(LOG_ERROR, "Failed to get temporary pvt\n"); 08976 return -1; 08977 } 08978 08979 /* XXX the structure may be dirty from previous usage. 08980 * Here we should state clearly how we should reinitialize it 08981 * before using it. 08982 * E.g. certainly the threadstorage should be left alone, 08983 * but other thihngs such as flags etc. maybe need cleanup ? 08984 */ 08985 08986 /* Initialize the bare minimum */ 08987 p->method = intended_method; 08988 08989 if (!sin) 08990 p->ourip = internip; 08991 else { 08992 p->sa = *sin; 08993 ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip, p); 08994 } 08995 08996 p->branch = ast_random(); 08997 make_our_tag(p->tag, sizeof(p->tag)); 08998 p->ocseq = INITIAL_CSEQ; 08999 09000 if (useglobal_nat && sin) { 09001 ast_copy_flags(&p->flags[0], &global_flags[0], SIP_NAT); 09002 p->recv = *sin; 09003 do_setnat(p, ast_test_flag(&p->flags[0], SIP_NAT) & SIP_NAT_ROUTE); 09004 } 09005 09006 ast_string_field_set(p, fromdomain, default_fromdomain); 09007 build_via(p); 09008 ast_string_field_set(p, callid, callid); 09009 09010 copy_socket_data(&p->socket, &req->socket); 09011 09012 /* Use this temporary pvt structure to send the message */ 09013 __transmit_response(p, msg, req, XMIT_UNRELIABLE); 09014 09015 /* Free the string fields, but not the pool space */ 09016 ast_string_field_init(p, 0); 09017 09018 return 0; 09019 }
| 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 9086 of file chan_sip.c.
References add_header(), add_header_contentLength(), respprep(), and send_response().
Referenced by handle_incoming(), and handle_request_options().
09087 { 09088 struct sip_request resp; 09089 respprep(&resp, p, msg, req); 09090 add_header(&resp, "Accept", "application/sdp"); 09091 add_header_contentLength(&resp, 0); 09092 return send_response(p, &resp, reliable, 0); 09093 }
| 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 9096 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().
09097 { 09098 struct sip_request resp; 09099 char tmp[512]; 09100 int seqno = 0; 09101 09102 if (reliable && (sscanf(get_header(req, "CSeq"), "%30d ", &seqno) != 1)) { 09103 ast_log(LOG_WARNING, "Unable to determine sequence number from '%s'\n", get_header(req, "CSeq")); 09104 return -1; 09105 } 09106 /* Stale means that they sent us correct authentication, but 09107 based it on an old challenge (nonce) */ 09108 snprintf(tmp, sizeof(tmp), "Digest algorithm=MD5, realm=\"%s\", nonce=\"%s\"%s", global_realm, randdata, stale ? ", stale=true" : ""); 09109 respprep(&resp, p, msg, req); 09110 add_header(&resp, header, tmp); 09111 add_header_contentLength(&resp, 0); 09112 append_history(p, "AuthChal", "Auth challenge sent for %s - nc %d", p->username, p->noncecount); 09113 return send_response(p, &resp, reliable, seqno); 09114 }
| 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 9076 of file chan_sip.c.
References add_header_contentLength(), append_date(), respprep(), send_response(), and XMIT_UNRELIABLE.
Referenced by register_verify().
09077 { 09078 struct sip_request resp; 09079 respprep(&resp, p, msg, req); 09080 append_date(&resp); 09081 add_header_contentLength(&resp, 0); 09082 return send_response(p, &resp, XMIT_UNRELIABLE, 0); 09083 }
| 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 9039 of file chan_sip.c.
References add_header(), add_header_contentLength(), append_date(), respprep(), send_response(), and XMIT_UNRELIABLE.
Referenced by handle_request_invite().
09040 { 09041 struct sip_request resp; 09042 char minse_str[20]; 09043 09044 respprep(&resp, p, msg, req); 09045 append_date(&resp); 09046 09047 snprintf(minse_str, sizeof(minse_str), "%d", minse_int); 09048 add_header(&resp, "Min-SE", minse_str); 09049 09050 add_header_contentLength(&resp, 0); 09051 return send_response(p, &resp, XMIT_UNRELIABLE, 0); 09052 }
| 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 9784 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().
09785 { 09786 struct sip_request resp; 09787 int seqno; 09788 if (sscanf(get_header(req, "CSeq"), "%30d ", &seqno) != 1) { 09789 ast_log(LOG_WARNING, "Unable to get seqno from '%s'\n", get_header(req, "CSeq")); 09790 return -1; 09791 } 09792 respprep(&resp, p, msg, req); 09793 if (p->rtp) { 09794 if (!p->autoframing && !ast_test_flag(&p->flags[0], SIP_OUTGOING)) { 09795 ast_debug(1, "Setting framing from config on incoming call\n"); 09796 ast_rtp_codec_setpref(p->rtp, &p->prefs); 09797 } 09798 try_suggested_sip_codec(p); 09799 if (p->t38.state == T38_ENABLED) { 09800 add_sdp(&resp, p, oldsdp, TRUE, TRUE); 09801 } else { 09802 add_sdp(&resp, p, oldsdp, TRUE, FALSE); 09803 } 09804 } else 09805 ast_log(LOG_ERROR, "Can't add SDP to response, since we have no RTP session allocated. Call-ID %s\n", p->callid); 09806 if (reliable && !p->pendinginvite) 09807 p->pendinginvite = seqno; /* Buggy clients sends ACK on RINGING too */ 09808 return send_response(p, &resp, reliable, seqno); 09809 }
| 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 9738 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().
09739 { 09740 struct sip_request resp; 09741 int seqno; 09742 09743 if (sscanf(get_header(req, "CSeq"), "%30d ", &seqno) != 1) { 09744 ast_log(LOG_WARNING, "Unable to get seqno from '%s'\n", get_header(req, "CSeq")); 09745 return -1; 09746 } 09747 respprep(&resp, p, msg, req); 09748 if (p->udptl) { 09749 add_sdp(&resp, p, 0, 0, 1); 09750 } else 09751 ast_log(LOG_ERROR, "Can't add SDP to response, since we have no UDPTL session allocated. Call-ID %s\n", p->callid); 09752 if (retrans && !p->pendinginvite) 09753 p->pendinginvite = seqno; /* Buggy clients sends ACK on RINGING too */ 09754 return send_response(p, &resp, retrans, seqno); 09755 }
| 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 9028 of file chan_sip.c.
References add_header(), add_header_contentLength(), append_date(), respprep(), send_response(), and XMIT_UNRELIABLE.
Referenced by handle_request_invite().
09029 { 09030 struct sip_request resp; 09031 respprep(&resp, p, msg, req); 09032 append_date(&resp); 09033 add_header(&resp, "Unsupported", unsupported); 09034 add_header_contentLength(&resp, 0); 09035 return send_response(p, &resp, XMIT_UNRELIABLE, 0); 09036 }
| 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 10310 of file chan_sip.c.
References add_header(), add_header_contentLength(), add_line(), ast_copy_string(), 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, cfsubscription_types::event, sip_pvt::expiry, sip_pvt::exten, find_subscription_type(), get_header(), get_in_brackets(), sip_pvt::initreq, LOG_WARNING, cfsubscription_types::mediatype, 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().
10311 { 10312 struct ast_str *tmp = ast_str_alloca(4000); 10313 char from[256], to[256]; 10314 char *c, *mfrom, *mto; 10315 struct sip_request req; 10316 char hint[AST_MAX_EXTENSION]; 10317 char *statestring = "terminated"; 10318 const struct cfsubscription_types *subscriptiontype; 10319 enum state { NOTIFY_OPEN, NOTIFY_INUSE, NOTIFY_CLOSED } local_state = NOTIFY_OPEN; 10320 char *pidfstate = "--"; 10321 char *pidfnote= "Ready"; 10322 10323 memset(from, 0, sizeof(from)); 10324 memset(to, 0, sizeof(to)); 10325 10326 switch (state) { 10327 case (AST_EXTENSION_RINGING | AST_EXTENSION_INUSE): 10328 statestring = (global_notifyringing) ? "early" : "confirmed"; 10329 local_state = NOTIFY_INUSE; 10330 pidfstate = "busy"; 10331 pidfnote = "Ringing"; 10332 break; 10333 case AST_EXTENSION_RINGING: 10334 statestring = "early"; 10335 local_state = NOTIFY_INUSE; 10336 pidfstate = "busy"; 10337 pidfnote = "Ringing"; 10338 break; 10339 case AST_EXTENSION_INUSE: 10340 statestring = "confirmed"; 10341 local_state = NOTIFY_INUSE; 10342 pidfstate = "busy"; 10343 pidfnote = "On the phone"; 10344 break; 10345 case AST_EXTENSION_BUSY: 10346 statestring = "confirmed"; 10347 local_state = NOTIFY_CLOSED; 10348 pidfstate = "busy"; 10349 pidfnote = "On the phone"; 10350 break; 10351 case AST_EXTENSION_UNAVAILABLE: 10352 statestring = "terminated"; 10353 local_state = NOTIFY_CLOSED; 10354 pidfstate = "away"; 10355 pidfnote = "Unavailable"; 10356 break; 10357 case AST_EXTENSION_ONHOLD: 10358 statestring = "confirmed"; 10359 local_state = NOTIFY_CLOSED; 10360 pidfstate = "busy"; 10361 pidfnote = "On hold"; 10362 break; 10363 case AST_EXTENSION_NOT_INUSE: 10364 default: 10365 /* Default setting */ 10366 break; 10367 } 10368 10369 subscriptiontype = find_subscription_type(p->subscribed); 10370 10371 /* Check which device/devices we are watching and if they are registered */ 10372 if (ast_get_hint(hint, sizeof(hint), NULL, 0, NULL, p->context, p->exten)) { 10373 char *hint2 = hint, *individual_hint = NULL; 10374 int hint_count = 0, unavailable_count = 0; 10375 10376 while ((individual_hint = strsep(&hint2, "&"))) { 10377 hint_count++; 10378 10379 if (ast_device_state(individual_hint) == AST_DEVICE_UNAVAILABLE) 10380 unavailable_count++; 10381 } 10382 10383 /* If none of the hinted devices are registered, we will 10384 * override notification and show no availability. 10385 */ 10386 if (hint_count > 0 && hint_count == unavailable_count) { 10387 local_state = NOTIFY_CLOSED; 10388 pidfstate = "away"; 10389 pidfnote = "Not online"; 10390 } 10391 } 10392 10393 ast_copy_string(from, get_header(&p->initreq, "From"), sizeof(from)); 10394 c = get_in_brackets(from); 10395 if (strncasecmp(c, "sip:", 4) && strncasecmp(c, "sips:", 5)) { 10396 ast_log(LOG_WARNING, "Huh? Not a SIP header (%s)?\n", c); 10397 return -1; 10398 } 10399 10400 mfrom = remove_uri_parameters(c); 10401 10402 ast_copy_string(to, get_header(&p->initreq, "To"), sizeof(to)); 10403 c = get_in_brackets(to); 10404 if (strncasecmp(c, "sip:", 4) && strncasecmp(c, "sips:", 5)) { 10405 ast_log(LOG_WARNING, "Huh? Not a SIP header (%s)?\n", c); 10406 return -1; 10407 } 10408 mto = remove_uri_parameters(c); 10409 10410 reqprep(&req, p, SIP_NOTIFY, 0, 1); 10411 10412 10413 add_header(&req, "Event", subscriptiontype->event); 10414 add_header(&req, "Content-Type", subscriptiontype->mediatype); 10415 switch(state) { 10416 case AST_EXTENSION_DEACTIVATED: 10417 if (timeout) 10418 add_header(&req, "Subscription-State", "terminated;reason=timeout"); 10419 else { 10420 add_header(&req, "Subscription-State", "terminated;reason=probation"); 10421 add_header(&req, "Retry-After", "60"); 10422 } 10423 break; 10424 case AST_EXTENSION_REMOVED: 10425 add_header(&req, "Subscription-State", "terminated;reason=noresource"); 10426 break; 10427 default: 10428 if (p->expiry) 10429 add_header(&req, "Subscription-State", "active"); 10430 else /* Expired */ 10431 add_header(&req, "Subscription-State", "terminated;reason=timeout"); 10432 } 10433 switch (p->subscribed) { 10434 case XPIDF_XML: 10435 case CPIM_PIDF_XML: 10436 ast_str_append(&tmp, 0, 10437 "<?xml version=\"1.0\"?>\n" 10438 "<!DOCTYPE presence PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n" 10439 "<presence>\n"); 10440 ast_str_append(&tmp, 0, "<presentity uri=\"%s;method=SUBSCRIBE\" />\n", mfrom); 10441 ast_str_append(&tmp, 0, "<atom id=\"%s\">\n", p->exten); 10442 ast_str_append(&tmp, 0, "<address uri=\"%s;user=ip\" priority=\"0.800000\">\n", mto); 10443 ast_str_append(&tmp, 0, "<status status=\"%s\" />\n", (local_state == NOTIFY_OPEN) ? "open" : (local_state == NOTIFY_INUSE) ? "inuse" : "closed"); 10444 ast_str_append(&tmp, 0, "<msnsubstatus substatus=\"%s\" />\n", (local_state == NOTIFY_OPEN) ? "online" : (local_state == NOTIFY_INUSE) ? "onthephone" : "offline"); 10445 ast_str_append(&tmp, 0, "</address>\n</atom>\n</presence>\n"); 10446 break; 10447 case PIDF_XML: /* Eyebeam supports this format */ 10448 ast_str_append(&tmp, 0, 10449 "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n" 10450 "<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); 10451 ast_str_append(&tmp, 0, "<pp:person><status>\n"); 10452 if (pidfstate[0] != '-') 10453 ast_str_append(&tmp, 0, "<ep:activities><ep:%s/></ep:activities>\n", pidfstate); 10454 ast_str_append(&tmp, 0, "</status></pp:person>\n"); 10455 ast_str_append(&tmp, 0, "<note>%s</note>\n", pidfnote); /* Note */ 10456 ast_str_append(&tmp, 0, "<tuple id=\"%s\">\n", p->exten); /* Tuple start */ 10457 ast_str_append(&tmp, 0, "<contact priority=\"1\">%s</contact>\n", mto); 10458 if (pidfstate[0] == 'b') /* Busy? Still open ... */ 10459 ast_str_append(&tmp, 0, "<status><basic>open</basic></status>\n"); 10460 else 10461 ast_str_append(&tmp, 0, "<status><basic>%s</basic></status>\n", (local_state != NOTIFY_CLOSED) ? "open" : "closed"); 10462 ast_str_append(&tmp, 0, "</tuple>\n</presence>\n"); 10463 break; 10464 case DIALOG_INFO_XML: /* SNOM subscribes in this format */ 10465 ast_str_append(&tmp, 0, "<?xml version=\"1.0\"?>\n"); 10466 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); 10467 if ((state & AST_EXTENSION_RINGING) && global_notifyringing) 10468 ast_str_append(&tmp, 0, "<dialog id=\"%s\" direction=\"recipient\">\n", p->exten); 10469 else 10470 ast_str_append(&tmp, 0, "<dialog id=\"%s\">\n", p->exten); 10471 ast_str_append(&tmp, 0, "<state>%s</state>\n", statestring); 10472 if (state == AST_EXTENSION_ONHOLD) { 10473 ast_str_append(&tmp, 0, "<local>\n<target uri=\"%s\">\n" 10474 "<param pname=\"+sip.rendering\" pvalue=\"no\"/>\n" 10475 "</target>\n</local>\n", mto); 10476 } 10477 ast_str_append(&tmp, 0, "</dialog>\n</dialog-info>\n"); 10478 break; 10479 case NONE: 10480 default: 10481 break; 10482 } 10483 10484 add_header_contentLength(&req, tmp->used); 10485 add_line(&req, tmp->str); 10486 10487 p->pendinginvite = p->ocseq; /* Remember that we have a pending NOTIFY in order not to confuse the NOTIFY subsystem */ 10488 10489 return send_request(p, &req, XMIT_RELIABLE, p->ocseq); 10490 }
| static void try_suggested_sip_codec | ( | struct sip_pvt * | p | ) | [static] |
Try setting codec suggested by the SIP_CODEC channel variable.
Definition at line 5760 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().
05761 { 05762 int fmt; 05763 const char *codec; 05764 05765 codec = pbx_builtin_getvar_helper(p->owner, "SIP_CODEC"); 05766 if (!codec) 05767 return; 05768 05769 fmt = ast_getformatbyname(codec); 05770 if (fmt) { 05771 ast_log(LOG_NOTICE, "Changing codec to '%s' for this call because of ${SIP_CODEC} variable\n", codec); 05772 if (p->jointcapability & fmt) { 05773 p->jointcapability &= fmt; 05774 p->capability &= fmt; 05775 } else 05776 ast_log(LOG_NOTICE, "Ignoring ${SIP_CODEC} variable because it is not shared by both ends.\n"); 05777 } else 05778 ast_log(LOG_NOTICE, "Ignoring ${SIP_CODEC} variable because of unrecognized/not configured codec (check allow/disallow in sip.conf): %s\n", codec); 05779 return; 05780 }
| static int unload_module | ( | void | ) | [static] |
PBX unload module API.
Definition at line 24748 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, ast_tls_config::cafile, ast_tls_config::capath, ast_tls_config::certfile, ast_tls_config::cipher, clear_realm_authentication(), clear_sip_domains(), default_tls_cfg, dialog_unlink_all(), dialogs, ast_tcptls_session_args::master, monlock, sip_pvt::owner, regl, sched_context_destroy(), sip_registry_destroy(), sip_threadinfo::stop, thread, sip_threadinfo::threadid, and TRUE.
24749 { 24750 struct sip_pvt *p; 24751 struct sip_threadinfo *th; 24752 struct ast_context *con; 24753 struct ao2_iterator i; 24754 24755 ast_sched_dump(sched); 24756 24757 /* First, take us out of the channel type list */ 24758 ast_channel_unregister(&sip_tech); 24759 24760 /* Unregister dial plan functions */ 24761 ast_custom_function_unregister(&sipchaninfo_function); 24762 ast_custom_function_unregister(&sippeer_function); 24763 ast_custom_function_unregister(&sip_header_function); 24764 ast_custom_function_unregister(&checksipdomain_function); 24765 24766 /* Unregister dial plan applications */ 24767 ast_unregister_application(app_dtmfmode); 24768 ast_unregister_application(app_sipaddheader); 24769 24770 /* Unregister CLI commands */ 24771 ast_cli_unregister_multiple(cli_sip, sizeof(cli_sip) / sizeof(struct ast_cli_entry)); 24772 24773 /* Disconnect from the RTP subsystem */ 24774 ast_rtp_proto_unregister(&sip_rtp); 24775 24776 /* Disconnect from UDPTL */ 24777 ast_udptl_proto_unregister(&sip_udptl); 24778 24779 /* Unregister AMI actions */ 24780 ast_manager_unregister("SIPpeers"); 24781 ast_manager_unregister("SIPshowpeer"); 24782 ast_manager_unregister("SIPqualifypeer"); 24783 ast_manager_unregister("SIPshowregistry"); 24784 ast_manager_unregister("SIPnotify"); 24785 24786 /* Kill TCP/TLS server threads */ 24787 if (sip_tcp_desc.master) 24788 ast_tcptls_server_stop(&sip_tcp_desc); 24789 if (sip_tls_desc.master) 24790 ast_tcptls_server_stop(&sip_tls_desc); 24791 24792 /* Kill all existing TCP/TLS threads */ 24793 i = ao2_iterator_init(threadt, 0); 24794 while ((th = ao2_t_iterator_next(&i, "iterate through tcp threads for 'sip show tcp'"))) { 24795 pthread_t thread = th->threadid; 24796 th->stop = 1; 24797 pthread_kill(thread, SIGURG); 24798 pthread_join(thread, NULL); 24799 ao2_t_ref(th, -1, "decrement ref from iterator"); 24800 } 24801 ao2_iterator_destroy(&i); 24802 24803 /* Hangup all dialogs if they have an owner */ 24804 i = ao2_iterator_init(dialogs, 0); 24805 while ((p = ao2_t_iterator_next(&i, "iterate thru dialogs"))) { 24806 if (p->owner) 24807 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD); 24808 ao2_t_ref(p, -1, "toss dialog ptr from iterator_next"); 24809 } 24810 ao2_iterator_destroy(&i); 24811 24812 ast_mutex_lock(&monlock); 24813 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) { 24814 pthread_cancel(monitor_thread); 24815 pthread_kill(monitor_thread, SIGURG); 24816 pthread_join(monitor_thread, NULL); 24817 } 24818 monitor_thread = AST_PTHREADT_STOP; 24819 ast_mutex_unlock(&monlock); 24820 24821 /* Destroy all the dialogs and free their memory */ 24822 i = ao2_iterator_init(dialogs, 0); 24823 while ((p = ao2_t_iterator_next(&i, "iterate thru dialogs"))) { 24824 dialog_unlink_all(p, TRUE, TRUE); 24825 ao2_t_ref(p, -1, "throw away iterator result"); 24826 } 24827 ao2_iterator_destroy(&i); 24828 24829 /* Free memory for local network address mask */ 24830 ast_free_ha(localaddr); 24831 24832 clear_realm_authentication(authl); 24833 24834 24835 if (default_tls_cfg.certfile) 24836 ast_free(default_tls_cfg.certfile); 24837 if (default_tls_cfg.cipher) 24838 ast_free(default_tls_cfg.cipher); 24839 if (default_tls_cfg.cafile) 24840 ast_free(default_tls_cfg.cafile); 24841 if (default_tls_cfg.capath) 24842 ast_free(default_tls_cfg.capath); 24843 24844 ASTOBJ_CONTAINER_DESTROYALL(®l, sip_registry_destroy); 24845 ASTOBJ_CONTAINER_DESTROY(®l); 24846 24847 ao2_t_ref(peers, -1, "unref the peers table"); 24848 ao2_t_ref(peers_by_ip, -1, "unref the peers_by_ip table"); 24849 ao2_t_ref(dialogs, -1, "unref the dialogs table"); 24850 ao2_t_ref(threadt, -1, "unref the thread table"); 24851 24852 clear_sip_domains(); 24853 ast_free_ha(global_contact_ha); 24854 close(sipsock); 24855 sched_context_destroy(sched); 24856 con = ast_context_find(used_context); 24857 if (con) 24858 ast_context_destroy(con, "SIP"); 24859 ast_unload_realtime("sipregs"); 24860 ast_unload_realtime("sippeers"); 24861 24862 return 0; 24863 }
| 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 2748 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(), realtime_peer(), reg_source_db(), register_verify(), reload_config(), 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().
02749 { 02750 ao2_t_ref(peer, -1, tag); 02751 return NULL; 02752 }
| 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 5235 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().
05236 { 05237 char name[256]; 05238 int *inuse = NULL, *call_limit = NULL, *inringing = NULL; 05239 int outgoing = fup->outgoing_call; 05240 struct sip_peer *p = NULL; 05241 05242 ast_debug(3, "Updating call counter for %s call\n", outgoing ? "outgoing" : "incoming"); 05243 05244 05245 /* Test if we need to check call limits, in order to avoid 05246 realtime lookups if we do not need it */ 05247 if (!ast_test_flag(&fup->flags[0], SIP_CALL_LIMIT) && !ast_test_flag(&fup->flags[1], SIP_PAGE2_CALL_ONHOLD)) 05248 return 0; 05249 05250 ast_copy_string(name, fup->username, sizeof(name)); 05251 05252 /* Check the list of devices */ 05253 if ((p = find_peer(ast_strlen_zero(fup->peername) ? name : fup->peername, NULL, TRUE, FINDALLDEVICES, FALSE, 0))) { /* Try to find peer */ 05254 inuse = &p->inUse; 05255 call_limit = &p->call_limit; 05256 inringing = &p->inRinging; 05257 ast_copy_string(name, fup->peername, sizeof(name)); 05258 } 05259 if (!p) { 05260 ast_debug(2, "%s is not a local device, no call limit\n", name); 05261 return 0; 05262 } 05263 05264 switch(event) { 05265 /* incoming and outgoing affects the inUse counter */ 05266 case DEC_CALL_LIMIT: 05267 /* Decrement inuse count if applicable */ 05268 if (inuse) { 05269 sip_pvt_lock(fup); 05270 ao2_lock(p); 05271 if (*inuse > 0) { 05272 if (ast_test_flag(&fup->flags[0], SIP_INC_COUNT)) { 05273 (*inuse)--; 05274 ast_clear_flag(&fup->flags[0], SIP_INC_COUNT); 05275 } 05276 } else { 05277 *inuse = 0; 05278 } 05279 ao2_unlock(p); 05280 sip_pvt_unlock(fup); 05281 } 05282 05283 /* Decrement ringing count if applicable */ 05284 if (inringing) { 05285 sip_pvt_lock(fup); 05286 ao2_lock(p); 05287 if (*inringing > 0) { 05288 if (ast_test_flag(&fup->flags[0], SIP_INC_RINGING)) { 05289 (*inringing)--; 05290 ast_clear_flag(&fup->flags[0], SIP_INC_RINGING); 05291 } 05292 } else { 05293 *inringing = 0; 05294 } 05295 ao2_unlock(p); 05296 sip_pvt_unlock(fup); 05297 } 05298 05299 /* Decrement onhold count if applicable */ 05300 sip_pvt_lock(fup); 05301 ao2_lock(p); 05302 if (ast_test_flag(&fup->flags[1], SIP_PAGE2_CALL_ONHOLD) && global_notifyhold) { 05303 ast_clear_flag(&fup->flags[1], SIP_PAGE2_CALL_ONHOLD); 05304 ao2_unlock(p); 05305 sip_pvt_unlock(fup); 05306 sip_peer_hold(fup, FALSE); 05307 } else { 05308 ao2_unlock(p); 05309 sip_pvt_unlock(fup); 05310 } 05311 if (sipdebug) 05312 ast_debug(2, "Call %s %s '%s' removed from call limit %d\n", outgoing ? "to" : "from", "peer", name, *call_limit); 05313 break; 05314 05315 case INC_CALL_RINGING: 05316 case INC_CALL_LIMIT: 05317 /* If call limit is active and we have reached the limit, reject the call */ 05318 if (*call_limit > 0 ) { 05319 if (*inuse >= *call_limit) { 05320 ast_log(LOG_ERROR, "Call %s %s '%s' rejected due to usage limit of %d\n", outgoing ? "to" : "from", "peer", name, *call_limit); 05321 unref_peer(p, "update_call_counter: unref peer p, call limit exceeded"); 05322 return -1; 05323 } 05324 } 05325 if (inringing && (event == INC_CALL_RINGING)) { 05326 sip_pvt_lock(fup); 05327 ao2_lock(p); 05328 if (!ast_test_flag(&fup->flags[0], SIP_INC_RINGING)) { 05329 (*inringing)++; 05330 ast_set_flag(&fup->flags[0], SIP_INC_RINGING); 05331 } 05332 ao2_unlock(p); 05333 sip_pvt_unlock(fup); 05334 } 05335 if (inuse) { 05336 sip_pvt_lock(fup); 05337 ao2_lock(p); 05338 if (!ast_test_flag(&fup->flags[0], SIP_INC_COUNT)) { 05339 (*inuse)++; 05340 ast_set_flag(&fup->flags[0], SIP_INC_COUNT); 05341 } 05342 ao2_unlock(p); 05343 sip_pvt_unlock(fup); 05344 } 05345 if (sipdebug) { 05346 ast_debug(2, "Call %s %s '%s' is %d out of %d\n", outgoing ? "to" : "from", "peer", name, *inuse, *call_limit); 05347 } 05348 break; 05349 05350 case DEC_CALL_RINGING: 05351 if (inringing) { 05352 sip_pvt_lock(fup); 05353 ao2_lock(p); 05354 if (ast_test_flag(&fup->flags[0], SIP_INC_RINGING)) { 05355 if (*inringing > 0) { 05356 (*inringing)--; 05357 } 05358 ast_clear_flag(&fup->flags[0], SIP_INC_RINGING); 05359 } 05360 ao2_unlock(p); 05361 sip_pvt_unlock(fup); 05362 } 05363 break; 05364 05365 default: 05366 ast_log(LOG_ERROR, "update_call_counter(%s, %d) called with no event!\n", name, event); 05367 } 05368 05369 if (p) { 05370 ast_devstate_changed(AST_DEVICE_UNKNOWN, "SIP/%s", p->name); 05371 unref_peer(p, "update_call_counter: unref_peer from call counter"); 05372 } 05373 return 0; 05374 }
| static void update_peer | ( | struct sip_peer * | p, | |
| int | expire | |||
| ) | [static] |
Update peer data in database (if used).
Definition at line 4309 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().
04310 { 04311 int rtcachefriends = ast_test_flag(&p->flags[1], SIP_PAGE2_RTCACHEFRIENDS); 04312 if (sip_cfg.peer_rtupdate && 04313 (p->is_realtime || rtcachefriends)) { 04314 realtime_update_peer(p->name, &p->addr, p->username, rtcachefriends ? p->fullcontact : NULL, p->useragent, expire, p->deprecated_username, p->lastms); 04315 } 04316 }
| static void update_provisional_keepalive | ( | struct sip_pvt * | pvt, | |
| int | with_sdp | |||
| ) | [static] |
Definition at line 3803 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, send_provisional_keepalive(), and send_provisional_keepalive_with_sdp().
Referenced by transmit_provisional_response().
03804 { 03805 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")); 03806 03807 pvt->provisional_keepalive_sched_id = ast_sched_add(sched, PROVIS_KEEPALIVE_TIMEOUT, 03808 with_sdp ? send_provisional_keepalive_with_sdp : send_provisional_keepalive, dialog_ref(pvt, "Increment refcount to pass dialog pointer to sched callback")); 03809 }
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 24869 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 24332 of file chan_sip.c.
char* app_sipaddheader = "SIPAddHeader" [static] |
Definition at line 24334 of file chan_sip.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 24869 of file chan_sip.c.
Authentication list for realm authentication.
Definition at line 1815 of file chan_sip.c.
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 1836 of file chan_sip.c.
Referenced by ast_sip_ouraddrfor(), create_addr(), create_addr_from_peer(), handle_request_invite(), reload_config(), sip_alloc(), sip_show_settings(), and sipsock_read().
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 11768 of file chan_sip.c.
Referenced by check_auth(), and transmit_fake_auth_response().
struct ast_custom_function checksipdomain_function [static] |
Definition at line 16460 of file chan_sip.c.
struct ast_cli_entry cli_sip[] [static] |
SIP Cli commands definition.
Definition at line 24627 of file chan_sip.c.
struct ast_cli_entry cli_sip_do_history_deprecated = AST_CLI_DEFINE(sip_do_history_deprecated, "Enable/Disable SIP history") [static] |
Definition at line 24625 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 1881 of file chan_sip.c.
Referenced by sip_debug_test_addr(), sip_do_debug(), sip_do_debug_ip(), and sip_do_debug_peer().
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 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 2346 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 24331 of file chan_sip.c.
char* descrip_sipaddheader [static] |
Definition at line 24337 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 1418 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 14088 of file chan_sip.c.
Referenced by conf_run(), handle_link_data(), handle_remote_data(), and send_dtmf().
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 1867 of file chan_sip.c.
char externhost[MAXHOSTNAMELEN] [static] |
External host name
Definition at line 1866 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 1864 of file chan_sip.c.
Referenced by ast_sip_ouraddrfor(), reload_config(), and sip_show_settings().
int externrefresh = 10 [static] |
Definition at line 1868 of file chan_sip.c.
struct _map_x_s faxecmodes[] [static] |
Definition at line 14538 of file chan_sip.c.
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] |
Codecs that we support by default:.
Definition at line 810 of file chan_sip.c.
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.
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.
struct ast_jb_conf global_jbconf [static] |
Global jitterbuffer configuration
Definition at line 284 of file chan_sip.c.
Referenced by reload_config(), sip_get_rtp_peer(), sip_new(), and sip_show_settings().
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(), reload_config(), 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.
static 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 1672 of file chan_sip.c.
int hash_peer_size = 563 [static] |
Size of peer hash table, prime number preferred!
Definition at line 1671 of file chan_sip.c.
int hash_user_size = 563 [static] |
Definition at line 1673 of file chan_sip.c.
struct _map_x_s insecurestr[] [static] |
Definition at line 14109 of file chan_sip.c.
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 1844 of file chan_sip.c.
Referenced by ast_sip_ouraddrfor(), reload_config(), sip_alloc(), sip_show_settings(), transmit_register(), and transmit_response_using_temp().
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 1877 of file chan_sip.c.
char mandescr_show_peer[] [static] |
"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 14421 of file chan_sip.c.
char mandescr_show_peers[] [static] |
Definition at line 13798 of file chan_sip.c.
char mandescr_show_registry[] [static] |
Manager Action SIPShowRegistry description.
Definition at line 13752 of file chan_sip.c.
char mandescr_sipnotify[] [static] |
Definition at line 10646 of file chan_sip.c.
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.
Referenced by do_monitor(), restart_monitor(), and unload_module().
Definition at line 13533 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.
Referenced by handle_request_do(), and reload_config().
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 1883 of file chan_sip.c.
int ourport_tcp [static] |
The port used for TCP connections
Definition at line 1879 of file chan_sip.c.
int ourport_tls [static] |
The port used for TCP/TLS connections
Definition at line 1880 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 |
The peer list: Users, Peers and Friends.
Definition at line 1680 of file chan_sip.c.
| struct ao2_container* peers_by_ip |
Definition at line 1681 of file chan_sip.c.
int recordhistory [static] |
Record SIP history. Off by default
Definition at line 788 of file chan_sip.c.
struct _map_x_s referstatusstrings[] [static] |
Definition at line 1162 of file chan_sip.c.
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] |
Definition at line 10655 of file chan_sip.c.
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(), reload_config(), sip_poke_noanswer(), sip_show_settings(), and update_peer().
struct ast_custom_function sip_header_function [static] |
Definition at line 16436 of file chan_sip.c.
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] |
Definition at line 844 of file chan_sip.c.
Referenced by do_monitor(), and sip_reload().
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 2401 of file chan_sip.c.
struct ast_tcptls_session_args sip_tcp_desc [static] |
The TCP server definition.
Definition at line 2349 of file chan_sip.c.
struct ast_channel_tech sip_tech [static] |
Definition of this channel for PBX channel registration.
Definition at line 2305 of file chan_sip.c.
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 2339 of file chan_sip.c.
Referenced by load_module(), and sip_new().
struct ast_tls_config sip_tls_cfg [static] |
Working TLS connection configuration.
Definition at line 2343 of file chan_sip.c.
struct ast_tcptls_session_args sip_tls_desc [static] |
The TCP/TLS server definition.
Definition at line 2360 of file chan_sip.c.
struct ast_udptl_protocol sip_udptl [static] |
{
type: "SIP",
get_udptl_info: sip_get_udptl_peer,
set_udptl_peer: sip_set_udptl_peer,
}
Interface structure with callbacks used to connect to UDPTL module.
Definition at line 2872 of file chan_sip.c.
struct ast_custom_function sipchaninfo_function [static] |
Structure to declare a dialplan function: SIPCHANINFO.
Definition at line 16651 of file chan_sip.c.
enum sip_debug_e sipdebug [static] |
Definition at line 1116 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 1122 of file chan_sip.c.
Structure to declare a dialplan function: SIPPEER.
Definition at line 16559 of file chan_sip.c.
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 1834 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 13573 of file chan_sip.c.
struct _map_x_s strefreshers[] [static] |
Definition at line 13591 of file chan_sip.c.
struct sockaddr_in stunaddr [static] |
stun server address
Definition at line 1869 of file chan_sip.c.
Referenced by ast_sip_ouraddrfor(), reload_config(), and sip_show_settings().
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 24330 of file chan_sip.c.
char* synopsis_sipaddheader = "Add a SIP header to the outbound call" [static] |
Definition at line 24335 of file chan_sip.c.
struct ao2_container* threadt [static] |
The table of TCP threads.
Definition at line 1677 of file chan_sip.c.
struct ast_threadstorage ts_temp_pvt = { .once = PTHREAD_ONCE_INIT , .key_init = __init_ts_temp_pvt , .custom_init = temp_pvt_init , } [static] |
Definition at line 1803 of file chan_sip.c.
Referenced by transmit_response_using_temp().
char used_context[AST_MAX_CONTEXT] [static] |
name of automatically created context for unloading
Definition at line 835 of file chan_sip.c.
1.6.1