[asterisk-commits] oej: branch oej/codename-pineapple r53128 - in /team/oej/codename-pineapple: ...

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Fri Feb 2 13:38:19 MST 2007


Author: oej
Date: Fri Feb  2 14:38:18 2007
New Revision: 53128

URL: http://svn.digium.com/view/asterisk?view=rev&rev=53128
Log:
Major update - the "Rod" version :-)

Added:
    team/oej/codename-pineapple/channels/sip3/sip3_objects.c   (with props)
    team/oej/codename-pineapple/channels/sip3/sip3_transmit.c   (with props)
Modified:
    team/oej/codename-pineapple/Makefile
    team/oej/codename-pineapple/channels/Makefile
    team/oej/codename-pineapple/channels/chan_iax2.c
    team/oej/codename-pineapple/channels/chan_sip.c
    team/oej/codename-pineapple/channels/chan_sip3.c
    team/oej/codename-pineapple/channels/sip3/Makefile
    team/oej/codename-pineapple/channels/sip3/sip3.h
    team/oej/codename-pineapple/channels/sip3/sip3_auth.c
    team/oej/codename-pineapple/channels/sip3/sip3_callerid.c
    team/oej/codename-pineapple/channels/sip3/sip3_cliami.c
    team/oej/codename-pineapple/channels/sip3/sip3_compose.c
    team/oej/codename-pineapple/channels/sip3/sip3_config.c
    team/oej/codename-pineapple/channels/sip3/sip3_dialog.c
    team/oej/codename-pineapple/channels/sip3/sip3_domain.c
    team/oej/codename-pineapple/channels/sip3/sip3_monitor.c
    team/oej/codename-pineapple/channels/sip3/sip3_network.c
    team/oej/codename-pineapple/channels/sip3/sip3_parse.c
    team/oej/codename-pineapple/channels/sip3/sip3_pokedevice.c
    team/oej/codename-pineapple/channels/sip3/sip3_refer.c
    team/oej/codename-pineapple/channels/sip3/sip3_sdprtp.c
    team/oej/codename-pineapple/channels/sip3/sip3_services.c
    team/oej/codename-pineapple/channels/sip3/sip3_subscribe.c
    team/oej/codename-pineapple/channels/sip3/sip3_utils.c
    team/oej/codename-pineapple/channels/sip3/sip3funcs.h
    team/oej/codename-pineapple/configs/sip3.conf.sample
    team/oej/codename-pineapple/funcs/func_strings.c
    team/oej/codename-pineapple/main/asterisk.c
    team/oej/codename-pineapple/main/cdr.c
    team/oej/codename-pineapple/main/devicestate.c
    team/oej/codename-pineapple/main/http.c
    team/oej/codename-pineapple/main/manager.c
    team/oej/codename-pineapple/main/pbx.c
    team/oej/codename-pineapple/main/rtp.c

Modified: team/oej/codename-pineapple/Makefile
URL: http://svn.digium.com/view/asterisk/team/oej/codename-pineapple/Makefile?view=diff&rev=53128&r1=53127&r2=53128
==============================================================================
--- team/oej/codename-pineapple/Makefile (original)
+++ team/oej/codename-pineapple/Makefile Fri Feb  2 14:38:18 2007
@@ -540,6 +540,7 @@
 		echo "" ; \
 		echo ";[options]" ; \
 		echo ";internal_timing = yes" ; \
+		echo ";systemname = my_system_name ; prefix uniqueid with a system name for global uniqueness issues" ; \
 		echo "; Changing the following lines may compromise your security." ; \
 		echo ";[files]" ; \
 		echo ";astctlpermissions = 0660" ; \

Modified: team/oej/codename-pineapple/channels/Makefile
URL: http://svn.digium.com/view/asterisk/team/oej/codename-pineapple/channels/Makefile?view=diff&rev=53128&r1=53127&r2=53128
==============================================================================
--- team/oej/codename-pineapple/channels/Makefile (original)
+++ team/oej/codename-pineapple/channels/Makefile Fri Feb  2 14:38:18 2007
@@ -16,7 +16,8 @@
 SIP3_MODULES=chan_sip3.o sip3/sip3_network.o sip3/sip3_subscribe.o sip3/sip3_refer.o sip3/sip3_domain.o \
 	sip3/sip3_callerid.o sip3/sip3_auth.o sip3/sip3_sdprtp.o sip3/sip3_config.o \
 	sip3/sip3_cliami.o sip3/sip3_dialog.o sip3/sip3_services.o sip3/sip3_compose.o \
-	sip3/sip3_parse.o sip3/sip3_utils.o sip3/sip3_pokedevice.o sip3/sip3_monitor.o
+	sip3/sip3_parse.o sip3/sip3_utils.o sip3/sip3_pokedevice.o sip3/sip3_monitor.o \
+	sip3/sip3_objects.o sip3/sip3_transmit.o
 
 ifeq ($(OSARCH),OpenBSD)
   PTLIB=-lpt_OpenBSD_x86_r
@@ -59,7 +60,7 @@
   LOADABLE_MODS:=
 endif
 
-all: _all sip3
+all: _all 
 
 include $(ASTTOPDIR)/Makefile.moddir_rules
 

Modified: team/oej/codename-pineapple/channels/chan_iax2.c
URL: http://svn.digium.com/view/asterisk/team/oej/codename-pineapple/channels/chan_iax2.c?view=diff&rev=53128&r1=53127&r2=53128
==============================================================================
--- team/oej/codename-pineapple/channels/chan_iax2.c (original)
+++ team/oej/codename-pineapple/channels/chan_iax2.c Fri Feb  2 14:38:18 2007
@@ -6163,6 +6163,8 @@
 	if (ast_pthread_create(&newthread, &attr, dp_lookup_thread, dpr)) {
 		ast_log(LOG_WARNING, "Unable to start lookup thread!\n");
 	}
+
+	pthread_attr_destroy(&attr);
 }
 
 struct iax_dual {
@@ -6237,8 +6239,11 @@
 
 		d->chan1 = chan1m;
 		d->chan2 = chan2m;
-		if (!ast_pthread_create_background(&th, &attr, iax_park_thread, d))
+		if (!ast_pthread_create_background(&th, &attr, iax_park_thread, d)) {
+			pthread_attr_destroy(&attr);
 			return 0;
+		}
+		pthread_attr_destroy(&attr);
 		free(d);
 	}
 	return -1;

Modified: team/oej/codename-pineapple/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/oej/codename-pineapple/channels/chan_sip.c?view=diff&rev=53128&r1=53127&r2=53128
==============================================================================
--- team/oej/codename-pineapple/channels/chan_sip.c (original)
+++ team/oej/codename-pineapple/channels/chan_sip.c Fri Feb  2 14:38:18 2007
@@ -526,6 +526,7 @@
 static struct ast_codec_pref default_prefs;		/*!< Default codec prefs */
 
 /* Global settings only apply to the channel */
+static int global_directrtpsetup;	/*!< Enable support for Direct RTP setup (no re-invites) */
 static int global_limitonpeers;		/*!< Match call limit on peers only */
 static int global_rtautoclear;
 static int global_notifyringing;	/*!< Send notifications on ringing */
@@ -562,7 +563,6 @@
 
 /*! \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 */
@@ -944,6 +944,7 @@
 	int peercapability;			/*!< Supported peer capability */
 	int prefcodec;				/*!< Preferred codec (outbound only) */
 	int noncodeccapability;			/*!< DTMF RFC2833 telephony-event */
+	int jointnoncodeccapability;            /*!< Joint Non codec capability */
 	int redircodecs;			/*!< Redirect codecs */
 	int maxcallbitrate;			/*!< Maximum Call Bitrate for Video Calls */	
 	struct t38properties t38;		/*!< T38 settings */
@@ -1095,6 +1096,7 @@
 	int inRinging;			/*!< Number of calls ringing */
 	int onHold;                     /*!< Peer has someone on hold */
 	int call_limit;			/*!< Limit of concurrent calls */
+	int busy_limit;			/*!< Limit where we signal busy */
 	enum transfermodes allowtransfer;	/*! SIP Refer restriction scheme */
 	char vmexten[AST_MAX_EXTENSION]; /*!< Dialplan extension for MWI notify message*/
 	char mailbox[AST_MAX_EXTENSION]; /*!< Mailbox setting for MWI checks */
@@ -1331,7 +1333,7 @@
 static int sip_do_reload(enum channelreloadreason reason);
 static int reload_config(enum channelreloadreason reason);
 static int expire_register(void *data);
-static void *do_sip_monitor(void *data);
+static void *do_monitor(void *data);
 static int restart_monitor(void);
 static int sip_send_mwi_to_peer(struct sip_peer *peer);
 static void sip_destroy(struct sip_pvt *p);
@@ -2960,7 +2962,8 @@
 
 	p->callingpres = ast->cid.cid_pres;
 	p->jointcapability = ast_translate_available_formats(p->capability, p->prefcodec);
-	
+	p->jointnoncodeccapability = p->noncodeccapability;
+
 	/* If there are no audio formats left to offer, punt */
 	if (!(p->jointcapability & AST_FORMAT_AUDIO_MASK)) {
 		ast_log(LOG_WARNING, "No audio format found to offer. Cancelling call to %s\n", p->username);
@@ -3013,6 +3016,12 @@
 
 	if (sip_debug_test_pvt(p) || option_debug > 2)
 		ast_verbose("Really destroying SIP dialog '%s' Method: %s\n", p->callid, sip_methods[p->method].text);
+
+	if (ast_test_flag(&p->flags[0], SIP_INC_COUNT)) {
+		update_call_counter(p, DEC_CALL_LIMIT);
+		if (option_debug > 1)
+			ast_log(LOG_DEBUG, "This call did not properly clean up call limits. Call ID %s\n", p->callid);
+	}
 
 	/* Remove link from peer to subscription of MWI */
 	if (p->relatedpeer && p->relatedpeer->mwipvt) 
@@ -3155,9 +3164,10 @@
 	/* incoming and outgoing affects the inUse counter */
 	case DEC_CALL_LIMIT:
 		/* Decrement inuse count if applicable */
-		if (inuse && ast_test_flag(&fup->flags[0], SIP_INC_COUNT))
+		if (inuse && ast_test_flag(&fup->flags[0], SIP_INC_COUNT)) {
 			ast_atomic_fetchadd_int(inuse, -1);
-		else
+			ast_clear_flag(&fup->flags[0], SIP_INC_COUNT);
+		} else
 			*inuse = 0;
 		/* Decrement ringing count if applicable */
 		if (inringing && ast_test_flag(&fup->flags[1], SIP_PAGE2_INC_RINGING)) {
@@ -3642,7 +3652,7 @@
 				we simply forget the frames if we get modem frames before the bridge is up.
 				Fax will re-transmit.
 			*/
-			if (p->udptl && ast->_state != AST_STATE_UP) 
+			if (p->udptl && ast->_state == AST_STATE_UP) 
 				res = ast_udptl_write(p->udptl, frame);
 			sip_pvt_unlock(p);
 		}
@@ -5207,7 +5217,7 @@
 
 	newjointcapability = p->capability & (peercapability | vpeercapability);
 	newpeercapability = (peercapability | vpeercapability);
-	newnoncodeccapability = noncodeccapability & peernoncodeccapability;
+	newnoncodeccapability = p->noncodeccapability & peernoncodeccapability;
 		
 		
 	if (debug) {
@@ -5221,7 +5231,7 @@
 			    ast_getformatname_multiple(s4, BUFSIZ, newjointcapability));
 
 		ast_verbose("Non-codec capabilities (dtmf): us - %s, peer - %s, combined - %s\n",
-			    ast_rtp_lookup_mime_multiple(s1, BUFSIZ, noncodeccapability, 0, 0),
+			    ast_rtp_lookup_mime_multiple(s1, BUFSIZ, p->noncodeccapability, 0, 0),
 			    ast_rtp_lookup_mime_multiple(s2, BUFSIZ, peernoncodeccapability, 0, 0),
 			    ast_rtp_lookup_mime_multiple(s3, BUFSIZ, newnoncodeccapability, 0, 0));
 	}
@@ -5240,9 +5250,9 @@
 
 	/* We are now ready to change the sip session and p->rtp and p->vrtp with the offered codecs, since
 		they are acceptable */
-	p->jointcapability = newjointcapability;	/* Our joint codec profile for this call */
-	p->peercapability = newpeercapability;		/* The other sides capability in latest offer */
-	p->noncodeccapability = newnoncodeccapability;	/* DTMF capabilities */
+	p->jointcapability = newjointcapability;	        /* Our joint codec profile for this call */
+	p->peercapability = newpeercapability;		        /* The other sides capability in latest offer */
+	p->jointnoncodeccapability = newnoncodeccapability;	/* DTMF capabilities */
 
 	ast_rtp_pt_copy(p->rtp, newaudiortp);
 	if (p->vrtp)
@@ -6394,7 +6404,7 @@
 
 	/* Now add DTMF RFC2833 telephony-event as a codec */
 	for (x = 1; x <= AST_RTP_MAX; x <<= 1) {
-		if (!(p->noncodeccapability & x))
+		if (!(p->jointnoncodeccapability & x))
 			continue;
 
 		add_noncodec_to_sdp(p, x, 8000,
@@ -6965,6 +6975,10 @@
 		pidfnote = "Unavailable";
 		break;
 	case AST_EXTENSION_ONHOLD:
+		statestring = "confirmed";
+		local_state = NOTIFY_INUSE;
+		pidfstate = "busy";
+		pidfnote = "On hold";
 		break;
 	case AST_EXTENSION_NOT_INUSE:
 	default:
@@ -7060,6 +7074,11 @@
 		else
 			ast_build_string(&t, &maxbytes, "<dialog id=\"%s\">\n", p->exten);
 		ast_build_string(&t, &maxbytes, "<state>%s</state>\n", statestring);
+		if (state == AST_EXTENSION_ONHOLD) {
+			ast_build_string(&t, &maxbytes, "<local>\n<target uri=\"%s\">\n"
+			                                "<param pname=\"+sip.rendering\" pvalue=\"no\">\n"
+			                                "</target>\n</local>\n", mto);
+		}
 		ast_build_string(&t, &maxbytes, "</dialog>\n</dialog-info>\n");
 		break;
 	case NONE:
@@ -10198,6 +10217,8 @@
 		ast_cli(fd, "  VM Extension : %s\n", peer->vmexten);
 		ast_cli(fd, "  LastMsgsSent : %d/%d\n", (peer->lastmsgssent & 0x7fff0000) >> 16, peer->lastmsgssent & 0xffff);
 		ast_cli(fd, "  Call limit   : %d\n", peer->call_limit);
+		if (peer->busy_limit)
+			ast_cli(fd, "  Busy limit   : %d\n", peer->busy_limit);
 		ast_cli(fd, "  Dynamic      : %s\n", (ast_test_flag(&peer->flags[1], SIP_PAGE2_DYNAMIC)?"Yes":"No"));
 		ast_cli(fd, "  Callerid     : %s\n", ast_callerid_merge(cbuf, sizeof(cbuf), peer->cid_name, peer->cid_num, "<unspecified>"));
 		ast_cli(fd, "  MaxCallBR    : %d kbps\n", peer->maxcallbitrate);
@@ -10285,7 +10306,8 @@
 		astman_append(s, "VoiceMailbox: %s\r\n", peer->mailbox);
 		astman_append(s, "TransferMode: %s\r\n", transfermode2str(peer->allowtransfer));
 		astman_append(s, "LastMsgsSent: %d\r\n", peer->lastmsgssent);
-		astman_append(s, "Call limit: %d\r\n", peer->call_limit);
+		astman_append(s, "Call-limit: %d\r\n", peer->call_limit);
+		astman_append(s, "Busy-limit: %d\r\n", peer->busy_limit);
 		astman_append(s, "MaxCallBR: %d kbps\r\n", peer->maxcallbitrate);
 		astman_append(s, "Dynamic: %s\r\n", (ast_test_flag(&peer->flags[1], SIP_PAGE2_DYNAMIC)?"Y":"N"));
 		astman_append(s, "Callerid: %s\r\n", ast_callerid_merge(cbuf, sizeof(cbuf), peer->cid_name, peer->cid_num, ""));
@@ -10457,6 +10479,7 @@
 	ast_cli(fd, "  Realm. auth:            %s\n", authl ? "Yes": "No");
  	ast_cli(fd, "  Always auth rejects:    %s\n", global_alwaysauthreject ? "Yes" : "No");
 	ast_cli(fd, "  Call limit peers only:  %s\n", global_limitonpeers ? "Yes" : "No");
+	ast_cli(fd, "  Direct RTP setup:       %s\n", global_directrtpsetup ? "Yes" : "No");
 	ast_cli(fd, "  User Agent:             %s\n", global_useragent);
 	ast_cli(fd, "  MWI checking interval:  %d secs\n", global_mwitime);
 	ast_cli(fd, "  Reg. context:           %s\n", S_OR(global_regcontext, "(not set)"));
@@ -12841,8 +12864,10 @@
 			/* Could not start thread */
 			free(d);	/* We don't need it anymore. If thread is created, d will be free'd
 					   by sip_park_thread() */
+			pthread_attr_destroy(&attr);
 			return 0;
 		}
+		pthread_attr_destroy(&attr);
 	} 
 	return -1;
 }
@@ -15108,7 +15133,7 @@
 \note	This thread monitors all the SIP sessions and peers that needs notification of mwi
 	(and thus do not have a separate thread) indefinitely 
 */
-static void *do_sip_monitor(void *data)
+static void *do_monitor(void *data)
 {
 	int res;
 	struct sip_pvt *dialog;
@@ -15233,7 +15258,7 @@
 		pthread_kill(monitor_thread, SIGURG);
 	} else {
 		/* Start a new monitor */
-		if (ast_pthread_create_background(&monitor_thread, NULL, do_sip_monitor, NULL) < 0) {
+		if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
 			ast_mutex_unlock(&monlock);
 			ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
 			return -1;
@@ -15343,9 +15368,13 @@
 		- not registered			AST_DEVICE_UNAVAILABLE
 		- registered				AST_DEVICE_NOT_INUSE
 		- fixed IP (!dynamic)			AST_DEVICE_NOT_INUSE
+	
+	Peers that does not have a known call and can't be reached by OPTIONS
+		- unreachable				AST_DEVICE_UNAVAILABLE
 
 	If we return AST_DEVICE_UNKNOWN, the device state engine will try to find
 	out a state by walking the channel list.
+
 */
 static int sip_devicestate(void *data)
 {
@@ -15369,27 +15398,38 @@
 	if ((p = find_peer(host, NULL, 1))) {
 		if (p->addr.sin_addr.s_addr || p->defaddr.sin_addr.s_addr) {
 			/* we have an address for the peer */
-			/* if qualify is turned on, check the status */
-			if (p->maxms && (p->lastms > p->maxms)) {
+		
+			/* Check status in this order
+				- Hold
+				- Ringing
+				- Busy (enforced only by call limit)
+				- Inuse (we have a call)
+				- Unreachable (qualify)
+			   If we don't find any of these state, report AST_DEVICE_NOT_INUSE
+			   for registered devices */
+
+			if (p->onHold)
+				/* First check for hold or ring states */
+				res = AST_DEVICE_ONHOLD;
+			else if (p->inRinging) {
+				if (p->inRinging == p->inUse)
+					res = AST_DEVICE_RINGING;
+				else
+					res = AST_DEVICE_RINGINUSE;
+			} else if (p->call_limit && (p->inUse == p->call_limit))
+				/* check call limit */
+				res = AST_DEVICE_BUSY;
+			else if (p->call_limit && p->busy_limit && p->inUse >= p->busy_limit)
+				/* We're forcing busy before we've reached the call limit */
+				res = AST_DEVICE_BUSY;
+			else if (p->call_limit && p->inUse)
+				/* Not busy, but we do have a call */
+				res = AST_DEVICE_INUSE;
+			else if (p->maxms && (p->lastms > p->maxms)) 
+				/* We don't have a call. Are we reachable at all? Requires qualify= */
 				res = AST_DEVICE_UNAVAILABLE;
-			} else {
-				/* qualify is not on, or the peer is responding properly */
-				/* check call limit */
-				if (p->call_limit && (p->inUse == p->call_limit))
-					res = AST_DEVICE_BUSY;
-				else if (p->call_limit && p->inUse)
-					res = AST_DEVICE_INUSE;
-				else
-					res = AST_DEVICE_NOT_INUSE;
-				if (p->onHold)
-					res = AST_DEVICE_ONHOLD;
-				else if (p->inRinging) {
-					if (p->inRinging == p->inUse)
-						res = AST_DEVICE_RINGING;
-					else
-						res = AST_DEVICE_RINGINUSE;
-				}
-			}
+			else	/* Default reply if we're registered and have no other data */
+				res = AST_DEVICE_NOT_INUSE;
 		} else {
 			/* there is no address, it's unavailable */
 			res = AST_DEVICE_UNAVAILABLE;
@@ -16299,6 +16339,7 @@
 	global_notifyringing = DEFAULT_NOTIFYRINGING;
 	global_limitonpeers = FALSE;		/*!< Match call limit on peers only */
 	global_notifyhold = FALSE;		/*!< Keep track of hold status for a peer */
+	global_directrtpsetup = FALSE;		/* Experimental feature, disabled by default */
 	global_alwaysauthreject = 0;
 	global_allowsubscribe = FALSE;
 	snprintf(global_useragent, sizeof(global_useragent), "%s %s", DEFAULT_USERAGENT, ASTERISK_VERSION);
@@ -16425,6 +16466,8 @@
 			ast_copy_string(default_notifymime, v->value, sizeof(default_notifymime));
 		} else if (!strcasecmp(v->name, "limitonpeers")) {
 			global_limitonpeers = ast_true(v->value);
+		} else if (!strcasecmp(v->name, "directrtpsetup")) {
+			global_directrtpsetup = ast_true(v->value);
 		} else if (!strcasecmp(v->name, "notifyringing")) {
 			global_notifyringing = ast_true(v->value);
 		} else if (!strcasecmp(v->name, "notifyhold")) {
@@ -16975,6 +17018,11 @@
 	p = chan->tech_pvt;
 	if (!p) 
 		return -1;
+
+	/* Disable early RTP bridge  */
+	if (chan->_state != AST_STATE_UP && !global_directrtpsetup) 	/* We are in early state */
+		return 0;
+
 	sip_pvt_lock(p);
 	if (ast_test_flag(&p->flags[0], SIP_ALREADYGONE)) {
 		/* If we're destroyed, don't bother */

Modified: team/oej/codename-pineapple/channels/chan_sip3.c
URL: http://svn.digium.com/view/asterisk/team/oej/codename-pineapple/channels/chan_sip3.c?view=diff&rev=53128&r1=53127&r2=53128
==============================================================================
--- team/oej/codename-pineapple/channels/chan_sip3.c (original)
+++ team/oej/codename-pineapple/channels/chan_sip3.c Fri Feb  2 14:38:18 2007
@@ -9,7 +9,7 @@
 /*
  * Asterisk -- An open source telephony toolkit.
  *
- * Copyright (C) 1999 - 2006, Digium, Inc.
+ * Copyright (C) 1999 - 2007, Digium, Inc.
  *
  * Mark Spencer <markster at digium.com>
  * Chan_sip3 changes by Olle E. Johansson <oej at edvina.net>
@@ -50,7 +50,8 @@
  *
  * \ingroup channel_drivers
  */
-/*! \page Chan_sip3_overview Chan_SIP3:: Overview
+
+/*! \page chan_sip3_overview Chan_SIP3:: Overview
  *
  * \par Overview of the handling of SIP sessions
  * The SIP channel handles several types of SIP sessions, or dialogs,
@@ -113,14 +114,20 @@
 /*!	\page chan_sip3_00index Chan_sip3: Index over docs
 	\title Chan_sip3 :: Index
 
+	- \ref chan_sip3_overview
 	- \subpage chan_sip3_start
+	- \subpage chan_sip3_security
 	- \subpage chan_sip3_objects
+	- \subpage chan_sip3_registrydb
 	- \subpage chan_sip3_files
 	- \subpage chan_sip3_auth
 	- \subpage chan_sip3_dialogs
 	- \subpage chan_sip3_transactions
-	- \ref chan_sip3_overview
+	- \subpage sip3_timer_doc
 	- \subpage sip3_dialog_match
+	- \subpage chan_sip3_dialstring
+	- \subpage chan_sip3_natsupport
+
 	\par todo Things to do, ideas
 	- \subpage chan_sip3_todo
 	- \subpage chan_sip3_subs
@@ -137,11 +144,33 @@
 	to break the backwards compatibility. That's why the old channel
 	will still be around for a while.
 
+	Chan_sip3 is the road towards security (see \ref chan_sip3_security).
+	By adding a transaction layer and support for TCP connections, we can
+	add TLS for the TCP connections and negotiate keys for secure media
+	with SRTP.
+
 	** This work is sponsored by voop.com - the Internet Dialtone.
 	   I am open for more sponsors - contact me on oej at edvina.net
 
 	\page chan_sip3_todo Chan_sip3: Things to do
 	\b Done
+	- Trying to reduce memory allocations for packets.
+		- sipsock_read allocates a packet that stays in memory
+		  until the transaction is finished. If it's an initial
+		  request, it's flagged to stay in memory and kept until
+		  destruction of the dialog (or replacement of initreq).
+		- The issue here is parsing, since parsing destroys the
+		  in-memory copy of the outbound message thus stopping
+		  proper re-transmits. Added flag for parsing of packet,
+		  trying to delay parsing until we send a response.
+	- Added new CLI command "sip list configs" to list all configuration options 
+	  Mostly for debugging
+
+	- Added new configuration engine
+	- Add T1 timer configuration settings
+	- Added configurable T2 timer, see \ref sip3_timer_doc
+	- Added time to astdb registry storage, so that expired registrations
+	  won't be activated at restart
 	- removed pedantic mode
 	- added config option for qualify frequency timers
 	- merged peermatch and sipregister branches
@@ -156,11 +185,36 @@
 	- T38 does no longer depend on canreinvite settings
 	- removed userconf support (in favour of astum)
 
+	\b Larger changes required outside of chan_sip
+	- dnsmgr needs to follow DNS ttl
+	- dnsmgr needs to handle SRV, NAPTR
+
 	\b Halfdone
 	- Added separate TOS setting for presence. Need to run setsockopt
 	  in a locked socket for that to work on the SIP interface.
 
-	\b Todo
+	\par Todo - architecture
+	- check if the "defaultport" and "port" settings are working - port for remote peer?
+	- dnsmgr needs to be integrated and updated
+	- netsock?
+	- thread and separate port for outbound registrations
+	- receive queue between sipsock_read and handle_request
+	- inbound call authentication
+
+	\par Todo - ideas
+	- Implement support for a:rtcp sdp (needs changes in the rtp interface)
+	- Implement "busylimit" for signalling busy, but not enforcing a call limit
+	- Use "accept-language" to set language tags in error messages etc
+	- Implement "holdaction = music | sendhold"
+	- Handle 423 Interval too brief on registrations
+	- Accept-language to language tag.
+	- Fix T4 implementation
+		- Configuration setting implemented in global
+	- Check if usereqphone is a global flag
+	- Fix compact headers per peer
+	- Always enable "alwaysauthreject" and remove that option
+	- Check "insecure" option - do we still need it?
+	- Only check for pickup code if callgroup/pickupgroups are specified in config
 	- check resp 491 to INVITE processing
 	- Make show devices and the completion support domains too
 	- Fix realtime caching and optional loading
@@ -168,7 +222,6 @@
 		- authuser as a separate config option, please, please
 	- Split up source code file
 	- Add astum
-	- Add T1 timer configuration settings
 	- Add auto-nat for RFC 1918 networks
 	- Add type=device for peers
 	- Add type=service for register= replacement
@@ -188,6 +241,7 @@
 	- Make debugaddr a ha list instead of one address and move it out of sipnet
 	- Save the last sent request/response for re-transmits
 	- RTP keepalives (STUN) for video
+	- Clean up 302 redirect - remove "promisredir" setting 
 
 	\b Maybe
 	- add support for Path header
@@ -198,6 +252,20 @@
 
 	- ... And much more
 */
+/*!
+	\page chan_sip3_security	Chan_sip3: The road to SIP security
+
+	Codename pineapple is the road towards SIP security. 
+
+	- SIP/TLS is the way to secure signalling
+	- In order to get there, we need TCP
+	- In order to get TCP, we need a transaction state engine
+	- We also need a separation of network transmission over
+		reliable and unreliable transports and the SIP
+		core
+	- When we have that, we can add SRTP
+
+ */
 /*!
 	\page chan_sip3_objects	Chan_sip3: Devices, trunks and services
 	- \b phones are devices that connect to Asterisk. They register with  
@@ -280,7 +348,7 @@
 		
 */
 /*!
- *	\page chan_sip3_transactions Implementing transactions
+ *	\page chan_sip3_transactions Chan_sip3: Implementing transactions
  *
  *	A SIP transaction is a request and one or several responses. 
  *	The INVITE transaction is special, it's a three-way handshake
@@ -324,6 +392,7 @@
  *	- For SUBSCRIBE dialogs, we need to keep the initial SUBSCRIBE
  *	  Then unacknowledged NOTIFY transactions. Keep the transaction
  *	  until timer expires
+ *	- Queue system for incoming packets?
  *
  *	SIP_dialog
  *	   - sip_trans
@@ -370,7 +439,6 @@
 #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"
@@ -384,7 +452,6 @@
 #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"
@@ -435,7 +502,6 @@
 /* --- Linked lists of various objects --------*/
 
 struct sip_dialog *dialoglist = NULL;        /*!< List of concurrent SIP dialogs */
-struct sip_device_list devicelist;           /*!< The device list */
 struct ast_config *notify_types;	     /*!< The list of manual NOTIFY types we know how to send */
 
 /*---------------------------- Forward declarations of functions in chan_sip3.c */
@@ -452,21 +518,8 @@
 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_begin(struct ast_channel *ast, char digit);
-static int sip_senddigit_end(struct ast_channel *ast, char digit);
-
-/*--- Transmitting responses and requests */
-static int transmit_sip_request(struct sip_dialog *p, struct sip_request *req);
-static int transmit_request(struct sip_dialog *p, int sipmethod, int inc, enum xmittype reliable, int newbranch);
-static int transmit_response_reliable(struct sip_dialog *p, const char *msg, const struct sip_request *req);
-static int transmit_response_with_attachment(enum responseattach attach, struct sip_dialog *p, const char *msg, 
-		const struct sip_request *req, enum xmittype reliable);
-static int transmit_response_with_unsupported(struct sip_dialog *p, const char *msg, const struct sip_request *req, const char *unsupported);
-static void transmit_fake_auth_response(struct sip_dialog *p, struct sip_request *req, int reliable);
-static int transmit_info_with_digit(struct sip_dialog *p, const char digit);
-static int transmit_info_with_vidupdate(struct sip_dialog *p);
-static int transmit_message_with_text(struct sip_dialog *p, const char *text);
-static int transmit_refer(struct sip_dialog *p, const char *dest);
-static int transmit_notify_with_mwi(struct sip_dialog *p, int newmsgs, int oldmsgs, char *vmexten);
+static int sip_senddigit_end(struct ast_channel *ast, char digit, unsigned int duration);
+
 static void receive_message(struct sip_dialog *p, struct sip_request *req);
 
 /*--- Dialog management */
@@ -479,17 +532,16 @@
 static int sip_sipredirect(struct sip_dialog *p, const char *dest);
 
 /*--- Codec handling / SDP */
-static void try_suggested_sip_codec(struct sip_dialog *p);
+GNURK void try_suggested_sip_codec(struct sip_dialog *p);
 
 /*--- Authentication stuff */
 static enum check_auth_result check_user_full(struct sip_dialog *p, struct sip_request *req,
 		      int sipmethod, char *uri, enum xmittype reliable,
-		      struct sockaddr_in *sin, struct sip_peer **authpeer);
+		      struct sockaddr_in *sin, struct sip_device **authpeer);
 static int check_user(struct sip_dialog *p, struct sip_request *req, int sipmethod, char *uri, enum xmittype reliable, struct sockaddr_in *sin);
 
 /*--- Misc functions */
 static int sip_sipredirect(struct sip_dialog *p, const char *dest);
-static int sip_addrcmp(char *name, struct sockaddr_in *sin);	/* Support for peer matching */
 
 /*--- Device monitoring and Device/extension state handling */
 static int cb_extensionstate(char *context, char* exten, int state, void *data);
@@ -497,9 +549,9 @@
 
 /*--- Applications, functions, CLI and manager command helpers */
 GNURK int sip_notify(int fd, int argc, char *argv[]);
-static int func_header_read(struct ast_channel *chan, char *function, char *data, char *buf, size_t len);
-static int function_sippeer(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len);
-static int function_sipchaninfo_read(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len);
+static int func_header_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
+static int function_sippeer(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len);
+static int function_sipchaninfo_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len);
 static int sip_dtmfmode(struct ast_channel *chan, void *data);
 static int sip_addheader(struct ast_channel *chan, void *data);
 
@@ -511,14 +563,7 @@
 GNURK inline int sip_debug_test_pvt(struct sip_dialog *p);
 
 /*--- Device object handling */
-static struct sip_peer *temp_peer(const char *name);
-static struct sip_peer *temp_peer(const char *name);
-static void register_peer_exten(struct sip_peer *peer, int onoff);
-static enum parse_register_result parse_register_contact(struct sip_dialog *pvt, struct sip_peer *p, struct sip_request *req);
-
-/* Realtime device support */
-static void realtime_update_peer(const char *peername, struct sockaddr_in *sin, const char *username, const char *fullcontact, int expirey);
-static void update_peer(struct sip_peer *p, int expiry);
+static enum parse_register_result parse_register_contact(struct sip_dialog *pvt, struct sip_device *p, struct sip_request *req);
 
 /*--- Parsing SIP requests and responses */
 static int get_also_info(struct sip_dialog *p, struct sip_request *oreq);
@@ -528,7 +573,7 @@
 static int get_msg_text(char *buf, int len, struct sip_request *req);
 
 /*--- Constructing requests and responses */
-static int create_addr_from_peer(struct sip_dialog *r, struct sip_peer *peer);
+static int create_addr_from_peer(struct sip_dialog *r, struct sip_device *peer);
 static int add_vidupdate(struct sip_request *req);
 
 /*------Request handling functions */
@@ -575,130 +620,31 @@
 	.send_text = sip_sendtext,		/*!< Get text from the PBX to send out */
 };
 
-/*! \brief Initialize the initital request packet in the pvt structure.
- 	This packet is used for creating replies and future requests in
-	a dialog */
-GNURK void initialize_initreq(struct sip_dialog *dialog, struct sip_request *req)
-{
-	if (dialog->initreq.headers && option_debug) {
-		ast_log(LOG_DEBUG, "Initializing already initialized SIP dialog %s (presumably reinvite)\n", dialog->callid);
-	}
-	/* Use this as the basis */
-	copy_request(&dialog->initreq, req);
-	/* XX Instead -allocate this request in the dialog->packets linked list */
-	ast_set_flag(&dialog->initreq, SIP_PKT_INITREQ);
-	parse_request(&dialog->initreq);
-	if (ast_test_flag(req, SIP_PKT_DEBUG))
-		ast_verbose("Initreq: %d headers, %d lines\n", dialog->initreq.headers, dialog->initreq.lines);
-}
-
-/*! \brief Find via branch parameter */
-GNURK void find_via_branch(struct sip_request *req, char *viabuf, size_t vialen)
-{
-	char *dupvia;
-	char *viabranch;
-	char *sep;
-
-	if (ast_strlen_zero(req->via))
-		return;
-	dupvia = ast_strdupa(req->via);
-	if (!(viabranch = strcasestr(dupvia, ";branch=")))
-		return;
-	viabranch += 8;
-	if ((sep = strchr(viabranch, ';')))
-		*sep = '\0';
-	if (ast_test_flag(req, SIP_PKT_DEBUG) && option_debug > 3)
-		ast_log(LOG_DEBUG, "* Found via branch %s\n", viabranch);
-	strncpy(viabuf, viabranch, vialen);
-}
-
-
-/*! \brief Make branch tag for via header if it does not exist yet */
-static char *ourdialogbranch(struct sip_dialog *dialog, int forcenewbranch)
-{
-	char branch[20];
-	int seed = 0;
-
-	if (forcenewbranch || ast_strlen_zero(dialog->ourbranch)) {
-		if (forcenewbranch)
-			seed ^= ast_random();
-		else
-			seed = ast_random();
-		snprintf(branch, sizeof(branch), "z9hG4bk%08x", seed);
-		ast_string_field_set(dialog, ourbranch, branch);
-	}
-
-	return((char *) dialog->ourbranch);
-	
-}
-
-/*! \brief Build a Via header for a request */
-GNURK void build_via(struct sip_dialog *dialog, int forcenewbranch)
-{
-	/* Work around buggy UNIDEN UIP200 firmware */
-	const char *rport = ast_test_flag(&dialog->flags[0], SIP_NAT) & SIP_NAT_RFC3581 ? ";rport" : "";
-
-	/* z9hG4bK is a magic cookie.  See RFC 3261 section 8.1.1.7 */
-	ast_string_field_build(dialog, via, "SIP/2.0/UDP %s:%d;branch=%s%s",
-			ast_inet_ntoa(dialog->ourip), sipnet_ourport(), 
-			ourdialogbranch(dialog, forcenewbranch), rport);
-}
-
-GNURK void append_history_full(struct sip_dialog *p, const char *fmt, ...)
-	__attribute__ ((format (printf, 2, 3)));
-
-/*! \brief Append to SIP dialog history with arg list  */
-GNURK void append_history_va(struct sip_dialog *p, const char *fmt, va_list ap)
-{
-	char buf[80], *c = buf; /* max history length */
-	struct sip_history *hist;
-	int l;
-
-	vsnprintf(buf, sizeof(buf), fmt, ap);
-	strsep(&c, "\r\n"); /* Trim up everything after \r or \n */
-	l = strlen(buf) + 1;
-	if (!(hist = ast_calloc(1, sizeof(*hist) + l)))
-		return;
-	if (!p->history && !(p->history = ast_calloc(1, sizeof(*p->history)))) {
-		free(hist);
-		return;
-	}
-	memcpy(hist->event, buf, l);
-	AST_LIST_INSERT_TAIL(p->history, hist, list);
-}
-
-/*! \brief Append to SIP dialog history with arg list  */
-GNURK void append_history_full(struct sip_dialog *dialog, const char *fmt, ...)
-{
-	va_list ap;
-
-	if (!dialog)
-		return;
-	va_start(ap, fmt);
-	append_history_va(dialog, fmt, ap);
-	va_end(ap);
-
-	return;
-}
-
-/*! \brief Copy SIP request, pre-parse it */
-GNURK void parse_copy(struct sip_request *dst, const struct sip_request *src)
-{
-	memset(dst, 0, sizeof(*dst));
-	memcpy(dst->data, src->data, sizeof(dst->data));
-	dst->len = src->len;
-	parse_request(dst);
-}
-
-/*! \brief add a blank line if no body */
-GNURK void add_blank(struct sip_request *req)
-{
-	if (!req->lines) {
-		/* Add extra empty return. add_header() reserves 4 bytes so cannot be truncated */
-		snprintf(req->data + req->len, sizeof(req->data) - req->len, "\r\n");
-		req->len += strlen(req->data + req->len);
-	}
-}
+/*! \brief This version of the sip channel tech has no send_digit_begin
+ *  callback.  This is for use with channels using SIP INFO DTMF so that
+ *  the core knows that the channel doesn't want DTMF BEGIN frames. */
+static const struct ast_channel_tech sip_tech_info = {
+	.type = "SIP",
+	.description = "Session Initiation Protocol (SIP)",
+	.capabilities = ((AST_FORMAT_MAX_AUDIO << 1) - 1),
+	.properties = AST_CHAN_TP_WANTSJITTER | AST_CHAN_TP_CREATESJITTER,
+	.requester = sip_request_call,		/*!< Where we set up a call, but don't actually activate it */
+	.devicestate = sip_devicestate,		/*!< Checking the status of a known SIP device */
+	.call = sip_call,			/*!< Try calling Bob, says Alice */
+	.hangup = sip_hangup,			/*!< Alice does not want to talk to Bob any more */
+	.answer = sip_answer,			/*!< Bob answers the call */
+	.read = sip_read,			/*!< Deliver media to the PBX */
+	.write = sip_write,			/*!< Get media from the PBX side */
+	.write_video = sip_write,		/*!< Get video media from the PBX side */
+	.indicate = sip_indicate,		/*!< Get indications from the PBX side */
+	.transfer = sip_transfer,		/*!< Transfer a call, severely broken */
+	.fixup = sip_fixup,
+	.send_digit_end = sip_senddigit_end,		/*!< DTMF support */
+	.bridge = ast_rtp_bridge,
+	.early_bridge = ast_rtp_early_bridge,
+	.send_text = sip_sendtext,		/*!< Get text from the PBX to send out */
+};
+
 
 /*! \brief Send SIP MESSAGE text within a call
 	Called from PBX core sendtext() application */
@@ -707,8 +653,6 @@
 	struct sip_dialog *dialog = ast->tech_pvt;
 	int debug = sip_debug_test_pvt(dialog);
 
-	if (debug)
-		ast_verbose("Sending text %s on %s\n", text, ast->name);
 	if (!dialog)
 		return -1;
 	if (ast_strlen_zero(text))
@@ -719,165 +663,6 @@
 	return 0;	
 }
 
-/*! \brief Update peer object in realtime storage 
-	If the Asterisk system name is set in asterisk.conf, we will use
-	that name and store that in the "regserver" field in the sippeers
-	table to facilitate multi-server setups.
-*/
-static void realtime_update_peer(const char *peername, struct sockaddr_in *sin, const char *username, const char *fullcontact, int expirey)
-{
-	char port[10];
-	char ipaddr[INET_ADDRSTRLEN];
-	char regseconds[20];
-
-	char *sysname = ast_config_AST_SYSTEM_NAME;
-	char *syslabel = NULL;
-
-	time_t nowtime = time(NULL) + expirey;
-	const char *fc = fullcontact ? "fullcontact" : NULL;
-	
-	snprintf(regseconds, sizeof(regseconds), "%d", (int)nowtime);	/* Expiration time */
-	ast_copy_string(ipaddr, ast_inet_ntoa(sin->sin_addr), sizeof(ipaddr));
-	snprintf(port, sizeof(port), "%d", ntohs(sin->sin_port));
-	
-	if (ast_strlen_zero(sysname))	/* No system name, disable this */
-		sysname = NULL;
-	else if (ast_test_flag(&global.flags[1], SIP_PAGE2_RTSAVE_SYSNAME))
-		syslabel = "regserver";
-
-	if (fc)
-		ast_update_realtime("sippeers", "name", peername, "ipaddr", ipaddr,
-			"port", port, "regseconds", regseconds,
-			"defaultuser", username, fc, fullcontact, syslabel, sysname, NULL); /* note fc and syslabel _can_ be NULL */
-	else
-		ast_update_realtime("sippeers", "name", peername, "ipaddr", ipaddr,
-			"port", port, "regseconds", regseconds,
-			"defaultuser", username, syslabel, sysname, NULL); /* note syslabel _can_ be NULL */
-}
-
-/*! \brief Automatically add peer extension to dial plan */
-static void register_peer_exten(struct sip_peer *device, int onoff)
-{
-	char multi[256];
-	char *stringp, *ext, *context;
-
-	/* XXX note that global.regcontext is both a global 'enable' flag and
-	 * the name of the global regexten context, if not specified
-	 * individually.
-	 */
-	if (ast_strlen_zero(global.regcontext))
-		return;
-
-	ast_copy_string(multi, S_OR(device->regexten, device->name), sizeof(multi));
-	stringp = multi;
-	while ((ext = strsep(&stringp, "&"))) {
-		if ((context = strchr(ext, '@'))) {
-			*context++ = '\0';	/* split ext at context */
-			if (!ast_context_find(context)) {
-				ast_log(LOG_WARNING, "Context %s must exist in regcontext= in sip.conf!\n", context);
-				continue;
-			}
-		} else {
-			context = global.regcontext;
-		}
-		if (onoff)
-			ast_add_extension(context, 1, ext, 1, NULL, NULL, "Noop",
-				 ast_strdup(device->name), ast_free, "SIP");
-		else
-			ast_context_remove_extension(context, ext, 1, NULL);
-	}
-}
-
-/*! \brief Destroy device object from memory */
-GNURK void sip_destroy_device(struct sip_peer *device)
-{
-	logdebug(3, "Destroying SIP device %s\n", device->name);
-	//if (option_debug > 2)
-		//ast_log(LOG_DEBUG, "Destroying SIP %s %s\n", device->type & SIP_USER ? "user" : "peer", device->name);
-
-	/* Delete it, it needs to disappear */
-	if (device->call)
-		sip_destroy(device->call);
-	if (device->chanvars) {
-		ast_variables_destroy(device->chanvars);
-		device->chanvars = NULL;
-	}
-
-	if (device->mwipvt) 		/* We have an active subscription, delete it */
-		sip_destroy(device->mwipvt);
-
-	if (device->expire > -1)
-		ast_sched_del(sched, device->expire);
-	if (device->pokeexpire > -1)
-		ast_sched_del(sched, device->pokeexpire);
-	ast_free_ha(device->ha);
-
-	if (device->type & SIP_PEER) {
-		register_peer_exten(device, FALSE);
-		clear_realm_authentication(device->auth);
-		device->auth = (struct sip_auth *) NULL;
-		if (ast_test_flag((&device->flags[1]), SIP_PAGE2_SELFDESTRUCT))
-			sipcounters.autocreated_peers--;

[... 11359 lines stripped ...]


More information about the asterisk-commits mailing list