[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