Skip to content
Snippets Groups Projects
chan_sip.c 428 KiB
Newer Older
  • Learn to ignore specific revisions
  • Mark Spencer's avatar
    Mark Spencer committed
    /*
    
     * Asterisk -- An open source telephony toolkit.
    
    Mark Spencer's avatar
    Mark Spencer committed
     *
    
     * Copyright (C) 1999 - 2005, Digium, Inc.
    
    Mark Spencer's avatar
    Mark Spencer committed
     *
    
     * Mark Spencer <markster@digium.com>
    
    Mark Spencer's avatar
    Mark Spencer committed
     *
    
     * See http://www.asterisk.org for more information about
     * the Asterisk project. Please do not directly contact
     * any of the maintainers of this project for assistance;
     * the project provides a web site, mailing lists and IRC
     * channels for your use.
     *
    
    Mark Spencer's avatar
    Mark Spencer committed
     * This program is free software, distributed under the terms of
    
     * the GNU General Public License Version 2. See the LICENSE file
     * at the top of the source tree.
     */
    
    
    /*!
     * \file
     * \brief Implementation of Session Initiation Protocol
    
     * Implementation of RFC 3261 - without S/MIME, TCP and TLS support
    
     * Configuration file \link Config_sip sip.conf \endlink
    
     *
     * \todo SIP over TCP
     * \todo SIP over TLS
     * \todo Better support of forking
    
    Mark Spencer's avatar
    Mark Spencer committed
    #include <stdio.h>
    
    Mark Spencer's avatar
    Mark Spencer committed
    #include <ctype.h>
    
    Mark Spencer's avatar
    Mark Spencer committed
    #include <string.h>
    
    #include <sys/socket.h>
    #include <sys/ioctl.h>
    #include <net/if.h>
    #include <errno.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <netdb.h>
    #include <signal.h>
    #include <sys/signal.h>
    
    #include <netinet/ip.h>
    #include <regex.h>
    
    #include "asterisk.h"
    
    
    Kevin P. Fleming's avatar
    Kevin P. Fleming committed
    ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
    
    #include "asterisk/lock.h"
    #include "asterisk/channel.h"
    #include "asterisk/config.h"
    #include "asterisk/logger.h"
    #include "asterisk/module.h"
    #include "asterisk/pbx.h"
    #include "asterisk/options.h"
    #include "asterisk/lock.h"
    #include "asterisk/sched.h"
    #include "asterisk/io.h"
    #include "asterisk/rtp.h"
    #include "asterisk/acl.h"
    #include "asterisk/manager.h"
    #include "asterisk/callerid.h"
    #include "asterisk/cli.h"
    #include "asterisk/app.h"
    #include "asterisk/musiconhold.h"
    #include "asterisk/dsp.h"
    #include "asterisk/features.h"
    #include "asterisk/acl.h"
    #include "asterisk/srv.h"
    #include "asterisk/astdb.h"
    #include "asterisk/causes.h"
    #include "asterisk/utils.h"
    #include "asterisk/file.h"
    #include "asterisk/astobj.h"
    #include "asterisk/dnsmgr.h"
    
    #include "asterisk/linkedlists.h"
    
    
    #ifdef OSP_SUPPORT
    
    #ifndef DEFAULT_USERAGENT
    #define DEFAULT_USERAGENT "Asterisk PBX"
    #endif
     
    
    #define VIDEO_CODEC_MASK	0x1fc0000 /* Video codecs from H.261 thru AST_FORMAT_MAX_VIDEO */
    
    Mark Spencer's avatar
    Mark Spencer committed
    #ifndef IPTOS_MINCOST
    
    #define IPTOS_MINCOST		0x02
    
    Mark Spencer's avatar
    Mark Spencer committed
    #endif
    
    
    Mark Spencer's avatar
    Mark Spencer committed
    /* #define VOCAL_DATA_HACK */
    
    Mark Spencer's avatar
    Mark Spencer committed
    
    #define SIPDUMPER
    
    Mark Spencer's avatar
    Mark Spencer committed
    #define DEFAULT_DEFAULT_EXPIRY  120
    
    #define DEFAULT_MAX_EXPIRY	3600
    
    #define DEFAULT_REGISTRATION_TIMEOUT	20
    
    #define DEFAULT_MAX_FORWARDS	"70"
    
    
    /* guard limit must be larger than guard secs */
    
    /* guard min must be < 1000, and should be >= 250 */
    
    #define EXPIRY_GUARD_SECS	15	/* How long before expiry do we reregister */
    
    #define EXPIRY_GUARD_LIMIT	30	/* Below here, we use EXPIRY_GUARD_PCT instead of 
    
    					   EXPIRY_GUARD_SECS */
    #define EXPIRY_GUARD_MIN	500	/* This is the minimum guard time applied. If 
    					   GUARD_PCT turns out to be lower than this, it 
    					   will use this time instead.
    					   This is in milliseconds. */
    
    #define EXPIRY_GUARD_PCT	0.20	/* Percentage of expires timeout to use when 
    
    					   below EXPIRY_GUARD_LIMIT */
    
    static int max_expiry = DEFAULT_MAX_EXPIRY;
    static int default_expiry = DEFAULT_DEFAULT_EXPIRY;
    
    
    #ifndef MAX
    #define MAX(a,b) ((a) > (b) ? (a) : (b))
    #endif
    
    Mark Spencer's avatar
    Mark Spencer committed
    #define DEFAULT_MAXMS		2000		/* Must be faster than 2 seconds by default */
    
    #define DEFAULT_FREQ_OK		60 * 1000	/* How often to check for the host to be up */
    #define DEFAULT_FREQ_NOTOK	10 * 1000	/* How often to check, if the host is down... */
    
    #define DEFAULT_RETRANS		1000		/* How frequently to retransmit */
    						/* 2 * 500 ms in RFC 3261 */
    
    #define MAX_RETRANS		6		/* Try only 6 times for retransmissions, a total of 7 transmissions */
    
    #define MAX_AUTHTRIES		3		/* Try authentication three times, then fail */
    
    #define DEBUG_READ	0			/* Recieved data	*/
    #define DEBUG_SEND	1			/* Transmit data	*/
    
    static const char desc[] = "Session Initiation Protocol (SIP)";
    static const char channeltype[] = "SIP";
    static const char config[] = "sip.conf";
    static const char notify_config[] = "sip_notify.conf";
    
    /* Do _NOT_ make any changes to this enum, or the array following it;
       if you think you are doing the right thing, you are probably
       not doing the right thing. If you think there are changes
       needed, get someone else to review them first _before_
       submitting a patch. If these two lists do not match properly
       bad things will happen.
    */
    
    
    enum subscriptiontype { 
    	NONE = 0,
    	TIMEOUT,
    	XPIDF_XML,
    	DIALOG_INFO_XML,
    	CPIM_PIDF_XML,
    	PIDF_XML
    };
    
    static const struct cfsubscription_types {
    	enum subscriptiontype type;
    	const char * const event;
    	const char * const mediatype;
    	const char * const text;
    } subscription_types[] = {
    	{ NONE,            "-",        "unknown",	                  "unknown" },
     	/* IETF draft: draft-ietf-sipping-dialog-package-05.txt */
    	{ DIALOG_INFO_XML, "dialog",   "application/dialog-info+xml", "dialog-info+xml" },
    	{ CPIM_PIDF_XML,   "presence", "application/cpim-pidf+xml",   "cpim-pidf+xml" },  /* RFC 3863 */
    	{ PIDF_XML,        "presence", "application/pidf+xml",        "pidf+xml" },       /* RFC 3863 */
    	{ XPIDF_XML,       "presence", "application/xpidf+xml",       "xpidf+xml" }       /* Pre-RFC 3863 with MS additions */
    };
    
    
    enum sipmethod {
    	SIP_UNKNOWN,
    	SIP_RESPONSE,
    	SIP_REGISTER,
    	SIP_OPTIONS,
    	SIP_NOTIFY,
    	SIP_INVITE,
    	SIP_ACK,
    	SIP_PRACK,
    	SIP_BYE,
    	SIP_REFER,
    	SIP_SUBSCRIBE,
    	SIP_MESSAGE,
    	SIP_UPDATE,
    	SIP_INFO,
    	SIP_CANCEL,
    	SIP_PUBLISH,
    } sip_method_list;
    
    
    enum sip_auth_type {
    	PROXY_AUTH,
    	WWW_AUTH,
    };
    
    
    Kevin P. Fleming's avatar
    Kevin P. Fleming committed
    static const struct  cfsip_methods { 
    
    	int need_rtp;		/*!< when this is the 'primary' use for a pvt structure, does it need RTP? */
    
    Kevin P. Fleming's avatar
    Kevin P. Fleming committed
    	char * const text;
    
    	{ SIP_RESPONSE,	 NO_RTP, "SIP/2.0" },
    
    	{ SIP_REGISTER,	 NO_RTP, "REGISTER" },
     	{ SIP_OPTIONS,	 NO_RTP, "OPTIONS" },
    	{ SIP_NOTIFY,	 NO_RTP, "NOTIFY" },
    
    Kevin P. Fleming's avatar
    Kevin P. Fleming committed
    	{ SIP_INVITE,	 RTP,    "INVITE" },
    
    	{ SIP_ACK,	 NO_RTP, "ACK" },
    	{ SIP_PRACK,	 NO_RTP, "PRACK" },
    	{ SIP_BYE,	 NO_RTP, "BYE" },
    	{ SIP_REFER,	 NO_RTP, "REFER" },
    	{ SIP_SUBSCRIBE, NO_RTP, "SUBSCRIBE" },
    	{ SIP_MESSAGE,	 NO_RTP, "MESSAGE" },
    	{ SIP_UPDATE,	 NO_RTP, "UPDATE" },
    	{ SIP_INFO,	 NO_RTP, "INFO" },
    	{ SIP_CANCEL,	 NO_RTP, "CANCEL" },
    	{ SIP_PUBLISH,	 NO_RTP, "PUBLISH" }
    
    /*! \brief Structure for conversion between compressed SIP and "normal" SIP */
    
    static const struct cfalias {
    	char * const fullname;
    	char * const shortname;
    
    } aliases[] = {
    	{ "Content-Type", "c" },
    	{ "Content-Encoding", "e" },
    	{ "From", "f" },
    	{ "Call-ID", "i" },
    	{ "Contact", "m" },
    	{ "Content-Length", "l" },
    	{ "Subject", "s" },
    	{ "To", "t" },
    	{ "Supported", "k" },
    	{ "Refer-To", "r" },
    
    	{ "Referred-By", "b" },
    
    	{ "Allow-Events", "u" },
    	{ "Event", "o" },
    	{ "Via", "v" },
    
    	{ "Accept-Contact",      "a" },
    	{ "Reject-Contact",      "j" },
    	{ "Request-Disposition", "d" },
    	{ "Session-Expires",     "x" },
    
    /*!  Define SIP option tags, used in Require: and Supported: headers 
     	We need to be aware of these properties in the phones to use 
    
    	the replace: header. We should not do that without knowing
    	that the other end supports it... 
    	This is nothing we can configure, we learn by the dialog
    	Supported: header on the REGISTER (peer) or the INVITE
    	(other devices)
    	We are not using many of these today, but will in the future.
    	This is documented in RFC 3261
    */
    #define SUPPORTED		1
    #define NOT_SUPPORTED		0
    
    #define SIP_OPT_REPLACES	(1 << 0)
    #define SIP_OPT_100REL		(1 << 1)
    #define SIP_OPT_TIMER		(1 << 2)
    #define SIP_OPT_EARLY_SESSION	(1 << 3)
    #define SIP_OPT_JOIN		(1 << 4)
    #define SIP_OPT_PATH		(1 << 5)
    #define SIP_OPT_PREF		(1 << 6)
    #define SIP_OPT_PRECONDITION	(1 << 7)
    #define SIP_OPT_PRIVACY		(1 << 8)
    #define SIP_OPT_SDP_ANAT	(1 << 9)
    #define SIP_OPT_SEC_AGREE	(1 << 10)
    #define SIP_OPT_EVENTLIST	(1 << 11)
    #define SIP_OPT_GRUU		(1 << 12)
    #define SIP_OPT_TARGET_DIALOG	(1 << 13)
    
    
    /*! \brief List of well-known SIP options. If we get this in a require,
    
       we should check the list and answer accordingly. */
    
    Kevin P. Fleming's avatar
    Kevin P. Fleming committed
    static const struct cfsip_options {
    
    	int id;			/*!< Bitmap ID */
    	int supported;		/*!< Supported by Asterisk ? */
    	char * const text;	/*!< Text id, as in standard */
    
    } sip_options[] = {
    	/* Replaces: header for transfer */
    	{ SIP_OPT_REPLACES,	SUPPORTED,	"replaces" },	
    	/* RFC3262: PRACK 100% reliability */
    	{ SIP_OPT_100REL,	NOT_SUPPORTED,	"100rel" },	
    	/* SIP Session Timers */
    	{ SIP_OPT_TIMER,	NOT_SUPPORTED,	"timer" },
    	/* RFC3959: SIP Early session support */
    	{ SIP_OPT_EARLY_SESSION, NOT_SUPPORTED,	"early-session" },
    	/* SIP Join header support */
    	{ SIP_OPT_JOIN,		NOT_SUPPORTED,	"join" },
    	/* RFC3327: Path support */
    	{ SIP_OPT_PATH,		NOT_SUPPORTED,	"path" },
    	/* RFC3840: Callee preferences */
    	{ SIP_OPT_PREF,		NOT_SUPPORTED,	"pref" },
    	/* RFC3312: Precondition support */
    	{ SIP_OPT_PRECONDITION,	NOT_SUPPORTED,	"precondition" },
    	/* RFC3323: Privacy with proxies*/
    	{ SIP_OPT_PRIVACY,	NOT_SUPPORTED,	"privacy" },
    
    	/* RFC4092: Usage of the SDP ANAT Semantics in the SIP */
    	{ SIP_OPT_SDP_ANAT,	NOT_SUPPORTED,	"sdp-anat" },
    
    	/* RFC3329: Security agreement mechanism */
    	{ SIP_OPT_SEC_AGREE,	NOT_SUPPORTED,	"sec_agree" },
    	/* SIMPLE events:  draft-ietf-simple-event-list-07.txt */
    	{ SIP_OPT_EVENTLIST,	NOT_SUPPORTED,	"eventlist" },
    	/* GRUU: Globally Routable User Agent URI's */
    	{ SIP_OPT_GRUU,		NOT_SUPPORTED,	"gruu" },
    	/* Target-dialog: draft-ietf-sip-target-dialog-00.txt */
    	{ SIP_OPT_TARGET_DIALOG,NOT_SUPPORTED,	"target-dialog" },
    };
    
    /*! \brief SIP Methods we support */
    
    #define ALLOWED_METHODS "INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY"
    
    /*! \brief SIP Extensions we support */
    
    #define DEFAULT_SIP_PORT	5060	/*!< From RFC 3261 (former 2543) */
    #define SIP_MAX_PACKET		4096	/*!< Also from RFC 3261 (2543), should sub headers tho */
    
    static char default_useragent[AST_MAX_EXTENSION] = DEFAULT_USERAGENT;
    
    #define DEFAULT_CONTEXT "default"
    
    static char default_context[AST_MAX_CONTEXT] = DEFAULT_CONTEXT;
    
    static char default_subscribecontext[AST_MAX_CONTEXT];
    
    #define DEFAULT_VMEXTEN "asterisk"
    static char global_vmexten[AST_MAX_EXTENSION] = DEFAULT_VMEXTEN;
    
    
    static char default_language[MAX_LANGUAGE] = "";
    
    #define DEFAULT_CALLERID "asterisk"
    static char default_callerid[AST_MAX_EXTENSION] = DEFAULT_CALLERID;
    
    static char default_fromdomain[AST_MAX_EXTENSION] = "";
    
    #define DEFAULT_NOTIFYMIME "application/simple-message-summary"
    static char default_notifymime[AST_MAX_EXTENSION] = DEFAULT_NOTIFYMIME;
    
    static int global_notifyringing = 1;	/*!< Send notifications on ringing */
    
    static int default_qualify = 0;		/*!< Default Qualify= setting */
    
    static struct ast_flags global_flags = {0};		/*!< global SIP_ flags */
    static struct ast_flags global_flags_page2 = {0};	/*!< more global SIP_ flags */
    
    static int srvlookup = 0;		/*!< SRV Lookup on or off. Default is off, RFC behavior is on */
    
    static int pedanticsipchecking = 0;	/*!< Extra checking ?  Default off */
    
    static int autocreatepeer = 0;		/*!< Auto creation of peers at registration? Default off. */
    
    static int relaxdtmf = 0;
    
    
    static int global_rtpkeepalive = 0;
    
    
    static int global_reg_timeout = DEFAULT_REGISTRATION_TIMEOUT;	
    
    static int global_regattempts_max = 0;
    
    /* Object counters */
    static int suserobjs = 0;
    static int ruserobjs = 0;
    static int speerobjs = 0;
    static int rpeerobjs = 0;
    static int apeerobjs = 0;
    static int regobjs = 0;
    
    
    static int global_allowguest = 1;    /*!< allow unauthenticated users/peers to connect? */
    
    #define DEFAULT_MWITIME 10
    
    static int global_mwitime = DEFAULT_MWITIME;	/*!< Time between MWI checks for peers */
    
    Mark Spencer's avatar
    Mark Spencer committed
    static int usecnt =0;
    
    AST_MUTEX_DEFINE_STATIC(usecnt_lock);
    
    Kevin P. Fleming's avatar
    Kevin P. Fleming committed
    AST_MUTEX_DEFINE_STATIC(rand_lock);
    
    /*! \brief Protect the interface list (of sip_pvt's) */
    
    AST_MUTEX_DEFINE_STATIC(iflock);
    
    /*! \brief Protect the monitoring thread, so only one process can kill or start it, and not
    
    Mark Spencer's avatar
    Mark Spencer committed
       when it's doing something critical. */
    
    AST_MUTEX_DEFINE_STATIC(netlock);
    
    AST_MUTEX_DEFINE_STATIC(monlock);
    
    /*! \brief This is the thread for the monitor which checks for input on the channels
    
    Mark Spencer's avatar
    Mark Spencer committed
       which are not currently in use.  */
    
    static pthread_t monitor_thread = AST_PTHREADT_NULL;
    
    Mark Spencer's avatar
    Mark Spencer committed
    
    static int restart_monitor(void);
    
    
    /*! \brief Codecs that we support by default: */
    
    static int global_capability = AST_FORMAT_ULAW | AST_FORMAT_ALAW | AST_FORMAT_GSM | AST_FORMAT_H263;
    
    Mark Spencer's avatar
    Mark Spencer committed
    static int noncodeccapability = AST_RTP_DTMF;
    
    Mark Spencer's avatar
    Mark Spencer committed
    static struct in_addr __ourip;
    
    static struct sockaddr_in outboundproxyip;
    
    Mark Spencer's avatar
    Mark Spencer committed
    static int ourport;
    
    
    #define SIP_DEBUG_CONFIG 1 << 0
    #define SIP_DEBUG_CONSOLE 1 << 1
    
    Mark Spencer's avatar
    Mark Spencer committed
    static int sipdebug = 0;
    
    static struct sockaddr_in debugaddr;
    
    Mark Spencer's avatar
    Mark Spencer committed
    
    static int tos = 0;
    
    
    static int compactheaders = 0;				/*!< send compact sip headers */
    
    static int recordhistory = 0;				/*!< Record SIP history. Off by default */
    static int dumphistory = 0;				/*!< Dump history to verbose before destroying SIP dialog */
    
    static char global_musicclass[MAX_MUSICCLASS] = "";	/*!< Global music on hold class */
    
    #define DEFAULT_REALM	"asterisk"
    
    static char global_realm[MAXHOSTNAMELEN] = DEFAULT_REALM; 	/*!< Default realm */
    static char regcontext[AST_MAX_CONTEXT] = "";		/*!< Context for auto-extensions */
    
    #define DEFAULT_EXPIRY 900				/*!< Expire slowly */
    
    static int expiry = DEFAULT_EXPIRY;
    
    Mark Spencer's avatar
    Mark Spencer committed
    
    static struct sched_context *sched;
    static struct io_context *io;
    
    
    #define SIP_MAX_HEADERS		64			/*!< Max amount of SIP headers to read */
    #define SIP_MAX_LINES 		64			/*!< Max amount of lines in SIP attachment (like SDP) */
    
    #define DEC_CALL_LIMIT	0
    #define INC_CALL_LIMIT	1
    
    static struct ast_codec_pref prefs;
    
    
    /*! \brief sip_request: The data grabbed from the UDP socket */
    
    Mark Spencer's avatar
    Mark Spencer committed
    struct sip_request {
    
    	char *rlPart1; 		/*!< SIP Method Name or "SIP/2.0" protocol version */
    	char *rlPart2; 		/*!< The Request URI or Response Status */
    	int len;		/*!< Length */
    	int headers;		/*!< # of SIP Headers */
    	int method;		/*!< Method of this request */
    
    Mark Spencer's avatar
    Mark Spencer committed
    	char *header[SIP_MAX_HEADERS];
    
    	int lines;		/*!< SDP Content */
    
    Mark Spencer's avatar
    Mark Spencer committed
    	char *line[SIP_MAX_LINES];
    	char data[SIP_MAX_PACKET];
    
    	int debug;		/*!< Debug flag for this packet */
    	unsigned int flags;	/*!< SIP_PKT Flags for this packet */
    
    Mark Spencer's avatar
    Mark Spencer committed
    struct sip_pkt;
    
    
    /*! \brief Parameters to the transmit_invite function */
    
    	char *distinctive_ring;	/*!< Distinctive ring header */
    	char *osptoken;		/*!< OSP token for this call */
    	int addsipheaders;	/*!< Add extra SIP headers */
    	char *uri_options;	/*!< URI options to add to the URI */
    	char *vxml_url;		/*!< VXML url for Cisco phones */
    	char *auth;		/*!< Authentication */
    	char *authheader;	/*!< Auth header */
    	enum sip_auth_type auth_type;	/*!< Authentication type */
    
    struct sip_route {
    	struct sip_route *next;
    	char hop[0];
    };
    
    
    	SIP_DOMAIN_AUTO,	/*!< This domain is auto-configured */
    	SIP_DOMAIN_CONFIG,	/*!< This domain is from configuration */
    
    	char domain[MAXHOSTNAMELEN];		/*!< SIP domain we are responsible for */
    	char context[AST_MAX_EXTENSION];	/*!< Incoming context for this domain */
    	enum domain_mode mode;			/*!< How did we find this domain? */
    	AST_LIST_ENTRY(domain) list;		/*!< List mechanics */
    
    static AST_LIST_HEAD_STATIC(domain_list, domain);	/*!< The SIP domain list */
    
    int allow_external_domains;		/*!< Accept calls to external SIP domains? */
    
    /*! \brief sip_history: Structure for saving transactions within a SIP dialog */
    
    struct sip_history {
    	char event[80];
    	struct sip_history *next;
    };
    
    
    /*! \brief sip_auth: Creadentials for authentication to other SIP services */
    
    struct sip_auth {
    
    	char realm[AST_MAX_EXTENSION];  /*!< Realm in which these credentials are valid */
    	char username[256];             /*!< Username */
    	char secret[256];               /*!< Secret */
    	char md5secret[256];            /*!< MD5Secret */
    	struct sip_auth *next;          /*!< Next auth structure in list */
    
    #define SIP_ALREADYGONE		(1 << 0)	/*!< Whether or not we've already been destroyed by our peer */
    #define SIP_NEEDDESTROY		(1 << 1)	/*!< if we need to be destroyed */
    #define SIP_NOVIDEO		(1 << 2)	/*!< Didn't get video in invite, don't offer */
    #define SIP_RINGING		(1 << 3)	/*!< Have sent 180 ringing */
    #define SIP_PROGRESS_SENT	(1 << 4)	/*!< Have sent 183 message progress */
    #define SIP_NEEDREINVITE	(1 << 5)	/*!< Do we need to send another reinvite? */
    #define SIP_PENDINGBYE		(1 << 6)	/*!< Need to send bye after we ack? */
    #define SIP_GOTREFER		(1 << 7)	/*!< Got a refer? */
    #define SIP_PROMISCREDIR	(1 << 8)	/*!< Promiscuous redirection */
    #define SIP_TRUSTRPID		(1 << 9)	/*!< Trust RPID headers? */
    #define SIP_USEREQPHONE		(1 << 10)	/*!< Add user=phone to numeric URI. Default off */
    #define SIP_REALTIME		(1 << 11)	/*!< Flag for realtime users */
    #define SIP_USECLIENTCODE	(1 << 12)	/*!< Trust X-ClientCode info message */
    #define SIP_OUTGOING		(1 << 13)	/*!< Is this an outgoing call? */
    
    #define SIP_DYNAMIC		(1 << 15)	/*!< Is this a dynamic peer? */
    
    /* --- Choices for DTMF support in SIP channel */
    
    #define SIP_DTMF		(3 << 16)	/*!< three settings, uses two bits */
    #define SIP_DTMF_RFC2833	(0 << 16)	/*!< RTP DTMF */
    #define SIP_DTMF_INBAND		(1 << 16)	/*!< Inband audio, only for ULAW/ALAW */
    #define SIP_DTMF_INFO		(2 << 16)	/*!< SIP Info messages */
    #define SIP_DTMF_AUTO		(3 << 16)	/*!< AUTO switch between rfc2833 and in-band DTMF */
    
    /* NAT settings */
    
    #define SIP_NAT			(3 << 18)	/*!< four settings, uses two bits */
    #define SIP_NAT_NEVER		(0 << 18)	/*!< No nat support */
    
    #define SIP_NAT_RFC3581		(1 << 18)
    #define SIP_NAT_ROUTE		(2 << 18)
    #define SIP_NAT_ALWAYS		(3 << 18)
    /* re-INVITE related settings */
    
    #define SIP_REINVITE		(3 << 20)	/*!< two bits used */
    #define SIP_CAN_REINVITE	(1 << 20)	/*!< allow peers to be reinvited to send media directly p2p */
    #define SIP_REINVITE_UPDATE	(2 << 20)	/*!< use UPDATE (RFC3311) when reinviting this peer */
    
    /* "insecure" settings */
    
    #define SIP_INSECURE_PORT	(1 << 22)	/*!< don't require matching port for incoming requests */
    #define SIP_INSECURE_INVITE	(1 << 23)	/*!< don't require authentication for incoming INVITEs */
    
    /* Sending PROGRESS in-band settings */
    
    #define SIP_PROG_INBAND		(3 << 24)	/*!< three settings, uses two bits */
    
    #define SIP_PROG_INBAND_NEVER	(0 << 24)
    #define SIP_PROG_INBAND_NO	(1 << 24)
    #define SIP_PROG_INBAND_YES	(2 << 24)
    /* Open Settlement Protocol authentication */
    
    #define SIP_OSPAUTH		(3 << 26)	/*!< four settings, uses two bits */
    
    #define SIP_OSPAUTH_NO		(0 << 26)
    
    #define SIP_OSPAUTH_GATEWAY	(1 << 26)
    #define SIP_OSPAUTH_PROXY	(2 << 26)
    #define SIP_OSPAUTH_EXCLUSIVE	(3 << 26)
    
    Mark Spencer's avatar
    Mark Spencer committed
    /* Call states */
    
    #define SIP_CALL_ONHOLD		(1 << 28)	 
    #define SIP_CALL_LIMIT		(1 << 29)
    
    /* Remote Party-ID Support */
    #define SIP_SENDRPID		(1 << 30)
    
    #define SIP_FLAGS_TO_COPY \
    	(SIP_PROMISCREDIR | SIP_TRUSTRPID | SIP_SENDRPID | SIP_DTMF | SIP_REINVITE | \
    	 SIP_PROG_INBAND | SIP_OSPAUTH | SIP_USECLIENTCODE | SIP_NAT | \
    	 SIP_INSECURE_PORT | SIP_INSECURE_INVITE)
    
    
    /* a new page of flags for peer */
    
    #define SIP_PAGE2_RTCACHEFRIENDS	(1 << 0)
    #define SIP_PAGE2_RTUPDATE		(1 << 1)
    #define SIP_PAGE2_RTAUTOCLEAR		(1 << 2)
    
    #define SIP_PAGE2_IGNOREREGEXPIRE	(1 << 3)
    #define SIP_PAGE2_RT_FROMCONTACT 	(1 << 4)
    
    /* SIP packet flags */
    
    #define SIP_PKT_DEBUG		(1 << 0)	/*!< Debug this packet */
    #define SIP_PKT_WITH_TOTAG	(1 << 1)	/*!< This packet has a to-tag */
    
    static int global_rtautoclear = 120;
    
    
    /*! \brief sip_pvt: PVT structures are used for each SIP conversation, ie. a call  */
    
    Mark Spencer's avatar
    Mark Spencer committed
    static struct sip_pvt {
    
    	ast_mutex_t lock;			/*!< Channel private lock */
    	int method;				/*!< SIP method of this packet */
    	char callid[80];			/*!< Global CallID */
    	char randdata[80];			/*!< Random data */
    	struct ast_codec_pref prefs;		/*!< codec prefs */
    	unsigned int ocseq;			/*!< Current outgoing seqno */
    	unsigned int icseq;			/*!< Current incoming seqno */
    	ast_group_t callgroup;			/*!< Call group */
    	ast_group_t pickupgroup;		/*!< Pickup group */
    	int lastinvite;				/*!< Last Cseq of invite */
    	unsigned int flags;			/*!< SIP_ flags */	
    	int timer_t1;				/*!< SIP timer T1, ms rtt */
    	unsigned int sipoptions;		/*!< Supported SIP sipoptions on the other end */
    	int capability;				/*!< Special capability (codec) */
    	int jointcapability;			/*!< Supported capability at both ends (codecs ) */
    	int peercapability;			/*!< Supported peer capability */
    	int prefcodec;				/*!< Preferred codec (outbound only) */
    
    Mark Spencer's avatar
    Mark Spencer committed
    	int noncodeccapability;
    
    	int callingpres;			/*!< Calling presentation */
    	int authtries;				/*!< Times we've tried to authenticate */
    	int expiry;				/*!< How long we take to expire */
    	int branch;				/*!< One random number */
    	char tag[11];				/*!< Another random number */
    	int sessionid;				/*!< SDP Session ID */
    	int sessionversion;			/*!< SDP Session Version */
    	struct sockaddr_in sa;			/*!< Our peer */
    	struct sockaddr_in redirip;		/*!< Where our RTP should be going if not to us */
    	struct sockaddr_in vredirip;		/*!< Where our Video RTP should be going if not to us */
    	int redircodecs;			/*!< Redirect codecs */
    	struct sockaddr_in recv;		/*!< Received as */
    	struct in_addr ourip;			/*!< Our IP */
    	struct ast_channel *owner;		/*!< Who owns us */
    	char exten[AST_MAX_EXTENSION];		/*!< Extension where to start */
    	char refer_to[AST_MAX_EXTENSION];	/*!< Place to store REFER-TO extension */
    	char referred_by[AST_MAX_EXTENSION];	/*!< Place to store REFERRED-BY extension */
    	char refer_contact[AST_MAX_EXTENSION];	/*!< Place to store Contact info from a REFER extension */
    	struct sip_pvt *refer_call;		/*!< Call we are referring */
    	struct sip_route *route;		/*!< Head of linked list of routing steps (fm Record-Route) */
    	int route_persistant;			/*!< Is this the "real" route? */
    	char from[256];				/*!< The From: header */
    	char useragent[256];			/*!< User agent in SIP request */
    	char context[AST_MAX_CONTEXT];		/*!< Context for this call */
    	char subscribecontext[AST_MAX_CONTEXT];	/*!< Subscribecontext */
    	char fromdomain[MAXHOSTNAMELEN];	/*!< Domain to show in the from field */
    	char fromuser[AST_MAX_EXTENSION];	/*!< User to show in the user field */
    	char fromname[AST_MAX_EXTENSION];	/*!< Name to show in the user field */
    	char tohost[MAXHOSTNAMELEN];		/*!< Host we should put in the "to" field */
    	char language[MAX_LANGUAGE];		/*!< Default language for this call */
    	char musicclass[MAX_MUSICCLASS];	/*!< Music on Hold class */
    	char rdnis[256];			/*!< Referring DNIS */
    	char theirtag[256];			/*!< Their tag */
    	char username[256];			/*!< [user] name */
    	char peername[256];			/*!< [peer] name, not set if [user] */
    	char authname[256];			/*!< Who we use for authentication */
    	char uri[256];				/*!< Original requested URI */
    	char okcontacturi[256];			/*!< URI from the 200 OK on INVITE */
    	char peersecret[256];			/*!< Password */
    
    	char peermd5secret[256];
    
    	struct sip_auth *peerauth;		/*!< Realm authentication */
    	char cid_num[256];			/*!< Caller*ID */
    	char cid_name[256];			/*!< Caller*ID */
    	char via[256];				/*!< Via: header */
    	char fullcontact[128];			/*!< The Contact: that the UA registers with us */
    	char accountcode[AST_MAX_ACCOUNT_CODE];	/*!< Account code */
    	char our_contact[256];			/*!< Our contact header */
    	char *rpid;				/*!< Our RPID header */
    	char *rpid_from;			/*!< Our RPID From header */
    	char realm[MAXHOSTNAMELEN];		/*!< Authorization realm */
    	char nonce[256];			/*!< Authorization nonce */
    	int noncecount;				/*!< Nonce-count */
    	char opaque[256];			/*!< Opaque nonsense */
    	char qop[80];				/*!< Quality of Protection, since SIP wasn't complicated enough yet. */
    	char domain[MAXHOSTNAMELEN];		/*!< Authorization domain */
    	char lastmsg[256];			/*!< Last Message sent/received */
    	int amaflags;				/*!< AMA Flags */
    	int pendinginvite;			/*!< Any pending invite */
    
    	int osphandle;				/*!< OSP Handle for call */
    	time_t ospstart;			/*!< OSP Start time */
    	unsigned int osptimelimit;		/*!< OSP call duration limit */
    
    	struct sip_request initreq;		/*!< Initial request */
    
    	int maxtime;				/*!< Max time for first response */
    	int initid;				/*!< Auto-congest ID if appropriate */
    	int autokillid;				/*!< Auto-kill ID */
    	time_t lastrtprx;			/*!< Last RTP received */
    	time_t lastrtptx;			/*!< Last RTP sent */
    	int rtptimeout;				/*!< RTP timeout time */
    	int rtpholdtimeout;			/*!< RTP timeout when on hold */
    	int rtpkeepalive;			/*!< Send RTP packets for keepalive */
    	enum subscriptiontype subscribed;	/*!< Is this call a subscription?  */
    
    	int stateid;
    
    	int laststate;                          /*!< Last known extension state */
    
    	struct ast_dsp *vad;			/*!< Voice Activation Detection dsp */
    
    	struct sip_peer *peerpoke;		/*!< If this calls is to poke a peer, which one */
    	struct sip_registry *registry;		/*!< If this is a REGISTER call, to which registry */
    	struct ast_rtp *rtp;			/*!< RTP Session */
    	struct ast_rtp *vrtp;			/*!< Video RTP session */
    	struct sip_pkt *packets;		/*!< Packets scheduled for re-transmission */
    	struct sip_history *history;		/*!< History of this SIP dialog */
    	struct ast_variable *chanvars;		/*!< Channel variables to set for call */
    	struct sip_pvt *next;			/*!< Next call in chain */
    	struct sip_invite_param *options;	/*!< Options for INVITE */
    
    Mark Spencer's avatar
    Mark Spencer committed
    } *iflist = NULL;
    
    
    #define FLAG_RESPONSE (1 << 0)
    #define FLAG_FATAL (1 << 1)
    
    
    /*! \brief sip packet - read in sipsock_read, transmitted in send_request */
    
    Mark Spencer's avatar
    Mark Spencer committed
    struct sip_pkt {
    
    	struct sip_pkt *next;			/*!< Next packet */
    	int retrans;				/*!< Retransmission number */
    	int method;				/*!< SIP method for this packet */
    	int seqno;				/*!< Sequence number */
    	unsigned int flags;			/*!< non-zero if this is a response packet (e.g. 200 OK) */
    	struct sip_pvt *owner;			/*!< Owner call */
    	int retransid;				/*!< Retransmission ID */
    	int timer_a;				/*!< SIP timer A, retransmission timer */
    	int timer_t1;				/*!< SIP Timer T1, estimated RTT or 500 ms */
    	int packetlen;				/*!< Length of packet */
    
    Mark Spencer's avatar
    Mark Spencer committed
    	char data[0];
    };	
    
    /*! \brief Structure for SIP user data. User's place calls to us */
    
    Mark Spencer's avatar
    Mark Spencer committed
    struct sip_user {
    	/* Users who can access various contexts */
    
    	char secret[80];		/*!< Password */
    	char md5secret[80];		/*!< Password in md5 */
    	char context[AST_MAX_CONTEXT];	/*!< Default context for incoming calls */
    
    	char subscribecontext[AST_MAX_CONTEXT];	/* Default context for subscriptions */
    
    	char cid_num[80];		/*!< Caller ID num */
    	char cid_name[80];		/*!< Caller ID name */
    
    	char accountcode[AST_MAX_ACCOUNT_CODE];	/* Account code */
    
    	char language[MAX_LANGUAGE];	/*!< Default language for this user */
    	char musicclass[MAX_MUSICCLASS];/*!< Music on Hold class */
    	char useragent[256];		/*!< User agent in SIP request */
    	struct ast_codec_pref prefs;	/*!< codec prefs */
    	ast_group_t callgroup;		/*!< Call group */
    	ast_group_t pickupgroup;	/*!< Pickup Group */
    	unsigned int flags;		/*!< SIP flags */	
    	unsigned int sipoptions;	/*!< Supported SIP options */
    	struct ast_flags flags_page2;	/*!< SIP_PAGE2 flags */
    	int amaflags;			/*!< AMA flags for billing */
    	int callingpres;		/*!< Calling id presentation */
    	int capability;			/*!< Codec capability */
    	int inUse;			/*!< Number of calls in use */
    	int call_limit;			/*!< Limit of concurrent calls */
    	struct ast_ha *ha;		/*!< ACL setting */
    	struct ast_variable *chanvars;	/*!< Variables to set for channel created by user */
    
    /* Structure for SIP peer data, we place calls to peers if registered  or fixed IP address (host) */
    
    Mark Spencer's avatar
    Mark Spencer committed
    struct sip_peer {
    
    	ASTOBJ_COMPONENTS(struct sip_peer);	/*!< name, refcount, objflags,  object pointers */
    					/*!< peer->name is the unique name of this object */
    	char secret[80];		/*!< Password */
    	char md5secret[80];		/*!< Password in MD5 */
    	struct sip_auth *auth;		/*!< Realm authentication list */
    	char context[AST_MAX_CONTEXT];	/*!< Default context for incoming calls */
    	char subscribecontext[AST_MAX_CONTEXT];	/*!< Default context for subscriptions */
    	char username[80];		/*!< Temporary username until registration */ 
    	char accountcode[AST_MAX_ACCOUNT_CODE];	/*!< Account code */
    	int amaflags;			/*!< AMA Flags (for billing) */
    	char tohost[MAXHOSTNAMELEN];	/*!< If not dynamic, IP address */
    	char regexten[AST_MAX_EXTENSION]; /*!< Extension to register (if regcontext is used) */
    	char fromuser[80];		/*!< From: user when calling this peer */
    	char fromdomain[MAXHOSTNAMELEN];	/*!< From: domain when calling this peer */
    	char fullcontact[256];		/*!< Contact registered with us (not in sip.conf) */
    	char cid_num[80];		/*!< Caller ID num */
    	char cid_name[80];		/*!< Caller ID name */
    	int callingpres;		/*!< Calling id presentation */
    	int inUse;			/*!< Number of calls in use */
    	int call_limit;			/*!< Limit of concurrent calls */
    	char vmexten[AST_MAX_EXTENSION]; /*!< Dialplan extension for MWI notify message*/
    	char mailbox[AST_MAX_EXTENSION]; /*!< Mailbox setting for MWI checks */
    	char language[MAX_LANGUAGE];	/*!<  Default language for prompts */
    	char musicclass[MAX_MUSICCLASS];/*!<  Music on Hold class */
    	char useragent[256];		/*!<  User agent in SIP request (saved from registration) */
    	struct ast_codec_pref prefs;	/*!<  codec prefs */
    
    	int lastmsgssent;
    
    	time_t	lastmsgcheck;		/*!<  Last time we checked for MWI */
    	unsigned int flags;		/*!<  SIP flags */	
    	unsigned int sipoptions;	/*!<  Supported SIP options */
    	struct ast_flags flags_page2;	/*!<  SIP_PAGE2 flags */
    	int expire;			/*!<  When to expire this peer registration */
    	int capability;			/*!<  Codec capability */
    	int rtptimeout;			/*!<  RTP timeout */
    	int rtpholdtimeout;		/*!<  RTP Hold Timeout */
    	int rtpkeepalive;		/*!<  Send RTP packets for keepalive */
    	ast_group_t callgroup;		/*!<  Call group */
    	ast_group_t pickupgroup;	/*!<  Pickup group */
    	struct ast_dnsmgr_entry *dnsmgr;/*!<  DNS refresh manager for peer */
    	struct sockaddr_in addr;	/*!<  IP address of peer */
    
    Mark Spencer's avatar
    Mark Spencer committed
    
    	/* Qualification */
    
    	struct sip_pvt *call;		/*!<  Call pointer */
    	int pokeexpire;			/*!<  When to expire poke (qualify= checking) */
    	int lastms;			/*!<  How long last response took (in ms), or -1 for no response */
    	int maxms;			/*!<  Max ms we will accept for the host to be up, 0 to not monitor */
    	struct timeval ps;		/*!<  Ping send time */
    
    	struct sockaddr_in defaddr;	/*!<  Default IP address, used until registration */
    	struct ast_ha *ha;		/*!<  Access control list */
    	struct ast_variable *chanvars;	/*!<  Variables to set for channel created by user */
    
    Mark Spencer's avatar
    Mark Spencer committed
    	int lastmsg;
    
    AST_MUTEX_DEFINE_STATIC(sip_reload_lock);
    
    static int sip_reloading = 0;
    
    /* States for outbound registrations (with register= lines in sip.conf */
    #define REG_STATE_UNREGISTERED		0
    #define REG_STATE_REGSENT		1
    #define REG_STATE_AUTHSENT		2
    #define REG_STATE_REGISTERED   		3
    #define REG_STATE_REJECTED	   	4
    #define REG_STATE_TIMEOUT	   	5
    #define REG_STATE_NOAUTH	   	6
    
    #define REG_STATE_FAILED		7
    
    /*! \brief sip_registry: Registrations with other SIP proxies */
    
    Mark Spencer's avatar
    Mark Spencer committed
    struct sip_registry {
    
    	ASTOBJ_COMPONENTS_FULL(struct sip_registry,1,1);
    
    	int portno;			/*!<  Optional port override */
    	char username[80];		/*!<  Who we are registering as */
    	char authuser[80];		/*!< Who we *authenticate* as */
    	char hostname[MAXHOSTNAMELEN];	/*!< Domain or host we register to */
    	char secret[80];		/*!< Password in clear text */	
    	char md5secret[80];		/*!< Password in md5 */
    	char contact[256];		/*!< Contact extension */
    
    Mark Spencer's avatar
    Mark Spencer committed
    	char random[80];
    
    	int expire;			/*!< Sched ID of expiration */
    	int regattempts;		/*!< Number of attempts (since the last success) */
    	int timeout; 			/*!< sched id of sip_reg_timeout */
    	int refresh;			/*!< How often to refresh */
    	struct sip_pvt *call;		/*!< create a sip_pvt structure for each outbound "registration call" in progress */
    	int regstate;			/*!< Registration state (see above) */
    	int callid_valid;		/*!< 0 means we haven't chosen callid for this registry yet. */
    	char callid[80];		/*!< Global CallID for this registry */
    	unsigned int ocseq;		/*!< Sequence number we got to for REGISTERs for this registry */
    	struct sockaddr_in us;		/*!< Who the server thinks we are */
    
     	char realm[MAXHOSTNAMELEN];	/*!< Authorization realm */
     	char nonce[256];		/*!< Authorization nonce */
     	char domain[MAXHOSTNAMELEN];	/*!< Authorization domain */
     	char opaque[256];		/*!< Opaque nonsense */
     	char qop[80];			/*!< Quality of Protection. */
    	int noncecount;			/*!< Nonce-count */
    
     	char lastmsg[256];		/*!< Last Message sent/received */
    
    /*! \brief  The user list: Users and friends ---*/
    
    static struct ast_user_list {
    
    	ASTOBJ_CONTAINER_COMPONENTS(struct sip_user);
    
    /*! \brief  The peer list: Peers and Friends ---*/
    
    static struct ast_peer_list {
    
    	ASTOBJ_CONTAINER_COMPONENTS(struct sip_peer);
    
    /*! \brief  The register list: Other SIP proxys we register with and call ---*/
    
    static struct ast_register_list {
    
    	ASTOBJ_CONTAINER_COMPONENTS(struct sip_registry);
    
    static int __sip_do_register(struct sip_registry *r);
    
    Mark Spencer's avatar
    Mark Spencer committed
    static int sipsock  = -1;
    
    static struct sockaddr_in bindaddr = { 0, };
    
    static struct sockaddr_in externip;
    
    static char externhost[MAXHOSTNAMELEN] = "";
    
    static time_t externexpire = 0;
    static int externrefresh = 10;
    
    /* The list of manual NOTIFY types we know how to send */
    struct ast_config *notify_types;
    
    
    static struct sip_auth *authl;          /*!< Authentication list */
    
    Mark Spencer's avatar
    Mark Spencer committed
    static struct ast_frame  *sip_read(struct ast_channel *ast);
    
    Mark Spencer's avatar
    Mark Spencer committed
    static int transmit_response(struct sip_pvt *p, char *msg, struct sip_request *req);
    
    static int transmit_response_with_sdp(struct sip_pvt *p, char *msg, struct sip_request *req, int retrans);
    
    static int transmit_response_with_unsupported(struct sip_pvt *p, char *msg, struct sip_request *req, char *unsupported);
    
    static int transmit_response_with_auth(struct sip_pvt *p, char *msg, struct sip_request *req, char *rand, int reliable, char *header, int stale);
    
    static int transmit_request(struct sip_pvt *p, int sipmethod, int inc, int reliable, int newbranch);
    static int transmit_request_with_auth(struct sip_pvt *p, int sipmethod, int inc, int reliable, int newbranch);
    
    static int transmit_invite(struct sip_pvt *p, int sipmethod, int sendsdp, int init);
    
    static int transmit_reinvite_with_sdp(struct sip_pvt *p);
    
    static int transmit_info_with_digit(struct sip_pvt *p, char digit);
    
    Mark Spencer's avatar
    Mark Spencer committed
    static int transmit_info_with_vidupdate(struct sip_pvt *p);
    
    static int transmit_message_with_text(struct sip_pvt *p, const char *text);
    static int transmit_refer(struct sip_pvt *p, const char *dest);
    static int sip_sipredirect(struct sip_pvt *p, const char *dest);
    
    static struct sip_peer *temp_peer(const char *name);
    
    static int do_proxy_auth(struct sip_pvt *p, struct sip_request *req, char *header, char *respheader, int sipmethod, int init);
    
    static void free_old_route(struct sip_route *route);
    
    static int build_reply_digest(struct sip_pvt *p, int method, char *digest, int digest_len);
    
    static int update_call_counter(struct sip_pvt *fup, int event);
    
    Mark Spencer's avatar
    Mark Spencer committed
    static struct sip_peer *build_peer(const char *name, struct ast_variable *v, int realtime);
    static struct sip_user *build_user(const char *name, struct ast_variable *v, int realtime);
    
    static int sip_do_reload(void);
    
    static int expire_register(void *data);
    
    static int callevents = 0;
    
    static struct ast_channel *sip_request_call(const char *type, int format, void *data, int *cause);
    
    static int sip_devicestate(void *data);
    
    static int sip_sendtext(struct ast_channel *ast, const char *text);
    
    static int sip_call(struct ast_channel *ast, char *dest, int timeout);
    static int sip_hangup(struct ast_channel *ast);
    static int sip_answer(struct ast_channel *ast);
    static struct ast_frame *sip_read(struct ast_channel *ast);
    static int sip_write(struct ast_channel *ast, struct ast_frame *frame);
    static int sip_indicate(struct ast_channel *ast, int condition);
    
    static int sip_transfer(struct ast_channel *ast, const char *dest);
    
    static int sip_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
    static int sip_senddigit(struct ast_channel *ast, char digit);
    
    static int clear_realm_authentication(struct sip_auth *authlist);                            /* Clear realm authentication list (at reload) */
    static struct sip_auth *add_realm_authentication(struct sip_auth *authlist, char *configuration, int lineno);   /* Add realm authentication in list */
    static struct sip_auth *find_realm_authentication(struct sip_auth *authlist, char *realm);         /* Find authentication for a specific realm */
    
    static int check_sip_domain(const char *domain, char *context, size_t len); /* Check if domain is one of our local domains */
    
    static void append_date(struct sip_request *req);	/* Append date to SIP packet */
    
    static int determine_firstline_parts(struct sip_request *req);
    
    static void sip_dump_history(struct sip_pvt *dialog);	/* Dump history to LOG_DEBUG at end of dialog, before destroying data */
    
    static const struct cfsubscription_types *find_subscription_type(enum subscriptiontype subtype);
    static int transmit_state_notify(struct sip_pvt *p, int state, int full, int substate);
    
    static char *gettag(struct sip_request *req, char *header, char *tagbuf, int tagbufsize);
    
    /*! \brief Definition of this channel for PBX channel registration */
    
    static const struct ast_channel_tech sip_tech = {
    	.type = channeltype,
    	.description = "Session Initiation Protocol (SIP)",
    	.capabilities = ((AST_FORMAT_MAX_AUDIO << 1) - 1),
    
    	.devicestate = sip_devicestate,
    	.call = sip_call,
    	.hangup = sip_hangup,
    	.answer = sip_answer,
    	.read = sip_read,
    	.write = sip_write,
    	.write_video = sip_write,
    	.indicate = sip_indicate,
    	.transfer = sip_transfer,
    	.fixup = sip_fixup,
    	.send_digit = sip_senddigit,
    	.bridge = ast_rtp_bridge,
    	.send_text = sip_sendtext,
    };
    
    
    Kevin P. Fleming's avatar
    Kevin P. Fleming committed
    /*!
      \brief Thread-safe random number generator
      \return a random number
    
      This function uses a mutex lock to guarantee that no
      two threads will receive the same random number.
     */
    static force_inline int thread_safe_rand(void)
    {
    	int val;
    
    	ast_mutex_lock(&rand_lock);
    	val = rand();
    	ast_mutex_unlock(&rand_lock);
    	
    	return val;
    }
    
    
    /*! \brief  find_sip_method: Find SIP method from header
     * Strictly speaking, SIP methods are case SENSITIVE, but we don't check 
     * following Jon Postel's rule: Be gentle in what you accept, strict with what you send */
    
    int find_sip_method(char *msg)
    {
    	int i, res = 0;
    
    	for (i = 1; (i < (sizeof(sip_methods) / sizeof(sip_methods[0]))) && !res; i++) {
    
    		if (!strcasecmp(sip_methods[i].text, msg)) 
    			res = sip_methods[i].id;
    	}
    	return res;
    }
    
    
    /*! \brief  parse_sip_options: Parse supported header in incoming packet */
    
    unsigned int parse_sip_options(struct sip_pvt *pvt, char *supported)
    {
    	char *next = NULL;
    	char *sep = NULL;
    	char *temp = ast_strdupa(supported);
    	int i;
    	unsigned int profile = 0;
    
    
    		return 0;
    
    	if (option_debug > 2 && sipdebug)
    		ast_log(LOG_DEBUG, "Begin: parsing SIP \"Supported: %s\"\n", supported);
    
    	next = temp;
    	while (next) {
    		char res=0;
    		if ( (sep = strchr(next, ',')) != NULL) {