[svn-commits] oej: branch oej/codename-pineapple r44696 - /team/oej/codename-pineapple/chan...

svn-commits at lists.digium.com svn-commits at lists.digium.com
Sat Oct 7 08:32:33 MST 2006


Author: oej
Date: Sat Oct  7 10:32:33 2006
New Revision: 44696

URL: http://svn.digium.com/view/asterisk?rev=44696&view=rev
Log:
Adding peermatch

Added:
    team/oej/codename-pineapple/channels/chan_sip3.c   (with props)

Added: team/oej/codename-pineapple/channels/chan_sip3.c
URL: http://svn.digium.com/view/asterisk/team/oej/codename-pineapple/channels/chan_sip3.c?rev=44696&view=auto
==============================================================================
--- team/oej/codename-pineapple/channels/chan_sip3.c (added)
+++ team/oej/codename-pineapple/channels/chan_sip3.c Sat Oct  7 10:32:33 2006
@@ -1,0 +1,16773 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 1999 - 2006, Digium, Inc.
+ *
+ * Mark Spencer <markster at digium.com>
+ *
+ *
+ *
+ * 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.
+ *
+ * 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
+ * Version 3 of chan_sip
+ *
+ * \author Mark Spencer <markster at digium.com>
+ * \author Olle E. Johansson <oej at edvina.net>
+ *
+ * See Also:
+ * \arg \ref AstCREDITS
+ *
+ * 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
+ * \todo VIA branch tag transaction checking
+ * \todo Transaction support
+ *
+ * \ingroup channel_drivers
+ *
+ * \par 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"
+ *
+ * \par incoming packets
+ * Incoming packets are received in the monitoring thread, then handled by
+ * sipsock_read(). This function parses the packet and matches an existing
+ * dialog or starts a new SIP dialog.
+ * 
+ * sipsock_read sends the packet to handle_request(), that parses a bit more.
+ * if it's a response to an outbound request, it's sent to handle_response().
+ * If it is a request, handle_request 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 
+ * 
+ * \par Outbound calls
+ * Outbound calls are set up by the PBX through the sip_request_call()
+ * function. After that, they are activated by sip_call().
+ * 
+ * \par Hanging up
+ * The PBX issues a hangup on both incoming and outgoing calls through
+ * the sip_hangup() function
+ */
+
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <unistd.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/in.h>
+#include <netinet/in_systm.h>
+#include <arpa/inet.h>
+#include <netinet/ip.h>
+#include <regex.h>
+
+#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/udptl.h"
+#include "asterisk/acl.h"
+#include "asterisk/manager.h"
+#include "asterisk/callerid.h"
+#include "asterisk/cli.h"
+#include "asterisk/app.h"
+#include "asterisk/musiconhold.h"
+#include "asterisk/dsp.h"
+#include "asterisk/features.h"
+#include "asterisk/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/devicestate.h"
+#include "asterisk/linkedlists.h"
+#include "asterisk/stringfields.h"
+#include "asterisk/monitor.h"
+#include "asterisk/localtime.h"
+#include "asterisk/abstract_jb.h"
+#include "asterisk/compiler.h"
+
+#define SIPLABEL	sip3
+
+#ifndef FALSE
+#define FALSE    0
+#endif
+
+#ifndef TRUE
+#define TRUE     1
+#endif
+
+#define VIDEO_CODEC_MASK        0x1fc0000 /*!< Video codecs from H.261 thru AST_FORMAT_MAX_VIDEO */
+#ifndef IPTOS_MINCOST
+#define IPTOS_MINCOST           0x02
+#endif
+
+/* #define VOCAL_DATA_HACK */
+
+#define DEFAULT_DEFAULT_EXPIRY  120
+#define DEFAULT_MIN_EXPIRY      60
+#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 */
+#define DEFAULT_EXPIRY 900                          /*!< Expire slowly */
+
+static int min_expiry = DEFAULT_MIN_EXPIRY;        /*!< Minimum accepted registration time */
+static int max_expiry = DEFAULT_MAX_EXPIRY;        /*!< Maximum accepted registration time */
+static int default_expiry = DEFAULT_DEFAULT_EXPIRY;
+static int expiry = DEFAULT_EXPIRY;
+
+#ifndef MAX
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#endif
+
+#define CALLERID_UNKNOWN        "Unknown"
+
+#define DEFAULT_MAXMS                2000             /*!< Qualification: Must be faster than 2 seconds by default */
+#define DEFAULT_FREQ_OK              60 * 1000        /*!< Qualification: How often to check for the host to be up */
+#define DEFAULT_FREQ_NOTOK           10 * 1000        /*!< Qualification: How often to check, if the host is down... */
+
+#define DEFAULT_RETRANS              1000             /*!< How frequently to retransmit Default: 2 * 500 ms in RFC 3261 */
+#define MAX_RETRANS                  6                /*!< Try only 6 times for retransmissions, a total of 7 transmissions */
+#define SIP_TRANS_TIMEOUT            32000            /*!< SIP request timeout (rfc 3261) 64*T1 
+                                                      \todo Use known T1 for timeout (peerpoke)
+                                                      */
+#define DEFAULT_TRANS_TIMEOUT        -1               /* Use default SIP transaction timeout */
+#define MAX_AUTHTRIES                3                /*!< Try authentication three times, then fail */
+
+#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 SIP_MAX_PACKET               4096             /*!< Also from RFC 3261 (2543), should sub headers tho */
+
+#define INITIAL_CSEQ                 101              /*!< our initial sip sequence number */
+
+/*! \brief Global jitterbuffer configuration - by default, jb is disabled */
+static struct ast_jb_conf default_jbconf =
+{
+        .flags = 0,
+	.max_size = -1,
+	.resync_threshold = -1,
+	.impl = ""
+};
+static struct ast_jb_conf global_jbconf;
+
+static const char config[] = "sip3.conf";
+static const char notify_config[] = "sip3_notify.conf";
+static int usecnt = 0;
+
+
+#define RTP 	1
+#define NO_RTP	0
+
+/*! \brief Authorization scheme for call transfers 
+\note Not a bitfield flag, since there are plans for other modes,
+	like "only allow transfers for authenticated devices" */
+enum transfermodes {
+	TRANSFER_OPENFORALL,            /*!< Allow all SIP transfers */
+	TRANSFER_CLOSED,                /*!< Allow no SIP transfers */
+};
+
+
+enum sip_result {
+	AST_SUCCESS = 0,
+	AST_FAILURE = -1,
+};
+
+/* 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 objecttype {
+	SIP_USER = (1 << 0),		/* USER places calls to the PBX */
+	SIP_PEER = (1 << 1),		/* Peer receives calls from PBX (and places calls) */
+};
+
+enum xmittype {
+	XMIT_CRITICAL = 2,              /*!< Transmit critical SIP message reliably, with re-transmits.
+                                              If it fails, it's critical and will cause a teardown of the session */
+	XMIT_RELIABLE = 1,              /*!< Transmit SIP message reliably, with re-transmits */
+	XMIT_UNRELIABLE = 0,            /*!< Transmit SIP message without bothering with re-transmits */
+};
+
+enum parse_register_result {
+	PARSE_REGISTER_FAILED,
+	PARSE_REGISTER_UPDATE,
+	PARSE_REGISTER_QUERY,
+};
+
+enum subscriptiontype { 
+	NONE = 0,
+	TIMEOUT,
+	XPIDF_XML,
+	DIALOG_INFO_XML,
+	CPIM_PIDF_XML,
+	PIDF_XML,
+	MWI_NOTIFICATION
+};
+
+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" },
+ 	/* RFC 4235: SIP Dialog event package */
+	{ 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 */
+	{ MWI_NOTIFICATION,	"message-summary", "application/simple-message-summary", "mwi" } /* RFC 3842: Mailbox notification */
+};
+
+/*! \brief SIP Request methods known by Asterisk */
+enum sipmethod {
+	SIP_UNKNOWN,		/* Unknown response */
+	SIP_RESPONSE,		/* Not request, response to outbound request */
+	SIP_REGISTER,
+	SIP_OPTIONS,
+	SIP_NOTIFY,
+	SIP_INVITE,
+	SIP_ACK,
+	SIP_PRACK,		/* Not supported at all */
+	SIP_BYE,
+	SIP_REFER,
+	SIP_SUBSCRIBE,
+	SIP_MESSAGE,
+	SIP_UPDATE,		/* We can send UPDATE; but not accept it */
+	SIP_INFO,
+	SIP_CANCEL,
+	SIP_PUBLISH,		/* Not supported at all */
+};
+
+/*! \brief Authentication types - proxy or www authentication 
+	\note Endpoints, like Asterisk, should always use WWW authentication to
+	allow multiple authentications in the same call - to the proxy and
+	to the end point.
+*/
+enum sip_auth_type {
+	PROXY_AUTH,
+	WWW_AUTH,
+};
+
+/*! \brief Authentication result from check_auth* functions */
+enum check_auth_result {
+	AUTH_SUCCESSFUL = 0,
+	AUTH_CHALLENGE_SENT = 1,
+	AUTH_SECRET_FAILED = -1,
+	AUTH_USERNAME_MISMATCH = -2,
+	AUTH_NOT_FOUND = -3,
+	AUTH_FAKE_AUTH = -4,
+	AUTH_UNKNOWN_DOMAIN = -5,
+};
+
+/*! \brief States for outbound registrations (with register= lines in sip.conf */
+enum sipregistrystate {
+	REG_STATE_UNREGISTERED = 0,	/*!< We are not registred */
+	REG_STATE_REGSENT,	/*!< Registration request sent */
+	REG_STATE_AUTHSENT,	/*!< We have tried to authenticate */
+	REG_STATE_REGISTERED,	/*!< Registred and done */
+	REG_STATE_REJECTED,	/*!< Registration rejected */
+	REG_STATE_TIMEOUT,	/*!< Registration timed out */
+	REG_STATE_NOAUTH,	/*!< We have no accepted credentials */
+	REG_STATE_FAILED,	/*!< Registration failed after several tries */
+};
+
+
+/*! XXX Note that sip_methods[i].id == i must hold or the code breaks */
+static const struct  cfsip_methods { 
+	enum sipmethod id;
+	int need_rtp;		/*!< when this is the 'primary' use for a pvt structure, does it need RTP? */
+	char * const text;
+} sip_methods[] = {
+	{ SIP_UNKNOWN,	 RTP,    "-UNKNOWN-" },
+	{ SIP_RESPONSE,	 NO_RTP, "SIP/2.0" },
+	{ SIP_REGISTER,	 NO_RTP, "REGISTER" },
+ 	{ SIP_OPTIONS,	 NO_RTP, "OPTIONS" },
+	{ SIP_NOTIFY,	 NO_RTP, "NOTIFY" },
+	{ 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" }
+};
+
+/*!  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)
+#define SIP_OPT_NOREFERSUB	(1 << 14)
+#define SIP_OPT_HISTINFO	(1 << 15)
+#define SIP_OPT_RESPRIORITY	(1 << 16)
+
+/*! \brief List of well-known SIP options. If we get this in a require,
+   we should check the list and answer accordingly. */
+static const struct cfsip_options {
+	int id;			/*!< Bitmap ID */
+	int supported;		/*!< Supported by Asterisk ? */
+	char * const text;	/*!< Text id, as in standard */
+} sip_options[] = {	/* XXX used in 3 places */
+	/* RFC3891: Replaces: header for transfer */
+	{ SIP_OPT_REPLACES,	SUPPORTED,	"replaces" },	
+	/* One version of Polycom firmware has the wrong label */
+	{ SIP_OPT_REPLACES,	SUPPORTED,	"replace" },	
+	/* RFC3262: PRACK 100% reliability */
+	{ SIP_OPT_100REL,	NOT_SUPPORTED,	"100rel" },	
+	/* RFC4028: SIP Session Timers */
+	{ SIP_OPT_TIMER,	NOT_SUPPORTED,	"timer" },
+	/* RFC3959: SIP Early session support */
+	{ SIP_OPT_EARLY_SESSION, NOT_SUPPORTED,	"early-session" },
+	/* RFC3911: 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-03.txt */
+	{ SIP_OPT_TARGET_DIALOG,NOT_SUPPORTED,	"tdialog" },
+	/* Disable the REFER subscription, RFC 4488 */
+	{ SIP_OPT_NOREFERSUB,	NOT_SUPPORTED,	"norefersub" },
+	/* ietf-sip-history-info-06.txt */
+	{ SIP_OPT_HISTINFO,	NOT_SUPPORTED,	"histinfo" },
+	/* ietf-sip-resource-priority-10.txt */
+	{ SIP_OPT_RESPRIORITY,	NOT_SUPPORTED,	"resource-priority" },
+};
+
+
+/*! \brief SIP Methods we support */
+#define ALLOWED_METHODS "INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY"
+
+/*! \brief SIP Extensions we support */
+#define SUPPORTED_EXTENSIONS "replaces" 
+
+
+/* Default values, set and reset in reload_config before reading configuration */
+/* These are default values in the source. There are other recommended values in the
+   sip.conf.sample for new installations. These may differ to keep backwards compatibility,
+   yet encouraging new behaviour on new installations 
+ */
+#define DEFAULT_SIP_PORT	5060	/*!< From RFC 3261 (former 2543) */
+#define DEFAULT_CONTEXT		"default"
+#define DEFAULT_MOHINTERPRET    "default"
+#define DEFAULT_MOHSUGGEST      ""
+#define DEFAULT_VMEXTEN 	"asterisk"
+#define DEFAULT_CALLERID 	"asterisk"
+#define DEFAULT_NOTIFYMIME 	"application/simple-message-summary"
+#define DEFAULT_MWITIME 	10
+#define DEFAULT_ALLOWGUEST	TRUE
+#define DEFAULT_SRVLOOKUP	FALSE		/*!< Recommended setting is ON */
+#define DEFAULT_COMPACTHEADERS	FALSE
+#define DEFAULT_TOS_SIP         0               /*!< Call signalling packets should be marked as DSCP CS3, but the default is 0 to be compatible with previous versions. */
+#define DEFAULT_TOS_AUDIO       0               /*!< Audio packets should be marked as DSCP EF (Expedited Forwarding), but the default is 0 to be compatible with previous versions. */
+#define DEFAULT_TOS_VIDEO       0               /*!< Video packets should be marked as DSCP AF41, but the default is 0 to be compatible with previous versions. */
+#define DEFAULT_ALLOW_EXT_DOM	TRUE
+#define DEFAULT_REALM		"asterisk"
+#define DEFAULT_NOTIFYRINGING	TRUE
+#define DEFAULT_PEDANTIC	FALSE
+#define DEFAULT_AUTOCREATEPEER	FALSE
+#define DEFAULT_QUALIFY		FALSE
+#define DEFAULT_T1MIN		100		/*!< 100 MS for minimal roundtrip time */
+#define DEFAULT_MAX_CALL_BITRATE (384)		/*!< Max bitrate for video */
+#ifndef DEFAULT_USERAGENT
+#define DEFAULT_USERAGENT "Asterisk PBX"	/*!< Default Useragent: header unless re-defined in sip.conf */
+#endif
+
+
+/* Default setttings are used as a channel setting and as a default when
+   configuring devices */
+static char default_context[AST_MAX_CONTEXT];
+static char default_subscribecontext[AST_MAX_CONTEXT];
+static char default_language[MAX_LANGUAGE];
+static char default_callerid[AST_MAX_EXTENSION];
+static char default_fromdomain[AST_MAX_EXTENSION];
+static char default_notifymime[AST_MAX_EXTENSION];
+static int default_qualify;		/*!< Default Qualify= setting */
+static char default_vmexten[AST_MAX_EXTENSION];
+static char default_mohinterpret[MAX_MUSICCLASS];  /*!< Global setting for moh class to use when put on hold */
+static char default_mohsuggest[MAX_MUSICCLASS];	   /*!< Global setting for moh class to suggest when putting 
+                                                    *   a bridged channel on hold */
+static int default_maxcallbitrate;	/*!< Maximum bitrate for call */
+static struct ast_codec_pref default_prefs;		/*!< Default codec prefs */
+
+/* Global settings only apply to the channel */
+static int global_rtautoclear;
+static int global_notifyringing;	/*!< Send notifications on ringing */
+static int global_alwaysauthreject;	/*!< Send 401 Unauthorized for all failing requests */
+static int srvlookup;			/*!< SRV Lookup on or off. Default is off, RFC behavior is on */
+static int pedanticsipchecking;		/*!< Extra checking ?  Default off */
+static int autocreatepeer;		/*!< Auto creation of peers at registration? Default off. */
+static int global_relaxdtmf;			/*!< Relax DTMF */
+static int global_rtptimeout;		/*!< Time out call if no RTP */
+static int global_rtpholdtimeout;
+static int global_rtpkeepalive;		/*!< Send RTP keepalives */
+static int global_reg_timeout;	
+static int global_regattempts_max;	/*!< Registration attempts before giving up */
+static int global_allowguest;		/*!< allow unauthenticated users/peers to connect? */
+static int global_allowsubscribe;	/*!< Flag for disabling ALL subscriptions, this is FALSE only if all peers are FALSE 
+					    the global setting is in globals_flags[1] */
+static int global_mwitime;		/*!< Time between MWI checks for peers */
+static unsigned int global_tos_sip;		/*!< IP type of service for SIP packets */
+static unsigned int global_tos_audio;		/*!< IP type of service for audio RTP packets */
+static unsigned int global_tos_video;		/*!< IP type of service for video RTP packets */
+static int compactheaders;		/*!< send compact sip headers */
+static int recordhistory;		/*!< Record SIP history. Off by default */
+static int dumphistory;			/*!< Dump history to verbose before destroying SIP dialog */
+static char global_realm[MAXHOSTNAMELEN]; 		/*!< Default realm */
+static char global_regcontext[AST_MAX_CONTEXT];		/*!< Context for auto-extensions */
+static char global_useragent[AST_MAX_EXTENSION];	/*!< Useragent for the SIP channel */
+static int allow_external_domains;	/*!< Accept calls to external SIP domains? */
+static int global_callevents;		/*!< Whether we send manager events or not */
+static int global_t1min;		/*!< T1 roundtrip time minimum */
+static enum transfermodes global_allowtransfer;	/*!< SIP Refer restriction scheme */
+
+/*! \brief Codecs that we support by default: */
+static int global_capability = AST_FORMAT_ULAW | AST_FORMAT_ALAW | AST_FORMAT_GSM | AST_FORMAT_H263;
+static int noncodeccapability = AST_RTP_DTMF;
+
+/* Object counters */
+static int suserobjs = 0;                /*!< Static users */
+static int ruserobjs = 0;                /*!< Realtime users */
+static int speerobjs = 0;                /*!< Statis peers */
+static int rpeerobjs = 0;                /*!< Realtime peers */
+static int apeerobjs = 0;                /*!< Autocreated peer objects */
+static int regobjs = 0;                  /*!< Registry objects */
+
+static struct ast_flags global_flags[2] = {{0}};        /*!< global SIP_ flags */
+
+static int global_autoframing = 0;
+
+/*! \brief Protect the SIP dialog 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
+   when it's doing something critical. */
+AST_MUTEX_DEFINE_STATIC(netlock);
+
+AST_MUTEX_DEFINE_STATIC(monlock);
+
+AST_MUTEX_DEFINE_STATIC(sip_reload_lock);
+
+/*! \brief This is the thread for the monitor which checks for input on the channels
+   which are not currently in use.  */
+static pthread_t monitor_thread = AST_PTHREADT_NULL;
+
+static int sip_reloading = FALSE;                       /*!< Flag for avoiding multiple reloads at the same time */
+static enum channelreloadreason sip_reloadreason;       /*!< Reason for last reload/load of configuration */
+
+static struct sched_context *sched;     /*!< The scheduling context */
+static struct io_context *io;           /*!< The IO context */
+static int *sipsock_read_id;            /*!< ID of IO entry for sipsock FD */
+
+#define DEC_CALL_LIMIT	0
+#define INC_CALL_LIMIT	1
+#define DEC_CALL_RINGING 2
+#define INC_CALL_RINGING 3
+
+/*! \brief sip_request: The data grabbed from the UDP socket */
+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 */
+	int lines;              /*!< Body Content */
+	unsigned int flags;     /*!< SIP_PKT Flags for this packet */
+	char *header[SIP_MAX_HEADERS];
+	char *line[SIP_MAX_LINES];
+	char data[SIP_MAX_PACKET];
+	unsigned int sdp_start; /*!< the line number where the SDP begins */
+	unsigned int sdp_end;   /*!< the line number where the SDP ends */
+};
+
+/*
+ * A sip packet is stored into the data[] buffer, with the header followed
+ * by an empty line and the body of the message.
+ * On outgoing packets, data is accumulated in data[] with len reflecting
+ * the next available byte, headers and lines count the number of lines
+ * in both parts. There are no '\0' in data[0..len-1].
+ *
+ * On received packet, the input read from the socket is copied into data[],
+ * len is set and the string is NUL-terminated. Then a parser fills up
+ * the other fields -header[] and line[] to point to the lines of the
+ * message, rlPart1 and rlPart2 parse the first lnie as below:
+ *
+ * Requests have in the first line	METHOD URI SIP/2.0
+ *	rlPart1 = method; rlPart2 = uri;
+ * Responses have in the first line	SIP/2.0 code description
+ *	rlPart1 = SIP/2.0; rlPart2 = code + description;
+ *
+ */
+
+/*! \brief structure used in transfers */
+struct sip_dual {
+	struct ast_channel *chan1;	/*!< First channel involved */
+	struct ast_channel *chan2;	/*!< Second channel involved */
+	struct sip_request req;		/*!< Request that caused the transfer (REFER) */
+	int seqno;			/*!< Sequence number */
+};
+
+struct sip_pkt;
+
+/*! \brief Parameters to the transmit_invite function */
+struct sip_invite_param {
+	int addsipheaders;		/*!< Add extra SIP headers */
+	const char *uri_options;	/*!< URI options to add to the URI */
+	const char *vxml_url;		/*!< VXML url for Cisco phones */
+	char *auth;			/*!< Authentication */
+	char *authheader;		/*!< Auth header */
+	enum sip_auth_type auth_type;	/*!< Authentication type */
+	const char *replaces;		/*!< Replaces header for call transfers */
+	int transfer;			/*!< Flag - is this Invite part of a SIP transfer? (invite/replaces) */
+};
+
+/*! \brief Structure to save routing information for a SIP session */
+struct sip_route {
+	struct sip_route *next;
+	char hop[0];
+};
+
+/*! \brief Modes for SIP domain handling in the PBX */
+enum domain_mode {
+	SIP_DOMAIN_AUTO,		/*!< This domain is auto-configured */
+	SIP_DOMAIN_CONFIG,		/*!< This domain is from configuration */
+};
+
+/*! \brief Domain data structure. 
+	\note In the future, we will connect this to a configuration tree specific
+	for this domain
+*/
+struct domain {
+	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 */
+
+
+/*! \brief sip_history: Structure for saving transactions within a SIP dialog */
+struct sip_history {
+	AST_LIST_ENTRY(sip_history) list;
+	char event[0];	/* actually more, depending on needs */
+};
+
+AST_LIST_HEAD_NOLOCK(sip_history_head, sip_history); /*!< history list, entry in sip_pvt */
+
+/*! \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 */
+};
+
+/*--- Various flags for the flags field in the pvt structure */
+#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 by the monitor thread */
+#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_CAN_BYE		(1 << 14)	/*!< Can we send BYE on this dialog? */
+#define SIP_DEFER_BYE_ON_TRANSFER	(1 << 15)	/*!< Do not hangup at first ast_hangup */
+#define SIP_DTMF		(3 << 16)	/*!< DTMF Support: four settings, uses two bits */
+#define SIP_DTMF_RFC2833	(0 << 16)	/*!< DTMF Support: RTP DTMF - "rfc2833" */
+#define SIP_DTMF_INBAND		(1 << 16)	/*!< DTMF Support: Inband audio, only for ULAW/ALAW - "inband" */
+#define SIP_DTMF_INFO		(2 << 16)	/*!< DTMF Support: SIP Info messages - "info" */
+#define SIP_DTMF_AUTO		(3 << 16)	/*!< DTMF Support: 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)	/*!< NAT RFC3581 */
+#define SIP_NAT_ROUTE		(2 << 18)	/*!< NAT Only ROUTE */
+#define SIP_NAT_ALWAYS		(3 << 18)	/*!< NAT Both ROUTE and RFC3581 */
+/* re-INVITE related settings */
+#define SIP_REINVITE		(7 << 20)	/*!< three bits used */
+#define SIP_CAN_REINVITE	(1 << 20)	/*!< allow peers to be reinvited to send media directly p2p */
+#define SIP_CAN_REINVITE_NAT	(2 << 20)	/*!< allow media reinvite when new peer is behind NAT */
+#define SIP_REINVITE_UPDATE	(4 << 20)	/*!< use UPDATE (RFC3311) when reinviting this peer */
+/* "insecure" settings */
+#define SIP_INSECURE_PORT	(1 << 23)	/*!< don't require matching port for incoming requests */
+#define SIP_INSECURE_INVITE	(1 << 24)	/*!< don't require authentication for incoming INVITEs */
+/* Sending PROGRESS in-band settings */
+#define SIP_PROG_INBAND		(3 << 25)	/*!< three settings, uses two bits */
+#define SIP_PROG_INBAND_NEVER	(0 << 25)
+#define SIP_PROG_INBAND_NO	(1 << 25)
+#define SIP_PROG_INBAND_YES	(2 << 25)
+#define SIP_FREE_BIT		(1 << 27)	/*!< Undefined bit - not in use */
+#define SIP_CALL_LIMIT		(1 << 28)	/*!< Call limit enforced for this call */
+#define SIP_SENDRPID		(1 << 29)	/*!< Remote Party-ID Support */
+#define SIP_INC_COUNT		(1 << 30)	/*!< Did this connection increment the counter of in-use calls? */
+#define SIP_G726_NONSTANDARD	(1 << 31)	/*!< Use non-standard packing for G726-32 data */
+
+#define SIP_FLAGS_TO_COPY \
+	(SIP_PROMISCREDIR | SIP_TRUSTRPID | SIP_SENDRPID | SIP_DTMF | SIP_REINVITE | \
+	 SIP_PROG_INBAND | SIP_USECLIENTCODE | SIP_NAT | SIP_G726_NONSTANDARD | \
+	 SIP_USEREQPHONE | SIP_INSECURE_PORT | SIP_INSECURE_INVITE)
+
+/*--- a new page of flags (for flags[1] */
+/* realtime flags */
+#define SIP_PAGE2_RTCACHEFRIENDS	(1 << 0)
+#define SIP_PAGE2_RTUPDATE		(1 << 1)
+#define SIP_PAGE2_RTAUTOCLEAR		(1 << 2)
+#define SIP_PAGE2_RT_FROMCONTACT 	(1 << 4)
+#define SIP_PAGE2_RTSAVE_SYSNAME 	(1 << 5)
+/* Space for addition of other realtime flags in the future */
+#define SIP_PAGE2_IGNOREREGEXPIRE	(1 << 10)
+#define SIP_PAGE2_DEBUG			(3 << 11)
+#define SIP_PAGE2_DEBUG_CONFIG 		(1 << 11)
+#define SIP_PAGE2_DEBUG_CONSOLE 	(1 << 12)
+#define SIP_PAGE2_DYNAMIC		(1 << 13)	/*!< Dynamic Peers register with Asterisk */
+#define SIP_PAGE2_SELFDESTRUCT		(1 << 14)	/*!< Automatic peers need to destruct themselves */
+#define SIP_PAGE2_VIDEOSUPPORT		(1 << 15)
+#define SIP_PAGE2_ALLOWSUBSCRIBE	(1 << 16)	/*!< Allow subscriptions from this peer? */
+#define SIP_PAGE2_ALLOWOVERLAP		(1 << 17)	/*!< Allow overlap dialing ? */
+#define SIP_PAGE2_SUBSCRIBEMWIONLY	(1 << 18)	/*!< Only issue MWI notification if subscribed to */
+#define SIP_PAGE2_INC_RINGING		(1 << 19)	/*!< Did this connection increment the counter of in-use calls? */
+#define SIP_PAGE2_T38SUPPORT		(7 << 20)	/*!< T38 Fax Passthrough Support */
+#define SIP_PAGE2_T38SUPPORT_UDPTL	(1 << 20)	/*!< 20: T38 Fax Passthrough Support */
+#define SIP_PAGE2_T38SUPPORT_RTP	(2 << 20)	/*!< 21: T38 Fax Passthrough Support */
+#define SIP_PAGE2_T38SUPPORT_TCP	(4 << 20)	/*!< 22: T38 Fax Passthrough Support */
+#define SIP_PAGE2_CALL_ONHOLD		(3 << 23)	/*!< Call states */
+#define SIP_PAGE2_CALL_ONHOLD_ONEDIR	(1 << 23)	/*!< 23: One directional hold */
+#define SIP_PAGE2_CALL_ONHOLD_INACTIVE	(2 << 24)	/*!< 24: Inactive  */
+#define SIP_PAGE2_RFC2833_COMPENSATE    (1 << 26)
+
+#define SIP_PAGE2_FLAGS_TO_COPY \
+	(SIP_PAGE2_ALLOWSUBSCRIBE | SIP_PAGE2_ALLOWOVERLAP | SIP_PAGE2_VIDEOSUPPORT | SIP_PAGE2_T38SUPPORT | SIP_PAGE2_RFC2833_COMPENSATE)
+
+/* 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 */
+#define SIP_PKT_IGNORE 		(1 << 2)	/*!< This is a re-transmit, ignore it */
+#define SIP_PKT_IGNORE_RESP	(1 << 3)	/*!< Resp ignore - ??? */
+#define SIP_PKT_IGNORE_REQ	(1 << 4)	/*!< Req ignore - ??? */
+
+/* T.38 set of flags */
+#define T38FAX_FILL_BIT_REMOVAL		(1 << 0)	/*!< Default: 0 (unset)*/
+#define T38FAX_TRANSCODING_MMR			(1 << 1)	/*!< Default: 0 (unset)*/
+#define T38FAX_TRANSCODING_JBIG		(1 << 2)	/*!< Default: 0 (unset)*/
+/* Rate management */
+#define T38FAX_RATE_MANAGEMENT_TRANSFERED_TCF	(0 << 3)
+#define T38FAX_RATE_MANAGEMENT_LOCAL_TCF	(1 << 3)	/*!< Unset for transferredTCF (UDPTL), set for localTCF (TPKT) */
+/* UDP Error correction */
+#define T38FAX_UDP_EC_NONE			(0 << 4)	/*!< two bits, if unset NO t38UDPEC field in T38 SDP*/
+#define T38FAX_UDP_EC_FEC			(1 << 4)	/*!< Set for t38UDPFEC */
+#define T38FAX_UDP_EC_REDUNDANCY		(2 << 4)	/*!< Set for t38UDPRedundancy */
+/* T38 Spec version */
+#define T38FAX_VERSION				(3 << 6)	/*!< two bits, 2 values so far, up to 4 values max */
+#define T38FAX_VERSION_0			(0 << 6)	/*!< Version 0 */
+#define T38FAX_VERSION_1			(1 << 6)	/*!< Version 1 */
+/* Maximum Fax Rate */
+#define T38FAX_RATE_2400			(1 << 8)	/*!< 2400 bps t38FaxRate */
+#define T38FAX_RATE_4800			(1 << 9)	/*!< 4800 bps t38FaxRate */
+#define T38FAX_RATE_7200			(1 << 10)	/*!< 7200 bps t38FaxRate */
+#define T38FAX_RATE_9600			(1 << 11)	/*!< 9600 bps t38FaxRate */
+#define T38FAX_RATE_12000			(1 << 12)	/*!< 12000 bps t38FaxRate */
+#define T38FAX_RATE_14400			(1 << 13)	/*!< 14400 bps t38FaxRate */
+
+/*!< This is default: NO MMR and JBIG trancoding, NO fill bit removal, transferredTCF TCF, UDP FEC, Version 0 and 9600 max fax rate */
+static int global_t38_capability = T38FAX_VERSION_0 | T38FAX_RATE_2400 | T38FAX_RATE_4800 | T38FAX_RATE_7200 | T38FAX_RATE_9600;
+
+#define sipdebug		ast_test_flag(&global_flags[1], SIP_PAGE2_DEBUG)
+#define sipdebug_config		ast_test_flag(&global_flags[1], SIP_PAGE2_DEBUG_CONFIG)
+#define sipdebug_console	ast_test_flag(&global_flags[1], SIP_PAGE2_DEBUG_CONSOLE)
+
+/*! \brief T38 States for a call */
+enum t38state {
+        T38_DISABLED = 0,                /*!< Not enabled */
+        T38_LOCAL_DIRECT,                /*!< Offered from local */
+        T38_LOCAL_REINVITE,              /*!< Offered from local - REINVITE */
+        T38_PEER_DIRECT,                 /*!< Offered from peer */
+        T38_PEER_REINVITE,               /*!< Offered from peer - REINVITE */
+        T38_ENABLED                      /*!< Negotiated (enabled) */
+};
+
+/*! \brief T.38 channel settings (at some point we need to make this alloc'ed */
+struct t38properties {
+	struct ast_flags t38support;	/*!< Flag for udptl, rtp or tcp support for this session */
+	int capability;			/*!< Our T38 capability */
+	int peercapability;		/*!< Peers T38 capability */
+	int jointcapability;		/*!< Supported T38 capability at both ends */
+	enum t38state state;		/*!< T.38 state */
+};
+
+/*! \brief Parameters to know status of transfer */
+enum referstatus {
+        REFER_IDLE,                    /*!< No REFER is in progress */
+        REFER_SENT,                    /*!< Sent REFER to transferee */
+        REFER_RECEIVED,                /*!< Received REFER from transferer */
+        REFER_CONFIRMED,               /*!< Refer confirmed with a 100 TRYING */
+        REFER_ACCEPTED,                /*!< Accepted by transferee */
+        REFER_RINGING,                 /*!< Target Ringing */
+        REFER_200OK,                   /*!< Answered by transfer target */
+        REFER_FAILED,                  /*!< REFER declined - go on */
+        REFER_NOAUTH                   /*!< We had no auth for REFER */
+};
+
+static const struct c_referstatusstring {
+	enum referstatus status;
+	char *text;
+} referstatusstrings[] = {
+	{ REFER_IDLE,		"<none>" },
+	{ REFER_SENT,		"Request sent" },
+	{ REFER_RECEIVED,	"Request received" },
+	{ REFER_ACCEPTED,	"Accepted" },
+	{ REFER_RINGING,	"Target ringing" },
+	{ REFER_200OK,		"Done" },
+	{ REFER_FAILED,		"Failed" },
+	{ REFER_NOAUTH,		"Failed - auth failure" }
+} ;
+
+/*! \brief Structure to handle SIP transfers. Dynamically allocated when needed  */
+/* OEJ: Should be moved to string fields */
+struct sip_refer {
+	char refer_to[AST_MAX_EXTENSION];		/*!< Place to store REFER-TO extension */
+	char refer_to_domain[AST_MAX_EXTENSION];	/*!< Place to store REFER-TO domain */
+	char refer_to_urioption[AST_MAX_EXTENSION];	/*!< Place to store REFER-TO uri options */
+	char refer_to_context[AST_MAX_EXTENSION];	/*!< Place to store REFER-TO context */
+	char referred_by[AST_MAX_EXTENSION];		/*!< Place to store REFERRED-BY extension */
+	char referred_by_name[AST_MAX_EXTENSION];	/*!< Place to store REFERRED-BY extension */
+	char refer_contact[AST_MAX_EXTENSION];		/*!< Place to store Contact info from a REFER extension */
+	char replaces_callid[BUFSIZ];			/*!< Replace info: callid */
+	char replaces_callid_totag[BUFSIZ/2];		/*!< Replace info: to-tag */
+	char replaces_callid_fromtag[BUFSIZ/2];		/*!< Replace info: from-tag */
+	struct sip_pvt *refer_call;			/*!< Call we are referring */
+	int attendedtransfer;				/*!< Attended or blind transfer? */
+	int localtransfer;				/*!< Transfer to local domain? */
+	enum referstatus status;			/*!< REFER status */
+};
+
+/*! \brief sip_pvt: PVT structures are used for each SIP dialog, ie. a call, a registration, a subscribe  */
+static struct sip_pvt {
+	ast_mutex_t lock;			/*!< Dialog private lock */
+	int method;				/*!< SIP method that opened this dialog */
+	AST_DECLARE_STRING_FIELDS(
+		AST_STRING_FIELD(callid);	/*!< Global CallID */
+		AST_STRING_FIELD(randdata);	/*!< Random data */
+		AST_STRING_FIELD(accountcode);	/*!< Account code */
+		AST_STRING_FIELD(realm);	/*!< Authorization realm */
+		AST_STRING_FIELD(nonce);	/*!< Authorization nonce */
+		AST_STRING_FIELD(opaque);	/*!< Opaque nonsense */
+		AST_STRING_FIELD(qop);		/*!< Quality of Protection, since SIP wasn't complicated enough yet. */

[... 15909 lines stripped ...]


More information about the svn-commits mailing list