chan_sip.c File Reference

Implementation of Session Initiation Protocol. More...

#include "asterisk.h"
#include <signal.h>
#include <sys/signal.h>
#include <regex.h>
#include <inttypes.h>
#include "asterisk/network.h"
#include "asterisk/paths.h"
#include "asterisk/lock.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/rtp_engine.h"
#include "asterisk/udptl.h"
#include "asterisk/acl.h"
#include "asterisk/manager.h"
#include "asterisk/callerid.h"
#include "asterisk/cli.h"
#include "asterisk/musiconhold.h"
#include "asterisk/dsp.h"
#include "asterisk/pickup.h"
#include "asterisk/parking.h"
#include "asterisk/srv.h"
#include "asterisk/astdb.h"
#include "asterisk/causes.h"
#include "asterisk/utils.h"
#include "asterisk/file.h"
#include "asterisk/astobj2.h"
#include "asterisk/dnsmgr.h"
#include "asterisk/devicestate.h"
#include "asterisk/monitor.h"
#include "asterisk/netsock2.h"
#include "asterisk/localtime.h"
#include "asterisk/abstract_jb.h"
#include "asterisk/threadstorage.h"
#include "asterisk/translate.h"
#include "asterisk/ast_version.h"
#include "asterisk/data.h"
#include "asterisk/aoc.h"
#include "asterisk/message.h"
#include "sip/include/sip.h"
#include "sip/include/globals.h"
#include "sip/include/config_parser.h"
#include "sip/include/reqresp_parser.h"
#include "sip/include/sip_utils.h"
#include "asterisk/sdp_srtp.h"
#include "asterisk/ccss.h"
#include "asterisk/xml.h"
#include "sip/include/dialog.h"
#include "sip/include/dialplan_functions.h"
#include "sip/include/security_events.h"
#include "sip/include/route.h"
#include "asterisk/sip_api.h"
#include "asterisk/app.h"
#include "asterisk/bridge.h"
#include "asterisk/stasis.h"
#include "asterisk/stasis_endpoints.h"
#include "asterisk/stasis_system.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/features_config.h"
#include "asterisk/http_websocket.h"
#include "asterisk/format_cache.h"

Go to the source code of this file.

Data Structures

struct  blind_transfer_cb_data
struct  cfalias
 Structure for conversion between compressed SIP and "normal" SIP headers. More...
struct  cfsip_methods
 The core structure to setup dialogs. We parse incoming messages by using structure and then route the messages according to the type. More...
struct  cfsubscription_types
 Subscription types that we support. We support
  • dialoginfo updates (really device status, not dialog info as was the original intent of the standard)
  • SIMPLE presence used for device status
  • Voicemail notification subscriptions.
More...
struct  domain_list
struct  epa_static_data_list
struct  event_state_compositor
 The Event State Compositors. More...
struct  invstate2stringtable
 Readable descriptions of device states. More...
struct  match_req_args
struct  show_peers_context
 Used in the sip_show_peers functions to pass parameters. More...
struct  sip_history_head
struct  sip_reasons
 Diversion header reasons. More...
struct  state_notify_data

DefaultSettings

Default setttings are used as a channel setting and as a default when configuring devices

#define SIP_PEDANTIC_DECODE(str)
static unsigned int chan_idx
static char default_callerid [AST_MAX_EXTENSION]
static char default_engine [256]
static char default_fromdomain [AST_MAX_EXTENSION]
static int default_fromdomainport
static int default_keepalive
static char default_language [MAX_LANGUAGE]
static int default_maxcallbitrate
static char default_mohinterpret [MAX_MUSICCLASS]
static char default_mohsuggest [MAX_MUSICCLASS]
static char default_mwi_from [80]
static char default_notifymime [AST_MAX_EXTENSION]
static char default_parkinglot [AST_MAX_CONTEXT]
static unsigned int default_primary_transport
static int default_qualify
static unsigned int default_transports
static char default_vmexten [AST_MAX_EXTENSION]
static char default_zone [MAX_TONEZONE_COUNTRY]
static unsigned int dumphistory
static int global_authfailureevents
static unsigned int global_autoframing
static int global_callcounter
static unsigned int global_cos_audio
static unsigned int global_cos_sip
static unsigned int global_cos_text
static unsigned int global_cos_video
static int global_dynamic_exclude_static = 0
static int global_match_auth_username
static int global_max_se
static int global_min_se
static int global_prematuremediafilter
static int global_qualify_gap
static int global_qualify_peers
static int global_qualifyfreq
static unsigned char global_refer_addheaders
static int global_reg_retry_403
static int global_reg_timeout
static int global_regattempts_max
static int global_relaxdtmf
static int global_rtpholdtimeout
static int global_rtpkeepalive
static int global_rtptimeout
static char global_sdpowner [AST_MAX_EXTENSION]
static char global_sdpsession [AST_MAX_EXTENSION]
static int global_shrinkcallerid
static enum st_mode global_st_mode
static enum st_refresher_param global_st_refresher
static int global_store_sip_cause
static int global_t1
static int global_t1min
static int global_timer_b
static unsigned int global_tos_audio
static unsigned int global_tos_sip
static unsigned int global_tos_text
static unsigned int global_tos_video
static char global_useragent [AST_MAX_EXTENSION]
static unsigned int recordhistory
static struct sip_settings sip_cfg

Defines

#define append_history(p, event, fmt, args...)   append_history_full(p, "%-15s " fmt, event, ## args)
 Append to SIP dialog history.
#define BOGUS_PEER_MD5SECRET   "intentionally_invalid_md5_string"
 We can recognise the bogus peer by this invalid MD5 hash.
#define check_request_transport(peer, tmpl)
 generic function for determining if a correct transport is being used to contact a peer
#define CONTAINER_UNLINK(container, obj, tag)
 Unlink the given object from the container and return TRUE if it was in the container.
#define DATA_EXPORT_SIP_PEER(MEMBER)
#define find_call(req, addr, intended_method)   __find_call(req, addr, intended_method, __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define FORMAT   "%-15.15s %-15.15s %-15.15s %-15.15s %-3.3s %-3.3s %-15.15s %-10.10s %-10.10s\n"
#define FORMAT   "%-30.30s %-12.12s %-10.10s %-10.10s\n"
#define FORMAT   "%-15.15s %-11.11s %-8.8s %-10.10u%-1.1s %-10.10u (%5.2f%%) %-6.4lf %-10.10u%-1.1s %-10.10u (%5.2f%%) %-6.4lf\n"
#define FORMAT   "%-39.39s %-6.6s %-12.12s %8d %-20.20s %-25.25s\n"
#define FORMAT   "%-40.40s %-20.20s %-16.16s\n"
#define FORMAT   "%-25.25s %-15.15s %-15.15s %-15.15s %-5.5s%-10.10s\n"
#define FORMAT   "%-47.47s %-9.9s %-6.6s\n"
#define FORMAT   "%-25.25s %-15.15s %-15.15s \n"
#define FORMAT2   "%-15.15s %-15.15s %-15.15s %-15.15s %-7.7s %-15.15s %-10.10s %-10.10s\n"
#define FORMAT2   "%-15.15s %-11.11s %-8.8s %-10.10s %-10.10s ( %%) %-6.6s %-10.10s %-10.10s ( %%) %-6.6s\n"
#define FORMAT2   "%-39.39s %-6.6s %-12.12s %8.8s %-20.20s %-25.25s\n"
#define FORMAT2   "%-47.47s %9.9s %6.6s\n"
#define FORMAT2   "%-25.25s %-15.15s %-15.15s \n"
#define FORMAT3   "%-15.15s %-15.15s %-15.15s %-15.15s %-13.13s %-15.15s %-10.10s %-6.6s\n"
#define FORMAT4   "%-15.15s %-15.15s %-15.15s %-15.15s %-13.13s %-15.15s %-10.10s %-6.6d\n"
#define PEERS_FORMAT2   "%-25.25s %-39.39s %-3.3s %-10.10s %-10.10s %-3.3s %-8s %-11s %-32.32s %s\n"
#define sip_pvt_lock(x)   ao2_lock(x)
#define sip_pvt_trylock(x)   ao2_trylock(x)
#define sip_pvt_unlock(x)   ao2_unlock(x)
#define SIP_TRANSPORT_STR_BUFSIZE   128
 Size of the SIP transport buffer.
#define UNLINK(element, head, prev)

Enumerations

enum  match_req_res { SIP_REQ_MATCH, SIP_REQ_NOT_MATCH, SIP_REQ_LOOP_DETECTED, SIP_REQ_FORKED }
enum  message_integrity { MESSAGE_INVALID, MESSAGE_FRAGMENT, MESSAGE_FRAGMENT_COMPLETE, MESSAGE_COMPLETE }
 Indication of a TCP message's integrity. More...
enum  peer_unlink_flag_t { SIP_PEERS_MARKED, SIP_PEERS_ALL }

Functions

static struct sip_pvt__find_call (struct sip_request *req, struct ast_sockaddr *addr, const int intended_method, const char *file, int line, const char *func)
 find or create a dialog structure for an incoming SIP message. Connect incoming SIP message to current dialog or create new dialog structure Returns a reference to the sip_pvt object, remember to give it back once done. Called by handle_request_do
static const char * __get_header (const struct sip_request *req, const char *name, int *start)
static void __init_sip_content_buf (void)
static void __init_sip_transport_str_buf (void)
 A per-thread buffer for transport to string conversion.
static void __init_ts_temp_pvt (void)
 A per-thread temporary pvt structure.
static void __reg_module (void)
static int __set_address_from_contact (const char *fullcontact, struct ast_sockaddr *addr, int tcp)
int __sip_ack (struct sip_pvt *p, uint32_t seqno, int resp, int sipmethod)
 Acknowledges receipt of a packet and stops retransmission called with p locked.
struct sip_pvt__sip_alloc (ast_string_field callid, struct ast_sockaddr *addr, int useglobal_nat, const int intended_method, struct sip_request *req, ast_callid logger_callid, const char *file, int line, const char *func)
 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 int __sip_autodestruct (const void *data)
 Kill a SIP dialog (called only by the scheduler) The scheduler has a reference to this dialog when p->autokillid != -1, and we are called using that reference. So if the event is not rescheduled, we need to call dialog_unref().
void __sip_destroy (struct sip_pvt *p, int lockowner, int lockdialoglist)
 Execute destruction of SIP dialog structure, release memory.
static int __sip_do_register (struct sip_registry *r)
 Register with SIP proxy.
void __sip_pretend_ack (struct sip_pvt *p)
 Pretend to ack all packets called with p locked.
static int __sip_reliable_xmit (struct sip_pvt *p, uint32_t seqno, int resp, struct ast_str *data, int fatal, int sipmethod)
int __sip_semi_ack (struct sip_pvt *p, uint32_t seqno, int resp, int sipmethod)
 Acks receipt of packet, keep it around (used for provisional responses).
static int __sip_subscribe_mwi_do (struct sip_subscription_mwi *mwi)
 Actually setup an MWI subscription or resubscribe.
static int __sip_xmit (struct sip_pvt *p, struct ast_str *data)
static int __transmit_response (struct sip_pvt *p, const char *msg, const struct sip_request *req, enum xmittype reliable)
 Base transmit response function.
static void __unreg_module (void)
static char * _sip_qualify_peer (int type, int fd, struct mansession *s, const struct message *m, int argc, const char *argv[])
 Send qualify message to peer from cli or manager. Mostly for debugging.
static char * _sip_show_peer (int type, int fd, struct mansession *s, const struct message *m, int argc, const char *argv[])
 Show one peer in detail (main function).
static char * _sip_show_peers (int fd, int *total, struct mansession *s, const struct message *m, int argc, const char *argv[])
 Execute sip show peers command.
static struct sip_peer_sip_show_peers_one (int fd, struct mansession *s, struct show_peers_context *cont, struct sip_peer *peer)
 Emit informations for one peer during sip show peers command.
static void * _sip_tcp_helper_thread (struct ast_tcptls_session_instance *tcptls_session)
 SIP TCP thread management function This function reads from the socket, parses the packet into a request.
static void acl_change_event_stasis_unsubscribe (void)
static void acl_change_stasis_cb (void *data, struct stasis_subscription *sub, struct stasis_message *message)
static void acl_change_stasis_subscribe (void)
static void add_blank (struct sip_request *req)
 add a blank line if no body
static void add_cc_call_info_to_response (struct sip_pvt *p, struct sip_request *resp)
static void add_codec_to_sdp (const struct sip_pvt *p, struct ast_format *format, struct ast_str **m_buf, struct ast_str **a_buf, int debug, int *min_packet_size, int *max_packet_size)
 Add codec offer to SDP offer/answer body in INVITE or 200 OK.
static int add_content (struct sip_request *req, const char *line)
 Add content (not header) to SIP message.
static void add_date (struct sip_request *req)
 Add date header to SIP message.
static int add_digit (struct sip_request *req, char digit, unsigned int duration, int mode)
 Add DTMF INFO tone to sip message Mode = 0 for application/dtmf-relay (Cisco) 1 for application/dtmf.
static void add_diversion (struct sip_request *req, struct sip_pvt *pvt)
 Add "Diversion" header to outgoing message.
static void add_dtls_to_sdp (struct ast_rtp_instance *instance, struct ast_str **a_buf)
 Add DTLS attributes to SDP.
static void add_expires (struct sip_request *req, int expires)
 Add Expires header to SIP message.
static int add_header (struct sip_request *req, const char *var, const char *value)
 Add header to SIP message.
static void add_ice_to_sdp (struct ast_rtp_instance *instance, struct ast_str **a_buf)
 Add ICE attributes to SDP.
static int add_max_forwards (struct sip_pvt *dialog, struct sip_request *req)
 Add 'Max-Forwards' header to SIP message.
static void add_msg_header (struct sip_pvt *pvt, const char *hdr_name, const char *hdr_value)
static void add_noncodec_to_sdp (const struct sip_pvt *p, int format, struct ast_str **m_buf, struct ast_str **a_buf, int debug)
 Add RFC 2833 DTMF offer to SDP.
static void add_peer_mailboxes (struct sip_peer *peer, const char *value)
static void add_peer_mwi_subs (struct sip_peer *peer)
static void add_realm_authentication (struct sip_auth_container **credentials, const char *configuration, int lineno)
static void add_required_respheader (struct sip_request *req)
static void add_route (struct sip_request *req, struct sip_route *route, int skip)
 Add route header into request per learned route.
static int add_rpid (struct sip_request *req, struct sip_pvt *p)
 Add Remote-Party-ID header to SIP message.
static enum sip_result add_sdp (struct sip_request *resp, struct sip_pvt *p, int oldsdp, int add_audio, int add_t38)
 Add Session Description Protocol message.
static int add_sip_domain (const char *domain, const enum domain_mode mode, const char *context)
 Add SIP domain to list of domains we are responsible for.
static int add_supported (struct sip_pvt *pvt, struct sip_request *req)
 Add "Supported" header to sip message. Since some options may be disabled in the config, the sip_pvt must be inspected to determine what is supported for this dialog.
static void add_tcodec_to_sdp (const struct sip_pvt *p, struct ast_format *format, struct ast_str **m_buf, struct ast_str **a_buf, int debug, int *min_packet_size)
 Add text codec offer to SDP offer/answer body in INVITE or 200 OK.
static int add_text (struct sip_request *req, struct sip_pvt *p)
 Add text body to SIP message.
static struct ast_variableadd_var (const char *buf, struct ast_variable *list)
 implement the setvar config line
static void add_vcodec_to_sdp (const struct sip_pvt *p, struct ast_format *format, struct ast_str **m_buf, struct ast_str **a_buf, int debug, int *min_packet_size)
 Add video codec offer to SDP offer/answer body in INVITE or 200 OK.
static int add_vidupdate (struct sip_request *req)
 add XML encoded media control with update
static int allow_notify_user_presence (struct sip_pvt *p)
static const char * allowoverlap2str (int mode)
 Convert AllowOverlap setting to printable string.
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.
 AST_DATA_STRUCTURE (sip_peer, DATA_EXPORT_SIP_PEER)
static void ast_sip_ouraddrfor (const struct ast_sockaddr *them, struct ast_sockaddr *us, struct sip_pvt *p)
 NAT fix - decide which IP address to use for Asterisk server?
static int ast_sockaddr_resolve_first (struct ast_sockaddr *addr, const char *name, int flag)
 Return the first entry from ast_sockaddr_resolve filtered by family of binddaddr.
static int ast_sockaddr_resolve_first_af (struct ast_sockaddr *addr, const char *name, int flag, int family)
 Return the first entry from ast_sockaddr_resolve filtered by address family.
static int ast_sockaddr_resolve_first_transport (struct ast_sockaddr *addr, const char *name, int flag, unsigned int transport)
 Return the first entry from ast_sockaddr_resolve filtered by family of binddaddr.
static int auto_congest (const void *arg)
 Scheduled congestion on a call. Only called by the scheduler, must return the reference when done.
static const char * autocreatepeer2str (enum autocreatepeer_mode r)
static void blind_transfer_cb (struct ast_channel *chan, struct transfer_channel_data *user_data_wrapper, enum ast_transfer_type transfer_type)
static int block_msg_header (const char *header_name)
static void build_callid_pvt (struct sip_pvt *pvt)
 Build SIP Call-ID value for a non-REGISTER transaction.
static void build_callid_registry (struct sip_registry *reg, const struct ast_sockaddr *ourip, const char *fromdomain)
 Build SIP Call-ID value for a REGISTER transaction.
static void build_contact (struct sip_pvt *p, struct sip_request *req, int incoming)
 Build contact header.
static void build_localtag_registry (struct sip_registry *reg)
 Build SIP From tag value for REGISTER.
static void build_nonce (struct sip_pvt *p, int forceupdate)
 builds the sip_pvt's nonce field which is used for the authentication 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 int build_path (struct sip_pvt *p, struct sip_peer *peer, struct sip_request *req, const char *pathbuf)
 Build route list from Path header RFC 3327 requires that the Path header contains SIP URIs with lr paramter. Thus, we do not care about strict routing SIP routers.
static struct sip_peerbuild_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, int resp)
 Build route list from Record-Route header.
static void build_via (struct sip_pvt *p)
 Build a Via header for a request.
static int cb_extensionstate (char *context, char *exten, struct ast_state_cb_info *info, void *data)
 Callback for the devicestate notification (SUBSCRIBE) support subsystem.
static void cb_extensionstate_destroy (int id, void *data)
static void cc_epa_destructor (void *data)
static void cc_handle_publish_error (struct sip_pvt *pvt, const int resp, struct sip_request *req, struct sip_epa_entry *epa_entry)
static void change_callid_pvt (struct sip_pvt *pvt, const char *callid)
static void change_hold_state (struct sip_pvt *dialog, struct sip_request *req, int holdstate, int sendonly)
 Change hold state for a call.
static void change_redirecting_information (struct sip_pvt *p, struct sip_request *req, struct ast_party_redirecting *redirecting, struct ast_set_party_redirecting *update_redirecting, int set_call_forward)
 update redirecting information for a channel based on headers
static void change_t38_state (struct sip_pvt *p, int state)
 Change the T38 state on a SIP dialog.
static enum check_auth_result check_auth (struct sip_pvt *p, struct sip_request *req, const char *username, const char *secret, const char *md5secret, int sipmethod, const char *uri, enum xmittype reliable)
 Check user authorization from peer definition Some actions, like REGISTER and INVITEs from peers require authentication (if peer have secret set).
static void check_for_nat (const struct ast_sockaddr *addr, struct sip_pvt *p)
 Check and see if the requesting UA is likely to be behind a NAT.
static enum message_integrity check_message_integrity (struct ast_str **request, struct ast_str **overflow)
 Check that a message received over TCP is a full message.
static enum check_auth_result check_peer_ok (struct sip_pvt *p, char *of, struct sip_request *req, int sipmethod, struct ast_sockaddr *addr, struct sip_peer **authpeer, enum xmittype reliable, char *calleridname, char *uri2)
 Validate device authentication.
static void check_pendings (struct sip_pvt *p)
 Check pending actions on SIP call.
static int check_rtp_timeout (struct sip_pvt *dialog, time_t t)
 helper function for the monitoring thread -- seems to be called with the assumption that the dialog is locked
static int check_sip_domain (const char *domain, char *context, size_t len)
 check_sip_domain: Check if domain part of uri is local to our server
static int check_user (struct sip_pvt *p, struct sip_request *req, int sipmethod, const char *uri, enum xmittype reliable, struct ast_sockaddr *addr)
 Find user If we get a match, this will add a reference pointer to the user object, that needs to be unreferenced.
static enum check_auth_result check_user_full (struct sip_pvt *p, struct sip_request *req, int sipmethod, const char *uri, enum xmittype reliable, struct ast_sockaddr *addr, struct sip_peer **authpeer)
 Check if matching user or peer is defined Match user on From: user name and peer on IP/port This is used on first invite (not re-invites) and subscribe requests.
static void check_via (struct sip_pvt *p, const struct sip_request *req)
 check Via: header for hostname, port and rport request/answer
static void cleanup_all_regs (void)
static int cleanup_registration (void *obj, void *arg, int flags)
static void cleanup_stale_contexts (char *new, char *old)
 Destroy disused contexts between reloads Only used in reload_config so the code for regcontext doesn't get ugly.
static void clear_peer_mailboxes (struct sip_peer *peer)
static void clear_sip_domains (void)
 Clear our domain list (at reload).
static char * complete_sip_notify (const char *line, const char *word, int pos, int state)
 Support routine for 'sip notify' CLI.
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 int construct_pidf_body (enum sip_cc_publish_state state, char *pidf_body, size_t size, const char *presentity)
static int copy_all_header (struct sip_request *req, const struct sip_request *orig, const char *field)
 Copy all headers from one request to another.
static int copy_header (struct sip_request *req, const struct sip_request *orig, const char *field)
 Copy one header field from one request to another.
static void copy_request (struct sip_request *dst, const struct sip_request *src)
 copy SIP request (mostly used to save request for responses)
static void copy_socket_data (struct sip_socket *to_sock, const struct sip_socket *from_sock)
static struct ast_variablecopy_vars (struct ast_variable *src)
 duplicate a list of channel variables,
static int copy_via_headers (struct sip_pvt *p, struct sip_request *req, const struct sip_request *orig, const char *field)
 Copy SIP VIA Headers from the request to the response.
static int create_addr (struct sip_pvt *dialog, const char *opeer, struct ast_sockaddr *addr, int newdialog)
 create address structure from device name Or, if peer not found, find it in the global DNS returns TRUE (-1) on failure, FALSE on success
static int create_addr_from_peer (struct sip_pvt *dialog, struct sip_peer *peer)
 Create address structure from peer reference. This function copies data from peer to the dialog, so we don't have to look up the peer again from memory or database during the life time of the dialog.
static struct sip_epa_entrycreate_epa_entry (const char *const event_package, const char *const destination)
static struct sip_esc_entrycreate_esc_entry (struct event_state_compositor *esc, struct sip_request *req, const int expires)
static void create_new_sip_etag (struct sip_esc_entry *esc_entry, int is_linked)
static char * crypto_get_attrib (struct ast_sdp_srtp *srtp, int dtls_enabled, int default_taglen_32)
static int default_sip_port (enum ast_transport type)
 The default sip port for the given transport.
static void deinit_req (struct sip_request *req)
 Deinitialize SIP response/request.
static void destroy_association (struct sip_peer *peer)
 Remove registration data from realtime database or AST/DB when registration expires.
static void destroy_escs (void)
static void destroy_mailbox (struct sip_mailbox *mailbox)
static void destroy_msg_headers (struct sip_pvt *pvt)
static void destroy_realm_authentication (void *obj)
static int determine_firstline_parts (struct sip_request *req)
 Parse first line of incoming SIP request.
static enum sip_publish_type determine_sip_publish_type (struct sip_request *req, const char *const event, const char *const etag, const char *const expires, int *expires_int)
static int dialog_checkrtp_cb (void *dialogobj, void *arg, int flags)
 Check RTP Timeout on dialogs.
static int dialog_cmp_cb (void *obj, void *arg, int flags)
static int dialog_dump_func (void *userobj, void *arg, int flags)
static int dialog_find_multiple (void *obj, void *arg, int flags)
static int dialog_hash_cb (const void *obj, const int flags)
static int dialog_initialize_dtls_srtp (const struct sip_pvt *dialog, struct ast_rtp_instance *rtp, struct ast_sdp_srtp **srtp)
 Initialize DTLS-SRTP support on an RTP instance.
static int dialog_initialize_rtp (struct sip_pvt *dialog)
 Initialize RTP portion of a dialog.
static int dialog_needdestroy (void *dialogobj, void *arg, int flags)
 Match dialogs that need to be destroyed.
void dialog_unlink_all (struct sip_pvt *dialog)
 Unlink a dialog from the dialogs container, as well as any other places that it may be currently stored.
static void disable_dsp_detect (struct sip_pvt *p)
static void display_nat_warning (const char *cat, int reason, struct ast_flags *flags)
static int do_magic_pickup (struct ast_channel *channel, const char *extension, const char *context)
static int do_message_auth (struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, uint32_t seqno)
static void * do_monitor (void *data)
 The SIP monitoring thread.
static int do_proxy_auth (struct sip_pvt *p, struct sip_request *req, enum sip_auth_type code, int sipmethod, int init)
 Add authentication on outbound SIP packet.
static int do_register_auth (struct sip_pvt *p, struct sip_request *req, enum sip_auth_type code)
 Authenticate for outbound registration.
static void do_setnat (struct sip_pvt *p)
 Set nat mode on the various data sockets.
static const char * domain_mode_to_text (const enum domain_mode mode)
 Print domain mode to cli.
static const char * dtmfmode2str (int mode)
 Convert DTMF mode to printable string.
static void enable_dsp_detect (struct sip_pvt *p)
static int esc_cmp_fn (void *obj, void *arg, int flags)
static void esc_entry_destructor (void *obj)
static int esc_hash_fn (const void *obj, const int flags)
static int expire_register (const void *data)
 Expire registration of SIP peer.
static int extensionstate_update (const char *context, const char *exten, struct state_notify_data *data, struct sip_pvt *p, int force)
 Callback for the devicestate notification (SUBSCRIBE) support subsystem.
static void extract_host_from_hostport (char **hostport)
 Terminate a host:port at the ':'.
static void extract_uri (struct sip_pvt *p, struct sip_request *req)
 Check Contact: URI of SIP message.
static const char * faxec2str (int faxec)
static int finalize_content (struct sip_request *req)
 Add 'Content-Length' header and content to SIP message.
static const char * find_alias (const char *name, const char *_default)
 Find compressed SIP alias.
static int find_by_callid_helper (void *obj, void *arg, int flags)
static int find_by_name (void *obj, void *arg, void *data, int flags)
static int find_by_notify_uri_helper (void *obj, void *arg, int flags)
static int find_by_subscribe_uri_helper (void *obj, void *arg, int flags)
const char * find_closing_quote (const char *start, const char *lim)
 Locate closing quote in a string, skipping escaped quotes. optionally with a limit on the search. start must be past the first quote.
static const char * find_full_alias (const char *name, const char *_default)
 Find full SIP alias.
static struct sip_authfind_realm_authentication (struct sip_auth_container *credentials, const char *realm)
static struct ast_channelfind_ringing_channel (struct ao2_container *device_state_info, struct sip_pvt *p)
static int find_sdp (struct sip_request *req)
 Determine whether a SIP message contains an SDP in its body.
static struct ast_cc_agentfind_sip_cc_agent_by_notify_uri (const char *const uri)
static struct ast_cc_agentfind_sip_cc_agent_by_original_callid (struct sip_pvt *pvt)
static struct ast_cc_agentfind_sip_cc_agent_by_subscribe_uri (const char *const uri)
static int find_sip_method (const char *msg)
 find_sip_method: Find SIP method from header
static int find_sip_monitor_instance_by_subscription_pvt (void *obj, void *arg, int flags)
static int find_sip_monitor_instance_by_suspension_entry (void *obj, void *arg, int flags)
static struct epa_static_datafind_static_data (const char *const event_package)
static struct
cfsubscription_types
find_subscription_type (enum subscriptiontype subtype)
 Find subscription type in array.
static void forked_invite_init (struct sip_request *req, const char *new_theirtag, struct sip_pvt *original, struct ast_sockaddr *addr)
 This function creates a dialog to handle a forked request. This dialog exists only to properly terminiate the the forked request immediately.
static 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_sippeer (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 ${SIPPEER()} Dialplan function - reads peer data
static char * generate_random_string (char *buf, size_t size)
 Generate 32 byte random string for callid's etc.
static char * generate_uri (struct sip_pvt *pvt, char *buf, size_t size)
static int get_address_family_filter (unsigned int transport)
 Helper for dns resolution to filter by address family.
static int get_also_info (struct sip_pvt *p, struct sip_request *oreq)
 Call transfer support (old way, deprecated by the IETF).
static int get_cached_mwi (struct sip_peer *peer, int *new, int *old)
 Get cached MWI info.
static char * get_content (struct sip_request *req)
 Get message body content.
static char * get_content_line (struct sip_request *req, char *name, char delimiter)
 Get a specific line from the message content.
static enum sip_get_dest_result get_destination (struct sip_pvt *p, struct sip_request *oreq, int *cc_recall_core_id)
 Find out who the call is for.
static int get_domain (const char *str, char *domain, int len)
 Extract domain from SIP To/From header.
static struct
event_state_compositor
get_esc (const char *const event_package)
static struct sip_esc_entryget_esc_entry (const char *entity_tag, struct event_state_compositor *esc)
static struct ast_variableget_insecure_variable_from_config (struct ast_config *config)
static struct ast_variableget_insecure_variable_from_sippeers (const char *column, const char *value)
static struct ast_variableget_insecure_variable_from_sipregs (const char *column, const char *value, struct ast_variable **var)
static const char * get_name_from_variable (const struct ast_variable *var)
static void get_our_media_address (struct sip_pvt *p, int needvideo, int needtext, struct ast_sockaddr *addr, struct ast_sockaddr *vaddr, struct ast_sockaddr *taddr, struct ast_sockaddr *dest, struct ast_sockaddr *vdest, struct ast_sockaddr *tdest)
 Set all IP media addresses for this call.
static int get_pai (struct sip_pvt *p, struct sip_request *req)
 Parse the parts of the P-Asserted-Identity header on an incoming packet. Returns 1 if a valid header is found and it is different from the current caller id.
static int get_rdnis (struct sip_pvt *p, struct sip_request *oreq, char **name, char **number, int *reason_code, char **reason_str)
 Get referring dnis.
static void get_realm (struct sip_pvt *p, const struct sip_request *req)
 Choose realm based on From header and then To header or use globaly configured realm. Realm from From/To header should be listed among served domains in config file: domain=...
static int get_refer_info (struct sip_pvt *transferer, struct sip_request *outgoing_req)
 Call transfer support (the REFER method) Extracts Refer headers into pvt dialog structure.
static int get_rpid (struct sip_pvt *p, struct sip_request *oreq)
 Get name, number and presentation from remote party id header, returns true if a valid header was found and it was different from the current caller id.
static const char * get_sdp_iterate (int *start, struct sip_request *req, const char *name)
 Lookup 'name' in the SDP starting at the 'start' line. Returns the matching line, and 'start' is updated with the next line number.
static char get_sdp_line (int *start, int stop, struct sip_request *req, const char **value)
 Fetches the next valid SDP line between the 'start' line (inclusive) and the 'stop' line (exclusive). Returns the type ('a', 'c', ...) and matching line in reference 'start' is updated with the next line number.
static int get_sip_pvt_from_replaces (const char *callid, const char *totag, const char *fromtag, struct sip_pvt **out_pvt, struct ast_channel **out_chan)
 Find a companion dialog based on Replaces information.
static const char * get_srv_protocol (enum ast_transport t)
 Return protocol string for srv dns query.
static const char * get_srv_service (enum ast_transport t)
 Return service string for srv dns query.
static const char * get_transport_list (unsigned int transports)
 Return configuration of transports for a device.
static const char * get_transport_pvt (struct sip_pvt *p)
 Return transport of dialog.
static int get_transport_str2enum (const char *transport)
 Return int representing a bit field of transport types found in const char *transport.
static const char * gettag (const struct sip_request *req, const char *header, char *tagbuf, int tagbufsize)
 Get tag from packet.
static int handle_cc_notify (struct sip_pvt *pvt, struct sip_request *req)
static int handle_cc_subscribe (struct sip_pvt *p, struct sip_request *req)
static int handle_common_options (struct ast_flags *flags, struct ast_flags *mask, struct ast_variable *v)
 Handle flag-type options common to configuration of devices - peers.
static int handle_incoming (struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, int *recount, int *nounlock)
 Handle incoming SIP requests (methods).
static int handle_invite_replaces (struct sip_pvt *p, struct sip_request *req, int *nounlock, struct sip_pvt *replaces_pvt, struct ast_channel *replaces_chan)
 Handle the transfer part of INVITE with a replaces: header,.
static int handle_request_bye (struct sip_pvt *p, struct sip_request *req)
 Handle incoming BYE request.
static int handle_request_cancel (struct sip_pvt *p, struct sip_request *req)
 Handle incoming CANCEL request.
static int handle_request_do (struct sip_request *req, struct ast_sockaddr *addr)
 Handle incoming SIP message - request or response.
static void handle_request_info (struct sip_pvt *p, struct sip_request *req)
 Receive SIP INFO Message.
static int handle_request_invite (struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, uint32_t seqno, int *recount, const char *e, int *nounlock)
 Handle incoming INVITE request.
static int handle_request_invite_st (struct sip_pvt *p, struct sip_request *req, const char *required, int reinvite)
static int handle_request_message (struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, const char *e)
 Handle incoming MESSAGE request.
static int handle_request_notify (struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, uint32_t seqno, const char *e)
 Handle incoming notifications.
static int handle_request_options (struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, const char *e)
 Handle incoming OPTIONS request An OPTIONS request should be answered like an INVITE from the same UA, including SDP.
static int handle_request_publish (struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, const uint32_t seqno, const char *uri)
static int handle_request_refer (struct sip_pvt *p, struct sip_request *req, uint32_t seqno, int *nounlock)
static int handle_request_register (struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, const char *e)
 Handle incoming REGISTER request.
static int handle_request_subscribe (struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, uint32_t seqno, const char *e)
 Handle incoming SUBSCRIBE request.
static int handle_request_update (struct sip_pvt *p, struct sip_request *req)
 bare-bones support for SIP UPDATE
static void handle_response (struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, uint32_t seqno)
 Handle SIP response in dialogue.
static void handle_response_info (struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, uint32_t seqno)
static void handle_response_invite (struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, uint32_t seqno)
 Handle SIP response to INVITE dialogue.
static void handle_response_message (struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, uint32_t seqno)
static void handle_response_notify (struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, uint32_t seqno)
static void handle_response_peerpoke (struct sip_pvt *p, int resp, struct sip_request *req)
 Handle qualification responses (OPTIONS).
static void handle_response_publish (struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, uint32_t seqno)
static void handle_response_refer (struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, uint32_t seqno)
static int handle_response_register (struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, uint32_t seqno)
 Handle responses on REGISTER to services.
static void handle_response_subscribe (struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, uint32_t seqno)
static void handle_response_update (struct sip_pvt *p, int resp, const char *rest, struct sip_request *req, uint32_t seqno)
 Handle authentication challenge for SIP UPDATE.
static int handle_sip_publish_initial (struct sip_pvt *p, struct sip_request *req, struct event_state_compositor *esc, const int expires)
static int handle_sip_publish_modify (struct sip_pvt *p, struct sip_request *req, struct event_state_compositor *esc, const char *const etag, const int expires)
static int handle_sip_publish_refresh (struct sip_pvt *p, struct sip_request *req, struct event_state_compositor *esc, const char *const etag, const int expires)
static int handle_sip_publish_remove (struct sip_pvt *p, struct sip_request *req, struct event_state_compositor *esc, const char *const etag)
static int handle_t38_options (struct ast_flags *flags, struct ast_flags *mask, struct ast_variable *v, unsigned int *maxdatagram)
 Handle T.38 configuration options common to users and peers.
const char * hangup_cause2sip (int cause)
 Convert Asterisk hangup causes to SIP codes.
int hangup_sip2cause (int cause)
 Convert SIP hangup causes to Asterisk hangup causes.
static int has_media_stream (struct sip_pvt *p, enum media_type m)
 Check the media stream list to see if the given type already exists.
static int init_req (struct sip_request *req, int sipmethod, const char *recip)
 Initialize SIP request.
static int init_resp (struct sip_request *resp, const char *msg)
 Initialize SIP response, based on SIP request.
static int initialize_escs (void)
static void initialize_initreq (struct sip_pvt *p, struct sip_request *req)
 Initialize the initital request packet in the pvt structure. This packet is used for creating replies and future requests in a dialog.
static int initialize_udptl (struct sip_pvt *p)
static void initreqprep (struct sip_request *req, struct sip_pvt *p, int sipmethod, const char *const explicit_uri)
 Initiate new SIP request to peer/user.
static const char * insecure2str (int mode)
 Convert Insecure setting to printable string.
static int interpret_t38_parameters (struct sip_pvt *p, const struct ast_control_t38_parameters *parameters)
 Helper function which updates T.38 capability information and triggers a reinvite.
static int is_method_allowed (unsigned int *allowed_methods, enum sipmethod method)
 Check if method is allowed for a device or a dialog.
static int load_module (void)
 Load the module.
static int local_attended_transfer (struct sip_pvt *transferer, struct ast_channel *transferer_chan, uint32_t seqno, int *nounlock)
 Find all call legs and bridge transferee with target called from handle_request_refer.
static void lws2sws (struct ast_str *data)
 Parse multiline SIP headers into one header This is enabled if pedanticsipchecking is enabled.
static void make_our_tag (struct sip_pvt *pvt)
 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_peer_status (struct mansession *s, const struct message *m)
 Show SIP peers in the manager API.
static int manager_sip_qualify_peer (struct mansession *s, const struct message *m)
 Qualify SIP peers in the manager API.
static int manager_sip_show_peer (struct mansession *s, const struct message *m)
 Show SIP peers in the manager API.
static int manager_sip_show_peers (struct mansession *s, const struct message *m)
 Show SIP peers in the manager API.
static int manager_sipnotify (struct mansession *s, const struct message *m)
static int map_s_x (const struct _map_x_s *table, const char *s, int errorvalue)
 map from a string to an integer value, case insensitive. If no match is found, return errorvalue.
static const char * map_x_s (const struct _map_x_s *table, int x, const char *errorstring)
 map from an integer value to a string. If no match is found, return errorstring
static void mark_method_allowed (unsigned int *allowed_methods, enum sipmethod method)
static void mark_method_unallowed (unsigned int *allowed_methods, enum sipmethod method)
static void mark_parsed_methods (unsigned int *methods, char *methods_str)
static int match_and_cleanup_peer_sched (void *peerobj, void *arg, int flags)
static enum match_req_res match_req_to_dialog (struct sip_pvt *sip_pvt_ptr, struct match_req_args *arg)
static int method_match (enum sipmethod id, const char *name)
 returns true if 'name' (with optional trailing whitespace) matches the sip method 'id'. Strictly speaking, SIP methods are case SENSITIVE, but we do a case-insensitive comparison to be more tolerant. following Jon Postel's rule: Be gentle in what you accept, strict with what you send
static void mwi_event_cb (void *userdata, struct stasis_subscription *sub, struct stasis_message *msg)
 Receive MWI events that we have subscribed to.
static int network_change_sched_cb (const void *data)
static void network_change_stasis_cb (void *data, struct stasis_subscription *sub, struct stasis_message *message)
static void network_change_stasis_subscribe (void)
static void network_change_stasis_unsubscribe (void)
static struct sip_proxyobproxy_get (struct sip_pvt *dialog, struct sip_peer *peer)
 Get default outbound proxy or global proxy.
static void offered_media_list_destroy (struct sip_pvt *p)
 Destroy SDP media offer list.
static void on_dns_update_mwi (struct ast_sockaddr *old, struct ast_sockaddr *new, void *data)
static void on_dns_update_peer (struct ast_sockaddr *old, struct ast_sockaddr *new, void *data)
static void on_dns_update_registry (struct ast_sockaddr *old, struct ast_sockaddr *new, void *data)
static unsigned int parse_allowed_methods (struct sip_request *req)
 parse the Allow header to see what methods the endpoint we are communicating with allows.
static void parse_copy (struct sip_request *dst, const struct sip_request *src)
 Copy SIP request, parse it.
static int parse_minse (const char *p_hdrval, int *const p_interval)
 Session-Timers: Function for parsing Min-SE header.
static void parse_moved_contact (struct sip_pvt *p, struct sip_request *req, char **name, char **number, int set_call_forward)
 Parse 302 Moved temporalily response.
static int parse_ok_contact (struct sip_pvt *pvt, struct sip_request *req)
 Save contact header for 200 OK on INVITE.
static void parse_oli (struct sip_request *req, struct ast_channel *chan)
 Check for the presence of OLI tag(s) in the From header and set on the channel.
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_param *const p_ref)
 Session-Timers: Function for parsing Session-Expires header.
static int parse_uri_legacy_check (char *uri, const char *scheme, char **user, char **pass, char **hostport, char **transport)
 parse uri in a way that allows semicolon stripping if legacy mode is enabled
static int peer_cmp_cb (void *obj, void *arg, int flags)
static int peer_dump_func (void *userobj, void *arg, int flags)
static int peer_hash_cb (const void *obj, const int flags)
static int peer_ipcmp_cb (void *obj, void *arg, int flags)
static int peer_ipcmp_cb_full (void *obj, void *arg, void *data, int flags)
static int peer_iphash_cb (const void *obj, const int flags)
static void peer_mailboxes_to_str (struct ast_str **mailbox_str, struct sip_peer *peer)
 list peer mailboxes to CLI
static int peer_markall_autopeers_func (void *device, void *arg, int flags)
static int peer_markall_func (void *device, void *arg, int flags)
static void peer_sched_cleanup (struct sip_peer *peer)
static int peer_status (struct sip_peer *peer, char *status, int statuslen)
int peercomparefunc (const void *a, const void *b)
static int peers_data_provider_get (const struct ast_data_search *search, struct ast_data *data_root)
unsigned int port_str2int (const char *pt, unsigned int standard)
 converts ascii port to int representation. If no pt buffer is provided or the pt has errors when being converted to an int value, the port provided as the standard is used.
static void print_group (int fd, ast_group_t group, int crlf)
 Print call group and pickup group.
static void print_named_groups (int fd, struct ast_namedgroups *group, int crlf)
 Print named call groups and pickup groups.
static void proc_422_rsp (struct sip_pvt *p, struct sip_request *rsp)
 Handle 422 response to INVITE with session-timer requested.
static int proc_session_timer (const void *vp)
 Session-Timers: Process session refresh timeout event.
static int process_crypto (struct sip_pvt *p, struct ast_rtp_instance *rtp, struct ast_sdp_srtp **srtp, const char *a)
static int process_sdp (struct sip_pvt *p, struct sip_request *req, int t38action)
 Process SIP SDP offer, select formats and activate media channels If offer is rejected, we will not change any properties of the call Return 0 on success, a negative value on errors. Must be called after find_sdp().
static int process_sdp_a_audio (const char *a, struct sip_pvt *p, struct ast_rtp_codecs *newaudiortp, int *last_rtpmap_codec)
static int process_sdp_a_dtls (const char *a, struct sip_pvt *p, struct ast_rtp_instance *instance)
static int process_sdp_a_ice (const char *a, struct sip_pvt *p, struct ast_rtp_instance *instance)
static int process_sdp_a_image (const char *a, struct sip_pvt *p)
static int process_sdp_a_sendonly (const char *a, int *sendonly)
static int process_sdp_a_text (const char *a, struct sip_pvt *p, struct ast_rtp_codecs *newtextrtp, char *red_fmtp, int *red_num_gen, int *red_data_pt, int *last_rtpmap_codec)
static int process_sdp_a_video (const char *a, struct sip_pvt *p, struct ast_rtp_codecs *newvideortp, int *last_rtpmap_codec)
static int process_sdp_c (const char *c, struct ast_sockaddr *addr)
static int process_sdp_o (const char *o, struct sip_pvt *p)
static int process_via (struct sip_pvt *p, const struct sip_request *req)
 Process the Via header according to RFC 3261 section 18.2.2.
static struct sip_proxyproxy_from_config (const char *proxy, int sipconf_lineno, struct sip_proxy *dest)
 Parse proxy string and return an ao2_alloc'd proxy. If dest is non-NULL, no allocation is performed and dest is used instead. On error NULL is returned.
static int proxy_update (struct sip_proxy *proxy)
static int publish_expire (const void *data)
static void publish_qualify_peer_done (const char *id, const char *peer)
static void pvt_set_needdestroy (struct sip_pvt *pvt, const char *reason)
static int read_raw_content_length (const char *message)
 Get the content length from an unparsed SIP message.
static struct sip_peerrealtime_peer (const char *newpeername, struct ast_sockaddr *addr, char *callbackexten, int devstate_only, int which_objects)
 realtime_peer: Get peer from realtime storage Checks the "sippeers" realtime family from extconfig.conf Checks the "sipregs" realtime family from extconfig.conf if it's configured. This returns a pointer to a peer and because we use build_peer, we can rest assured that the refcount is bumped.
static int realtime_peer_by_addr (const char **name, struct ast_sockaddr *addr, const char *ipaddr, const char *callbackexten, struct ast_variable **var, struct ast_variable **varregs)
static int realtime_peer_by_name (const char *const *name, struct ast_sockaddr *addr, const char *ipaddr, struct ast_variable **var, struct ast_variable **varregs)
static struct ast_variablerealtime_peer_get_sippeer_helper (const char **name, struct ast_variable **varregs)
static void realtime_update_peer (const char *peername, struct ast_sockaddr *addr, const char *defaultuser, const char *fullcontact, const char *useragent, int expirey, unsigned short deprecated_username, int lastms, const char *path)
 Update peer object in realtime storage If the Asterisk system name is set in asterisk.conf, we will use that name and store that in the "regserver" field in the sippeers table to facilitate multi-server setups.
static void receive_message (struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, const char *e)
 Receive SIP MESSAGE method messages.
static void ref_proxy (struct sip_pvt *pvt, struct sip_proxy *proxy)
 maintain proper refcounts for a sip_pvt's outboundproxy
static const char * referstatus2str (enum referstatus rstatus)
 Convert transfer status to string.
static void reg_source_db (struct sip_peer *peer)
 Get registration details from Asterisk DB.
static void register_peer_exten (struct sip_peer *peer, int onoff)
 Automatically add peer extension to dial plan.
static int register_realtime_peers_with_callbackextens (void)
static enum check_auth_result register_verify (struct sip_pvt *p, struct ast_sockaddr *addr, struct sip_request *req, const char *uri)
 Verify registration of user.
static int registry_cmp_cb (void *obj, void *arg, int flags)
static int registry_hash_cb (const void *obj, const int flags)
static const char * regstate2str (enum sipregistrystate regstate)
 Convert registration state status to string.
static int reinvite_timeout (const void *data)
static int reload (void)
 Part of Asterisk module interface.
static int reload_config (enum channelreloadreason reason)
 Re-read SIP.conf config file.
static char * remove_uri_parameters (char *uri)
static int reply_digest (struct sip_pvt *p, struct sip_request *req, char *header, int sipmethod, char *digest, int digest_len)
 reply to authentication for outbound registrations
static int reqprep (struct sip_request *req, struct sip_pvt *p, int sipmethod, uint32_t seqno, int newbranch)
 Initialize a SIP request message (not the initial one in a dialog).
static int resp_needs_contact (const char *msg, enum sipmethod method)
 Test if this response needs a contact header.
static int respprep (struct sip_request *resp, struct sip_pvt *p, const char *msg, const struct sip_request *req)
 Prepare SIP response packet.
static int restart_monitor (void)
 Start the channel monitor thread.
static void restart_session_timer (struct sip_pvt *p)
 Session-Timers: Restart session timer.
static int retrans_pkt (const void *data)
 Retransmit SIP message if no answer (Called from scheduler).
static void send_manager_peer_status (struct mansession *s, struct sip_peer *peer, const char *idText)
static int send_provisional_keepalive (const void *data)
static int send_provisional_keepalive_full (struct sip_pvt *pvt, int with_sdp)
static int send_provisional_keepalive_with_sdp (const void *data)
static int send_request (struct sip_pvt *p, struct sip_request *req, enum xmittype reliable, uint32_t seqno)
static int send_response (struct sip_pvt *p, struct sip_request *req, enum xmittype reliable, uint32_t seqno)
 Transmit response on SIP request.
static void send_session_timeout (struct ast_channel *chan, const char *source)
 Sends a session timeout channel blob used to produce SessionTimeout AMI messages.
static enum ast_cc_service_type service_string_to_service_type (const char *const service_string)
static struct
ast_manager_event_blob
session_timeout_to_ami (struct stasis_message *msg)
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, const char *uri)
 Set destination from SIP URI.
static void set_insecure_flags (struct ast_flags *flags, const char *value, int lineno)
 Parse insecure= setting in sip.conf and set flags according to setting.
static int set_message_vars_from_req (struct ast_msg *msg, struct sip_request *req)
static void set_peer_defaults (struct sip_peer *peer)
 Set peer defaults before configuring specific configurations.
static void set_peer_nat (const struct sip_pvt *p, struct sip_peer *peer)
 Set the peers nat flags if they are using auto_* settings.
static unsigned int set_pvt_allowed_methods (struct sip_pvt *pvt, struct sip_request *req)
static void set_socket_transport (struct sip_socket *socket, int transport)
static void set_t38_capabilities (struct sip_pvt *p)
 Set the global T38 capabilities on a SIP dialog structure.
static int show_channels_cb (void *__cur, void *__arg, int flags)
 callback for show channel|subscription
static int show_chanstats_cb (void *__cur, void *__arg, int flags)
 Callback for show_chanstats.
static int sip_addheader (struct ast_channel *chan, const char *data)
 Add a SIP header to an outbound INVITE.
static int sip_allow_anyrtp_remote (struct ast_channel *chan1, struct ast_rtp_instance *instance, const char *rtptype)
static int sip_allow_rtp_remote (struct ast_channel *chan1, struct ast_rtp_instance *instance)
static int sip_allow_vrtp_remote (struct ast_channel *chan1, struct ast_rtp_instance *instance)
static void sip_alreadygone (struct sip_pvt *dialog)
 Encapsulate setting of SIP_ALREADYGONE to be able to trace it with debugging.
static int sip_answer (struct ast_channel *ast)
 sip_answer: Answer SIP call , send 200 OK on Invite Part of PBX interface
void sip_auth_headers (enum sip_auth_type code, char **header, char **respheader)
 return the request and response header for a 401 or 407 code
static int sip_call (struct ast_channel *ast, const char *dest, int timeout)
 Initiate SIP call from PBX used from the dial() application.
int sip_cancel_destroy (struct sip_pvt *p)
 Cancel destruction of SIP dialog. Be careful as this also absorbs the reference - if you call it from within the scheduler, this might be the last reference.
static void sip_cc_agent_destructor (struct ast_cc_agent *agent)
static int sip_cc_agent_init (struct ast_cc_agent *agent, struct ast_channel *chan)
static int sip_cc_agent_recall (struct ast_cc_agent *agent)
static void sip_cc_agent_respond (struct ast_cc_agent *agent, enum ast_cc_agent_response_reason reason)
static int sip_cc_agent_start_monitoring (struct ast_cc_agent *agent)
static int sip_cc_agent_start_offer_timer (struct ast_cc_agent *agent)
static int sip_cc_agent_status_request (struct ast_cc_agent *agent)
static int sip_cc_agent_stop_offer_timer (struct ast_cc_agent *agent)
static int sip_cc_monitor_cancel_available_timer (struct ast_cc_monitor *monitor, int *sched_id)
static void sip_cc_monitor_destructor (void *private_data)
static int sip_cc_monitor_request_cc (struct ast_cc_monitor *monitor, int *available_timer_id)
static int sip_cc_monitor_suspend (struct ast_cc_monitor *monitor)
static int sip_cc_monitor_unsuspend (struct ast_cc_monitor *monitor)
static int sip_check_authtimeout (time_t start)
 Check if the authtimeout has expired.
static char * sip_cli_notify (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Cli command to send SIP notify to peer.
static int sip_debug_test_addr (const struct ast_sockaddr *addr)
 See if we pass debug IP filter.
static int sip_debug_test_pvt (struct sip_pvt *p)
 Test PVT for debugging output.
struct sip_pvtsip_destroy (struct sip_pvt *p)
 Destroy SIP call structure. Make it return NULL so the caller can do things like foo = sip_destroy(foo); and reduce the chance of bugs due to dangling pointers.
static void sip_destroy_fn (void *p)
static void sip_destroy_peer (struct sip_peer *peer)
 Destroy peer object from memory.
static void sip_destroy_peer_fn (void *peer)
static int sip_devicestate (const char *data)
 Part of PBX channel interface.
void sip_digest_parser (char *c, struct digestkeys *keys)
 Takes the digest response and parses it.
static char * sip_do_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Turn on SIP debugging (CLI command).
static char * sip_do_debug_ip (int fd, const char *arg)
 Enable SIP Debugging for a single IP.
static char * sip_do_debug_peer (int fd, const char *arg)
 Turn on SIP debugging for a given peer.
static int sip_do_reload (enum channelreloadreason reason)
 Reload module.
static int sip_dtmfmode (struct ast_channel *chan, const char *data)
 Set the DTMFmode for an outbound SIP call (application).
static void sip_dump_history (struct sip_pvt *dialog)
 Dump SIP history to debug log file at end of lifespan for SIP dialog.
static int sip_epa_register (const struct epa_static_data *static_data)
static void sip_epa_unregister_all (void)
struct sip_peersip_find_peer (const char *peer, struct ast_sockaddr *addr, int realtime, int which_objects, int devstate_only, int transport)
 Locate device by name or ip address.
static struct sip_peersip_find_peer_by_ip_and_exten (struct ast_sockaddr *addr, char *callbackexten, int transport)
static struct sip_peersip_find_peer_full (const char *peer, struct ast_sockaddr *addr, char *callbackexten, int realtime, int which_objects, int devstate_only, int transport)
static int sip_fixup (struct ast_channel *oldchan, struct ast_channel *newchan)
 sip_fixup: Fix up a channel: If a channel is consumed, this is called. Basically update any ->owner links
static const char * sip_get_callid (struct ast_channel *chan)
 Deliver SIP call ID for the call.
static int sip_get_cc_information (struct sip_request *req, char *subscribe_uri, size_t size, enum ast_cc_service_type *service)
static void sip_get_codec (struct ast_channel *chan, struct ast_format_cap *result)
const char * sip_get_header (const struct sip_request *req, const char *name)
 Get header from SIP request.
static enum ast_rtp_glue_result sip_get_rtp_peer (struct ast_channel *chan, struct ast_rtp_instance **instance)
const char * sip_get_transport (enum ast_transport t)
 Return transport as string.
static enum ast_rtp_glue_result sip_get_trtp_peer (struct ast_channel *chan, struct ast_rtp_instance **instance)
static enum ast_rtp_glue_result sip_get_vrtp_peer (struct ast_channel *chan, struct ast_rtp_instance **instance)
static void sip_handle_cc (struct sip_pvt *pvt, struct sip_request *req, enum ast_cc_service_type service)
static int sip_hangup (struct ast_channel *ast)
 sip_hangup: Hangup SIP call Part of PBX interface, called from ast_hangup
static int sip_indicate (struct ast_channel *ast, int condition, const void *data, size_t datalen)
 Play indication to user With SIP a lot of indications is sent as messages, letting the device play the indication - busy signal, congestion etc.
static int sip_is_xml_parsable (void)
static void sip_keepalive_all_peers (void)
 Send a keepalive to all known peers.
static int sip_monitor_instance_cmp_fn (void *obj, void *arg, int flags)
static void sip_monitor_instance_destructor (void *data)
static int sip_monitor_instance_hash_fn (const void *obj, const int flags)
static struct
sip_monitor_instance
sip_monitor_instance_init (int core_id, const char *const subscribe_uri, const char *const peername, const char *const device_name)
static int sip_msg_send (const struct ast_msg *msg, const char *to, const char *from)
static const char * sip_nat_mode (const struct sip_pvt *p)
 Display SIP nat mode.
static struct ast_channelsip_new (struct sip_pvt *i, int state, const char *title, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, ast_callid callid)
 Initiate a call in the SIP channel.
static int sip_notify_alloc (struct sip_pvt *p)
 Allocate SIP refer structure.
static int sip_offer_timer_expire (const void *data)
static void sip_peer_hold (struct sip_pvt *p, int hold)
 Change onhold state of a peer using a pvt structure.
static int sip_pickup (struct ast_channel *chan)
 Pickup a call using the subsystem in features.c This is executed in a separate thread.
static void * sip_pickup_thread (void *stuff)
 SIP pickup support function Starts in a new thread, then pickup the call.
static void sip_poke_all_peers (void)
 Send a poke to all known peers.
static int sip_poke_noanswer (const void *data)
 React to lack of answer to Qualify poke.
static int sip_poke_peer (struct sip_peer *peer, int force)
 Check availability of peer, also keep NAT open.
static int sip_poke_peer_now (const void *data)
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 void sip_publish_registry (const char *username, const char *domain, const char *status)
static void sip_pvt_callid_set (struct sip_pvt *pvt, ast_callid callid)
static struct ast_channelsip_pvt_lock_full (struct sip_pvt *pvt)
static char * sip_qualify_peer (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Send an OPTIONS packet to a SIP peer.
static int sip_queryoption (struct ast_channel *chan, int option, void *data, int *datalen)
 Query an option on a SIP dialog.
static void sip_queue_hangup_cause (struct sip_pvt *p, int cause)
static struct ast_framesip_read (struct ast_channel *ast)
 Read SIP RTP from channel.
static struct ast_sockaddrsip_real_dst (const struct sip_pvt *p)
 The real destination address for a write.
static const char * sip_reason_code_to_str (struct ast_party_redirecting_reason *reason, int *table_lookup)
static enum AST_REDIRECTING_REASON sip_reason_str_to_code (const char *text)
static int sip_refer_alloc (struct sip_pvt *p)
 Allocate SIP refer structure.
static void sip_refer_destroy (struct sip_pvt *p)
 Destroy SIP refer structure.
static int sip_reg_timeout (const void *data)
 Registration timeout, register again Registered as a timeout handler during transmit_register(), to retransmit the packet if a reply does not come back. This is called by the scheduler so the event is not pending anymore when we are called.
static int sip_register (const char *value, int lineno)
 create sip_registry object from register=> line in sip.conf and link into reg container
static void sip_register_tests (void)
 SIP test registration.
static void sip_registry_destroy (void *obj)
 Destroy registry object Objects created with the register= statement in static configuration.
static int sip_reinvite_retry (const void *data)
 Reset the NEEDREINVITE flag after waiting when we get 491 on a Re-invite to avoid race conditions between asterisk servers. Called from the scheduler.
static char * sip_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Force reload of module from cli.
static int sip_removeheader (struct ast_channel *chan, const char *data)
 Remove SIP headers added previously with SipAddHeader application.
static struct ast_channelsip_request_call (const char *type, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *dest, int *cause)
 PBX interface function -build SIP pvt structure SIP calls initiated by the PBX arrive here.
static int sip_reregister (const void *data)
 Update registration with SIP Proxy. Called from the scheduler when the previous registration expires, so we don't have to cancel the pending event. We assume the reference so the sip_registry is valid, since it is stored in the scheduled event anyways.
static struct ast_framesip_rtp_read (struct ast_channel *ast, struct sip_pvt *p, int *faxdetect)
 Read RTP from network.
static const char * sip_sanitized_host (const char *host)
void sip_scheddestroy (struct sip_pvt *p, int ms)
 Schedule destruction of SIP dialog.
void sip_scheddestroy_final (struct sip_pvt *p, int ms)
 Schedule final destruction of SIP dialog. This can not be canceled. This function is used to keep a dialog around for a period of time in order to properly respond to any retransmits.
static void sip_send_all_mwi_subscriptions (void)
 Send all MWI subscriptions.
static void sip_send_all_registers (void)
 Send all known registrations.
static int sip_send_keepalive (const void *data)
 Send keep alive packet to peer.
static int sip_send_mwi_to_peer (struct sip_peer *peer, int cache_only)
 Send message waiting indication to alert peer that they've got voicemail.
static int sip_senddigit_begin (struct ast_channel *ast, char digit)
static int sip_senddigit_end (struct ast_channel *ast, char digit, unsigned int duration)
 Send DTMF character on SIP channel within one call, we're able to transmit in many methods simultaneously.
static int sip_sendhtml (struct ast_channel *chan, int subclass, const char *data, int datalen)
 Send message with Access-URL header, if this is an HTML URL only!
static int sip_sendtext (struct ast_channel *ast, const char *text)
static void sip_set_default_format_capabilities (struct ast_format_cap *cap)
static char * sip_set_history (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Enable/Disable SIP History logging (CLI).
static void sip_set_owner (struct sip_pvt *p, struct ast_channel *chan)
 Set the owning channel on the sip_pvt object.
static void sip_set_redirstr (struct sip_pvt *p, char *reason)
 Translate referring cause.
static int sip_set_rtp_peer (struct ast_channel *chan, struct ast_rtp_instance *instance, struct ast_rtp_instance *vinstance, struct ast_rtp_instance *tinstance, const struct ast_format_cap *cap, int nat_active)
static int sip_setoption (struct ast_channel *chan, int option, void *data, int datalen)
 Set an option on a SIP dialog.
static char * sip_show_channel (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Show details of one active dialog.
static char * sip_show_channels (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI for show channels or subscriptions. This is a new-style CLI handler so a single function contains the prototype for the function, the 'generator' to produce multiple entries in case it is required, and the actual handler for the command.
static char * sip_show_channelstats (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 SIP show channelstats CLI (main function).
static char * sip_show_domains (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command to list local domains.
static char * sip_show_history (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Show history details of one dialog.
static char * sip_show_inuse (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI Command to show calls within limits set by call_limit.
static char * sip_show_mwi (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * sip_show_objects (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 List all allocated SIP Objects (realtime or static).
static char * sip_show_peer (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Show one peer in detail.
static char * sip_show_peers (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI Show Peers command.
static char * sip_show_registry (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Show SIP Registry (registrations with other SIP proxies.
static char * sip_show_sched (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * sip_show_settings (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 List global settings for the SIP channel.
static char * sip_show_tcp (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Show active TCP connections.
static char * sip_show_user (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Show one user in detail.
static char * sip_show_users (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI Command 'SIP Show Users'.
static int sip_sipredirect (struct sip_pvt *p, const char *dest)
 Transfer call before connect with a 302 redirect.
static struct sip_st_dlgsip_st_alloc (struct sip_pvt *const p)
 Allocate Session-Timers struct w/in dialog.
static int sip_standard_port (enum ast_transport type, int port)
 Returns the port to use for this socket.
static int sip_subscribe_mwi (const char *value, int lineno)
 Parse mwi=> line in sip.conf and add to list.
static void sip_subscribe_mwi_destroy (void *data)
 Destroy MWI subscription object.
static int sip_subscribe_mwi_do (const void *data)
 Send a subscription or resubscription for MWI.
static int sip_t38_abort (const void *data)
 Called to deny a T38 reinvite if the core does not respond to our request.
static struct
ast_tcptls_session_instance
sip_tcp_locate (struct ast_sockaddr *s)
 Find thread for TCP/TLS session (based on IP/Port.
static void * sip_tcp_worker_fn (void *data)
 SIP TCP connection handler.
static void sip_tcptls_client_args_destructor (void *obj)
static int sip_tcptls_read (struct sip_request *req, struct ast_tcptls_session_instance *tcptls_session, int authenticated, time_t start)
 Read SIP request or response from a TCP/TLS connection.
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_threadinfosip_threadinfo_create (struct ast_tcptls_session_instance *tcptls_session, int transport)
 creates a sip_threadinfo object and links it into the threadt table.
static void sip_threadinfo_destructor (void *obj)
static int sip_transfer (struct ast_channel *ast, const char *dest)
 Transfer SIP call.
static char * sip_unregister (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Unregister (force expiration) a SIP peer in the registry via CLI.
static void sip_unregister_tests (void)
 SIP test registration.
static void sip_websocket_callback (struct ast_websocket *session, struct ast_variable *parameters, struct ast_variable *headers)
 SIP WebSocket connection handler.
static int sip_write (struct ast_channel *ast, struct ast_frame *frame)
 Send frame to media channel (rtp).
static int sipinfo_send (struct ast_channel *chan, struct ast_variable *headers, const char *content_type, const char *content, const char *useragent_filter)
static int sipsock_read (int *id, int fd, short events, void *ignore)
 Read data from SIP UDP socket.
static int sockaddr_is_null_or_any (const struct ast_sockaddr *addr)
static enum st_mode st_get_mode (struct sip_pvt *p, int no_cached)
 Get the session-timer mode.
static enum st_refresher st_get_refresher (struct sip_pvt *p)
 Get the entity (UAC or UAS) that's acting as the session-timer refresher.
static int st_get_se (struct sip_pvt *p, int max)
 Get Max or Min SE (session timer expiry).
static void start_ice (struct ast_rtp_instance *instance, int offer)
 Start ICE negotiation on an RTP instance.
static void start_session_timer (struct sip_pvt *p)
 Session-Timers: Start session timer.
 STASIS_MESSAGE_TYPE_DEFN_LOCAL (session_timeout_type,.to_ami=session_timeout_to_ami,)
static void state_notify_build_xml (struct state_notify_data *data, int full, const char *exten, const char *context, struct ast_str **tmp, struct sip_pvt *p, int subscribed, const char *mfrom, const char *mto)
 Builds XML portion of NOTIFY messages for presence or dialog updates.
static const char * stmode2str (enum st_mode m)
static void stop_media_flows (struct sip_pvt *p)
 Immediately stop RTP, VRTP and UDPTL as applicable.
static void stop_session_timer (struct sip_pvt *p)
 Session-Timers: Stop session timer.
static int str2dtmfmode (const char *str)
 maps a string to dtmfmode, returns -1 on error
static enum st_mode str2stmode (const char *s)
static enum st_refresher_param str2strefresherparam (const char *s)
static const char * strefresher2str (enum st_refresher r)
static const char * strefresherparam2str (enum st_refresher_param 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_peertemp_peer (const char *name)
 Create temporary peer (used in autocreatepeer mode).
static void temp_pvt_cleanup (void *)
static int temp_pvt_init (void *)
static char * terminate_uri (char *uri)
static int threadinfo_locate_cb (void *obj, void *arg, int flags)
static int threadt_cmp_cb (void *obj, void *arg, int flags)
static int threadt_hash_cb (const void *obj, const int flags)
static char * transfermode2str (enum transfermodes mode)
 Convert transfer mode to text string.
static int transmit_cc_notify (struct ast_cc_agent *agent, struct sip_pvt *subscription, enum sip_cc_notify_state state)
static void transmit_fake_auth_response (struct sip_pvt *p, struct sip_request *req, enum xmittype reliable)
 Send a fake 401 Unauthorized response when the administrator wants to hide the names of local devices from fishers.
static int transmit_info_with_aoc (struct sip_pvt *p, struct ast_aoc_decoded *decoded)
 Send SIP INFO advice of charge message.
static int transmit_info_with_digit (struct sip_pvt *p, const char digit, unsigned int duration)
 Send SIP INFO dtmf message, see Cisco documentation on cisco.com.
static int transmit_info_with_vidupdate (struct sip_pvt *p)
 Send SIP INFO with video update request.
static int transmit_invite (struct sip_pvt *p, int sipmethod, int sdp, int init, const char *const explicit_uri)
 Build REFER/INVITE/OPTIONS/SUBSCRIBE message and transmit it.
static int transmit_message (struct sip_pvt *p, int init, int auth)
 Transmit with SIP MESSAGE method.
static int transmit_notify_with_mwi (struct sip_pvt *p, int newmsgs, int oldmsgs, const char *vmexten)
 Notify user of messages waiting in voicemail (RFC3842).
static int transmit_notify_with_sipfrag (struct sip_pvt *p, int cseq, char *message, int terminate)
 Notify a transferring party of the status of transfer (RFC3515).
static int transmit_provisional_response (struct sip_pvt *p, const char *msg, const struct sip_request *req, int with_sdp)
static int transmit_publish (struct sip_epa_entry *epa_entry, enum sip_publish_type publish_type, const char *const explicit_uri)
static int transmit_refer (struct sip_pvt *p, const char *dest)
 Transmit SIP REFER message (initiated by the transfer() dialplan application.
static int transmit_register (struct sip_registry *r, int sipmethod, const char *auth, const char *authheader)
 Transmit register to SIP proxy or UA auth = NULL on the initial registration (from sip_reregister()).
static int transmit_reinvite_with_sdp (struct sip_pvt *p, int t38version, int oldsdp)
 Transmit reinvite with SDP.
static int transmit_request (struct sip_pvt *p, int sipmethod, uint32_t seqno, enum xmittype reliable, int newbranch)
 Transmit generic SIP request returns XMIT_ERROR if transmit failed with a critical error (don't retry).
static int transmit_request_with_auth (struct sip_pvt *p, int sipmethod, uint32_t seqno, enum xmittype reliable, int newbranch)
 Transmit SIP request, auth added.
static int transmit_response (struct sip_pvt *p, const char *msg, const struct sip_request *req)
 Transmit response, no retransmits.
static int transmit_response_reliable (struct sip_pvt *p, const char *msg, const struct sip_request *req)
 Transmit response, Make sure you get an ACK This is only used for responses to INVITEs, where we need to make sure we get an ACK.
static int transmit_response_using_temp (ast_string_field callid, struct ast_sockaddr *addr, int useglobal_nat, const int intended_method, const struct sip_request *req, const char *msg)
 Transmit response, no retransmits, using a temporary pvt structure.
static int transmit_response_with_allow (struct sip_pvt *p, const char *msg, const struct sip_request *req, enum xmittype reliable)
 Append Accept header, content length before transmitting response.
static int transmit_response_with_auth (struct sip_pvt *p, const char *msg, const struct sip_request *req, const char *nonce, 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)
 Add date before transmitting response.
static int transmit_response_with_minexpires (struct sip_pvt *p, const char *msg, const struct sip_request *req, int minexpires)
 Append Min-Expires header, content length before transmitting response.
static int transmit_response_with_minse (struct sip_pvt *p, const char *msg, const struct sip_request *req, int minse_int)
 Transmit 422 response with Min-SE header (Session-Timers).
static int transmit_response_with_retry_after (struct sip_pvt *p, const char *msg, const struct sip_request *req, const char *seconds)
 Append Retry-After header field when transmitting response.
static int transmit_response_with_sdp (struct sip_pvt *p, const char *msg, const struct sip_request *req, enum xmittype reliable, int oldsdp, int rpid)
 Used for 200 OK and 183 early media.
static int transmit_response_with_sip_etag (struct sip_pvt *p, const char *msg, const struct sip_request *req, struct sip_esc_entry *esc_entry, int need_new_etag)
static int transmit_response_with_t38_sdp (struct sip_pvt *p, char *msg, struct sip_request *req, int retrans)
 Used for 200 OK and 183 early media.
static int transmit_response_with_unsupported (struct sip_pvt *p, const char *msg, const struct sip_request *req, const char *unsupported)
 Transmit response, no retransmits.
static int transmit_state_notify (struct sip_pvt *p, struct state_notify_data *data, int full, int timeout)
 Used in the SUBSCRIBE notification subsystem (RFC3265).
static const char * trust_id_outbound2str (int mode)
static void try_suggested_sip_codec (struct sip_pvt *p)
 Try setting the codecs suggested by the SIP_CODEC channel variable.
static int uac_sips_contact (struct sip_request *req)
 Determine if, as a UAC, we need to use a SIPS Contact.
static int uas_sips_contact (struct sip_request *req)
 Determine if, as a UAS, we need to use a SIPS Contact.
static void unlink_all_peers_from_tables (void)
static void unlink_marked_peers_from_tables (void)
static void unlink_peers_from_tables (peer_unlink_flag_t flag)
static int unload_module (void)
 PBX unload module API.
static int update_call_counter (struct sip_pvt *fup, int event)
 update_call_counter: Handle call_limit for SIP devices Setting a call-limit will cause calls above the limit not to be accepted.
static void update_connectedline (struct sip_pvt *p, const void *data, size_t datalen)
 Notify peer that the connected line has changed.
static void update_peer (struct sip_peer *p, int expire)
 Update peer data in database (if used).
static void update_peer_lastmsgssent (struct sip_peer *peer, int value, int locked)
static void update_provisional_keepalive (struct sip_pvt *pvt, int with_sdp)
static void update_redirecting (struct sip_pvt *p, const void *data, size_t datalen)
 Send a provisional response indicating that a call was redirected.

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Session Initiation Protocol (SIP)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DRIVER, .nonoptreq = "res_crypto,res_http_websocket", }
static struct stasis_subscriptionacl_change_sub
static struct cfalias aliases []
static struct _map_x_s allowoverlapstr []
static char * app_dtmfmode = "SIPDtmfMode"
static char * app_sipaddheader = "SIPAddHeader"
static char * app_sipremoveheader = "SIPRemoveHeader"
static struct ast_module_infoast_module_info = &__mod_info
static struct sip_auth_containerauthl = NULL
 Authentication container for realm authentication.
static ast_mutex_t authl_lock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 }
 Global authentication container protection while adjusting the references.
static int authlimit = DEFAULT_AUTHLIMIT
static int authtimeout = DEFAULT_AUTHTIMEOUT
static struct _map_x_s autopeermodes []
struct ast_sockaddr bindaddr
static struct sip_peerbogus_peer
 A bogus peer, to be used when authentication should fail.
static int can_parse_xml
static struct epa_static_data cc_epa_static_data
static struct ast_sip_api_tech chan_sip_api_provider
static struct ast_custom_function checksipdomain_function
static struct ast_cli_entry cli_sip []
 SIP Cli commands definition.
static const char config [] = "sip.conf"
static struct ast_sockaddr debugaddr
static struct ast_rtp_dtls_cfg default_dtls_cfg
 Default DTLS connection configuration.
static int default_expiry = DEFAULT_DEFAULT_EXPIRY
static struct ast_jb_conf default_jbconf
 Global jitterbuffer configuration - by default, jb is disabled.
static const int DEFAULT_PUBLISH_EXPIRES = 3600
static struct ast_tls_config default_tls_cfg
 Default TLS connection configuration.
static struct ao2_containerdialogs
struct ao2_containerdialogs_needdestroy
struct ao2_containerdialogs_rtpcheck
static struct _map_x_s dtmfstr []
 mapping between dtmf flags and strings
static int esc_etag_counter
static const int ESC_MAX_BUCKETS = 37
static struct
event_state_compositor 
event_state_compositors []
 The Event State Compositors.
static struct ast_sockaddr externaddr
 our external IP address/port for SIP sessions. externaddr.sin_addr is only set when we know we might be behind a NAT, and this is done using a variety of (mutually exclusive) ways from the config file:
static time_t externexpire
static char externhost [MAXHOSTNAMELEN]
static int externrefresh = 10
static uint16_t externtcpport
static uint16_t externtlsport
static struct _map_x_s faxecmodes []
static struct ast_flags global_flags [3] = {{0}}
static struct ast_jb_conf global_jbconf
static unsigned int global_t38_maxdatagram
static const int HASH_DIALOG_SIZE = 563
static const int HASH_PEER_SIZE = 563
static const int HASH_REGISTRY_SIZE = 563
static struct _map_x_s insecurestr []
static struct ast_sockaddr internip
 our (internal) default address/port to put in SIP/SDP messages internip is initialized picking a suitable address from one of the interfaces, and the same port number we bind to. It is used as the default address/port in SIP messages, and as the default address (but not port) in SDP messages.
static struct invstate2stringtable invitestate2string []
 Readable descriptions of device states.
static struct io_contextio
static struct ast_halocaladdr
 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 int max_expiry = DEFAULT_MAX_EXPIRY
static int max_subexpiry = DEFAULT_MAX_EXPIRY
static struct ast_sockaddr media_address
static int min_expiry = DEFAULT_MIN_EXPIRY
static int min_subexpiry = DEFAULT_MIN_EXPIRY
static pthread_t monitor_thread = AST_PTHREADT_NULL
 This is the thread for the monitor which checks for input on the channels which are not currently in use.
static ast_mutex_t monlock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 }
 Protect the monitoring thread, so only one process can kill or start it, and not when it's doing something critical.
static int mwi_expiry = DEFAULT_MWI_EXPIRY
static ast_mutex_t netlock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 }
static int network_change_sched_id = -1
static struct stasis_subscriptionnetwork_change_sub
static const char notify_config [] = "sip_notify.conf"
static struct ast_confignotify_types = NULL
static int ourport_tcp
static int ourport_tls
static struct ao2_containerpeers
 The peer list: Users, Peers and Friends.
static struct ao2_containerpeers_by_ip
static struct ast_data_handler peers_data_provider
static struct _map_x_s referstatusstrings []
static struct ao2_containerregistry_list
 The register list: Other SIP proxies we register with and receive calls from.
static struct _map_x_s regstatestrings []
static struct ast_sockaddr rtpbindaddr
struct ast_sched_contextsched
static struct
ast_cc_agent_callbacks 
sip_cc_agent_callbacks
static struct
ast_cc_monitor_callbacks 
sip_cc_monitor_callbacks
struct {
   enum sip_cc_notify_state   state
   const char *   state_string
sip_cc_notify_state_map []
struct {
   enum ast_cc_service_type   service
   const char *   service_string
sip_cc_service_map []
static struct ast_threadstorage sip_content_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_sip_content_buf , .custom_init = NULL , }
static struct ast_data_entry sip_data_providers []
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.
struct ao2_containersip_monitor_instances
static struct ast_msg_tech sip_msg_tech
static struct sip_reasons sip_reason_table []
 Diversion header reasons.
static ast_mutex_t sip_reload_lock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 }
static int sip_reloading = FALSE
static enum channelreloadreason sip_reloadreason
static struct ast_rtp_glue sip_rtp_glue
static struct
ast_tcptls_session_args 
sip_tcp_desc
 The TCP server definition.
struct ast_channel_tech sip_tech
 Definition of this channel for PBX channel registration.
struct ast_channel_tech sip_tech_info
 This version of the sip channel tech has no send_digit_begin callback so that the core knows that the channel does not want DTMF BEGIN frames. The struct is initialized just before registering the channel driver, and is for use with channels using SIP INFO DTMF.
static struct ast_tls_config sip_tls_cfg
 Working TLS connection configuration.
static struct
ast_tcptls_session_args 
sip_tls_desc
 The TCP/TLS server definition.
static struct ast_threadstorage sip_transport_str_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_sip_transport_str_buf , .custom_init = NULL , }
static enum sip_debug_e sipdebug
static int sipdebug_text
 extra debugging for 'text' related events. At the moment this is set together with sip_debug_console.
static struct ast_custom_function sippeer_function
 Structure to declare a dialplan function: SIPPEER.
static int sipsock = -1
 Main socket for UDP SIP communication.
static int * sipsock_read_id
static struct _map_x_s stmodes []
 Report Peer status in character string.
static struct _map_x_s strefresher_params []
static struct _map_x_s strefreshers []
static struct ao2_containersubscription_mwi_list
 The MWI subscription list.
static struct cfsubscription_types subscription_types []
 Subscription types that we support. We support
  • dialoginfo updates (really device status, not dialog info as was the original intent of the standard)
  • SIMPLE presence used for device status
  • Voicemail notification subscriptions.

static struct ao2_containerthreadt
 The table of TCP threads.
static struct _map_x_s trust_id_outboundstr []
static struct ast_threadstorage ts_temp_pvt = { .once = PTHREAD_ONCE_INIT , .key_init = __init_ts_temp_pvt , .custom_init = temp_pvt_init , }
static int unauth_sessions = 0
static char used_context [AST_MAX_CONTEXT]
Object counters @{
Bug:
These counters are not handled in a thread-safe way ast_atomic_fetchadd_int() should be used to modify these values.


static int apeerobjs = 0
static int rpeerobjs = 0
static int speerobjs = 0


Detailed Description

Implementation of Session Initiation Protocol.

Author:
Mark Spencer <markster@digium.com>
See Also: Implementation of RFC 3261 - without S/MIME, and experimental TCP and TLS support Configuration file sip.conf

********** IMPORTANT *

Note:
TCP/TLS support is EXPERIMENTAL and WILL CHANGE. This applies to configuration settings, dialplan commands and dialplans apps/functions See SIP TCP and TLS support
******** General TODO:s
Todo:
Better support of forking
Todo:
VIA branch tag transaction checking
Todo:
Transaction support
******** Wishlist: Improvements

Overview of the handling of SIP sessions
The SIP channel handles several types of SIP sessions, or dialogs, not all of them being "telephone calls".
  • Incoming calls that will be sent to the PBX core
  • Outgoing calls, generated by the PBX
  • SIP subscriptions and notifications of states and voicemail messages
  • SIP registrations, both inbound and outbound
  • SIP peer management (peerpoke, OPTIONS)
  • SIP text messages
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"

incoming packets
Incoming packets are received in the monitoring thread, then handled by sipsock_read() for udp only. In tcp, packets are read by the tcp_helper thread. sipsock_read() function parses the packet and matches an existing dialog or starts a new SIP dialog.
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

Outbound calls
Outbound calls are set up by the PBX through the sip_request_call() function. After that, they are activated by sip_call().
Hanging up
The PBX issues a hangup on both incoming and outgoing calls through the sip_hangup() function

Definition in file chan_sip.c.


Define Documentation

#define append_history ( p,
event,
fmt,
args...   )     append_history_full(p, "%-15s " fmt, event, ## args)

#define BOGUS_PEER_MD5SECRET   "intentionally_invalid_md5_string"

We can recognise the bogus peer by this invalid MD5 hash.

Definition at line 1004 of file chan_sip.c.

Referenced by check_auth(), load_module(), and sip_reload().

#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 2430 of file chan_sip.c.

Referenced by create_addr_from_peer(), and register_verify().

#define CONTAINER_UNLINK ( container,
obj,
tag   ) 

Unlink the given object from the container and return TRUE if it was in the container.

Definition at line 8492 of file chan_sip.c.

Referenced by change_callid_pvt().

#define DATA_EXPORT_SIP_PEER ( MEMBER   ) 

Definition at line 34172 of file chan_sip.c.

#define find_call ( req,
addr,
intended_method   )     __find_call(req, addr, intended_method, __FILE__, __LINE__, __PRETTY_FUNCTION__)

#define FORMAT   "%-15.15s %-15.15s %-15.15s %-15.15s %-3.3s %-3.3s %-15.15s %-10.10s %-10.10s\n"

Definition at line 21203 of file chan_sip.c.

#define FORMAT   "%-30.30s %-12.12s %-10.10s %-10.10s\n"

Definition at line 21203 of file chan_sip.c.

#define FORMAT   "%-15.15s %-11.11s %-8.8s %-10.10u%-1.1s %-10.10u (%5.2f%%) %-6.4lf %-10.10u%-1.1s %-10.10u (%5.2f%%) %-6.4lf\n"

Definition at line 21203 of file chan_sip.c.

#define FORMAT   "%-39.39s %-6.6s %-12.12s %8d %-20.20s %-25.25s\n"

Definition at line 21203 of file chan_sip.c.

#define FORMAT   "%-40.40s %-20.20s %-16.16s\n"

Definition at line 21203 of file chan_sip.c.

#define FORMAT   "%-25.25s %-15.15s %-15.15s %-15.15s %-5.5s%-10.10s\n"

Definition at line 21203 of file chan_sip.c.

#define FORMAT   "%-47.47s %-9.9s %-6.6s\n"

Definition at line 21203 of file chan_sip.c.

#define FORMAT   "%-25.25s %-15.15s %-15.15s \n"

Definition at line 21203 of file chan_sip.c.

#define FORMAT2   "%-15.15s %-15.15s %-15.15s %-15.15s %-7.7s %-15.15s %-10.10s %-10.10s\n"

Definition at line 21202 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 21202 of file chan_sip.c.

#define FORMAT2   "%-39.39s %-6.6s %-12.12s %8.8s %-20.20s %-25.25s\n"

Definition at line 21202 of file chan_sip.c.

#define FORMAT2   "%-47.47s %9.9s %6.6s\n"

Definition at line 21202 of file chan_sip.c.

#define FORMAT2   "%-25.25s %-15.15s %-15.15s \n"

Definition at line 21202 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 21201 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 21200 of file chan_sip.c.

Referenced by show_channels_cb().

#define PEERS_FORMAT2   "%-25.25s %-39.39s %-3.3s %-10.10s %-10.10s %-3.3s %-8s %-11s %-32.32s %s\n"

Definition at line 19358 of file chan_sip.c.

#define SIP_PEDANTIC_DECODE ( str   ) 

#define sip_pvt_lock (  )     ao2_lock(x)

#define sip_pvt_trylock (  )     ao2_trylock(x)

Definition at line 991 of file chan_sip.c.

Referenced by dialog_checkrtp_cb(), dialog_needdestroy(), and forked_invite_init().

#define sip_pvt_unlock (  )     ao2_unlock(x)

#define SIP_TRANSPORT_STR_BUFSIZE   128

Size of the SIP transport buffer.

Definition at line 1022 of file chan_sip.c.

Referenced by get_transport_list().

#define UNLINK ( element,
head,
prev   ) 

some list management macros.

Definition at line 1103 of file chan_sip.c.

Referenced by __sip_ack(), handle_request_cancel(), and retrans_pkt().


Enumeration Type Documentation

Enumerator:
SIP_REQ_MATCH 
SIP_REQ_NOT_MATCH 
SIP_REQ_LOOP_DETECTED 
SIP_REQ_FORKED 

Definition at line 8819 of file chan_sip.c.

08819                    {
08820    SIP_REQ_MATCH,
08821    SIP_REQ_NOT_MATCH,
08822    SIP_REQ_LOOP_DETECTED, /* multiple incoming requests with same call-id but different branch parameters have been detected */
08823    SIP_REQ_FORKED, /* An outgoing request has been forked as result of receiving two differing 200ok responses. */
08824 };

Indication of a TCP message's integrity.

Enumerator:
MESSAGE_INVALID  The message has an error in it with regards to its Content-Length header
MESSAGE_FRAGMENT  The message is incomplete
MESSAGE_FRAGMENT_COMPLETE  The data contains a complete message plus a fragment of another.
MESSAGE_COMPLETE  The message is complete

Definition at line 2689 of file chan_sip.c.

02689                        {
02690    /*!
02691     * The message has an error in it with
02692     * regards to its Content-Length header
02693     */
02694    MESSAGE_INVALID,
02695    /*!
02696     * The message is incomplete
02697     */
02698    MESSAGE_FRAGMENT,
02699    /*!
02700     * The data contains a complete message
02701     * plus a fragment of another.
02702     */
02703    MESSAGE_FRAGMENT_COMPLETE,
02704    /*!
02705     * The message is complete
02706     */
02707    MESSAGE_COMPLETE,
02708 };

Enumerator:
SIP_PEERS_MARKED 
SIP_PEERS_ALL 

Definition at line 3157 of file chan_sip.c.

03157              {
03158    SIP_PEERS_MARKED,
03159    SIP_PEERS_ALL,
03160 } peer_unlink_flag_t;


Function Documentation

static struct sip_pvt * __find_call ( struct sip_request req,
struct ast_sockaddr addr,
const int  intended_method,
const char *  file,
int  line,
const char *  func 
) [static, read]

find or create a dialog structure for an incoming SIP message. Connect incoming SIP message to current dialog or create new dialog structure Returns a reference to the sip_pvt object, remember to give it back once done. Called by handle_request_do

Definition at line 9123 of file chan_sip.c.

References __ao2_callback_debug(), __ao2_find_debug(), __ao2_ref_debug(), ao2_iterator_destroy(), ao2_iterator_next, args, ast_create_callid(), ast_debug, ast_skip_blanks(), ast_strlen_zero, match_req_args::authentication_present, sip_via::branch, match_req_args::callid, sip_pvt::callid, CAN_CREATE_DIALOG, CAN_CREATE_DIALOG_UNSUPPORTED_METHOD, dialog_find_multiple(), dialog_ref, dialog_unref, e, forked_invite_init(), free_via(), match_req_args::fromtag, gettag(), sip_request::has_to_tag, match_req_to_dialog(), sip_pvt::method, match_req_args::method, sip_request::method, NULL, OBJ_MULTIPLE, OBJ_POINTER, parse_via(), sip_settings::pedanticsipchecking, REQ_OFFSET_TO_STR, match_req_args::respid, match_req_args::ruri, sip_via::sent_by, match_req_args::seqno, SIP_ACK, sip_alloc, SIP_BYE, sip_cfg, sip_get_header(), SIP_INFO, SIP_INVITE, sip_methods, sip_pvt_lock, sip_pvt_unlock, SIP_REGISTER, SIP_REQ_FORKED, SIP_REQ_LOOP_DETECTED, SIP_REQ_MATCH, SIP_REQ_NOT_MATCH, SIP_RESPONSE, cfsip_methods::text, match_req_args::totag, transmit_response_using_temp(), match_req_args::viabranch, and match_req_args::viasentby.

09125 {
09126    char totag[128];
09127    char fromtag[128];
09128    const char *callid = sip_get_header(req, "Call-ID");
09129    const char *from = sip_get_header(req, "From");
09130    const char *to = sip_get_header(req, "To");
09131    const char *cseq = sip_get_header(req, "Cseq");
09132    struct sip_pvt *sip_pvt_ptr;
09133    uint32_t seqno;
09134    /* Call-ID, to, from and Cseq are required by RFC 3261. (Max-forwards and via too - ignored now) */
09135    /* sip_get_header always returns non-NULL so we must use ast_strlen_zero() */
09136    if (ast_strlen_zero(callid) || ast_strlen_zero(to) ||
09137          ast_strlen_zero(from) || ast_strlen_zero(cseq) ||
09138          (sscanf(cseq, "%30u", &seqno) != 1)) {
09139 
09140       /* RFC 3261 section 24.4.1.   Send a 400 Bad Request if the request is malformed. */
09141       if (intended_method != SIP_RESPONSE && intended_method != SIP_ACK) {
09142          transmit_response_using_temp(callid, addr, 1, intended_method,
09143                        req, "400 Bad Request");
09144       }
09145       return NULL;   /* Invalid packet */
09146    }
09147 
09148    if (sip_cfg.pedanticsipchecking) {
09149       /* In principle Call-ID's uniquely identify a call, but with a forking SIP proxy
09150          we need more to identify a branch - so we have to check branch, from
09151          and to tags to identify a call leg.
09152          For Asterisk to behave correctly, you need to turn on pedanticsipchecking
09153          in sip.conf
09154          */
09155       if (gettag(req, "To", totag, sizeof(totag)))
09156          req->has_to_tag = 1; /* Used in handle_request/response */
09157       gettag(req, "From", fromtag, sizeof(fromtag));
09158 
09159       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);
09160 
09161       /* All messages must always have From: tag */
09162       if (ast_strlen_zero(fromtag)) {
09163          ast_debug(5, "%s request has no from tag, dropping callid: %s from: %s\n", sip_methods[req->method].text , callid, from );
09164          return NULL;
09165       }
09166       /* reject requests that must always have a To: tag */
09167       if (ast_strlen_zero(totag) && (req->method == SIP_ACK || req->method == SIP_BYE || req->method == SIP_INFO )) {
09168          if (req->method != SIP_ACK) {
09169             transmit_response_using_temp(callid, addr, 1, intended_method, req, "481 Call leg/transaction does not exist");
09170          }
09171          ast_debug(5, "%s must have a to tag. dropping callid: %s from: %s\n", sip_methods[req->method].text , callid, from );
09172          return NULL;
09173       }
09174    }
09175 
09176    /* match on callid only for REGISTERs */
09177    if (!sip_cfg.pedanticsipchecking || req->method == SIP_REGISTER) {
09178       struct sip_pvt tmp_dialog = {
09179          .callid = callid,
09180       };
09181       sip_pvt_ptr = __ao2_find_debug(dialogs, &tmp_dialog, OBJ_POINTER,
09182          "find_call in dialogs", file, line, func);
09183       if (sip_pvt_ptr) {  /* well, if we don't find it-- what IS in there? */
09184          /* Found the call */
09185          return sip_pvt_ptr;
09186       }
09187    } else { /* in pedantic mode! -- do the fancy search */
09188       struct sip_pvt tmp_dialog = {
09189          .callid = callid,
09190       };
09191       /* if a Outbound forked Request is detected, this pvt will point
09192        * to the dialog the Request is forking off of. */
09193       struct sip_pvt *fork_pvt = NULL;
09194       struct match_req_args args = { 0, };
09195       int found;
09196       struct ao2_iterator *iterator = __ao2_callback_debug(dialogs,
09197          OBJ_POINTER | OBJ_MULTIPLE,
09198          dialog_find_multiple,
09199          &tmp_dialog,
09200          "pedantic ao2_find in dialogs",
09201          file, line, func);
09202       struct sip_via *via = NULL;
09203 
09204       args.method = req->method;
09205       args.callid = NULL; /* we already matched this. */
09206       args.totag = totag;
09207       args.fromtag = fromtag;
09208       args.seqno = seqno;
09209       /* get via header information. */
09210       args.ruri = REQ_OFFSET_TO_STR(req, rlpart2);
09211       via = parse_via(sip_get_header(req, "Via"));
09212       if (via) {
09213          args.viasentby = via->sent_by;
09214          args.viabranch = via->branch;
09215       }
09216       /* determine if this is a Request with authentication credentials. */
09217       if (!ast_strlen_zero(sip_get_header(req, "Authorization")) ||
09218          !ast_strlen_zero(sip_get_header(req, "Proxy-Authorization"))) {
09219          args.authentication_present = 1;
09220       }
09221       /* if it is a response, get the response code */
09222       if (req->method == SIP_RESPONSE) {
09223          const char* e = ast_skip_blanks(REQ_OFFSET_TO_STR(req, rlpart2));
09224          int respid;
09225          if (!ast_strlen_zero(e) && (sscanf(e, "%30d", &respid) == 1)) {
09226             args.respid = respid;
09227          }
09228       }
09229 
09230       /* Iterate a list of dialogs already matched by Call-id */
09231       while (iterator && (sip_pvt_ptr = ao2_iterator_next(iterator))) {
09232          sip_pvt_lock(sip_pvt_ptr);
09233          found = match_req_to_dialog(sip_pvt_ptr, &args);
09234          sip_pvt_unlock(sip_pvt_ptr);
09235 
09236          switch (found) {
09237          case SIP_REQ_MATCH:
09238             ao2_iterator_destroy(iterator);
09239             dialog_unref(fork_pvt, "unref fork_pvt");
09240             free_via(via);
09241             return sip_pvt_ptr; /* return pvt with ref */
09242          case SIP_REQ_LOOP_DETECTED:
09243             /* This is likely a forked Request that somehow resulted in us receiving multiple parts of the fork.
09244             * RFC 3261 section 8.2.2.2, Indicate that we want to merge requests by sending a 482 response. */
09245             transmit_response_using_temp(callid, addr, 1, intended_method, req, "482 (Loop Detected)");
09246             __ao2_ref_debug(sip_pvt_ptr, -1, "pvt did not match incoming SIP msg, unref from search.",
09247                file, line, func);
09248             ao2_iterator_destroy(iterator);
09249             dialog_unref(fork_pvt, "unref fork_pvt");
09250             free_via(via);
09251             return NULL;
09252          case SIP_REQ_FORKED:
09253             dialog_unref(fork_pvt, "throwing way pvt to fork off of.");
09254             fork_pvt = dialog_ref(sip_pvt_ptr, "this pvt has a forked request, save this off to copy information into new dialog\n");
09255             /* fall through */
09256          case SIP_REQ_NOT_MATCH:
09257          default:
09258             __ao2_ref_debug(sip_pvt_ptr, -1, "pvt did not match incoming SIP msg, unref from search",
09259                file, line, func);
09260             break;
09261          }
09262       }
09263       if (iterator) {
09264          ao2_iterator_destroy(iterator);
09265       }
09266 
09267       /* Handle any possible forked requests. This must be done only after transaction matching is complete. */
09268       if (fork_pvt) {
09269          /* XXX right now we only support handling forked INVITE Requests. Any other
09270           * forked request type must be added here. */
09271          if (fork_pvt->method == SIP_INVITE) {
09272             forked_invite_init(req, args.totag, fork_pvt, addr);
09273             dialog_unref(fork_pvt, "throwing way old forked pvt");
09274             free_via(via);
09275             return NULL;
09276          }
09277          fork_pvt = dialog_unref(fork_pvt, "throwing way pvt to fork off of");
09278       }
09279 
09280       free_via(via);
09281    } /* end of pedantic mode Request/Reponse to Dialog matching */
09282 
09283    /* See if the method is capable of creating a dialog */
09284    if (sip_methods[intended_method].can_create == CAN_CREATE_DIALOG) {
09285       struct sip_pvt *p = NULL;
09286       ast_callid logger_callid = 0;
09287 
09288       if (intended_method == SIP_INVITE) {
09289          logger_callid = ast_create_callid();
09290       }
09291 
09292       /* Ok, time to create a new SIP dialog object, a pvt */
09293       if (!(p = sip_alloc(callid, addr, 1, intended_method, req, logger_callid)))  {
09294          /* We have a memory or file/socket error (can't allocate RTP sockets or something) so we're not
09295             getting a dialog from sip_alloc.
09296 
09297             Without a dialog we can't retransmit and handle ACKs and all that, but at least
09298             send an error message.
09299 
09300             Sorry, we apologize for the inconvienience
09301          */
09302          transmit_response_using_temp(callid, addr, 1, intended_method, req, "500 Server internal error");
09303          ast_debug(4, "Failed allocating SIP dialog, sending 500 Server internal error and giving up\n");
09304       }
09305       return p; /* can be NULL */
09306    } else if( sip_methods[intended_method].can_create == CAN_CREATE_DIALOG_UNSUPPORTED_METHOD) {
09307       /* A method we do not support, let's take it on the volley */
09308       transmit_response_using_temp(callid, addr, 1, intended_method, req, "501 Method Not Implemented");
09309       ast_debug(2, "Got a request with unsupported SIP method.\n");
09310    } else if (intended_method != SIP_RESPONSE && intended_method != SIP_ACK) {
09311       /* This is a request outside of a dialog that we don't know about */
09312       transmit_response_using_temp(callid, addr, 1, intended_method, req, "481 Call leg/transaction does not exist");
09313       ast_debug(2, "That's odd...  Got a request in unknown dialog. Callid %s\n", callid ? callid : "<unknown>");
09314    }
09315    /* We do not respond to responses for dialogs that we don't know about, we just drop
09316       the session quickly */
09317    if (intended_method == SIP_RESPONSE)
09318       ast_debug(2, "That's odd...  Got a response on a call we don't know about. Callid %s\n", callid ? callid : "<unknown>");
09319 
09320    return NULL;
09321 }

static const char * __get_header ( const struct sip_request req,
const char *  name,
int *  start 
) [static]

Definition at line 8216 of file chan_sip.c.

References ast_skip_blanks(), find_alias(), sip_request::headers, len(), match(), NULL, sip_settings::pedanticsipchecking, REQ_OFFSET_TO_STR, and sip_cfg.

08217 {
08218    /*
08219     * Technically you can place arbitrary whitespace both before and after the ':' in
08220     * a header, although RFC3261 clearly says you shouldn't before, and place just
08221     * one afterwards.  If you shouldn't do it, what absolute idiot decided it was
08222     * a good idea to say you can do it, and if you can do it, why in the hell would.
08223     * you say you shouldn't.
08224     * Anyways, pedanticsipchecking controls whether we allow spaces before ':',
08225     * and we always allow spaces after that for compatibility.
08226     */
08227    const char *sname = find_alias(name, NULL);
08228    int x, len = strlen(name), slen = (sname ? 1 : 0);
08229    for (x = *start; x < req->headers; x++) {
08230       const char *header = REQ_OFFSET_TO_STR(req, header[x]);
08231       int smatch = 0, match = !strncasecmp(header, name, len);
08232       if (slen) {
08233          smatch = !strncasecmp(header, sname, slen);
08234       }
08235       if (match || smatch) {
08236          /* skip name */
08237          const char *r = header + (match ? len : slen );
08238          if (sip_cfg.pedanticsipchecking) {
08239             r = ast_skip_blanks(r);
08240          }
08241 
08242          if (*r == ':') {
08243             *start = x+1;
08244             return ast_skip_blanks(r+1);
08245          }
08246       }
08247    }
08248 
08249    /* Don't return NULL, so sip_get_header is always a valid pointer */
08250    return "";
08251 }

static void __init_sip_content_buf ( void   )  [static]

Definition at line 8263 of file chan_sip.c.

08267 {

static void __init_sip_transport_str_buf ( void   )  [static]

A per-thread buffer for transport to string conversion.

Definition at line 1019 of file chan_sip.c.

01052 : The address we bind to */

static void __init_ts_temp_pvt ( void   )  [static]

A per-thread temporary pvt structure.

Definition at line 1016 of file chan_sip.c.

01052 : The address we bind to */

static void __reg_module ( void   )  [static]

Definition at line 34761 of file chan_sip.c.

static int __set_address_from_contact ( const char *  fullcontact,
struct ast_sockaddr addr,
int  tcp 
) [static]

Definition at line 16082 of file chan_sip.c.

References ast_copy_string(), ast_log, ast_sockaddr_port, ast_sockaddr_resolve_first_transport(), ast_sockaddr_set_port, ast_strlen_zero, AST_TRANSPORT_TLS, get_transport_str2enum(), LOG_WARNING, NULL, parse_uri_legacy_check(), STANDARD_SIP_PORT, and STANDARD_TLS_PORT.

Referenced by build_peer(), create_addr_from_peer(), set_address_from_contact(), sip_poke_peer(), and sip_request_call().

16083 {
16084    char *hostport, *transport;
16085    char contact_buf[256];
16086    char *contact;
16087 
16088    /* Work on a copy */
16089    ast_copy_string(contact_buf, fullcontact, sizeof(contact_buf));
16090    contact = contact_buf;
16091 
16092    /*
16093     * We have only the part in <brackets> here so we just need to parse a SIP URI.
16094     *
16095     * Note: The outbound proxy could be using UDP between the proxy and Asterisk.
16096     * We still need to be able to send to the remote agent through the proxy.
16097     */
16098 
16099    if (parse_uri_legacy_check(contact, "sip:,sips:", &contact, NULL, &hostport,
16100             &transport)) {
16101       ast_log(LOG_WARNING, "Invalid contact uri %s (missing sip: or sips:), attempting to use anyway\n", fullcontact);
16102    }
16103 
16104    /* XXX This could block for a long time XXX */
16105    /* We should only do this if it's a name, not an IP */
16106    /* \todo - if there's no PORT number in contact - we are required to check NAPTR/SRV records
16107       to find transport, port address and hostname. If there's a port number, we have to
16108       assume that the hostport part is a host name and only look for an A/AAAA record in DNS.
16109    */
16110 
16111    /* If we took in an invalid URI, hostport may not have been initialized */
16112    /* ast_sockaddr_resolve requires an initialized hostport string. */
16113    if (ast_strlen_zero(hostport)) {
16114       ast_log(LOG_WARNING, "Invalid URI: parse_uri failed to acquire hostport\n");
16115       return -1;
16116    }
16117 
16118    if (ast_sockaddr_resolve_first_transport(addr, hostport, 0, get_transport_str2enum(transport))) {
16119       ast_log(LOG_WARNING, "Invalid host name in Contact: (can't "
16120          "resolve in DNS) : '%s'\n", hostport);
16121       return -1;
16122    }
16123 
16124    /* set port */
16125    if (!ast_sockaddr_port(addr)) {
16126       ast_sockaddr_set_port(addr,
16127                   (get_transport_str2enum(transport) ==
16128                    AST_TRANSPORT_TLS ||
16129                    !strncasecmp(fullcontact, "sips", 4)) ?
16130                   STANDARD_TLS_PORT : STANDARD_SIP_PORT);
16131    }
16132 
16133    return 0;
16134 }

int __sip_ack ( struct sip_pvt p,
uint32_t  seqno,
int  resp,
int  sipmethod 
)

Acknowledges receipt of a packet and stops retransmission called with p locked.

Definition at line 4336 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, sip_pkt::next, NULL, 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(), handle_request_publish(), and handle_response().

04337 {
04338    struct sip_pkt *cur, *prev = NULL;
04339    const char *msg = "Not Found";   /* used only for debugging */
04340    int res = FALSE;
04341 
04342    /* If we have an outbound proxy for this dialog, then delete it now since
04343      the rest of the requests in this dialog needs to follow the routing.
04344      If obforcing is set, we will keep the outbound proxy during the whole
04345      dialog, regardless of what the SIP rfc says
04346    */
04347    if (p->outboundproxy && !p->outboundproxy->force) {
04348       ref_proxy(p, NULL);
04349    }
04350 
04351    for (cur = p->packets; cur; prev = cur, cur = cur->next) {
04352       if (cur->seqno != seqno || cur->is_resp != resp) {
04353          continue;
04354       }
04355       if (cur->is_resp || cur->method == sipmethod) {
04356          res = TRUE;
04357          msg = "Found";
04358          if (!resp && (seqno == p->pendinginvite)) {
04359             ast_debug(1, "Acked pending invite %u\n", p->pendinginvite);
04360             p->pendinginvite = 0;
04361          }
04362          if (cur->retransid > -1) {
04363             if (sipdebug)
04364                ast_debug(4, "** SIP TIMER: Cancelling retransmit of packet (reply received) Retransid #%d\n", cur->retransid);
04365          }
04366          /* This odd section is designed to thwart a
04367           * race condition in the packet scheduler. There are
04368           * two conditions under which deleting the packet from the
04369           * scheduler can fail.
04370           *
04371           * 1. The packet has been removed from the scheduler because retransmission
04372           * is being attempted. The problem is that if the packet is currently attempting
04373           * retransmission and we are at this point in the code, then that MUST mean
04374           * that retrans_pkt is waiting on p's lock. Therefore we will relinquish the
04375           * lock temporarily to allow retransmission.
04376           *
04377           * 2. The packet has reached its maximum number of retransmissions and has
04378           * been permanently removed from the packet scheduler. If this is the case, then
04379           * the packet's retransid will be set to -1. The atomicity of the setting and checking
04380           * of the retransid to -1 is ensured since in both cases p's lock is held.
04381           */
04382          while (cur->retransid > -1 && ast_sched_del(sched, cur->retransid)) {
04383             sip_pvt_unlock(p);
04384             usleep(1);
04385             sip_pvt_lock(p);
04386          }
04387          UNLINK(cur, p->packets, prev);
04388          dialog_unref(cur->owner, "unref pkt cur->owner dialog from sip ack before freeing pkt");
04389          if (cur->data) {
04390             ast_free(cur->data);
04391          }
04392          ast_free(cur);
04393          break;
04394       }
04395    }
04396    ast_debug(1, "Stopping retransmission on '%s' of %s %u: Match %s\n",
04397       p->callid, resp ? "Response" : "Request", seqno, msg);
04398    return res;
04399 }

struct sip_pvt* __sip_alloc ( ast_string_field  callid,
struct ast_sockaddr addr,
int  useglobal_nat,
const int  intended_method,
struct sip_request req,
ast_callid  logger_callid,
const char *  file,
int  line,
const char *  func 
) [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 8596 of file chan_sip.c.

References __ao2_alloc_debug(), sip_pvt::allowed_methods, sip_settings::allowtransfer, sip_pvt::allowtransfer, AO2_ALLOC_OPT_LOCK_MUTEX, ao2_cleanup, ao2_t_link, ao2_t_ref, ast_cc_config_params_init, ast_copy_flags, ast_copy_string(), ast_debug, ast_format_cap_alloc, ast_format_cap_append_from_cap(), AST_FORMAT_CAP_FLAG_DEFAULT, AST_LIST_HEAD_INIT_NOLOCK, AST_MEDIA_TYPE_UNKNOWN, ast_random(), AST_RTP_DTMF, ast_sip_ouraddrfor(), ast_sockaddr_copy(), ast_string_field_init, ast_string_field_set, ast_strlen_zero, ast_test_flag, AST_TRANSPORT_UDP, sip_pvt::autoframing, sip_pvt::autokillid, sip_pvt::branch, sip_via::branch, build_callid_pvt(), build_via(), sip_pvt::callid, sip_settings::caps, sip_pvt::caps, sip_pvt::cc_params, check_via(), context, sip_settings::default_context, sip_settings::default_max_forwards, sip_pvt::do_history, do_setnat(), sip_socket::fd, sip_pvt::flags, free_via(), sip_pvt::fromdomainport, sip_pvt::init_icseq, INITIAL_CSEQ, sip_pvt::initid, internip, sip_pvt::jointcaps, make_our_tag(), sip_pvt::maxcallbitrate, sip_pvt::maxforwards, sip_pvt::method, mohinterpret, mohsuggest, sip_pvt::noncodeccapability, NONE, NULL, sip_pvt::ocseq, sip_pvt::offered_media, sip_pvt::ourip, parkinglot, parse_via(), sip_pvt::peercaps, sip_pvt::prefcaps, sip_pvt::provisional_keepalive_sched_id, sip_pvt::recv, sip_pvt::redircaps, sip_pvt::reinviteid, sip_pvt::request_queue, sip_pvt::request_queue_sched_id, sip_pvt::rtp, sip_pvt::sa, sip_via::sent_by, sip_pvt::session_modify, sip_pvt::sessionversion_remote, set_socket_transport(), sip_cfg, sip_destroy_fn(), SIP_DTMF, SIP_DTMF_AUTO, SIP_DTMF_RFC2833, SIP_FLAGS_TO_COPY, sip_get_header(), sip_methods, SIP_OPTIONS, SIP_PAGE2_FLAGS_TO_COPY, SIP_PAGE3_FLAGS_TO_COPY, sip_pvt_callid_set(), SIP_REGISTER, sip_request::socket, sip_pvt::socket, sip_pvt::stateid, sip_pvt::stimer, sip_pvt::subscribed, sip_pvt::t38id, cfsip_methods::text, sip_pvt::timer_b, sip_pvt::timer_t1, TRUE, sip_socket::type, sip_pvt::waitid, and sip_pvt::zone.

08599 {
08600    struct sip_pvt *p;
08601 
08602    p = __ao2_alloc_debug(sizeof(*p), sip_destroy_fn,
08603       AO2_ALLOC_OPT_LOCK_MUTEX, "allocate a dialog(pvt) struct",
08604       file, line, func, 1);
08605    if (!p) {
08606       return NULL;
08607    }
08608 
08609    if (ast_string_field_init(p, 512)) {
08610       ao2_t_ref(p, -1, "failed to string_field_init, drop p");
08611       return NULL;
08612    }
08613 
08614    if (!(p->cc_params = ast_cc_config_params_init())) {
08615       ao2_t_ref(p, -1, "Yuck, couldn't allocate cc_params struct. Get rid o' p");
08616       return NULL;
08617    }
08618 
08619    if (logger_callid) {
08620       sip_pvt_callid_set(p, logger_callid);
08621    }
08622 
08623    p->caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
08624    p->jointcaps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
08625    p->peercaps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
08626    p->redircaps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
08627    p->prefcaps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
08628 
08629    if (!p->caps|| !p->jointcaps || !p->peercaps || !p->redircaps || !p->prefcaps) {
08630       ao2_cleanup(p->caps);
08631       ao2_cleanup(p->jointcaps);
08632       ao2_cleanup(p->peercaps);
08633       ao2_cleanup(p->redircaps);
08634       ao2_cleanup(p->prefcaps);
08635       ao2_t_ref(p, -1, "Yuck, couldn't allocate format capabilities. Get rid o' p");
08636       return NULL;
08637    }
08638 
08639 
08640    /* If this dialog is created as a result of a request or response, lets store
08641     * some information about it in the dialog. */
08642    if (req) {
08643       struct sip_via *via;
08644       const char *cseq = sip_get_header(req, "Cseq");
08645       uint32_t seqno;
08646 
08647       /* get branch parameter from initial Request that started this dialog */
08648       via = parse_via(sip_get_header(req, "Via"));
08649       if (via) {
08650          /* only store the branch if it begins with the magic prefix "z9hG4bK", otherwise
08651           * it is not useful to us to have it */
08652          if (!ast_strlen_zero(via->branch) && !strncasecmp(via->branch, "z9hG4bK", 7)) {
08653             ast_string_field_set(p, initviabranch, via->branch);
08654             ast_string_field_set(p, initviasentby, via->sent_by);
08655          }
08656          free_via(via);
08657       }
08658 
08659       /* Store initial incoming cseq. An error in sscanf here is ignored.  There is no approperiate
08660        * except not storing the number.  CSeq validation must take place before dialog creation in find_call */
08661       if (!ast_strlen_zero(cseq) && (sscanf(cseq, "%30u", &seqno) == 1)) {
08662          p->init_icseq = seqno;
08663       }
08664       /* Later in ast_sip_ouraddrfor we need this to choose the right ip and port for the specific transport */
08665       set_socket_transport(&p->socket, req->socket.type);
08666    } else {
08667       set_socket_transport(&p->socket, AST_TRANSPORT_UDP);
08668    }
08669 
08670    p->socket.fd = -1;
08671    p->method = intended_method;
08672    p->initid = -1;
08673    p->waitid = -1;
08674    p->reinviteid = -1;
08675    p->autokillid = -1;
08676    p->request_queue_sched_id = -1;
08677    p->provisional_keepalive_sched_id = -1;
08678    p->t38id = -1;
08679    p->subscribed = NONE;
08680    p->stateid = -1;
08681    p->sessionversion_remote = -1;
08682    p->session_modify = TRUE;
08683    p->stimer = NULL;
08684    ast_copy_string(p->zone, default_zone, sizeof(p->zone));
08685    p->maxforwards = sip_cfg.default_max_forwards;
08686 
08687    if (intended_method != SIP_OPTIONS) {  /* Peerpoke has it's own system */
08688       p->timer_t1 = global_t1;   /* Default SIP retransmission timer T1 (RFC 3261) */
08689       p->timer_b = global_timer_b;  /* Default SIP transaction timer B (RFC 3261) */
08690    }
08691 
08692    if (!addr) {
08693       p->ourip = internip;
08694    } else {
08695       ast_sockaddr_copy(&p->sa, addr);
08696       ast_sip_ouraddrfor(&p->sa, &p->ourip, p);
08697    }
08698 
08699    /* Copy global flags to this PVT at setup. */
08700    ast_copy_flags(&p->flags[0], &global_flags[0], SIP_FLAGS_TO_COPY);
08701    ast_copy_flags(&p->flags[1], &global_flags[1], SIP_PAGE2_FLAGS_TO_COPY);
08702    ast_copy_flags(&p->flags[2], &global_flags[2], SIP_PAGE3_FLAGS_TO_COPY);
08703 
08704    p->do_history = recordhistory;
08705 
08706    p->branch = ast_random();
08707    make_our_tag(p);
08708    p->ocseq = INITIAL_CSEQ;
08709    p->allowed_methods = UINT_MAX;
08710 
08711    if (sip_methods[intended_method].need_rtp) {
08712       p->maxcallbitrate = default_maxcallbitrate;
08713       p->autoframing = global_autoframing;
08714    }
08715 
08716    if (useglobal_nat && addr) {
08717       /* Setup NAT structure according to global settings if we have an address */
08718       ast_sockaddr_copy(&p->recv, addr);
08719       check_via(p, req);
08720       do_setnat(p);
08721    }
08722 
08723    if (p->method != SIP_REGISTER) {
08724       ast_string_field_set(p, fromdomain, default_fromdomain);
08725       p->fromdomainport = default_fromdomainport;
08726    }
08727    build_via(p);
08728    if (!callid)
08729       build_callid_pvt(p);
08730    else
08731       ast_string_field_set(p, callid, callid);
08732    /* Assign default music on hold class */
08733    ast_string_field_set(p, mohinterpret, default_mohinterpret);
08734    ast_string_field_set(p, mohsuggest, default_mohsuggest);
08735    ast_format_cap_append_from_cap(p->caps, sip_cfg.caps, AST_MEDIA_TYPE_UNKNOWN);
08736    p->allowtransfer = sip_cfg.allowtransfer;
08737    if ((ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833) ||
08738        (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO)) {
08739       p->noncodeccapability |= AST_RTP_DTMF;
08740    }
08741    ast_string_field_set(p, context, sip_cfg.default_context);
08742    ast_string_field_set(p, parkinglot, default_parkinglot);
08743    ast_string_field_set(p, engine, default_engine);
08744 
08745    AST_LIST_HEAD_INIT_NOLOCK(&p->request_queue);
08746    AST_LIST_HEAD_INIT_NOLOCK(&p->offered_media);
08747 
08748    /* Add to active dialog list */
08749 
08750    ao2_t_link(dialogs, p, "link pvt into dialogs table");
08751 
08752    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");
08753    return p;
08754 }

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 4196 of file chan_sip.c.

References __sip_pretend_ack(), sip_pvt::alreadygone, append_history, AST_CAUSE_PROTOCOL_ERROR, ast_channel_name(), ast_channel_unlock, ast_channel_unref, ast_debug, AST_EXTENSION_DEACTIVATED, ast_log, ast_queue_hangup_with_cause(), sip_pvt::autokillid, CALL_COMPLETION, 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::ongoing_reinvite, sip_pvt::packets, pvt_set_needdestroy(), sip_pvt::refer, SIP_BYE, SIP_CANCEL, sip_methods, sip_pvt_lock, sip_pvt_lock_full(), sip_pvt_unlock, sip_scheddestroy(), state_notify_data::state, stop_media_flows(), sip_pvt::subscribed, cfsip_methods::text, transmit_request_with_auth(), transmit_state_notify(), TRUE, and XMIT_RELIABLE.

Referenced by sip_scheddestroy(), and sip_show_sched().

04197 {
04198    struct sip_pvt *p = (struct sip_pvt *)data;
04199    struct ast_channel *owner;
04200 
04201    /* If this is a subscription, tell the phone that we got a timeout */
04202    if (p->subscribed && p->subscribed != MWI_NOTIFICATION && p->subscribed != CALL_COMPLETION) {
04203       struct state_notify_data data = { 0, };
04204       data.state = AST_EXTENSION_DEACTIVATED;
04205 
04206       transmit_state_notify(p, &data, 1, TRUE); /* Send last notification */
04207       p->subscribed = NONE;
04208       append_history(p, "Subscribestatus", "timeout");
04209       ast_debug(3, "Re-scheduled destruction of SIP subscription %s\n", p->callid ? p->callid : "<unknown>");
04210       return 10000;  /* Reschedule this destruction so that we know that it's gone */
04211    }
04212 
04213    /* If there are packets still waiting for delivery, delay the destruction */
04214    if (p->packets) {
04215       if (!p->needdestroy) {
04216          char method_str[31];
04217          ast_debug(3, "Re-scheduled destruction of SIP call %s\n", p->callid ? p->callid : "<unknown>");
04218          append_history(p, "ReliableXmit", "timeout");
04219          if (sscanf(p->lastmsg, "Tx: %30s", method_str) == 1 || sscanf(p->lastmsg, "Rx: %30s", method_str) == 1) {
04220             if (p->ongoing_reinvite || method_match(SIP_CANCEL, method_str) || method_match(SIP_BYE, method_str)) {
04221                pvt_set_needdestroy(p, "autodestruct");
04222             }
04223          }
04224          return 10000;
04225       } else {
04226          /* They've had their chance to respond. Time to bail */
04227          __sip_pretend_ack(p);
04228       }
04229    }
04230 
04231    /* Reset schedule ID */
04232    p->autokillid = -1;
04233 
04234    /*
04235     * Lock both the pvt and the channel safely so that we can queue up a frame.
04236     */
04237    owner = sip_pvt_lock_full(p);
04238    if (owner) {
04239       ast_log(LOG_WARNING, "Autodestruct on dialog '%s' with owner %s in place (Method: %s). Rescheduling destruction for 10000 ms\n", p->callid, ast_channel_name(owner), sip_methods[p->method].text);
04240       ast_queue_hangup_with_cause(owner, AST_CAUSE_PROTOCOL_ERROR);
04241       ast_channel_unlock(owner);
04242       ast_channel_unref(owner);
04243       sip_pvt_unlock(p);
04244       return 10000;
04245    } else if (p->refer && !p->alreadygone) {
04246       ast_debug(3, "Finally hanging up channel after transfer: %s\n", p->callid);
04247       stop_media_flows(p);
04248       transmit_request_with_auth(p, SIP_BYE, 0, XMIT_RELIABLE, 1);
04249       append_history(p, "ReferBYE", "Sending BYE on transferer call leg %s", p->callid);
04250       sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
04251    } else {
04252       append_history(p, "AutoDestroy", "%s", p->callid);
04253       ast_debug(3, "Auto destroying SIP dialog '%s'\n", p->callid);
04254       sip_pvt_unlock(p);
04255       dialog_unlink_all(p); /* once it's unlinked and unrefd everywhere, it'll be freed automagically */
04256       sip_pvt_lock(p);
04257       /* dialog_unref(p, "unref dialog-- no other matching conditions"); -- unlink all now should finish off the dialog's references and free it. */
04258       /* sip_destroy(p); */      /* Go ahead and destroy dialog. All attempts to recover is done */
04259       /* sip_destroy also absorbs the reference */
04260    }
04261 
04262    sip_pvt_unlock(p);
04263 
04264    dialog_unref(p, "The ref to a dialog passed to this sched callback is going out of scope; unref it.");
04265 
04266    return 0;
04267 }

void __sip_destroy ( struct sip_pvt p,
int  lockowner,
int  lockdialoglist 
)

Execute destruction of SIP dialog structure, release memory.

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 6351 of file chan_sip.c.

References ao2_cleanup, ao2_ref, ao2_t_ref, ao2_t_replace, ast_cc_config_params_destroy(), ast_channel_lock, ast_channel_name(), ast_channel_softhangup_internal_flag_add(), ast_channel_tech_pvt_set(), ast_channel_unlock, ast_debug, ast_free, ast_free_acl_list(), AST_LIST_REMOVE_HEAD, ast_rtp_dtls_cfg_free(), ast_rtp_instance_destroy(), ast_sdp_srtp_destroy(), AST_SOFTHANGUP_DEV, ast_string_field_free_memory, ast_test_flag, ast_udptl_destroy(), ast_unref_namedgroups(), ast_variables_destroy(), ast_verbose, ast_websocket_unref(), sip_subscription_mwi::call, sip_registry::call, sip_peer::call, sip_pvt::callid, sip_pvt::caps, sip_pvt::cc_params, sip_pvt::chanvars, sip_notify::content, DEC_CALL_LIMIT, deinit_req(), destroy_msg_headers(), dialog_unref, sip_pvt::directmediaacl, sip_pvt::dtls_cfg, sip_pvt::epa_entry, sip_pvt::flags, sip_notify::headers, sip_pvt::history, sip_pvt::history_entries, sip_pvt::initreq, sip_pvt::jointcaps, sip_pvt::last_device_state_info, sip_pvt::method, sip_pvt::mwi, sip_peer::mwipvt, sip_pvt::named_callgroups, sip_pvt::named_pickupgroups, sip_pvt::notify, NULL, offered_media_list_destroy(), sip_pvt::options, sip_pvt::outboundproxy, sip_invite_param::outboundproxy, sip_pvt::owner, sip_pvt::peerauth, sip_pvt::peercaps, sip_pvt::prefcaps, sip_st_dlg::quit_flag, sip_pvt::redircaps, ref_proxy(), sip_pvt::registry, 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_refer_destroy(), sip_route_clear(), sip_unref_peer, sip_pvt::socket, sip_pvt::srtp, sip_pvt::stimer, stop_session_timer(), sip_socket::tcptls_session, cfsip_methods::text, sip_pvt::trtp, sip_pvt::tsrtp, sip_pvt::udptl, update_call_counter(), sip_pvt::vrtp, sip_pvt::vsrtp, and sip_socket::ws_session.

Referenced by sip_destroy().

06352 {
06353    struct sip_request *req;
06354 
06355    /* Destroy Session-Timers if allocated */
06356    if (p->stimer) {
06357       p->stimer->quit_flag = 1;
06358       stop_session_timer(p);
06359       ast_free(p->stimer);
06360       p->stimer = NULL;
06361    }
06362 
06363    if (sip_debug_test_pvt(p))
06364       ast_verbose("Really destroying SIP dialog '%s' Method: %s\n", p->callid, sip_methods[p->method].text);
06365 
06366    if (ast_test_flag(&p->flags[0], SIP_INC_COUNT) || ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD)) {
06367       update_call_counter(p, DEC_CALL_LIMIT);
06368       ast_debug(2, "This call did not properly clean up call limits. Call ID %s\n", p->callid);
06369    }
06370 
06371    /* Unlink us from the owner if we have one */
06372    if (p->owner) {
06373       if (lockowner)
06374          ast_channel_lock(p->owner);
06375       ast_debug(1, "Detaching from %s\n", ast_channel_name(p->owner));
06376       ast_channel_tech_pvt_set(p->owner, NULL);
06377       /* Make sure that the channel knows its backend is going away */
06378       ast_channel_softhangup_internal_flag_add(p->owner, AST_SOFTHANGUP_DEV);
06379       if (lockowner)
06380          ast_channel_unlock(p->owner);
06381       /* Give the channel a chance to react before deallocation */
06382       usleep(1);
06383    }
06384 
06385    /* Remove link from peer to subscription of MWI */
06386    if (p->relatedpeer && p->relatedpeer->mwipvt == p)
06387       p->relatedpeer->mwipvt = dialog_unref(p->relatedpeer->mwipvt, "delete ->relatedpeer->mwipvt");
06388    if (p->relatedpeer && p->relatedpeer->call == p)
06389       p->relatedpeer->call = dialog_unref(p->relatedpeer->call, "unset the relatedpeer->call field in tandem with relatedpeer field itself");
06390 
06391    if (p->relatedpeer)
06392       p->relatedpeer = sip_unref_peer(p->relatedpeer,"unsetting a dialog relatedpeer field in sip_destroy");
06393 
06394    if (p->registry) {
06395       if (p->registry->call == p)
06396          p->registry->call = dialog_unref(p->registry->call, "nulling out the registry's call dialog field in unlink_all");
06397       ao2_t_replace(p->registry, NULL, "delete p->registry");
06398    }
06399 
06400    if (p->mwi) {
06401       p->mwi->call = NULL;
06402       p->mwi = NULL;
06403    }
06404 
06405    if (dumphistory)
06406       sip_dump_history(p);
06407 
06408    if (p->options) {
06409       if (p->options->outboundproxy) {
06410          ao2_ref(p->options->outboundproxy, -1);
06411       }
06412       ast_free(p->options);
06413       p->options = NULL;
06414    }
06415 
06416    if (p->outboundproxy) {
06417       ref_proxy(p, NULL);
06418    }
06419 
06420    if (p->notify) {
06421       ast_variables_destroy(p->notify->headers);
06422       ast_free(p->notify->content);
06423       ast_free(p->notify);
06424       p->notify = NULL;
06425    }
06426    if (p->rtp) {
06427       ast_rtp_instance_destroy(p->rtp);
06428       p->rtp = NULL;
06429    }
06430    if (p->vrtp) {
06431       ast_rtp_instance_destroy(p->vrtp);
06432       p->vrtp = NULL;
06433    }
06434    if (p->trtp) {
06435       ast_rtp_instance_destroy(p->trtp);
06436       p->trtp = NULL;
06437    }
06438    if (p->udptl) {
06439       ast_udptl_destroy(p->udptl);
06440       p->udptl = NULL;
06441    }
06442    sip_refer_destroy(p);
06443    sip_route_clear(&p->route);
06444    deinit_req(&p->initreq);
06445 
06446    /* Clear history */
06447    if (p->history) {
06448       struct sip_history *hist;
06449       while ( (hist = AST_LIST_REMOVE_HEAD(p->history, list)) ) {
06450          ast_free(hist);
06451          p->history_entries--;
06452       }
06453       ast_free(p->history);
06454       p->history = NULL;
06455    }
06456 
06457    while ((req = AST_LIST_REMOVE_HEAD(&p->request_queue, next))) {
06458       ast_free(req);
06459    }
06460 
06461    offered_media_list_destroy(p);
06462 
06463    if (p->chanvars) {
06464       ast_variables_destroy(p->chanvars);
06465       p->chanvars = NULL;
06466    }
06467 
06468    destroy_msg_headers(p);
06469 
06470    if (p->srtp) {
06471       ast_sdp_srtp_destroy(p->srtp);
06472       p->srtp = NULL;
06473    }
06474 
06475    if (p->vsrtp) {
06476       ast_sdp_srtp_destroy(p->vsrtp);
06477       p->vsrtp = NULL;
06478    }
06479 
06480    if (p->tsrtp) {
06481       ast_sdp_srtp_destroy(p->tsrtp);
06482       p->tsrtp = NULL;
06483    }
06484 
06485    if (p->directmediaacl) {
06486       p->directmediaacl = ast_free_acl_list(p->directmediaacl);
06487    }
06488 
06489    ast_string_field_free_memory(p);
06490 
06491    ast_cc_config_params_destroy(p->cc_params);
06492    p->cc_params = NULL;
06493 
06494    if (p->epa_entry) {
06495       ao2_ref(p->epa_entry, -1);
06496       p->epa_entry = NULL;
06497    }
06498 
06499    if (p->socket.tcptls_session) {
06500       ao2_ref(p->socket.tcptls_session, -1);
06501       p->socket.tcptls_session = NULL;
06502    } else if (p->socket.ws_session) {
06503       ast_websocket_unref(p->socket.ws_session);
06504       p->socket.ws_session = NULL;
06505    }
06506 
06507    if (p->peerauth) {
06508       ao2_t_ref(p->peerauth, -1, "Removing active peer authentication");
06509       p->peerauth = NULL;
06510    }
06511 
06512    p->named_callgroups = ast_unref_namedgroups(p->named_callgroups);
06513    p->named_pickupgroups = ast_unref_namedgroups(p->named_pickupgroups);
06514 
06515    ao2_cleanup(p->caps);
06516    ao2_cleanup(p->jointcaps);
06517    ao2_cleanup(p->peercaps);
06518    ao2_cleanup(p->redircaps);
06519    ao2_cleanup(p->prefcaps);
06520 
06521    ast_rtp_dtls_cfg_free(&p->dtls_cfg);
06522 
06523    if (p->last_device_state_info) {
06524       ao2_ref(p->last_device_state_info, -1);
06525       p->last_device_state_info = NULL;
06526    }
06527 }

static int __sip_do_register ( struct sip_registry r  )  [static]

Register with SIP proxy.

Returns:
see __sip_xmit

Definition at line 15237 of file chan_sip.c.

References NULL, SIP_REGISTER, and transmit_register().

Referenced by sip_reregister().

15238 {
15239    int res;
15240 
15241    res = transmit_register(r, SIP_REGISTER, NULL, NULL);
15242    return res;
15243 }

void __sip_pretend_ack ( struct sip_pvt p  ) 

Pretend to ack all packets called with p locked.

Definition at line 4403 of file chan_sip.c.

References __sip_ack(), ast_log, ast_str_buffer(), sip_pkt::data, find_sip_method(), sip_pkt::is_resp, LOG_WARNING, sip_pkt::method, method, NULL, sip_pvt::packets, sip_pkt::seqno, sip_methods, and cfsip_methods::text.

Referenced by __sip_autodestruct(), handle_request_bye(), handle_request_cancel(), and sip_reg_timeout().

04404 {
04405    struct sip_pkt *cur = NULL;
04406 
04407    while (p->packets) {
04408       int method;
04409       if (cur == p->packets) {
04410          ast_log(LOG_WARNING, "Have a packet that doesn't want to give up! %s\n", sip_methods[cur->method].text);
04411          return;
04412       }
04413       cur = p->packets;
04414       method = (cur->method) ? cur->method : find_sip_method(ast_str_buffer(cur->data));
04415       __sip_ack(p, cur->seqno, cur->is_resp, method);
04416    }
04417 }

static enum sip_result __sip_reliable_xmit ( struct sip_pvt p,
uint32_t  seqno,
int  resp,
struct ast_str data,
int  fatal,
int  sipmethod 
) [static]

Todo:
According to the RFC some packets need to be retransmitted even if its TCP, so this needs to get revisited

Definition at line 4105 of file chan_sip.c.

References __sip_xmit(), append_history, ast_calloc, ast_debug, AST_FAILURE, ast_free, ast_log, AST_PTHREADT_NULL, AST_SCHED_DEL, AST_SCHED_REPLACE_VARIABLE, ast_str_buffer(), ast_str_create(), ast_str_set(), ast_str_strlen(), AST_SUCCESS, AST_TRANSPORT_UDP, ast_tvnow(), sip_pkt::data, DEFAULT_RETRANS, DEFAULT_TIMER_T1, dialog_ref, dialog_unref, sip_pkt::is_fatal, sip_pkt::is_resp, LOG_ERROR, sip_pkt::method, sip_pkt::next, NULL, sip_pkt::owner, sip_pvt::packets, sip_pvt::pendinginvite, sip_pkt::response_code, retrans_pkt(), sip_pkt::retrans_stop_time, sip_pkt::retransid, sip_pkt::seqno, SIP_INVITE, sip_pvt::socket, sip_pkt::time_sent, sip_pvt::timer_t1, sip_pkt::timer_t1, sip_socket::type, and XMIT_ERROR.

Referenced by send_request(), and send_response().

04106 {
04107    struct sip_pkt *pkt = NULL;
04108    int siptimer_a = DEFAULT_RETRANS;
04109    int xmitres = 0;
04110    unsigned respid;
04111 
04112    if (sipmethod == SIP_INVITE) {
04113       /* Note this is a pending invite */
04114       p->pendinginvite = seqno;
04115    }
04116 
04117    /* If the transport is something reliable (TCP or TLS) then don't really send this reliably */
04118    /* I removed the code from retrans_pkt that does the same thing so it doesn't get loaded into the scheduler */
04119    /*! \todo According to the RFC some packets need to be retransmitted even if its TCP, so this needs to get revisited */
04120    if (!(p->socket.type & AST_TRANSPORT_UDP)) {
04121       xmitres = __sip_xmit(p, data);   /* Send packet */
04122       if (xmitres == XMIT_ERROR) {  /* Serious network trouble, no need to try again */
04123          append_history(p, "XmitErr", "%s", fatal ? "(Critical)" : "(Non-critical)");
04124          return AST_FAILURE;
04125       } else {
04126          return AST_SUCCESS;
04127       }
04128    }
04129 
04130    if (!(pkt = ast_calloc(1, sizeof(*pkt)))) {
04131       return AST_FAILURE;
04132    }
04133    /* copy data, add a terminator and save length */
04134    if (!(pkt->data = ast_str_create(ast_str_strlen(data)))) {
04135       ast_free(pkt);
04136       return AST_FAILURE;
04137    }
04138    ast_str_set(&pkt->data, 0, "%s%s", ast_str_buffer(data), "\0");
04139    /* copy other parameters from the caller */
04140    pkt->method = sipmethod;
04141    pkt->seqno = seqno;
04142    pkt->is_resp = resp;
04143    pkt->is_fatal = fatal;
04144    pkt->owner = dialog_ref(p, "__sip_reliable_xmit: setting pkt->owner");
04145    pkt->next = p->packets;
04146    p->packets = pkt; /* Add it to the queue */
04147    if (resp) {
04148       /* Parse out the response code */
04149       if (sscanf(ast_str_buffer(pkt->data), "SIP/2.0 %30u", &respid) == 1) {
04150          pkt->response_code = respid;
04151       }
04152    }
04153    pkt->timer_t1 = p->timer_t1;  /* Set SIP timer T1 */
04154    pkt->retransid = -1;
04155    if (pkt->timer_t1) {
04156       siptimer_a = pkt->timer_t1;
04157    }
04158 
04159    pkt->time_sent = ast_tvnow(); /* time packet was sent */
04160    pkt->retrans_stop_time = 64 * (pkt->timer_t1 ? pkt->timer_t1 : DEFAULT_TIMER_T1); /* time in ms after pkt->time_sent to stop retransmission */
04161 
04162    /* Schedule retransmission */
04163    AST_SCHED_REPLACE_VARIABLE(pkt->retransid, sched, siptimer_a, retrans_pkt, pkt, 1);
04164    if (sipdebug) {
04165       ast_debug(4, "*** SIP TIMER: Initializing retransmit timer on packet: Id  #%d\n", pkt->retransid);
04166    }
04167 
04168    xmitres = __sip_xmit(pkt->owner, pkt->data); /* Send packet */
04169 
04170    if (xmitres == XMIT_ERROR) {  /* Serious network trouble, no need to try again */
04171       append_history(pkt->owner, "XmitErr", "%s", pkt->is_fatal ? "(Critical)" : "(Non-critical)");
04172       ast_log(LOG_ERROR, "Serious Network Trouble; __sip_xmit returns error for pkt data\n");
04173       AST_SCHED_DEL(sched, pkt->retransid);
04174       p->packets = pkt->next;
04175       pkt->owner = dialog_unref(pkt->owner,"pkt is being freed, its dialog ref is dead now");
04176       ast_free(pkt->data);
04177       ast_free(pkt);
04178       return AST_FAILURE;
04179    } else {
04180       /* This is odd, but since the retrans timer starts at 500ms and the do_monitor thread
04181        * only wakes up every 1000ms by default, we have to poke the thread here to make
04182        * sure it successfully detects this must be retransmitted in less time than
04183        * it usually sleeps for. Otherwise it might not retransmit this packet for 1000ms. */
04184       if (monitor_thread != AST_PTHREADT_NULL) {
04185          pthread_kill(monitor_thread, SIGURG);
04186       }
04187       return AST_SUCCESS;
04188    }
04189 }

int __sip_semi_ack ( struct sip_pvt p,
uint32_t  seqno,
int  resp,
int  sipmethod 
)

Acks receipt of packet, keep it around (used for provisional responses).

Definition at line 4420 of file chan_sip.c.

References ast_debug, AST_SCHED_DEL, ast_str_buffer(), 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, cfsip_methods::text, and TRUE.

Referenced by handle_response(), and sip_hangup().

04421 {
04422    struct sip_pkt *cur;
04423    int res = FALSE;
04424 
04425    for (cur = p->packets; cur; cur = cur->next) {
04426       if (cur->seqno == seqno && cur->is_resp == resp &&
04427          (cur->is_resp || method_match(sipmethod, ast_str_buffer(cur->data)))) {
04428          /* this is our baby */
04429          if (cur->retransid > -1) {
04430             if (sipdebug)
04431                ast_debug(4, "*** SIP TIMER: Cancelling retransmission #%d - %s (got response)\n", cur->retransid, sip_methods[sipmethod].text);
04432          }
04433          AST_SCHED_DEL(sched, cur->retransid);
04434          res = TRUE;
04435          break;
04436       }
04437    }
04438    ast_debug(1, "(Provisional) Stopping retransmission (but retaining packet) on '%s' %s %u: %s\n", p->callid, resp ? "Response" : "Request", seqno, res == -1 ? "Not Found" : "Found");
04439    return res;
04440 }

static int __sip_subscribe_mwi_do ( struct sip_subscription_mwi mwi  )  [static]

Actually setup an MWI subscription or resubscribe.

Definition at line 14454 of file chan_sip.c.

References ao2_t_bump, ao2_t_ref, ast_dnsmgr_lookup_cb(), ast_set_flag, ast_sip_ouraddrfor(), ast_sockaddr_port, ast_sockaddr_set_port, ast_string_field_set, ast_strlen_zero, sip_subscription_mwi::authuser, build_via(), sip_subscription_mwi::call, change_callid_pvt(), create_addr(), dialog_unlink_all(), dialog_unref, sip_subscription_mwi::dnsmgr, sip_pvt::expiry, sip_pvt::flags, get_address_family_filter(), get_srv_protocol(), get_srv_service(), sip_subscription_mwi::hostname, MAXHOSTNAMELEN, sip_pvt::mwi, MWI_NOTIFICATION, NULL, obproxy_get(), on_dns_update_mwi(), sip_pvt::ourip, sip_monitor_instance::peername, sip_socket::port, sip_subscription_mwi::portno, sip_pvt::recv, ref_proxy(), sip_pvt::sa, sip_subscription_mwi::secret, set_socket_transport(), sip_alloc, sip_cfg, SIP_OUTGOING, SIP_SUBSCRIBE, sip_pvt::socket, sip_settings::srvlookup, ast_sockaddr::ss, sip_pvt::subscribed, transmit_invite(), sip_subscription_mwi::transport, sip_subscription_mwi::us, and sip_subscription_mwi::username.

Referenced by sip_subscribe_mwi_do().

14455 {
14456    /* If we have no DNS manager let's do a lookup */
14457    if (!mwi->dnsmgr) {
14458       char transport[MAXHOSTNAMELEN];
14459       snprintf(transport, sizeof(transport), "_%s._%s", get_srv_service(mwi->transport), get_srv_protocol(mwi->transport));
14460 
14461       mwi->us.ss.ss_family = get_address_family_filter(mwi->transport); /* Filter address family */
14462       ao2_t_ref(mwi, +1, "dnsmgr reference to mwi");
14463       ast_dnsmgr_lookup_cb(mwi->hostname, &mwi->us, &mwi->dnsmgr, sip_cfg.srvlookup ? transport : NULL, on_dns_update_mwi, mwi);
14464       if (!mwi->dnsmgr) {
14465          ao2_t_ref(mwi, -1, "dnsmgr disabled, remove reference");
14466       }
14467    }
14468 
14469    /* If we already have a subscription up simply send a resubscription */
14470    if (mwi->call) {
14471       transmit_invite(mwi->call, SIP_SUBSCRIBE, 0, 0, NULL);
14472       return 0;
14473    }
14474 
14475    /* Create a dialog that we will use for the subscription */
14476    if (!(mwi->call = sip_alloc(NULL, NULL, 0, SIP_SUBSCRIBE, NULL, 0))) {
14477       return -1;
14478    }
14479 
14480    ref_proxy(mwi->call, obproxy_get(mwi->call, NULL));
14481 
14482    if (!ast_sockaddr_port(&mwi->us) && mwi->portno) {
14483       ast_sockaddr_set_port(&mwi->us, mwi->portno);
14484    }
14485 
14486    /* Setup the destination of our subscription */
14487    if (create_addr(mwi->call, mwi->hostname, &mwi->us, 0)) {
14488       dialog_unlink_all(mwi->call);
14489       mwi->call = dialog_unref(mwi->call, "unref dialog after unlink_all");
14490       return 0;
14491    }
14492 
14493    mwi->call->expiry = mwi_expiry;
14494 
14495    if (!mwi->dnsmgr && mwi->portno) {
14496       ast_sockaddr_set_port(&mwi->call->sa, mwi->portno);
14497       ast_sockaddr_set_port(&mwi->call->recv, mwi->portno);
14498    } else {
14499       mwi->portno = ast_sockaddr_port(&mwi->call->sa);
14500    }
14501 
14502    /* Set various other information */
14503    if (!ast_strlen_zero(mwi->authuser)) {
14504       ast_string_field_set(mwi->call, peername, mwi->authuser);
14505       ast_string_field_set(mwi->call, authname, mwi->authuser);
14506       ast_string_field_set(mwi->call, fromuser, mwi->authuser);
14507    } else {
14508       ast_string_field_set(mwi->call, peername, mwi->username);
14509       ast_string_field_set(mwi->call, authname, mwi->username);
14510       ast_string_field_set(mwi->call, fromuser, mwi->username);
14511    }
14512    ast_string_field_set(mwi->call, username, mwi->username);
14513    if (!ast_strlen_zero(mwi->secret)) {
14514       ast_string_field_set(mwi->call, peersecret, mwi->secret);
14515    }
14516    set_socket_transport(&mwi->call->socket, mwi->transport);
14517    mwi->call->socket.port = htons(mwi->portno);
14518    ast_sip_ouraddrfor(&mwi->call->sa, &mwi->call->ourip, mwi->call);
14519    build_via(mwi->call);
14520 
14521    /* Change the dialog callid. */
14522    change_callid_pvt(mwi->call, NULL);
14523 
14524    ast_set_flag(&mwi->call->flags[0], SIP_OUTGOING);
14525 
14526    /* Associate the call with us */
14527    mwi->call->mwi = ao2_t_bump(mwi, "Reference mwi from it's call");
14528 
14529    mwi->call->subscribed = MWI_NOTIFICATION;
14530 
14531    /* Actually send the packet */
14532    transmit_invite(mwi->call, SIP_SUBSCRIBE, 0, 2, NULL);
14533 
14534    return 0;
14535 }

static int __sip_xmit ( struct sip_pvt p,
struct ast_str data 
) [static]

Definition at line 3695 of file chan_sip.c.

References ast_debug, ast_log, ast_sendto(), ast_sockaddr_stringify(), ast_str_buffer(), ast_str_strlen(), AST_TRANSPORT_UDP, AST_WEBSOCKET_OPCODE_TEXT, ast_websocket_write(), errno, sip_socket::fd, get_transport_pvt(), LOG_WARNING, sip_prepare_socket(), sip_real_dst(), sip_tcptls_write(), sip_pvt::socket, sip_socket::tcptls_session, sip_socket::type, sip_socket::ws_session, and XMIT_ERROR.

Referenced by __sip_reliable_xmit(), retrans_pkt(), send_request(), and send_response().

03696 {
03697    int res = 0;
03698    const struct ast_sockaddr *dst = sip_real_dst(p);
03699 
03700    ast_debug(2, "Trying to put '%.11s' onto %s socket destined for %s\n", ast_str_buffer(data), get_transport_pvt(p), ast_sockaddr_stringify(dst));
03701 
03702    if (sip_prepare_socket(p) < 0) {
03703       return XMIT_ERROR;
03704    }
03705 
03706    if (p->socket.type == AST_TRANSPORT_UDP) {
03707       res = ast_sendto(p->socket.fd, ast_str_buffer(data), ast_str_strlen(data), 0, dst);
03708    } else if (p->socket.tcptls_session) {
03709       res = sip_tcptls_write(p->socket.tcptls_session, ast_str_buffer(data), ast_str_strlen(data));
03710    } else if (p->socket.ws_session) {
03711       if (!(res = ast_websocket_write(p->socket.ws_session, AST_WEBSOCKET_OPCODE_TEXT, ast_str_buffer(data), ast_str_strlen(data)))) {
03712          /* The WebSocket API just returns 0 on success and -1 on failure, while this code expects the payload length to be returned */
03713          res = ast_str_strlen(data);
03714       }
03715    } else {
03716       ast_debug(2, "Socket type is TCP but no tcptls_session is present to write to\n");
03717       return XMIT_ERROR;
03718    }
03719 
03720    if (res == -1) {
03721       switch (errno) {
03722       case EBADF:    /* Bad file descriptor - seems like this is generated when the host exist, but doesn't accept the UDP packet */
03723       case EHOSTUNREACH:   /* Host can't be reached */
03724       case ENETDOWN:    /* Interface down */
03725       case ENETUNREACH: /* Network failure */
03726       case ECONNREFUSED:      /* ICMP port unreachable */
03727          res = XMIT_ERROR; /* Don't bother with trying to transmit again */
03728       }
03729    }
03730    if (res != ast_str_strlen(data)) {
03731       ast_log(LOG_WARNING, "sip_xmit of %p (len %zu) to %s returned %d: %s\n", data, ast_str_strlen(data), ast_sockaddr_stringify(dst), res, strerror(errno));
03732    }
03733 
03734    return res;
03735 }

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 12013 of file chan_sip.c.

References add_cc_call_info_to_response(), add_diversion(), add_header(), add_rpid(), ast_cause2str(), ast_channel_hangupcause(), ast_clear_flag, ast_log, ast_test_flag, buf, sip_pvt::flags, hangup_sip2cause(), sip_pvt::hangupcause, LOG_WARNING, sip_pvt::method, sip_pvt::owner, respprep(), send_response(), sip_get_header(), SIP_INVITE, SIP_OFFER_CC, SIP_PAGE2_CONNECTLINEUPDATE_PEND, SIP_PAGE2_Q850_REASON, and SIP_SENDRPID.

Referenced by transmit_fake_auth_response(), transmit_response(), transmit_response_reliable(), and transmit_response_using_temp().

12014 {
12015    struct sip_request resp;
12016    uint32_t seqno = 0;
12017 
12018    if (reliable && (sscanf(sip_get_header(req, "CSeq"), "%30u ", &seqno) != 1)) {
12019       ast_log(LOG_WARNING, "Unable to determine sequence number from '%s'\n", sip_get_header(req, "CSeq"));
12020       return -1;
12021    }
12022    respprep(&resp, p, msg, req);
12023 
12024    if (ast_test_flag(&p->flags[0], SIP_SENDRPID)
12025          && ast_test_flag(&p->flags[1], SIP_PAGE2_CONNECTLINEUPDATE_PEND)
12026          && (!strncmp(msg, "180", 3) || !strncmp(msg, "183", 3))) {
12027       ast_clear_flag(&p->flags[1], SIP_PAGE2_CONNECTLINEUPDATE_PEND);
12028       add_rpid(&resp, p);
12029    }
12030    if (ast_test_flag(&p->flags[0], SIP_OFFER_CC)) {
12031       add_cc_call_info_to_response(p, &resp);
12032    }
12033 
12034    /* If we are sending a 302 Redirect we can add a diversion header if the redirect information is set */
12035    if (!strncmp(msg, "302", 3)) {
12036       add_diversion(&resp, p);
12037    }
12038 
12039    /* If we are cancelling an incoming invite for some reason, add information
12040       about the reason why we are doing this in clear text */
12041    if (p->method == SIP_INVITE && msg[0] != '1') {
12042       char buf[20];
12043 
12044       if (ast_test_flag(&p->flags[1], SIP_PAGE2_Q850_REASON)) {
12045          int hangupcause = 0;
12046 
12047          if (p->owner && ast_channel_hangupcause(p->owner)) {
12048             hangupcause = ast_channel_hangupcause(p->owner);
12049          } else if (p->hangupcause) {
12050             hangupcause = p->hangupcause;
12051          } else {
12052             int respcode;
12053             if (sscanf(msg, "%30d ", &respcode))
12054                hangupcause = hangup_sip2cause(respcode);
12055          }
12056 
12057          if (hangupcause) {
12058             sprintf(buf, "Q.850;cause=%i", hangupcause & 0x7f);
12059             add_header(&resp, "Reason", buf);
12060          }
12061       }
12062 
12063       if (p->owner && ast_channel_hangupcause(p->owner)) {
12064          add_header(&resp, "X-Asterisk-HangupCause", ast_cause2str(ast_channel_hangupcause(p->owner)));
12065          snprintf(buf, sizeof(buf), "%d", ast_channel_hangupcause(p->owner));
12066          add_header(&resp, "X-Asterisk-HangupCauseCode", buf);
12067       }
12068    }
12069    return send_response(p, &resp, reliable, seqno);
12070 }

static void __unreg_module ( void   )  [static]

Definition at line 34761 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 20155 of file chan_sip.c.

References ast_cli(), astman_get_header(), astman_send_ack(), astman_send_error(), CLI_SHOWUSAGE, CLI_SUCCESS, FALSE, FINDPEERS, NULL, publish_qualify_peer_done(), sip_find_peer(), sip_poke_peer(), sip_unref_peer, and TRUE.

Referenced by manager_sip_qualify_peer(), and sip_qualify_peer().

20156 {
20157    struct sip_peer *peer;
20158    int load_realtime;
20159 
20160    if (argc < 4)
20161       return CLI_SHOWUSAGE;
20162 
20163    load_realtime = (argc == 5 && !strcmp(argv[4], "load")) ? TRUE : FALSE;
20164    if ((peer = sip_find_peer(argv[3], NULL, load_realtime, FINDPEERS, FALSE, 0))) {
20165       const char *id = astman_get_header(m,"ActionID");
20166 
20167       if (type != 0) {
20168          astman_send_ack(s, m, "SIP peer found - will qualify");
20169       }
20170 
20171       sip_poke_peer(peer, 1);
20172 
20173       publish_qualify_peer_done(id, argv[3]);
20174 
20175       sip_unref_peer(peer, "qualify: done with peer");
20176    } else if (type == 0) {
20177       ast_cli(fd, "Peer '%s' not found\n", argv[3]);
20178    } else {
20179       astman_send_error(s, m, "Peer not found");
20180    }
20181 
20182    return CLI_SUCCESS;
20183 }

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 20247 of file chan_sip.c.

References sip_peer::accountcode, sip_peer::acl, sip_peer::addr, allowoverlap2str(), sip_peer::allowtransfer, sip_peer::amaflags, ao2_lock, ao2_t_ref, ao2_unlock, ARRAY_LEN, ast_acl_list_is_empty(), ast_callerid_merge(), ast_channel_amaflags2string(), ast_check_realtime(), ast_cli(), AST_CLI_YESNO, ast_describe_caller_presentation(), ast_format_cap_get_names(), ast_free, AST_LIST_TRAVERSE, ast_print_group(), ast_print_namedgroups(), ast_sched_when(), ast_sockaddr_port, ast_sockaddr_stringify(), ast_sockaddr_stringify_addr(), ast_str_alloca, ast_str_buffer(), ast_str_reset(), 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::caps, sip_peer::chanvars, sip_peer::cid_name, sip_peer::cid_num, CLI_SHOWUSAGE, CLI_SUCCESS, comedia_string(), sip_peer::context, sip_peer::defaddr, sip_peer::description, sip_peer::directmediaacl, dtmfmode2str(), sip_peer::engine, sip_peer::expire, FALSE, faxec2str(), FINDPEERS, sip_peer::flags, sip_proxy::force, force_rport_string(), sip_peer::fromdomain, sip_peer::fromdomainport, sip_peer::fromuser, sip_peer::fullcontact, get_transport_list(), sip_peer::host_dynamic, cfsip_options::id, insecure2str(), sip_peer::is_realtime, sip_peer::keepalive, sip_peer::language, sip_peer::lastmsgssent, sip_auth_container::list, sip_peer::maxcallbitrate, sip_peer::maxforwards, sip_auth::md5secret, sip_peer::md5secret, sip_peer::mohsuggest, ast_variable::name, sip_proxy::name, sip_peer::name, sip_peer::named_callgroups, sip_peer::named_pickupgroups, ast_variable::next, NULL, sip_peer::outboundproxy, sip_peer::parkinglot, sip_peer::path, peer_mailboxes_to_str(), peer_status(), sip_peer::pickupgroup, print_group(), print_named_groups(), sip_peer::qualifyfreq, sip_auth::realm, sip_peer::record_off_feature, sip_peer::record_on_feature, sip_settings::regcontext, sip_peer::regexten, sip_peer::remotesecret, S_OR, sip_auth::secret, sip_peer::secret, sip_cfg, SIP_DIRECT_MEDIA, SIP_DTMF, sip_find_peer(), sip_get_transport(), SIP_INSECURE, SIP_NAT_FORCE_RPORT, sip_options, SIP_PAGE2_ALLOWOVERLAP, SIP_PAGE2_ALLOWSUBSCRIBE, SIP_PAGE2_IGNORESDPVERSION, SIP_PAGE2_Q850_REASON, SIP_PAGE2_SYMMETRICRTP, SIP_PAGE2_T38SUPPORT, SIP_PAGE2_TEXTSUPPORT, SIP_PAGE2_TRUST_ID_OUTBOUND, SIP_PAGE2_USE_SRTP, SIP_PAGE2_VIDEOSUPPORT, SIP_PAGE2_VIDEOSUPPORT_ALWAYS, SIP_PAGE3_NAT_AUTO_COMEDIA, SIP_PAGE3_NAT_AUTO_RPORT, SIP_PROMISCREDIR, sip_route_list(), SIP_SENDRPID, SIP_TRUSTRPID, sip_unref_peer, SIP_USEPATH, 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, STANDARD_SIP_PORT, status, sip_peer::stimer, stmode2str(), strefresherparam2str(), sip_peer::subscribecontext, sip_peer::t38_maxdatagram, text, sip_peer::timer_b, sip_peer::timer_t1, sip_peer::tohost, transfermode2str(), sip_peer::transports, TRUE, trust_id_outbound2str(), sip_socket::type, sip_peer::useragent, sip_peer::username, sip_auth::username, ast_variable::value, sip_peer::vmexten, and sip_peer::zone.

Referenced by manager_sip_show_peer(), and sip_show_peer().

20248 {
20249    char status[30] = "";
20250    char cbuf[256];
20251    struct sip_peer *peer;
20252    struct ast_str *codec_buf = ast_str_alloca(64);
20253    struct ast_variable *v;
20254    int x = 0, load_realtime;
20255    int realtimepeers;
20256 
20257    realtimepeers = ast_check_realtime("sippeers");
20258 
20259    if (argc < 4)
20260       return CLI_SHOWUSAGE;
20261 
20262    load_realtime = (argc == 5 && !strcmp(argv[4], "load")) ? TRUE : FALSE;
20263    peer = sip_find_peer(argv[3], NULL, load_realtime, FINDPEERS, FALSE, 0);
20264 
20265    if (s) {    /* Manager */
20266       if (peer) {
20267          const char *id = astman_get_header(m, "ActionID");
20268 
20269          astman_append(s, "Response: Success\r\n");
20270          if (!ast_strlen_zero(id))
20271             astman_append(s, "ActionID: %s\r\n", id);
20272       } else {
20273          snprintf (cbuf, sizeof(cbuf), "Peer %s not found.", argv[3]);
20274          astman_send_error(s, m, cbuf);
20275          return CLI_SUCCESS;
20276       }
20277    }
20278    if (peer && type==0 ) { /* Normal listing */
20279       struct ast_str *mailbox_str = ast_str_alloca(512);
20280       struct ast_str *path;
20281       struct sip_auth_container *credentials;
20282 
20283       ao2_lock(peer);
20284       credentials = peer->auth;
20285       if (credentials) {
20286          ao2_t_ref(credentials, +1, "Ref peer auth for show");
20287       }
20288       ao2_unlock(peer);
20289 
20290       ast_cli(fd, "\n\n");
20291       ast_cli(fd, "  * Name       : %s\n", peer->name);
20292       ast_cli(fd, "  Description  : %s\n", peer->description);
20293       if (realtimepeers) { /* Realtime is enabled */
20294          ast_cli(fd, "  Realtime peer: %s\n", peer->is_realtime ? "Yes, cached" : "No");
20295       }
20296       ast_cli(fd, "  Secret       : %s\n", ast_strlen_zero(peer->secret)?"<Not set>":"<Set>");
20297       ast_cli(fd, "  MD5Secret    : %s\n", ast_strlen_zero(peer->md5secret)?"<Not set>":"<Set>");
20298       ast_cli(fd, "  Remote Secret: %s\n", ast_strlen_zero(peer->remotesecret)?"<Not set>":"<Set>");
20299       if (credentials) {
20300          struct sip_auth *auth;
20301 
20302          AST_LIST_TRAVERSE(&credentials->list, auth, node) {
20303             ast_cli(fd, "  Realm-auth   : Realm %-15.15s User %-10.20s %s\n",
20304                auth->realm,
20305                auth->username,
20306                !ast_strlen_zero(auth->secret)
20307                   ? "<Secret set>"
20308                   : (!ast_strlen_zero(auth->md5secret)
20309                      ? "<MD5secret set>" : "<Not set>"));
20310          }
20311          ao2_t_ref(credentials, -1, "Unref peer auth for show");
20312       }
20313       ast_cli(fd, "  Context      : %s\n", peer->context);
20314       ast_cli(fd, "  Record On feature : %s\n", peer->record_on_feature);
20315       ast_cli(fd, "  Record Off feature : %s\n", peer->record_off_feature);
20316       ast_cli(fd, "  Subscr.Cont. : %s\n", S_OR(peer->subscribecontext, "<Not set>") );
20317       ast_cli(fd, "  Language     : %s\n", peer->language);
20318       ast_cli(fd, "  Tonezone     : %s\n", peer->zone[0] != '\0' ? peer->zone : "<Not set>");
20319       if (!ast_strlen_zero(peer->accountcode))
20320          ast_cli(fd, "  Accountcode  : %s\n", peer->accountcode);
20321       ast_cli(fd, "  AMA flags    : %s\n", ast_channel_amaflags2string(peer->amaflags));
20322       ast_cli(fd, "  Transfer mode: %s\n", transfermode2str(peer->allowtransfer));
20323       ast_cli(fd, "  CallingPres  : %s\n", ast_describe_caller_presentation(peer->callingpres));
20324       if (!ast_strlen_zero(peer->fromuser))
20325          ast_cli(fd, "  FromUser     : %s\n", peer->fromuser);
20326       if (!ast_strlen_zero(peer->fromdomain))
20327          ast_cli(fd, "  FromDomain   : %s Port %d\n", peer->fromdomain, (peer->fromdomainport) ? peer->fromdomainport : STANDARD_SIP_PORT);
20328       ast_cli(fd, "  Callgroup    : ");
20329       print_group(fd, peer->callgroup, 0);
20330       ast_cli(fd, "  Pickupgroup  : ");
20331       print_group(fd, peer->pickupgroup, 0);
20332       ast_cli(fd, "  Named Callgr : ");
20333       print_named_groups(fd, peer->named_callgroups, 0);
20334       ast_cli(fd, "  Nam. Pickupgr: ");
20335       print_named_groups(fd, peer->named_pickupgroups, 0);
20336       peer_mailboxes_to_str(&mailbox_str, peer);
20337       ast_cli(fd, "  MOH Suggest  : %s\n", peer->mohsuggest);
20338       ast_cli(fd, "  Mailbox      : %s\n", ast_str_buffer(mailbox_str));
20339       ast_cli(fd, "  VM Extension : %s\n", peer->vmexten);
20340       ast_cli(fd, "  LastMsgsSent : %d/%d\n", (peer->lastmsgssent & 0x7fff0000) >> 16, peer->lastmsgssent & 0xffff);
20341       ast_cli(fd, "  Call limit   : %d\n", peer->call_limit);
20342       ast_cli(fd, "  Max forwards : %d\n", peer->maxforwards);
20343       if (peer->busy_level)
20344          ast_cli(fd, "  Busy level   : %d\n", peer->busy_level);
20345       ast_cli(fd, "  Dynamic      : %s\n", AST_CLI_YESNO(peer->host_dynamic));
20346       ast_cli(fd, "  Callerid     : %s\n", ast_callerid_merge(cbuf, sizeof(cbuf), peer->cid_name, peer->cid_num, "<unspecified>"));
20347       ast_cli(fd, "  MaxCallBR    : %d kbps\n", peer->maxcallbitrate);
20348       ast_cli(fd, "  Expire       : %ld\n", ast_sched_when(sched, peer->expire));
20349       ast_cli(fd, "  Insecure     : %s\n", insecure2str(ast_test_flag(&peer->flags[0], SIP_INSECURE)));
20350       ast_cli(fd, "  Force rport  : %s\n", force_rport_string(peer->flags));
20351       ast_cli(fd, "  Symmetric RTP: %s\n", comedia_string(peer->flags));
20352       ast_cli(fd, "  ACL          : %s\n", AST_CLI_YESNO(ast_acl_list_is_empty(peer->acl) == 0));
20353       ast_cli(fd, "  DirectMedACL : %s\n", AST_CLI_YESNO(ast_acl_list_is_empty(peer->directmediaacl) == 0));
20354       ast_cli(fd, "  T.38 support : %s\n", AST_CLI_YESNO(ast_test_flag(&peer->flags[1], SIP_PAGE2_T38SUPPORT)));
20355       ast_cli(fd, "  T.38 EC mode : %s\n", faxec2str(ast_test_flag(&peer->flags[1], SIP_PAGE2_T38SUPPORT)));
20356       ast_cli(fd, "  T.38 MaxDtgrm: %u\n", peer->t38_maxdatagram);
20357       ast_cli(fd, "  DirectMedia  : %s\n", AST_CLI_YESNO(ast_test_flag(&peer->flags[0], SIP_DIRECT_MEDIA)));
20358       ast_cli(fd, "  PromiscRedir : %s\n", AST_CLI_YESNO(ast_test_flag(&peer->flags[0], SIP_PROMISCREDIR)));
20359       ast_cli(fd, "  User=Phone   : %s\n", AST_CLI_YESNO(ast_test_flag(&peer->flags[0], SIP_USEREQPHONE)));
20360       ast_cli(fd, "  Video Support: %s\n", AST_CLI_YESNO(ast_test_flag(&peer->flags[1], SIP_PAGE2_VIDEOSUPPORT) || ast_test_flag(&peer->flags[1], SIP_PAGE2_VIDEOSUPPORT_ALWAYS)));
20361       ast_cli(fd, "  Text Support : %s\n", AST_CLI_YESNO(ast_test_flag(&peer->flags[1], SIP_PAGE2_TEXTSUPPORT)));
20362       ast_cli(fd, "  Ign SDP ver  : %s\n", AST_CLI_YESNO(ast_test_flag(&peer->flags[1], SIP_PAGE2_IGNORESDPVERSION)));
20363       ast_cli(fd, "  Trust RPID   : %s\n", AST_CLI_YESNO(ast_test_flag(&peer->flags[0], SIP_TRUSTRPID)));
20364       ast_cli(fd, "  Send RPID    : %s\n", AST_CLI_YESNO(ast_test_flag(&peer->flags[0], SIP_SENDRPID)));
20365       ast_cli(fd, "  Path support : %s\n", AST_CLI_YESNO(ast_test_flag(&peer->flags[0], SIP_USEPATH)));
20366       if ((path = sip_route_list(&peer->path, 1, 0))) {
20367          ast_cli(fd, "  Path         : %s\n", ast_str_buffer(path));
20368          ast_free(path);
20369       }
20370       ast_cli(fd, "  TrustIDOutbnd: %s\n", trust_id_outbound2str(ast_test_flag(&peer->flags[1], SIP_PAGE2_TRUST_ID_OUTBOUND)));
20371       ast_cli(fd, "  Subscriptions: %s\n", AST_CLI_YESNO(ast_test_flag(&peer->flags[1], SIP_PAGE2_ALLOWSUBSCRIBE)));
20372       ast_cli(fd, "  Overlap dial : %s\n", allowoverlap2str(ast_test_flag(&peer->flags[1], SIP_PAGE2_ALLOWOVERLAP)));
20373       if (peer->outboundproxy)
20374          ast_cli(fd, "  Outb. proxy  : %s %s\n", ast_strlen_zero(peer->outboundproxy->name) ? "<not set>" : peer->outboundproxy->name,
20375                      peer->outboundproxy->force ? "(forced)" : "");
20376 
20377       /* - is enumerated */
20378       ast_cli(fd, "  DTMFmode     : %s\n", dtmfmode2str(ast_test_flag(&peer->flags[0], SIP_DTMF)));
20379       ast_cli(fd, "  Timer T1     : %d\n", peer->timer_t1);
20380       ast_cli(fd, "  Timer B      : %d\n", peer->timer_b);
20381       ast_cli(fd, "  ToHost       : %s\n", peer->tohost);
20382       ast_cli(fd, "  Addr->IP     : %s\n", ast_sockaddr_stringify(&peer->addr));
20383       ast_cli(fd, "  Defaddr->IP  : %s\n", ast_sockaddr_stringify(&peer->defaddr));
20384       ast_cli(fd, "  Prim.Transp. : %s\n", sip_get_transport(peer->socket.type));
20385       ast_cli(fd, "  Allowed.Trsp : %s\n", get_transport_list(peer->transports));
20386       if (!ast_strlen_zero(sip_cfg.regcontext))
20387          ast_cli(fd, "  Reg. exten   : %s\n", peer->regexten);
20388       ast_cli(fd, "  Def. Username: %s\n", peer->username);
20389       ast_cli(fd, "  SIP Options  : ");
20390       if (peer->sipoptions) {
20391          int lastoption = -1;
20392          for (x = 0 ; x < ARRAY_LEN(sip_options); x++) {
20393             if (sip_options[x].id != lastoption) {
20394                if (peer->sipoptions & sip_options[x].id)
20395                   ast_cli(fd, "%s ", sip_options[x].text);
20396                lastoption = x;
20397             }
20398          }
20399       } else
20400          ast_cli(fd, "(none)");
20401 
20402       ast_cli(fd, "\n");
20403       ast_cli(fd, "  Codecs       : %s\n", ast_format_cap_get_names(peer->caps, &codec_buf));
20404 
20405       ast_cli(fd, "  Auto-Framing : %s\n", AST_CLI_YESNO(peer->autoframing));
20406       ast_cli(fd, "  Status       : ");
20407       peer_status(peer, status, sizeof(status));
20408       ast_cli(fd, "%s\n", status);
20409       ast_cli(fd, "  Useragent    : %s\n", peer->useragent);
20410       ast_cli(fd, "  Reg. Contact : %s\n", peer->fullcontact);
20411       ast_cli(fd, "  Qualify Freq : %d ms\n", peer->qualifyfreq);
20412       ast_cli(fd, "  Keepalive    : %d ms\n", peer->keepalive * 1000);
20413       if (peer->chanvars) {
20414          ast_cli(fd, "  Variables    :\n");
20415          for (v = peer->chanvars ; v ; v = v->next)
20416             ast_cli(fd, "                 %s = %s\n", v->name, v->value);
20417       }
20418 
20419       ast_cli(fd, "  Sess-Timers  : %s\n", stmode2str(peer->stimer.st_mode_oper));
20420       ast_cli(fd, "  Sess-Refresh : %s\n", strefresherparam2str(peer->stimer.st_ref));
20421       ast_cli(fd, "  Sess-Expires : %d secs\n", peer->stimer.st_max_se);
20422       ast_cli(fd, "  Min-Sess     : %d secs\n", peer->stimer.st_min_se);
20423       ast_cli(fd, "  RTP Engine   : %s\n", peer->engine);
20424       ast_cli(fd, "  Parkinglot   : %s\n", peer->parkinglot);
20425       ast_cli(fd, "  Use Reason   : %s\n", AST_CLI_YESNO(ast_test_flag(&peer->flags[1], SIP_PAGE2_Q850_REASON)));
20426       ast_cli(fd, "  Encryption   : %s\n", AST_CLI_YESNO(ast_test_flag(&peer->flags[1], SIP_PAGE2_USE_SRTP)));
20427       ast_cli(fd, "\n");
20428       peer = sip_unref_peer(peer, "sip_show_peer: sip_unref_peer: done with peer ptr");
20429    } else  if (peer && type == 1) { /* manager listing */
20430       char buffer[256];
20431       struct ast_str *tmp_str = ast_str_alloca(512);
20432       astman_append(s, "Channeltype: SIP\r\n");
20433       astman_append(s, "ObjectName: %s\r\n", peer->name);
20434       astman_append(s, "ChanObjectType: peer\r\n");
20435       astman_append(s, "SecretExist: %s\r\n", ast_strlen_zero(peer->secret)?"N":"Y");
20436       astman_append(s, "RemoteSecretExist: %s\r\n", ast_strlen_zero(peer->remotesecret)?"N":"Y");
20437       astman_append(s, "MD5SecretExist: %s\r\n", ast_strlen_zero(peer->md5secret)?"N":"Y");
20438       astman_append(s, "Context: %s\r\n", peer->context);
20439       if (!ast_strlen_zero(peer->subscribecontext)) {
20440          astman_append(s, "SubscribeContext: %s\r\n", peer->subscribecontext);
20441       }
20442       astman_append(s, "Language: %s\r\n", peer->language);
20443       astman_append(s, "ToneZone: %s\r\n", peer->zone[0] != '\0' ? peer->zone : "<Not set>");
20444       if (!ast_strlen_zero(peer->accountcode))
20445          astman_append(s, "Accountcode: %s\r\n", peer->accountcode);
20446       astman_append(s, "AMAflags: %s\r\n", ast_channel_amaflags2string(peer->amaflags));
20447       astman_append(s, "CID-CallingPres: %s\r\n", ast_describe_caller_presentation(peer->callingpres));
20448       if (!ast_strlen_zero(peer->fromuser))
20449          astman_append(s, "SIP-FromUser: %s\r\n", peer->fromuser);
20450       if (!ast_strlen_zero(peer->fromdomain))
20451          astman_append(s, "SIP-FromDomain: %s\r\nSip-FromDomain-Port: %d\r\n", peer->fromdomain, (peer->fromdomainport) ? peer->fromdomainport : STANDARD_SIP_PORT);
20452       astman_append(s, "Callgroup: ");
20453       astman_append(s, "%s\r\n", ast_print_group(buffer, sizeof(buffer), peer->callgroup));
20454       astman_append(s, "Pickupgroup: ");
20455       astman_append(s, "%s\r\n", ast_print_group(buffer, sizeof(buffer), peer->pickupgroup));
20456       astman_append(s, "Named Callgroup: ");
20457       astman_append(s, "%s\r\n", ast_print_namedgroups(&tmp_str, peer->named_callgroups));
20458       ast_str_reset(tmp_str);
20459       astman_append(s, "Named Pickupgroup: ");
20460       astman_append(s, "%s\r\n", ast_print_namedgroups(&tmp_str, peer->named_pickupgroups));
20461       ast_str_reset(tmp_str);
20462       astman_append(s, "MOHSuggest: %s\r\n", peer->mohsuggest);
20463       peer_mailboxes_to_str(&tmp_str, peer);
20464       astman_append(s, "VoiceMailbox: %s\r\n", ast_str_buffer(tmp_str));
20465       astman_append(s, "TransferMode: %s\r\n", transfermode2str(peer->allowtransfer));
20466       astman_append(s, "LastMsgsSent: %d\r\n", peer->lastmsgssent);
20467       astman_append(s, "Maxforwards: %d\r\n", peer->maxforwards);
20468       astman_append(s, "Call-limit: %d\r\n", peer->call_limit);
20469       astman_append(s, "Busy-level: %d\r\n", peer->busy_level);
20470       astman_append(s, "MaxCallBR: %d kbps\r\n", peer->maxcallbitrate);
20471       astman_append(s, "Dynamic: %s\r\n", peer->host_dynamic?"Y":"N");
20472       astman_append(s, "Callerid: %s\r\n", ast_callerid_merge(cbuf, sizeof(cbuf), peer->cid_name, peer->cid_num, ""));
20473       astman_append(s, "RegExpire: %ld seconds\r\n", ast_sched_when(sched, peer->expire));
20474       astman_append(s, "SIP-AuthInsecure: %s\r\n", insecure2str(ast_test_flag(&peer->flags[0], SIP_INSECURE)));
20475       astman_append(s, "SIP-Forcerport: %s\r\n", ast_test_flag(&peer->flags[2], SIP_PAGE3_NAT_AUTO_RPORT) ?
20476             (ast_test_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT) ? "A" : "a") :
20477             (ast_test_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT) ? "Y" : "N"));
20478       astman_append(s, "SIP-Comedia: %s\r\n", ast_test_flag(&peer->flags[2], SIP_PAGE3_NAT_AUTO_COMEDIA) ?
20479             (ast_test_flag(&peer->flags[1], SIP_PAGE2_SYMMETRICRTP) ? "A" : "a") :
20480             (ast_test_flag(&peer->flags[1], SIP_PAGE2_SYMMETRICRTP) ? "Y" : "N"));
20481       astman_append(s, "ACL: %s\r\n", (ast_acl_list_is_empty(peer->acl) ? "N" : "Y"));
20482       astman_append(s, "SIP-CanReinvite: %s\r\n", (ast_test_flag(&peer->flags[0], SIP_DIRECT_MEDIA)?"Y":"N"));
20483       astman_append(s, "SIP-DirectMedia: %s\r\n", (ast_test_flag(&peer->flags[0], SIP_DIRECT_MEDIA)?"Y":"N"));
20484       astman_append(s, "SIP-PromiscRedir: %s\r\n", (ast_test_flag(&peer->flags[0], SIP_PROMISCREDIR)?"Y":"N"));
20485       astman_append(s, "SIP-UserPhone: %s\r\n", (ast_test_flag(&peer->flags[0], SIP_USEREQPHONE)?"Y":"N"));
20486       astman_append(s, "SIP-VideoSupport: %s\r\n", (ast_test_flag(&peer->flags[1], SIP_PAGE2_VIDEOSUPPORT)?"Y":"N"));
20487       astman_append(s, "SIP-TextSupport: %s\r\n", (ast_test_flag(&peer->flags[1], SIP_PAGE2_TEXTSUPPORT)?"Y":"N"));
20488       astman_append(s, "SIP-T.38Support: %s\r\n", (ast_test_flag(&peer->flags[1], SIP_PAGE2_T38SUPPORT)?"Y":"N"));
20489       astman_append(s, "SIP-T.38EC: %s\r\n", faxec2str(ast_test_flag(&peer->flags[1], SIP_PAGE2_T38SUPPORT)));
20490       astman_append(s, "SIP-T.38MaxDtgrm: %u\r\n", peer->t38_maxdatagram);
20491       astman_append(s, "SIP-Sess-Timers: %s\r\n", stmode2str(peer->stimer.st_mode_oper));
20492       astman_append(s, "SIP-Sess-Refresh: %s\r\n", strefresherparam2str(peer->stimer.st_ref));
20493       astman_append(s, "SIP-Sess-Expires: %d\r\n", peer->stimer.st_max_se);
20494       astman_append(s, "SIP-Sess-Min: %d\r\n", peer->stimer.st_min_se);
20495       astman_append(s, "SIP-RTP-Engine: %s\r\n", peer->engine);
20496       astman_append(s, "SIP-Encryption: %s\r\n", ast_test_flag(&peer->flags[1], SIP_PAGE2_USE_SRTP) ? "Y" : "N");
20497 
20498       /* - is enumerated */
20499       astman_append(s, "SIP-DTMFmode: %s\r\n", dtmfmode2str(ast_test_flag(&peer->flags[0], SIP_DTMF)));
20500       astman_append(s, "ToHost: %s\r\n", peer->tohost);
20501       astman_append(s, "Address-IP: %s\r\nAddress-Port: %d\r\n", ast_sockaddr_stringify_addr(&peer->addr), ast_sockaddr_port(&peer->addr));
20502       astman_append(s, "Default-addr-IP: %s\r\nDefault-addr-port: %d\r\n", ast_sockaddr_stringify_addr(&peer->defaddr), ast_sockaddr_port(&peer->defaddr));
20503       astman_append(s, "Default-Username: %s\r\n", peer->username);
20504       if (!ast_strlen_zero(sip_cfg.regcontext))
20505          astman_append(s, "RegExtension: %s\r\n", peer->regexten);
20506       astman_append(s, "Codecs: %s\r\n", ast_format_cap_get_names(peer->caps, &codec_buf));
20507       astman_append(s, "Status: ");
20508       peer_status(peer, status, sizeof(status));
20509       astman_append(s, "%s\r\n", status);
20510       astman_append(s, "SIP-Useragent: %s\r\n", peer->useragent);
20511       astman_append(s, "Reg-Contact: %s\r\n", peer->fullcontact);
20512       astman_append(s, "QualifyFreq: %d ms\r\n", peer->qualifyfreq);
20513       astman_append(s, "Parkinglot: %s\r\n", peer->parkinglot);
20514       if (peer->chanvars) {
20515          for (v = peer->chanvars ; v ; v = v->next) {
20516             astman_append(s, "ChanVariable: %s=%s\r\n", v->name, v->value);
20517          }
20518       }
20519       astman_append(s, "SIP-Use-Reason-Header: %s\r\n", (ast_test_flag(&peer->flags[1], SIP_PAGE2_Q850_REASON)) ? "Y" : "N");
20520       astman_append(s, "Description: %s\r\n", peer->description);
20521 
20522       peer = sip_unref_peer(peer, "sip_show_peer: sip_unref_peer: done with peer");
20523 
20524    } else {
20525       ast_cli(fd, "Peer %s not found.\n", argv[3]);
20526       ast_cli(fd, "\n");
20527    }
20528 
20529    return CLI_SUCCESS;
20530 }

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 19373 of file chan_sip.c.

References _sip_show_peers_one(), ao2_callback, ao2_container_count(), ao2_iterator_destroy(), ao2_lock, ao2_t_iterator_next, ao2_unlock, ast_calloc, ast_check_realtime(), ast_cli(), ast_free, ast_log, AST_LOG_ERROR, ast_strlen_zero, astman_get_header(), CLI_FAILURE, CLI_SHOWUSAGE, CLI_SUCCESS, FALSE, show_peers_context::havepattern, id, show_peers_context::idtext, sip_peer::name, NULL, OBJ_MULTIPLE, peercomparefunc(), PEERS_FORMAT2, show_peers_context::peers_mon_offline, show_peers_context::peers_mon_online, show_peers_context::peers_unmon_offline, show_peers_context::peers_unmon_online, show_peers_context::realtimepeers, show_peers_context::regexbuf, SIP_TYPE_PEER, sip_unref_peer, TRUE, and sip_peer::type.

Referenced by manager_sip_show_peers(), and sip_show_peers().

19374 {
19375    struct show_peers_context cont = {
19376       .havepattern = FALSE,
19377       .idtext = "",
19378 
19379       .peers_mon_online = 0,
19380       .peers_mon_offline = 0,
19381       .peers_unmon_online = 0,
19382       .peers_unmon_offline = 0,
19383    };
19384 
19385    struct sip_peer *peer;
19386    struct ao2_iterator* it_peers;
19387 
19388    int total_peers = 0;
19389    const char *id;
19390    struct sip_peer **peerarray;
19391    int k;
19392 
19393    cont.realtimepeers = ast_check_realtime("sippeers");
19394 
19395    if (s) { /* Manager - get ActionID */
19396       id = astman_get_header(m, "ActionID");
19397       if (!ast_strlen_zero(id)) {
19398          snprintf(cont.idtext, sizeof(cont.idtext), "ActionID: %s\r\n", id);
19399       }
19400    }
19401 
19402    switch (argc) {
19403    case 5:
19404       if (!strcasecmp(argv[3], "like")) {
19405          if (regcomp(&cont.regexbuf, argv[4], REG_EXTENDED | REG_NOSUB)) {
19406             return CLI_SHOWUSAGE;
19407          }
19408          cont.havepattern = TRUE;
19409       } else {
19410          return CLI_SHOWUSAGE;
19411       }
19412    case 3:
19413       break;
19414    default:
19415       return CLI_SHOWUSAGE;
19416    }
19417 
19418    if (!s) {
19419       /* Normal list */
19420       ast_cli(fd, PEERS_FORMAT2, "Name/username", "Host", "Dyn", "Forcerport", "Comedia", "ACL", "Port", "Status", "Description", (cont.realtimepeers ? "Realtime" : ""));
19421    }
19422 
19423    ao2_lock(peers);
19424    if (!(it_peers = ao2_callback(peers, OBJ_MULTIPLE, NULL, NULL))) {
19425       ast_log(AST_LOG_ERROR, "Unable to create iterator for peers container for sip show peers\n");
19426       ao2_unlock(peers);
19427       return CLI_FAILURE;
19428    }
19429    if (!(peerarray = ast_calloc(sizeof(struct sip_peer *), ao2_container_count(peers)))) {
19430       ast_log(AST_LOG_ERROR, "Unable to allocate peer array for sip show peers\n");
19431       ao2_iterator_destroy(it_peers);
19432       ao2_unlock(peers);
19433       return CLI_FAILURE;
19434    }
19435    ao2_unlock(peers);
19436 
19437    while ((peer = ao2_t_iterator_next(it_peers, "iterate thru peers table"))) {
19438       ao2_lock(peer);
19439 
19440       if (!(peer->type & SIP_TYPE_PEER)) {
19441          ao2_unlock(peer);
19442          sip_unref_peer(peer, "unref peer because it's actually a user");
19443          continue;
19444       }
19445 
19446       if (cont.havepattern && regexec(&cont.regexbuf, peer->name, 0, NULL, 0)) {
19447          ao2_unlock(peer);
19448          sip_unref_peer(peer, "toss iterator peer ptr before continue");
19449          continue;
19450       }
19451 
19452       peerarray[total_peers++] = peer;
19453       ao2_unlock(peer);
19454    }
19455    ao2_iterator_destroy(it_peers);
19456 
19457    qsort(peerarray, total_peers, sizeof(struct sip_peer *), peercomparefunc);
19458 
19459    for(k = 0; k < total_peers; k++) {
19460       peerarray[k] = _sip_show_peers_one(fd, s, &cont, peerarray[k]);
19461    }
19462 
19463    if (!s) {
19464       ast_cli(fd, "%d sip peers [Monitored: %d online, %d offline Unmonitored: %d online, %d offline]\n",
19465               total_peers, cont.peers_mon_online, cont.peers_mon_offline, cont.peers_unmon_online, cont.peers_unmon_offline);
19466    }
19467 
19468    if (cont.havepattern) {
19469       regfree(&cont.regexbuf);
19470    }
19471 
19472    if (total) {
19473       *total = total_peers;
19474    }
19475 
19476    ast_free(peerarray);
19477 
19478    return CLI_SUCCESS;
19479 }

static struct sip_peer * _sip_show_peers_one ( int  fd,
struct mansession s,
struct show_peers_context cont,
struct sip_peer peer 
) [static, read]

Emit informations for one peer during sip show peers command.

Definition at line 19482 of file chan_sip.c.

References sip_peer::acl, sip_peer::addr, ao2_lock, ao2_unlock, ast_acl_list_is_empty(), ast_cli(), ast_copy_string(), ast_sockaddr_isnull(), ast_sockaddr_port, ast_sockaddr_stringify_addr(), ast_sockaddr_stringify_port(), ast_strdupa, ast_strlen_zero, ast_test_flag, astman_append(), comedia_string(), sip_peer::description, sip_peer::flags, force_rport_string(), show_peers_context::havepattern, sip_peer::host_dynamic, show_peers_context::idtext, sip_peer::is_realtime, sip_peer::name, name, NULL, peer_status(), PEERS_FORMAT2, show_peers_context::peers_mon_offline, show_peers_context::peers_mon_online, show_peers_context::peers_unmon_offline, show_peers_context::peers_unmon_online, show_peers_context::realtimepeers, show_peers_context::regexbuf, SIP_NAT_FORCE_RPORT, SIP_PAGE2_SYMMETRICRTP, SIP_PAGE2_TEXTSUPPORT, SIP_PAGE2_VIDEOSUPPORT, SIP_PAGE3_NAT_AUTO_COMEDIA, SIP_PAGE3_NAT_AUTO_RPORT, sip_unref_peer, status, and sip_peer::username.

Referenced by _sip_show_peers().

19483 {
19484    /* _sip_show_peers_one() is separated from _sip_show_peers() to properly free the ast_strdupa
19485     * (this is executed in a loop in _sip_show_peers() )
19486     */
19487 
19488    char name[256];
19489    char status[20] = "";
19490    char pstatus;
19491 
19492    /*
19493     * tmp_port and tmp_host store copies of ast_sockaddr_stringify strings since the
19494     * string pointers for that function aren't valid between subsequent calls to
19495     * ast_sockaddr_stringify functions
19496     */
19497    char *tmp_port;
19498    char *tmp_host;
19499 
19500    tmp_port = ast_sockaddr_isnull(&peer->addr) ?
19501       "0" : ast_strdupa(ast_sockaddr_stringify_port(&peer->addr));
19502 
19503    tmp_host = ast_sockaddr_isnull(&peer->addr) ?
19504       "(Unspecified)" : ast_strdupa(ast_sockaddr_stringify_addr(&peer->addr));
19505 
19506    ao2_lock(peer);
19507    if (cont->havepattern && regexec(&cont->regexbuf, peer->name, 0, NULL, 0)) {
19508       ao2_unlock(peer);
19509       return sip_unref_peer(peer, "toss iterator peer ptr no match");
19510    }
19511 
19512    if (!ast_strlen_zero(peer->username) && !s) {
19513       snprintf(name, sizeof(name), "%s/%s", peer->name, peer->username);
19514    } else {
19515       ast_copy_string(name, peer->name, sizeof(name));
19516    }
19517 
19518    pstatus = peer_status(peer, status, sizeof(status));
19519    if (pstatus == 1) {
19520       cont->peers_mon_online++;
19521    } else if (pstatus == 0) {
19522       cont->peers_mon_offline++;
19523    } else {
19524       if (ast_sockaddr_isnull(&peer->addr) ||
19525           !ast_sockaddr_port(&peer->addr)) {
19526          cont->peers_unmon_offline++;
19527       } else {
19528          cont->peers_unmon_online++;
19529       }
19530    }
19531 
19532    if (!s) { /* Normal CLI list */
19533       ast_cli(fd, PEERS_FORMAT2, name,
19534       tmp_host,
19535       peer->host_dynamic ? " D " : "   ", /* Dynamic or not? */
19536       force_rport_string(peer->flags),
19537       comedia_string(peer->flags),
19538       (!ast_acl_list_is_empty(peer->acl)) ? " A " : "   ",       /* permit/deny */
19539       tmp_port, status,
19540       peer->description ? peer->description : "",
19541       cont->realtimepeers ? (peer->is_realtime ? "Cached RT" : "") : "");
19542    } else { /* Manager format */
19543       /* The names here need to be the same as other channels */
19544       astman_append(s,
19545       "Event: PeerEntry\r\n%s"
19546       "Channeltype: SIP\r\n"
19547       "ObjectName: %s\r\n"
19548       "ChanObjectType: peer\r\n" /* "peer" or "user" */
19549       "IPaddress: %s\r\n"
19550       "IPport: %s\r\n"
19551       "Dynamic: %s\r\n"
19552       "AutoForcerport: %s\r\n"
19553       "Forcerport: %s\r\n"
19554       "AutoComedia: %s\r\n"
19555       "Comedia: %s\r\n"
19556       "VideoSupport: %s\r\n"
19557       "TextSupport: %s\r\n"
19558       "ACL: %s\r\n"
19559       "Status: %s\r\n"
19560       "RealtimeDevice: %s\r\n"
19561       "Description: %s\r\n\r\n",
19562       cont->idtext,
19563       peer->name,
19564       ast_sockaddr_isnull(&peer->addr) ? "-none-" : tmp_host,
19565       ast_sockaddr_isnull(&peer->addr) ? "0" : tmp_port,
19566       peer->host_dynamic ? "yes" : "no",  /* Dynamic or not? */
19567       ast_test_flag(&peer->flags[2], SIP_PAGE3_NAT_AUTO_RPORT) ? "yes" : "no",
19568       ast_test_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT) ? "yes" : "no",
19569       ast_test_flag(&peer->flags[2], SIP_PAGE3_NAT_AUTO_COMEDIA) ? "yes" : "no",
19570       ast_test_flag(&peer->flags[1], SIP_PAGE2_SYMMETRICRTP) ? "yes" : "no",
19571       ast_test_flag(&peer->flags[1], SIP_PAGE2_VIDEOSUPPORT) ? "yes" : "no",  /* VIDEOSUPPORT=yes? */
19572       ast_test_flag(&peer->flags[1], SIP_PAGE2_TEXTSUPPORT) ? "yes" : "no",   /* TEXTSUPPORT=yes? */
19573       ast_acl_list_is_empty(peer->acl) ? "no" : "yes",       /* permit/deny/acl */
19574       status,
19575       cont->realtimepeers ? (peer->is_realtime ? "yes" : "no") : "no",
19576       peer->description);
19577    }
19578    ao2_unlock(peer);
19579 
19580    return sip_unref_peer(peer, "toss iterator peer ptr");
19581 }

static void * _sip_tcp_helper_thread ( struct ast_tcptls_session_instance tcptls_session  )  [static]

SIP TCP thread management function This function reads from the socket, parses the packet into a request.

Definition at line 2913 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_atomic_fetchadd_int(), ast_debug, AST_LIST_REMOVE_HEAD, ast_log, ast_poll, ast_str_buffer(), ast_str_create(), ast_str_reset(), ast_str_strlen(), ast_tcptls_client_start(), ast_tcptls_close_session_file(), ast_tcptls_server_write(), ast_tcptls_stream_set_exclusive_input(), ast_tcptls_stream_set_timeout_disable(), ast_tcptls_stream_set_timeout_sequence(), AST_TRANSPORT_TCP, AST_TRANSPORT_TLS, ast_tvnow(), sip_request::authenticated, buf, cleanup(), ast_tcptls_session_instance::client, tcptls_packet::data, sip_request::data, deinit_req(), errno, sip_socket::fd, ast_tcptls_session_instance::fd, handle_request_do(), tcptls_packet::len, LOG_ERROR, LOG_WARNING, NULL, OBJ_POINTER, ast_tcptls_session_instance::overflow_buf, sip_threadinfo::packet_q, ast_tcptls_session_instance::parent, sip_socket::port, ast_tcptls_session_instance::remote_address, set_socket_transport(), sip_check_authtimeout(), SIP_MIN_PACKET, sip_tcptls_read(), sip_threadinfo_create(), sip_request::socket, ast_tcptls_session_instance::ssl, ast_tcptls_session_instance::stream_cookie, TCPTLS_ALERT_DATA, TCPTLS_ALERT_STOP, sip_socket::tcptls_session, sip_threadinfo::threadid, timeout, tmp(), and sip_socket::ws_session.

Referenced by sip_tcp_worker_fn().

02914 {
02915    int res, timeout = -1, authenticated = 0, flags;
02916    time_t start;
02917    struct sip_request req = { 0, } , reqcpy = { 0, };
02918    struct sip_threadinfo *me = NULL;
02919    char buf[1024] = "";
02920    struct pollfd fds[2] = { { 0 }, { 0 }, };
02921    struct ast_tcptls_session_args *ca = NULL;
02922 
02923    /* If this is a server session, then the connection has already been
02924     * setup. Check if the authlimit has been reached and if not create the
02925     * threadinfo object so we can access this thread for writing.
02926     *
02927     * if this is a client connection more work must be done.
02928     * 1. We own the parent session args for a client connection.  This pointer needs
02929     *    to be held on to so we can decrement it's ref count on thread destruction.
02930     * 2. The threadinfo object was created before this thread was launched, however
02931     *    it must be found within the threadt table.
02932     * 3. Last, the tcptls_session must be started.
02933     */
02934    if (!tcptls_session->client) {
02935       if (ast_atomic_fetchadd_int(&unauth_sessions, +1) >= authlimit) {
02936          /* unauth_sessions is decremented in the cleanup code */
02937          goto cleanup;
02938       }
02939 
02940       if ((flags = fcntl(tcptls_session->fd, F_GETFL)) == -1) {
02941          ast_log(LOG_ERROR, "error setting socket to non blocking mode, fcntl() failed: %s\n", strerror(errno));
02942          goto cleanup;
02943       }
02944 
02945       flags |= O_NONBLOCK;
02946       if (fcntl(tcptls_session->fd, F_SETFL, flags) == -1) {
02947          ast_log(LOG_ERROR, "error setting socket to non blocking mode, fcntl() failed: %s\n", strerror(errno));
02948          goto cleanup;
02949       }
02950 
02951       if (!(me = sip_threadinfo_create(tcptls_session, tcptls_session->ssl ? AST_TRANSPORT_TLS : AST_TRANSPORT_TCP))) {
02952          goto cleanup;
02953       }
02954       ao2_t_ref(me, +1, "Adding threadinfo ref for tcp_helper_thread");
02955    } else {
02956       struct sip_threadinfo tmp = {
02957          .tcptls_session = tcptls_session,
02958       };
02959 
02960       if ((!(ca = tcptls_session->parent)) ||
02961          (!(me = ao2_t_find(threadt, &tmp, OBJ_POINTER, "ao2_find, getting sip_threadinfo in tcp helper thread"))) ||
02962          (!(tcptls_session = ast_tcptls_client_start(tcptls_session)))) {
02963          goto cleanup;
02964       }
02965    }
02966 
02967    flags = 1;
02968    if (setsockopt(tcptls_session->fd, SOL_SOCKET, SO_KEEPALIVE, &flags, sizeof(flags))) {
02969       ast_log(LOG_ERROR, "error enabling TCP keep-alives on sip socket: %s\n", strerror(errno));
02970       goto cleanup;
02971    }
02972 
02973    me->threadid = pthread_self();
02974    ast_debug(2, "Starting thread for %s server\n", tcptls_session->ssl ? "TLS" : "TCP");
02975 
02976    /* set up pollfd to watch for reads on both the socket and the alert_pipe */
02977    fds[0].fd = tcptls_session->fd;
02978    fds[1].fd = me->alert_pipe[0];
02979    fds[0].events = fds[1].events = POLLIN | POLLPRI;
02980 
02981    if (!(req.data = ast_str_create(SIP_MIN_PACKET))) {
02982       goto cleanup;
02983    }
02984    if (!(reqcpy.data = ast_str_create(SIP_MIN_PACKET))) {
02985       goto cleanup;
02986    }
02987 
02988    if(time(&start) == -1) {
02989       ast_log(LOG_ERROR, "error executing time(): %s\n", strerror(errno));
02990       goto cleanup;
02991    }
02992 
02993    /*
02994     * We cannot let the stream exclusively wait for data to arrive.
02995     * We have to wake up the task to send outgoing messages.
02996     */
02997    ast_tcptls_stream_set_exclusive_input(tcptls_session->stream_cookie, 0);
02998 
02999    ast_tcptls_stream_set_timeout_sequence(tcptls_session->stream_cookie, ast_tvnow(),
03000       tcptls_session->client ? -1 : (authtimeout * 1000));
03001 
03002    for (;;) {
03003       struct ast_str *str_save;
03004 
03005       if (!tcptls_session->client && req.authenticated && !authenticated) {
03006          authenticated = 1;
03007          ast_tcptls_stream_set_timeout_disable(tcptls_session->stream_cookie);
03008          ast_atomic_fetchadd_int(&unauth_sessions, -1);
03009       }
03010 
03011       /* calculate the timeout for unauthenticated server sessions */
03012       if (!tcptls_session->client && !authenticated ) {
03013          if ((timeout = sip_check_authtimeout(start)) < 0) {
03014             goto cleanup;
03015          }
03016 
03017          if (timeout == 0) {
03018             ast_debug(2, "SIP %s server timed out\n", tcptls_session->ssl ? "TLS": "TCP");
03019             goto cleanup;
03020          }
03021       } else {
03022          timeout = -1;
03023       }
03024 
03025       if (ast_str_strlen(tcptls_session->overflow_buf) == 0) {
03026          res = ast_poll(fds, 2, timeout); /* polls for both socket and alert_pipe */
03027          if (res < 0) {
03028             ast_debug(2, "SIP %s server :: ast_wait_for_input returned %d\n", tcptls_session->ssl ? "TLS": "TCP", res);
03029             goto cleanup;
03030          } else if (res == 0) {
03031             /* timeout */
03032             ast_debug(2, "SIP %s server timed out\n", tcptls_session->ssl ? "TLS": "TCP");
03033             goto cleanup;
03034          }
03035       }
03036 
03037       /*
03038        * handle the socket event, check for both reads from the socket fd or TCP overflow buffer,
03039        * and writes from alert_pipe fd.
03040        */
03041       if (fds[0].revents || (ast_str_strlen(tcptls_session->overflow_buf) > 0)) { /* there is data on the socket to be read */
03042          fds[0].revents = 0;
03043 
03044          /* clear request structure */
03045          str_save = req.data;
03046          memset(&req, 0, sizeof(req));
03047          req.data = str_save;
03048          ast_str_reset(req.data);
03049 
03050          str_save = reqcpy.data;
03051          memset(&reqcpy, 0, sizeof(reqcpy));
03052          reqcpy.data = str_save;
03053          ast_str_reset(reqcpy.data);
03054 
03055          memset(buf, 0, sizeof(buf));
03056 
03057          if (tcptls_session->ssl) {
03058             set_socket_transport(&req.socket, AST_TRANSPORT_TLS);
03059             req.socket.port = htons(ourport_tls);
03060          } else {
03061             set_socket_transport(&req.socket, AST_TRANSPORT_TCP);
03062             req.socket.port = htons(ourport_tcp);
03063          }
03064          req.socket.fd = tcptls_session->fd;
03065 
03066          res = sip_tcptls_read(&req, tcptls_session, authenticated, start);
03067          if (res < 0) {
03068             goto cleanup;
03069          }
03070 
03071          req.socket.tcptls_session = tcptls_session;
03072          req.socket.ws_session = NULL;
03073          handle_request_do(&req, &tcptls_session->remote_address);
03074       }
03075 
03076       if (fds[1].revents) { /* alert_pipe indicates there is data in the send queue to be sent */
03077          enum sip_tcptls_alert alert;
03078          struct tcptls_packet *packet;
03079 
03080          fds[1].revents = 0;
03081 
03082          if (read(me->alert_pipe[0], &alert, sizeof(alert)) == -1) {
03083             ast_log(LOG_ERROR, "read() failed: %s\n", strerror(errno));
03084             continue;
03085          }
03086 
03087          switch (alert) {
03088          case TCPTLS_ALERT_STOP:
03089             goto cleanup;
03090          case TCPTLS_ALERT_DATA:
03091             ao2_lock(me);
03092             if (!(packet = AST_LIST_REMOVE_HEAD(&me->packet_q, entry))) {
03093                ast_log(LOG_WARNING, "TCPTLS thread alert_pipe indicated packet should be sent, but frame_q is empty\n");
03094             }
03095             ao2_unlock(me);
03096 
03097             if (packet) {
03098                if (ast_tcptls_server_write(tcptls_session, ast_str_buffer(packet->data), packet->len) == -1) {
03099                   ast_log(LOG_WARNING, "Failure to write to tcp/tls socket\n");
03100                }
03101                ao2_t_ref(packet, -1, "tcptls packet sent, this is no longer needed");
03102             }
03103             break;
03104          default:
03105             ast_log(LOG_ERROR, "Unknown tcptls thread alert '%u'\n", alert);
03106          }
03107       }
03108    }
03109 
03110    ast_debug(2, "Shutting down thread for %s server\n", tcptls_session->ssl ? "TLS" : "TCP");
03111 
03112 cleanup:
03113    if (tcptls_session && !tcptls_session->client && !authenticated) {
03114       ast_atomic_fetchadd_int(&unauth_sessions, -1);
03115    }
03116 
03117    if (me) {
03118       ao2_t_unlink(threadt, me, "Removing tcptls helper thread, thread is closing");
03119       ao2_t_ref(me, -1, "Removing tcp_helper_threads threadinfo ref");
03120    }
03121    deinit_req(&reqcpy);
03122    deinit_req(&req);
03123 
03124    /* if client, we own the parent session arguments and must decrement ref */
03125    if (ca) {
03126       ao2_t_ref(ca, -1, "closing tcptls thread, getting rid of client tcptls_session arguments");
03127    }
03128 
03129    if (tcptls_session) {
03130       ao2_lock(tcptls_session);
03131       ast_tcptls_close_session_file(tcptls_session);
03132       tcptls_session->parent = NULL;
03133       ao2_unlock(tcptls_session);
03134 
03135       ao2_ref(tcptls_session, -1);
03136       tcptls_session = NULL;
03137    }
03138    return NULL;
03139 }

static void acl_change_event_stasis_unsubscribe ( void   )  [static]

Definition at line 16759 of file chan_sip.c.

References stasis_unsubscribe_and_join().

Referenced by unload_module().

static void acl_change_stasis_cb ( void *  data,
struct stasis_subscription sub,
struct stasis_message message 
) [static]

Definition at line 28896 of file chan_sip.c.

References ast_log, ast_mutex_lock, ast_mutex_unlock, ast_named_acl_change_type(), ast_verbose, CHANNEL_ACL_RELOAD, LOG_NOTICE, restart_monitor(), sip_reload_lock, stasis_message_type(), and TRUE.

28898 {
28899    if (stasis_message_type(message) != ast_named_acl_change_type()) {
28900       return;
28901    }
28902 
28903    ast_log(LOG_NOTICE, "Reloading chan_sip in response to ACL change event.\n");
28904 
28905    ast_mutex_lock(&sip_reload_lock);
28906 
28907    if (sip_reloading) {
28908       ast_verbose("Previous SIP reload not yet done\n");
28909    } else {
28910       sip_reloading = TRUE;
28911       sip_reloadreason = CHANNEL_ACL_RELOAD;
28912    }
28913 
28914    ast_mutex_unlock(&sip_reload_lock);
28915 
28916    restart_monitor();
28917 }

static void acl_change_stasis_subscribe ( void   )  [static]

Definition at line 16750 of file chan_sip.c.

References acl_change_stasis_cb(), ast_security_topic(), NULL, and stasis_subscribe().

16751 {
16752    if (!acl_change_sub) {
16753       acl_change_sub = stasis_subscribe(ast_security_topic(),
16754          acl_change_stasis_cb, NULL);
16755    }
16756 
16757 }

static void add_blank ( struct sip_request req  )  [static]

add a blank line if no body

Definition at line 4451 of file chan_sip.c.

References ast_str_append(), sip_request::data, and sip_request::lines.

Referenced by send_request(), and send_response().

04452 {
04453    if (!req->lines) {
04454       /* Add extra empty return. add_header() reserves 4 bytes so cannot be truncated */
04455       ast_str_append(&req->data, 0, "\r\n");
04456    }
04457 }

static void add_cc_call_info_to_response ( struct sip_pvt p,
struct sip_request resp 
) [static]

Definition at line 13599 of file chan_sip.c.

References add_header(), ao2_ref, ast_copy_string(), ast_log, ast_str_alloca, ast_str_buffer(), ast_str_set(), ast_strlen_zero, sip_pvt::callid, find_sip_cc_agent_by_original_callid(), generate_uri(), LOG_WARNING, ast_cc_agent::private_data, SIPBUFSIZE, and sip_cc_agent_pvt::subscribe_uri.

Referenced by __transmit_response(), and transmit_response_with_sdp().

13600 {
13601    char uri[SIPBUFSIZE];
13602    struct ast_str *header = ast_str_alloca(SIPBUFSIZE);
13603    struct ast_cc_agent *agent = find_sip_cc_agent_by_original_callid(p);
13604    struct sip_cc_agent_pvt *agent_pvt;
13605 
13606    if (!agent) {
13607       /* Um, what? How could the SIP_OFFER_CC flag be set but there not be an
13608        * agent? Oh well, we'll just warn and return without adding the header.
13609        */
13610       ast_log(LOG_WARNING, "Can't find SIP CC agent for call '%s' even though OFFER_CC flag was set?\n", p->callid);
13611       return;
13612    }
13613 
13614    agent_pvt = agent->private_data;
13615 
13616    if (!ast_strlen_zero(agent_pvt->subscribe_uri)) {
13617       ast_copy_string(uri, agent_pvt->subscribe_uri, sizeof(uri));
13618    } else {
13619       generate_uri(p, uri, sizeof(uri));
13620       ast_copy_string(agent_pvt->subscribe_uri, uri, sizeof(agent_pvt->subscribe_uri));
13621    }
13622    /* XXX Hardcode "NR" as the m reason for now. This should perhaps be changed
13623     * to be more accurate. This parameter has no bearing on the actual operation
13624     * of the feature; it's just there for informational purposes.
13625     */
13626    ast_str_set(&header, 0, "<%s>;purpose=call-completion;m=%s", uri, "NR");
13627    add_header(resp, "Call-Info", ast_str_buffer(header));
13628    ao2_ref(agent, -1);
13629 }

static void add_codec_to_sdp ( const struct sip_pvt p,
struct ast_format codec,
struct ast_str **  m_buf,
struct ast_str **  a_buf,
int  debug,
int *  min_packet_size,
int *  max_packet_size 
) [static]

Add codec offer to SDP offer/answer body in INVITE or 200 OK.

Definition at line 12743 of file chan_sip.c.

References ast_format_cap_get_format_framing(), ast_format_cmp(), AST_FORMAT_CMP_EQUAL, ast_format_g719, ast_format_g723, ast_format_g729, ast_format_generate_sdp_fmtp(), ast_format_get_maximum_ms(), ast_format_get_name(), ast_format_ilbc, ast_format_opus, ast_format_siren14, ast_format_siren7, ast_rtp_codecs_payload_code(), ast_rtp_instance_get_codecs(), ast_rtp_lookup_mime_subtype2(), ast_rtp_lookup_sample_rate2(), AST_RTP_OPT_G726_NONSTANDARD, ast_str_append(), ast_test_flag, ast_verbose, sip_pvt::caps, sip_pvt::flags, sip_pvt::rtp, and SIP_G726_NONSTANDARD.

Referenced by add_sdp().

12750 {
12751    int rtp_code;
12752    const char *mime;
12753    unsigned int rate, framing;
12754 
12755    if (debug)
12756       ast_verbose("Adding codec %s to SDP\n", ast_format_get_name(format));
12757 
12758    if (((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(p->rtp), 1, format, 0)) == -1) ||
12759        !(mime = ast_rtp_lookup_mime_subtype2(1, format, 0, ast_test_flag(&p->flags[0], SIP_G726_NONSTANDARD) ? AST_RTP_OPT_G726_NONSTANDARD : 0)) ||
12760        !(rate = ast_rtp_lookup_sample_rate2(1, format, 0))) {
12761       return;
12762    }
12763 
12764    ast_str_append(m_buf, 0, " %d", rtp_code);
12765    /* Opus mandates 2 channels in rtpmap */
12766    if (ast_format_cmp(format, ast_format_opus) == AST_FORMAT_CMP_EQUAL) {
12767       ast_str_append(a_buf, 0, "a=rtpmap:%d %s/%u/2\r\n", rtp_code, mime, rate);
12768    } else {
12769       ast_str_append(a_buf, 0, "a=rtpmap:%d %s/%u\r\n", rtp_code, mime, rate);
12770    }
12771 
12772    ast_format_generate_sdp_fmtp(format, rtp_code, a_buf);
12773 
12774    framing = ast_format_cap_get_format_framing(p->caps, format);
12775 
12776    if (ast_format_cmp(format, ast_format_g729) == AST_FORMAT_CMP_EQUAL) {
12777       /* Indicate that we don't support VAD (G.729 annex B) */
12778       ast_str_append(a_buf, 0, "a=fmtp:%d annexb=no\r\n", rtp_code);
12779    } else if (ast_format_cmp(format, ast_format_g723) == AST_FORMAT_CMP_EQUAL) {
12780       /* Indicate that we don't support VAD (G.723.1 annex A) */
12781       ast_str_append(a_buf, 0, "a=fmtp:%d annexa=no\r\n", rtp_code);
12782    } else if (ast_format_cmp(format, ast_format_ilbc) == AST_FORMAT_CMP_EQUAL) {
12783       /* Add information about us using only 20/30 ms packetization */
12784       ast_str_append(a_buf, 0, "a=fmtp:%d mode=%u\r\n", rtp_code, framing);
12785    } else if (ast_format_cmp(format, ast_format_siren7) == AST_FORMAT_CMP_EQUAL) {
12786       /* Indicate that we only expect 32Kbps */
12787       ast_str_append(a_buf, 0, "a=fmtp:%d bitrate=32000\r\n", rtp_code);
12788    } else if (ast_format_cmp(format, ast_format_siren14) == AST_FORMAT_CMP_EQUAL) {
12789       /* Indicate that we only expect 48Kbps */
12790       ast_str_append(a_buf, 0, "a=fmtp:%d bitrate=48000\r\n", rtp_code);
12791    } else if (ast_format_cmp(format, ast_format_g719) == AST_FORMAT_CMP_EQUAL) {
12792       /* Indicate that we only expect 64Kbps */
12793       ast_str_append(a_buf, 0, "a=fmtp:%d bitrate=64000\r\n", rtp_code);
12794    }
12795 
12796    if (max_packet_size && ast_format_get_maximum_ms(format) &&
12797       (ast_format_get_maximum_ms(format) < *max_packet_size)) {
12798       *max_packet_size = ast_format_get_maximum_ms(format);
12799    }
12800 
12801    if (framing && (framing < *min_packet_size)) {
12802       *min_packet_size = framing;
12803    }
12804 
12805    /* Our first codec packetization processed cannot be zero */
12806    if ((*min_packet_size) == 0 && framing) {
12807       *min_packet_size = framing;
12808    }
12809 
12810    if ((*max_packet_size) == 0 && ast_format_get_maximum_ms(format)) {
12811       *max_packet_size = ast_format_get_maximum_ms(format);
12812    }
12813 }

static int add_content ( struct sip_request req,
const char *  line 
) [static]

Add content (not header) to SIP message.

Definition at line 11433 of file chan_sip.c.

References ast_log, ast_str_append(), sip_request::content, sip_request::lines, and LOG_WARNING.

Referenced by add_digit(), add_sdp(), add_text(), add_vidupdate(), sipinfo_send(), transmit_cc_notify(), transmit_invite(), transmit_notify_with_mwi(), transmit_notify_with_sipfrag(), and transmit_state_notify().

11434 {
11435    if (req->lines) {
11436       ast_log(LOG_WARNING, "Can't add more content when the content has been finalized\n");
11437       return -1;
11438    }
11439 
11440    ast_str_append(&req->content, 0, "%s", line);
11441    return 0;
11442 }

static void add_date ( struct sip_request req  )  [static]

Add date header to SIP message.

Definition at line 12196 of file chan_sip.c.

References add_header(), NULL, and tmp().

Referenced by transmit_invite(), transmit_response_with_date(), transmit_response_with_minse(), and transmit_response_with_unsupported().

12197 {
12198    char tmp[256];
12199    struct tm tm;
12200    time_t t = time(NULL);
12201 
12202    gmtime_r(&t, &tm);
12203    strftime(tmp, sizeof(tmp), "%a, %d %b %Y %T GMT", &tm);
12204    add_header(req, "Date", tmp);
12205 }

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 12462 of file chan_sip.c.

References add_content(), add_header(), and tmp().

Referenced by transmit_info_with_digit().

12463 {
12464    char tmp[256];
12465    int event;
12466    if (mode) {
12467       /* Application/dtmf short version used by some implementations */
12468       if ('0' <= digit && digit <= '9') {
12469          event = digit - '0';
12470       } else if (digit == '*') {
12471          event = 10;
12472       } else if (digit == '#') {
12473          event = 11;
12474       } else if ('A' <= digit && digit <= 'D') {
12475          event = 12 + digit - 'A';
12476       } else if ('a' <= digit && digit <= 'd') {
12477          event = 12 + digit - 'a';
12478       } else {
12479          /* Unknown digit */
12480          event = 0;
12481       }
12482       snprintf(tmp, sizeof(tmp), "%d\r\n", event);
12483       add_header(req, "Content-Type", "application/dtmf");
12484       add_content(req, tmp);
12485    } else {
12486       /* Application/dtmf-relay as documented by Cisco */
12487       snprintf(tmp, sizeof(tmp), "Signal=%c\r\nDuration=%u\r\n", digit, duration);
12488       add_header(req, "Content-Type", "application/dtmf-relay");
12489       add_content(req, tmp);
12490    }
12491    return 0;
12492 }

static void add_diversion ( struct sip_request req,
struct sip_pvt pvt 
) [static]

Add "Diversion" header to outgoing message.

We need to add a Diversion header if the owner channel of this dialog has redirecting information associated with it.

Parameters:
req The request/response to which we will add the header
pvt The sip_pvt which represents the call-leg

Definition at line 14107 of file chan_sip.c.

References add_header(), ast_channel_redirecting(), ast_channel_redirecting_effective_from(), ast_copy_string(), ast_escape_quoted(), ast_sockaddr_stringify_host_remote(), ast_strlen_zero, ast_uri_encode(), ast_uri_sip_user, ast_party_id::name, ast_party_id::number, sip_pvt::ourip, sip_pvt::owner, sip_settings::pedanticsipchecking, ast_party_redirecting::reason, sip_settings::send_diversion, sip_cfg, sip_reason_code_to_str(), SIPBUFSIZE, ast_party_name::str, ast_party_number::str, ast_party_name::valid, and ast_party_number::valid.

Referenced by __transmit_response(), transmit_invite(), and update_redirecting().

14108 {
14109    struct ast_party_id diverting_from;
14110    const char *reason;
14111    int found_in_table;
14112    char header_text[256];
14113    char encoded_number[SIPBUFSIZE/2];
14114 
14115    /* We skip this entirely if the configuration doesn't allow diversion headers */
14116    if (!sip_cfg.send_diversion) {
14117       return;
14118    }
14119 
14120    if (!pvt->owner) {
14121       return;
14122    }
14123 
14124    diverting_from = ast_channel_redirecting_effective_from(pvt->owner);
14125    if (!diverting_from.number.valid
14126       || ast_strlen_zero(diverting_from.number.str)) {
14127       return;
14128    }
14129 
14130    if (sip_cfg.pedanticsipchecking) {
14131       ast_uri_encode(diverting_from.number.str, encoded_number, sizeof(encoded_number), ast_uri_sip_user);
14132    } else {
14133       ast_copy_string(encoded_number, diverting_from.number.str, sizeof(encoded_number));
14134    }
14135 
14136    reason = sip_reason_code_to_str(&ast_channel_redirecting(pvt->owner)->reason, &found_in_table);
14137 
14138    /* We at least have a number to place in the Diversion header, which is enough */
14139    if (!diverting_from.name.valid
14140       || ast_strlen_zero(diverting_from.name.str)) {
14141       snprintf(header_text, sizeof(header_text), "<sip:%s@%s>;reason=%s%s%s",
14142             encoded_number,
14143             ast_sockaddr_stringify_host_remote(&pvt->ourip),
14144             found_in_table ? "" : "\"",
14145             reason,
14146             found_in_table ? "" : "\"");
14147    } else {
14148       char escaped_name[SIPBUFSIZE/2];
14149       if (sip_cfg.pedanticsipchecking) {
14150          ast_escape_quoted(diverting_from.name.str, escaped_name, sizeof(escaped_name));
14151       } else {
14152          ast_copy_string(escaped_name, diverting_from.name.str, sizeof(escaped_name));
14153       }
14154       snprintf(header_text, sizeof(header_text), "\"%s\" <sip:%s@%s>;reason=%s%s%s",
14155             escaped_name,
14156             encoded_number,
14157             ast_sockaddr_stringify_host_remote(&pvt->ourip),
14158             found_in_table ? "" : "\"",
14159             reason,
14160             found_in_table ? "" : "\"");
14161    }
14162 
14163    add_header(req, "Diversion", header_text);
14164 }

static void add_dtls_to_sdp ( struct ast_rtp_instance instance,
struct ast_str **  a_buf 
) [static]

Add DTLS attributes to SDP.

Definition at line 12696 of file chan_sip.c.

References ast_rtp_engine_dtls::active, AST_RTP_DTLS_CONNECTION_EXISTING, AST_RTP_DTLS_CONNECTION_NEW, AST_RTP_DTLS_HASH_SHA1, AST_RTP_DTLS_HASH_SHA256, AST_RTP_DTLS_SETUP_ACTIVE, AST_RTP_DTLS_SETUP_ACTPASS, AST_RTP_DTLS_SETUP_HOLDCONN, AST_RTP_DTLS_SETUP_PASSIVE, ast_rtp_instance_get_dtls(), ast_str_append(), ast_rtp_engine_dtls::get_connection, ast_rtp_engine_dtls::get_fingerprint, ast_rtp_engine_dtls::get_fingerprint_hash, and ast_rtp_engine_dtls::get_setup.

Referenced by add_sdp().

12697 {
12698    struct ast_rtp_engine_dtls *dtls;
12699    enum ast_rtp_dtls_hash hash;
12700    const char *fingerprint;
12701 
12702    if (!instance || !(dtls = ast_rtp_instance_get_dtls(instance)) || !dtls->active(instance)) {
12703       return;
12704    }
12705 
12706    switch (dtls->get_connection(instance)) {
12707    case AST_RTP_DTLS_CONNECTION_NEW:
12708       ast_str_append(a_buf, 0, "a=connection:new\r\n");
12709       break;
12710    case AST_RTP_DTLS_CONNECTION_EXISTING:
12711       ast_str_append(a_buf, 0, "a=connection:existing\r\n");
12712       break;
12713    default:
12714       break;
12715    }
12716 
12717    switch (dtls->get_setup(instance)) {
12718    case AST_RTP_DTLS_SETUP_ACTIVE:
12719       ast_str_append(a_buf, 0, "a=setup:active\r\n");
12720       break;
12721    case AST_RTP_DTLS_SETUP_PASSIVE:
12722       ast_str_append(a_buf, 0, "a=setup:passive\r\n");
12723       break;
12724    case AST_RTP_DTLS_SETUP_ACTPASS:
12725       ast_str_append(a_buf, 0, "a=setup:actpass\r\n");
12726       break;
12727    case AST_RTP_DTLS_SETUP_HOLDCONN:
12728       ast_str_append(a_buf, 0, "a=setup:holdconn\r\n");
12729       break;
12730    default:
12731       break;
12732    }
12733 
12734    hash = dtls->get_fingerprint_hash(instance);
12735    fingerprint = dtls->get_fingerprint(instance);
12736    if (fingerprint && (hash == AST_RTP_DTLS_HASH_SHA1 || hash == AST_RTP_DTLS_HASH_SHA256)) {
12737       ast_str_append(a_buf, 0, "a=fingerprint:%s %s\r\n", hash == AST_RTP_DTLS_HASH_SHA1 ? "SHA-1" : "SHA-256",
12738          fingerprint);
12739    }
12740 }

static void add_expires ( struct sip_request req,
int  expires 
) [static]

Add Expires header to SIP message.

Definition at line 12208 of file chan_sip.c.

References add_header(), and tmp().

Referenced by respprep(), transmit_invite(), and transmit_register().

12209 {
12210    char tmp[32];
12211 
12212    snprintf(tmp, sizeof(tmp), "%d", expires);
12213    add_header(req, "Expires", tmp);
12214 }

static int add_header ( struct sip_request req,
const char *  var,
const char *  value 
) [static]

Add header to SIP message.

Definition at line 11375 of file chan_sip.c.

References ast_log, ast_str_append(), ast_str_strlen(), sip_settings::compactheaders, sip_request::data, find_alias(), sip_request::header, sip_request::headers, sip_request::lines, LOG_WARNING, sip_cfg, and SIP_MAX_HEADERS.

11376 {
11377    if (req->headers == SIP_MAX_HEADERS) {
11378       ast_log(LOG_WARNING, "Out of SIP header space\n");
11379       return -1;
11380    }
11381 
11382    if (req->lines) {
11383       ast_log(LOG_WARNING, "Can't add more headers when lines have been added\n");
11384       return -1;
11385    }
11386 
11387    if (sip_cfg.compactheaders) {
11388       var = find_alias(var, var);
11389    }
11390 
11391    ast_str_append(&req->data, 0, "%s: %s\r\n", var, value);
11392    req->header[req->headers] = ast_str_strlen(req->data);
11393 
11394    req->headers++;
11395 
11396    return 0;
11397 }

static void add_ice_to_sdp ( struct ast_rtp_instance instance,
struct ast_str **  a_buf 
) [static]

Add ICE attributes to SDP.

Definition at line 12631 of file chan_sip.c.

References ast_rtp_engine_ice_candidate::address, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, AST_RTP_ICE_CANDIDATE_TYPE_HOST, AST_RTP_ICE_CANDIDATE_TYPE_RELAYED, AST_RTP_ICE_CANDIDATE_TYPE_SRFLX, ast_rtp_instance_get_ice(), ast_sockaddr_isnull(), ast_sockaddr_stringify_host(), ast_sockaddr_stringify_port(), ast_str_append(), ast_rtp_engine_ice_candidate::foundation, ast_rtp_engine_ice::get_local_candidates, ast_rtp_engine_ice::get_password, ast_rtp_engine_ice::get_ufrag, ast_rtp_engine_ice_candidate::id, password, ast_rtp_engine_ice_candidate::priority, ast_rtp_engine_ice_candidate::relay_address, ast_rtp_engine_ice_candidate::transport, and ast_rtp_engine_ice_candidate::type.

Referenced by add_sdp().

12632 {
12633    struct ast_rtp_engine_ice *ice = ast_rtp_instance_get_ice(instance);
12634    const char *username, *password;
12635    struct ao2_container *candidates;
12636    struct ao2_iterator i;
12637    struct ast_rtp_engine_ice_candidate *candidate;
12638 
12639    /* If no ICE support is present we can't very well add the attributes */
12640    if (!ice || !(candidates = ice->get_local_candidates(instance))) {
12641       return;
12642    }
12643 
12644    if ((username = ice->get_ufrag(instance))) {
12645       ast_str_append(a_buf, 0, "a=ice-ufrag:%s\r\n", username);
12646    }
12647    if ((password = ice->get_password(instance))) {
12648       ast_str_append(a_buf, 0, "a=ice-pwd:%s\r\n", password);
12649    }
12650 
12651    i = ao2_iterator_init(candidates, 0);
12652 
12653    while ((candidate = ao2_iterator_next(&i))) {
12654       ast_str_append(a_buf, 0, "a=candidate:%s %u %s %d ", candidate->foundation</