[asterisk-commits] oej: branch oej/cancel_elsewhere_1.4 r168475 - in /team/oej/cancel_elsewhere_...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Mon Jan 12 05:29:06 CST 2009


Author: oej
Date: Mon Jan 12 05:29:06 2009
New Revision: 168475

URL: http://svn.digium.com/svn-view/asterisk?view=rev&rev=168475
Log:
Reset automerge

Added:
    team/oej/cancel_elsewhere_1.4/funcs/func_audiohookinherit.c
      - copied unchanged from r168382, branches/1.4/funcs/func_audiohookinherit.c
Modified:
    team/oej/cancel_elsewhere_1.4/   (props changed)
    team/oej/cancel_elsewhere_1.4/CHANGES
    team/oej/cancel_elsewhere_1.4/README
    team/oej/cancel_elsewhere_1.4/apps/app_dial.c
    team/oej/cancel_elsewhere_1.4/apps/app_queue.c
    team/oej/cancel_elsewhere_1.4/channels/chan_alsa.c
    team/oej/cancel_elsewhere_1.4/channels/chan_dahdi.c
    team/oej/cancel_elsewhere_1.4/channels/chan_iax2.c
    team/oej/cancel_elsewhere_1.4/channels/chan_local.c
    team/oej/cancel_elsewhere_1.4/channels/chan_misdn.c
    team/oej/cancel_elsewhere_1.4/channels/chan_sip.c
    team/oej/cancel_elsewhere_1.4/channels/misdn_config.c
    team/oej/cancel_elsewhere_1.4/include/asterisk/audiohook.h
    team/oej/cancel_elsewhere_1.4/include/asterisk/pbx.h
    team/oej/cancel_elsewhere_1.4/include/asterisk/strings.h
    team/oej/cancel_elsewhere_1.4/main/asterisk.c
    team/oej/cancel_elsewhere_1.4/main/audiohook.c
    team/oej/cancel_elsewhere_1.4/main/channel.c
    team/oej/cancel_elsewhere_1.4/main/db.c
    team/oej/cancel_elsewhere_1.4/main/file.c
    team/oej/cancel_elsewhere_1.4/main/indications.c
    team/oej/cancel_elsewhere_1.4/main/utils.c
    team/oej/cancel_elsewhere_1.4/res/res_agi.c
    team/oej/cancel_elsewhere_1.4/res/res_features.c
    team/oej/cancel_elsewhere_1.4/res/res_musiconhold.c
    team/oej/cancel_elsewhere_1.4/sounds/Makefile

Propchange: team/oej/cancel_elsewhere_1.4/
------------------------------------------------------------------------------
    automerge = http://www.codename-pineapple.org/

Propchange: team/oej/cancel_elsewhere_1.4/
------------------------------------------------------------------------------
Binary property 'branch-1.2-merged' - no diff available.

Propchange: team/oej/cancel_elsewhere_1.4/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Mon Jan 12 05:29:06 2009
@@ -1,1 +1,1 @@
-/branches/1.4:1-166023
+/branches/1.4:1-168472

Modified: team/oej/cancel_elsewhere_1.4/CHANGES
URL: http://svn.digium.com/svn-view/asterisk/team/oej/cancel_elsewhere_1.4/CHANGES?view=diff&rev=168475&r1=168474&r2=168475
==============================================================================
--- team/oej/cancel_elsewhere_1.4/CHANGES (original)
+++ team/oej/cancel_elsewhere_1.4/CHANGES Mon Jan 12 05:29:06 2009
@@ -120,6 +120,7 @@
         19. SQL_ESC()
         20. STAT()
         21. STRPTIME()
+		22. AUDIOHOOK_INHERIT()
     * Apps that have changes to their interface:
          1. Authenticate() -- optional maxdigits argument added.
          2. ChanSpy() -- new options:

Modified: team/oej/cancel_elsewhere_1.4/README
URL: http://svn.digium.com/svn-view/asterisk/team/oej/cancel_elsewhere_1.4/README?view=diff&rev=168475&r1=168474&r2=168475
==============================================================================
--- team/oej/cancel_elsewhere_1.4/README (original)
+++ team/oej/cancel_elsewhere_1.4/README Mon Jan 12 05:29:06 2009
@@ -2,7 +2,7 @@
 by Mark Spencer <markster at digium.com>
 and the Asterisk.org developer community
 
-Copyright (C) 2001-2008 Digium, Inc.
+Copyright (C) 2001-2009 Digium, Inc.
 and other copyright holders.
 ================================================================
 
@@ -11,7 +11,7 @@
 the security information file (doc/security.txt) before you attempt 
 to configure and run an Asterisk server.
 
-* WHAT IS ASTERISK ?
+* WHAT IS ASTERISK?
   Asterisk is an Open Source PBX and telephony toolkit.  It is, in a
 sense, middleware between Internet and telephony channels on the bottom,
 and Internet and telephony applications at the top.  For more information

Modified: team/oej/cancel_elsewhere_1.4/apps/app_dial.c
URL: http://svn.digium.com/svn-view/asterisk/team/oej/cancel_elsewhere_1.4/apps/app_dial.c?view=diff&rev=168475&r1=168474&r2=168475
==============================================================================
--- team/oej/cancel_elsewhere_1.4/apps/app_dial.c (original)
+++ team/oej/cancel_elsewhere_1.4/apps/app_dial.c Mon Jan 12 05:29:06 2009
@@ -1847,37 +1847,29 @@
 			res = -1;
 		}
 
-		if (res != AST_PBX_NO_HANGUP_PEER && res != AST_PBX_NO_HANGUP_PEER_PARKED) {
-			if (res != AST_PBX_KEEPALIVE && !chan->_softhangup)
-				chan->hangupcause = peer->hangupcause;
-			ast_hangup(peer);
-		}
+		if (!chan->_softhangup)
+			chan->hangupcause = peer->hangupcause;
+		ast_hangup(peer);
 	}	
 out:
-	/* cleaning up chan is not a good idea here if AST_PBX_KEEPALIVE
-	   is returned; chan will get the love it needs from another
-	   thread */
-	if (res != AST_PBX_KEEPALIVE) {
-		if (moh) {
-			moh = 0;
-			ast_moh_stop(chan);
-		} else if (sentringing) {
-			sentringing = 0;
-			ast_indicate(chan, -1);
-		}
-		ast_rtp_early_bridge(chan, NULL);
-		hanguptree(outgoing, NULL, 0);
-		pbx_builtin_setvar_helper(chan, "DIALSTATUS", status);
-		if (option_debug)
-			ast_log(LOG_DEBUG, "Exiting with DIALSTATUS=%s.\n", status);
-		
-		if ((ast_test_flag(peerflags, OPT_GO_ON)) && (!chan->_softhangup) && (res != AST_PBX_KEEPALIVE)) {
-			if (timelimit)
-				chan->whentohangup = 0;
-			res = 0;
-		}
-	}
-
+	if (moh) {
+		moh = 0;
+		ast_moh_stop(chan);
+	} else if (sentringing) {
+		sentringing = 0;
+		ast_indicate(chan, -1);
+	}
+	ast_rtp_early_bridge(chan, NULL);
+	hanguptree(outgoing, NULL,0);
+	pbx_builtin_setvar_helper(chan, "DIALSTATUS", status);
+	if (option_debug)
+		ast_log(LOG_DEBUG, "Exiting with DIALSTATUS=%s.\n", status);
+	
+	if (ast_test_flag(peerflags, OPT_GO_ON) && !chan->_softhangup) {
+		if (calldurationlimit)
+			chan->whentohangup = 0;
+		res = 0;
+	}
 done:
 	ast_module_user_remove(u);    
 	return res;

Modified: team/oej/cancel_elsewhere_1.4/apps/app_queue.c
URL: http://svn.digium.com/svn-view/asterisk/team/oej/cancel_elsewhere_1.4/apps/app_queue.c?view=diff&rev=168475&r1=168474&r2=168475
==============================================================================
--- team/oej/cancel_elsewhere_1.4/apps/app_queue.c (original)
+++ team/oej/cancel_elsewhere_1.4/apps/app_queue.c Mon Jan 12 05:29:06 2009
@@ -3155,7 +3155,7 @@
 		transfer_ds = setup_transfer_datastore(qe, member, callstart, callcompletedinsl);
 		bridge = ast_bridge_call(qe->chan,peer, &bridge_config);
 
-		if (bridge != AST_PBX_KEEPALIVE && !attended_transfer_occurred(qe->chan)) {
+		if (!attended_transfer_occurred(qe->chan)) {
 			struct ast_datastore *tds;
 			if (strcasecmp(oldcontext, qe->chan->context) || strcasecmp(oldexten, qe->chan->exten)) {
 				ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "TRANSFER", "%s|%s|%ld|%ld",
@@ -3164,7 +3164,7 @@
 			} else if (qe->chan->_softhangup) {
 				ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "COMPLETECALLER", "%ld|%ld|%d",
 					(long) (callstart - qe->start), (long) (time(NULL) - callstart), qe->opos);
-				if (bridge != AST_PBX_NO_HANGUP_PEER && bridge != AST_PBX_NO_HANGUP_PEER_PARKED && qe->parent->eventwhencalled)
+				if (qe->parent->eventwhencalled)
 					manager_event(EVENT_FLAG_AGENT, "AgentComplete",
 							"Queue: %s\r\n"
 							"Uniqueid: %s\r\n"
@@ -3181,7 +3181,7 @@
 			} else {
 				ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "COMPLETEAGENT", "%ld|%ld|%d",
 					(long) (callstart - qe->start), (long) (time(NULL) - callstart), qe->opos);
-				if (bridge != AST_PBX_NO_HANGUP_PEER && bridge != AST_PBX_NO_HANGUP_PEER_PARKED && qe->parent->eventwhencalled)
+				if (qe->parent->eventwhencalled)
 					manager_event(EVENT_FLAG_AGENT, "AgentComplete",
 							"Queue: %s\r\n"
 							"Uniqueid: %s\r\n"
@@ -3206,8 +3206,7 @@
 		if (transfer_ds) {
 			ast_channel_datastore_free(transfer_ds);
 		}
-		if (bridge != AST_PBX_NO_HANGUP_PEER && bridge != AST_PBX_NO_HANGUP_PEER_PARKED)
-			ast_hangup(peer);
+		ast_hangup(peer);
 		res = bridge ? bridge : 1;
 		ao2_ref(member, -1);
 	}
@@ -4079,7 +4078,7 @@
 		}
 
 		/* Don't allow return code > 0 */
-		if (res >= 0 && res != AST_PBX_KEEPALIVE) {
+		if (res >= 0) {
 			res = 0;	
 			if (ringing) {
 				ast_indicate(chan, -1);

Modified: team/oej/cancel_elsewhere_1.4/channels/chan_alsa.c
URL: http://svn.digium.com/svn-view/asterisk/team/oej/cancel_elsewhere_1.4/channels/chan_alsa.c?view=diff&rev=168475&r1=168474&r2=168475
==============================================================================
--- team/oej/cancel_elsewhere_1.4/channels/chan_alsa.c (original)
+++ team/oej/cancel_elsewhere_1.4/channels/chan_alsa.c Mon Jan 12 05:29:06 2009
@@ -266,7 +266,9 @@
 	state = snd_pcm_state(alsa.ocard);
 	if (state == SND_PCM_STATE_XRUN)
 		snd_pcm_prepare(alsa.ocard);
-	res = snd_pcm_writei(alsa.ocard, frame, res);
+	while ((res = snd_pcm_writei(alsa.ocard, frame, res)) == -EAGAIN) {
+		usleep(1);
+	}
 	if (res > 0)
 		return 0;
 	return 0;
@@ -629,13 +631,17 @@
 		state = snd_pcm_state(alsa.ocard);
 		if (state == SND_PCM_STATE_XRUN)
 			snd_pcm_prepare(alsa.ocard);
-		res = snd_pcm_writei(alsa.ocard, sizbuf, len / 2);
+		while ((res = snd_pcm_writei(alsa.ocard, sizbuf, len / 2)) == -EAGAIN) {
+			usleep(1);
+		}
 		if (res == -EPIPE) {
 #if DEBUG
 			ast_log(LOG_DEBUG, "XRUN write\n");
 #endif
 			snd_pcm_prepare(alsa.ocard);
-			res = snd_pcm_writei(alsa.ocard, sizbuf, len / 2);
+			while ((res = snd_pcm_writei(alsa.ocard, sizbuf, len / 2)) == -EAGAIN) {
+				usleep(1);
+			}
 			if (res != len / 2) {
 				ast_log(LOG_ERROR, "Write error: %s\n", snd_strerror(res));
 				res = -1;

Modified: team/oej/cancel_elsewhere_1.4/channels/chan_dahdi.c
URL: http://svn.digium.com/svn-view/asterisk/team/oej/cancel_elsewhere_1.4/channels/chan_dahdi.c?view=diff&rev=168475&r1=168474&r2=168475
==============================================================================
--- team/oej/cancel_elsewhere_1.4/channels/chan_dahdi.c (original)
+++ team/oej/cancel_elsewhere_1.4/channels/chan_dahdi.c Mon Jan 12 05:29:06 2009
@@ -3727,15 +3727,26 @@
 			if (strcmp(ast->exten, "fax")) {
 				const char *target_context = S_OR(ast->macrocontext, ast->context);
 
+				/* We need to unlock 'ast' here because ast_exists_extension has the
+				 * potential to start autoservice on the channel. Such action is prone
+				 * to deadlock.
+				 */
+				ast_mutex_unlock(&p->lock);
+				ast_channel_unlock(ast);
 				if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
+					ast_channel_lock(ast);
+					ast_mutex_lock(&p->lock);
 					if (option_verbose > 2)
 						ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name);
 					/* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
 					pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
 					if (ast_async_goto(ast, target_context, "fax", 1))
 						ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
-				} else
+				} else {
+					ast_channel_lock(ast);
+					ast_mutex_lock(&p->lock);
 					ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
+				}
 			} else if (option_debug)
 				ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
 		} else if (option_debug)

Modified: team/oej/cancel_elsewhere_1.4/channels/chan_iax2.c
URL: http://svn.digium.com/svn-view/asterisk/team/oej/cancel_elsewhere_1.4/channels/chan_iax2.c?view=diff&rev=168475&r1=168474&r2=168475
==============================================================================
--- team/oej/cancel_elsewhere_1.4/channels/chan_iax2.c (original)
+++ team/oej/cancel_elsewhere_1.4/channels/chan_iax2.c Mon Jan 12 05:29:06 2009
@@ -155,6 +155,7 @@
 static int authdebug = 1;
 static int autokill = 0;
 static int iaxcompat = 0;
+static int last_authmethod = 0;
 
 static int iaxdefaultdpcache=10 * 60;	/* Cache dialplan entries for 10 minutes by default */
 
@@ -6376,23 +6377,34 @@
 	char challenge[10];
 	const char *peer_name;
 	int res = -1;
+	int sentauthmethod;
 
 	peer_name = ast_strdupa(iaxs[callno]->peer);
 
 	/* SLD: third call to find_peer in registration */
 	ast_mutex_unlock(&iaxsl[callno]);
-	p = find_peer(peer_name, 1);
+	if ((p = find_peer(peer_name, 1))) {
+		last_authmethod = p->authmethods;
+	}
+
 	ast_mutex_lock(&iaxsl[callno]);
 	if (!iaxs[callno])
 		goto return_unref;
-	if (!p) {
+	if (!p && !delayreject) {
 		ast_log(LOG_WARNING, "No such peer '%s'\n", peer_name);
 		goto return_unref;
 	}
 	
 	memset(&ied, 0, sizeof(ied));
-	iax_ie_append_short(&ied, IAX_IE_AUTHMETHODS, p->authmethods);
-	if (p->authmethods & (IAX_AUTH_RSA | IAX_AUTH_MD5)) {
+	/* The selection of which delayed reject is sent may leak information,
+	 * if it sets a static response.  For example, if a host is known to only
+	 * use MD5 authentication, then an RSA response would indicate that the
+	 * peer does not exist, and vice-versa.
+	 * Therefore, we use whatever the last peer used (which may vary over the
+	 * course of a server, which should leak minimal information). */
+	sentauthmethod = p ? p->authmethods : last_authmethod ? last_authmethod : (IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT);
+	iax_ie_append_short(&ied, IAX_IE_AUTHMETHODS, sentauthmethod);
+	if (sentauthmethod & (IAX_AUTH_RSA | IAX_AUTH_MD5)) {
 		/* Build the challenge */
 		snprintf(challenge, sizeof(challenge), "%d", (int)ast_random());
 		ast_string_field_set(iaxs[callno], challenge, challenge);
@@ -11231,6 +11243,7 @@
 	iax_set_error(iax_error_output);
 	jb_setoutput(jb_error_output, jb_warning_output, NULL);
 	
+#ifdef HAVE_DAHDI
 #ifdef DAHDI_TIMERACK
 	timingfd = open(DAHDI_FILE_TIMER, O_RDWR);
 	if (timingfd < 0)
@@ -11238,6 +11251,7 @@
 		timingfd = open(DAHDI_FILE_PSEUDO, O_RDWR);
 	if (timingfd < 0) 
 		ast_log(LOG_WARNING, "Unable to open IAX timing interface: %s\n", strerror(errno));
+#endif
 
 	memset(iaxs, 0, sizeof(iaxs));
 

Modified: team/oej/cancel_elsewhere_1.4/channels/chan_local.c
URL: http://svn.digium.com/svn-view/asterisk/team/oej/cancel_elsewhere_1.4/channels/chan_local.c?view=diff&rev=168475&r1=168474&r2=168475
==============================================================================
--- team/oej/cancel_elsewhere_1.4/channels/chan_local.c (original)
+++ team/oej/cancel_elsewhere_1.4/channels/chan_local.c Mon Jan 12 05:29:06 2009
@@ -490,6 +490,7 @@
 	p->chan->cid.cid_tns = p->owner->cid.cid_tns;
 	ast_string_field_set(p->chan, language, p->owner->language);
 	ast_string_field_set(p->chan, accountcode, p->owner->accountcode);
+	ast_string_field_set(p->chan, musicclass, p->owner->musicclass);
 	ast_cdr_update(p->chan);
 	p->chan->cdrflags = p->owner->cdrflags;
 

Modified: team/oej/cancel_elsewhere_1.4/channels/chan_misdn.c
URL: http://svn.digium.com/svn-view/asterisk/team/oej/cancel_elsewhere_1.4/channels/chan_misdn.c?view=diff&rev=168475&r1=168474&r2=168475
==============================================================================
--- team/oej/cancel_elsewhere_1.4/channels/chan_misdn.c (original)
+++ team/oej/cancel_elsewhere_1.4/channels/chan_misdn.c Mon Jan 12 05:29:06 2009
@@ -147,83 +147,272 @@
 #define ORG_MISDN 2
 
 struct hold_info {
+	/*!
+	 * \brief Logical port the channel call record is HOLDED on 
+	 * because the B channel is no longer associated. 
+	 */
 	int port;
+
+	/*!
+	 * \brief Original B channel number the HOLDED call was using. 
+	 * \note Used only for debug display messages.
+	 */
 	int channel;
 };
 
+/*!
+ * \brief Channel call record structure
+ */
 struct chan_list {
-  
+	/*! 
+	 * \brief The "allowed_bearers" string read in from /etc/asterisk/misdn.conf
+	 */
 	char allowed_bearers[BUFFERSIZE + 1];
 	
+	/*! 
+	 * \brief State of the channel
+	 */
 	enum misdn_chan_state state;
+
+	/*! 
+	 * \brief TRUE if a hangup needs to be queued 
+	 * \note This is a debug flag only used to catch calls to hangup_chan() that are already hungup.
+	 */
 	int need_queue_hangup;
+
+	/*!
+	 * \brief TRUE if a channel can be hung up by calling asterisk directly when done.
+	 */
 	int need_hangup;
+
+	/*!
+	 * \brief TRUE if we could send an AST_CONTROL_BUSY if needed.
+	 */
 	int need_busy;
 	
+	/*!
+	 * \brief Who originally created this channel. ORG_AST or ORG_MISDN
+	 */
 	int originator;
+
+	/*! 
+	 * \brief TRUE of we are not to respond immediately to a SETUP message.  Check the dialplan first.
+	 * \note The "noautorespond_on_setup" boolean read in from /etc/asterisk/misdn.conf
+	 */
 	int noautorespond_on_setup;
 	
-	int norxtone;
+	int norxtone;	/* Boolean assigned values but the value is not used. */
+
+	/*!
+	 * \brief TRUE if we are not to generate tones (Playtones)
+	 */
 	int notxtone; 
 
+	/*!
+	 * \brief TRUE if echo canceller is enabled.  Value is toggled.
+	 */
 	int toggle_ec;
 	
+	/*!
+	 * \brief TRUE if you want to send Tone Indications to an incoming
+	 * ISDN channel on a TE Port.
+	 * \note The "incoming_early_audio" boolean read in from /etc/asterisk/misdn.conf
+	 */
 	int incoming_early_audio;
 
+	/*!
+	 * \brief TRUE if DTMF digits are to be passed inband only.
+	 * \note It is settable by the misdn_set_opt() application.
+	 */
 	int ignore_dtmf;
 
+	/*!
+	 * \brief Pipe file descriptor handles array. 
+	 * Read from pipe[0], write to pipe[1] 
+	 */
 	int pipe[2];
+
+	/*!
+	 * \brief Read buffer for inbound audio from pipe[0]
+	 */
 	char ast_rd_buf[4096];
+
+	/*!
+	 * \brief Inbound audio frame returned by misdn_read().
+	 */
 	struct ast_frame frame;
 
-	int faxdetect; /*!<  0:no 1:yes 2:yes+nojump */
+	/*!
+	 * \brief Fax detection option. (0:no 1:yes 2:yes+nojump)
+	 * \note The "faxdetect" option string read in from /etc/asterisk/misdn.conf
+	 * \note It is settable by the misdn_set_opt() application.
+	 */
+	int faxdetect;
+
+	/*!
+	 * \brief Number of seconds to detect a Fax machine when detection enabled.
+	 * \note 0 disables the timeout.
+	 * \note The "faxdetect_timeout" value read in from /etc/asterisk/misdn.conf
+	 */
 	int faxdetect_timeout;
+
+	/*!
+	 * \brief Starting time of fax detection with timeout when nonzero.
+	 */
 	struct timeval faxdetect_tv;
+
+	/*!
+	 * \brief TRUE if a fax has been detected.
+	 */
 	int faxhandled;
 
+	/*!
+	 * \brief TRUE if we will use the Asterisk DSP to detect DTMF/Fax
+	 * \note The "astdtmf" boolean read in from /etc/asterisk/misdn.conf
+	 */
 	int ast_dsp;
 
+	/*!
+	 * \brief Jitterbuffer length
+	 * \note The "jitterbuffer" value read in from /etc/asterisk/misdn.conf
+	 */
 	int jb_len;
+
+	/*!
+	 * \brief Jitterbuffer upper threshold
+	 * \note The "jitterbuffer_upper_threshold" value read in from /etc/asterisk/misdn.conf
+	 */
 	int jb_upper_threshold;
+
+	/*!
+	 * \brief Allocated jitterbuffer controller
+	 * \note misdn_jb_init() creates the jitterbuffer.
+	 * \note Must use misdn_jb_destroy() to clean up. 
+	 */
 	struct misdn_jb *jb;
 	
+	/*!
+	 * \brief Allocated DSP controller
+	 * \note ast_dsp_new() creates the DSP controller.
+	 * \note Must use ast_dsp_free() to clean up. 
+	 */
 	struct ast_dsp *dsp;
+
+	/*!
+	 * \brief Allocated audio frame sample translator
+	 * \note ast_translator_build_path() creates the translator path.
+	 * \note Must use ast_translator_free_path() to clean up. 
+	 */
 	struct ast_trans_pvt *trans;
   
+	/*!
+	 * \brief Associated Asterisk channel structure.
+	 */
 	struct ast_channel * ast;
 
-	int dummy;
+	//int dummy;	/* Not used */
   
+	/*!
+	 * \brief Associated B channel structure.
+	 */
 	struct misdn_bchannel *bc;
 
+	/*!
+	 * \brief HOLDED channel information
+	 */
 	struct hold_info hold_info;
 
+	/*! 
+	 * \brief From associated B channel: Layer 3 process ID 
+	 * \note Used to find the HOLDED channel call record when retrieving a call. 
+	 */
 	unsigned int l3id;
+
+	/*! 
+	 * \brief From associated B channel: B Channel mISDN driver layer ID from mISDN_get_layerid()
+	 * \note Used only for debug display messages.
+	 */
 	int addr;
 
-	char context[BUFFERSIZE];
-
-	int zero_read_cnt;
+	/*!
+	 * \brief Incoming call dialplan context identifier.
+	 * \note The "context" string read in from /etc/asterisk/misdn.conf
+	 */
+	char context[AST_MAX_CONTEXT];
+
+	/*!
+	 * \brief The configured music-on-hold class to use for this call.
+	 * \note The "musicclass" string read in from /etc/asterisk/misdn.conf
+	 */
+	char mohinterpret[MAX_MUSICCLASS];
+
+	//int zero_read_cnt;	/* Not used */
+
+	/*!
+	 * \brief Number of outgoing audio frames dropped since last debug gripe message.
+	 */
 	int dropped_frame_cnt;
 
+	/*!
+	 * \brief TRUE if we must do the ringback tones.
+	 * \note The "far_alerting" boolean read in from /etc/asterisk/misdn.conf
+	 */
 	int far_alerting;
 
+	/*!
+	 * \brief TRUE if NT should disconnect an overlap dialing call when a timeout occurs.
+	 * \note The "nttimeout" boolean read in from /etc/asterisk/misdn.conf
+	 */
 	int nttimeout;
 
+	/*!
+	 * \brief Other channel call record PID 
+	 * \note Value imported from Asterisk environment variable MISDN_PID 
+	 */
 	int other_pid;
+
+	/*!
+	 * \brief Bridged other channel call record
+	 * \note Pointer set when other_pid imported from Asterisk environment 
+	 * variable MISDN_PID by either side.
+	 */
 	struct chan_list *other_ch;
 
+	/*!
+	 * \brief Tone zone sound used for dialtone generation.
+	 * \note Used as a boolean.  Non-NULL to prod generation if enabled. 
+	 */
 	const struct ind_tone_zone_sound *ts;
 	
+	/*!
+	 * \brief Enables overlap dialing for the set amount of seconds.  (0 = Disabled)
+	 * \note The "overlapdial" value read in from /etc/asterisk/misdn.conf
+	 */
 	int overlap_dial;
+
+	/*!
+	 * \brief Overlap dialing timeout Task ID.  -1 if not running.
+	 */
 	int overlap_dial_task;
+
+	/*!
+	 * \brief overlap_tv access lock.
+	 */
 	ast_mutex_t overlap_tv_lock;
+
+	/*!
+	 * \brief Overlap timer start time.  Timer restarted for every digit received.
+	 */
 	struct timeval overlap_tv;
   
-	struct chan_list *peer;
+	//struct chan_list *peer;	/* Not used */
+
+	/*!
+	 * \brief Next channel call record in the list.
+	 */
 	struct chan_list *next;
-	struct chan_list *prev;
-	struct chan_list *first;
+	//struct chan_list *prev;		/* Not used */
+	//struct chan_list *first;	/* Not used */
 };
 
 
@@ -323,6 +512,9 @@
 
 struct chan_list dummy_cl;
 
+/*!
+ * \brief Global channel call record list head.
+ */
 struct chan_list *cl_te=NULL;
 ast_mutex_t cl_te_lock;
 
@@ -431,7 +623,7 @@
 {
 	switch (fac->Function) {
 	case Fac_CD:
-		chan_misdn_log(1,bc->port," --> calldeflect to: %s, screened: %s\n", fac->u.CDeflection.DeflectedToNumber,
+		chan_misdn_log(1,bc->port," --> calldeflect to: %s, presentable: %s\n", fac->u.CDeflection.DeflectedToNumber,
 			fac->u.CDeflection.PresentationAllowed ? "yes" : "no");
 		break;
 	case Fac_AOCDCurrency:
@@ -1537,6 +1729,7 @@
 		"Usage: misdn set crypt debug <level>\n" }
 };
 
+/*! \brief Updates caller ID information from config */
 static int update_config(struct chan_list *ch, int orig) 
 {
 	struct ast_channel *ast;
@@ -1725,7 +1918,6 @@
 	int port;
 	int hdlc = 0;
 	char lang[BUFFERSIZE + 1];
-	char localmusicclass[BUFFERSIZE + 1];
 	char faxdetect[BUFFERSIZE + 1];
 	char buf[256];
 	char buf2[256];
@@ -1750,8 +1942,7 @@
 	misdn_cfg_get(port, MISDN_CFG_LANGUAGE, lang, BUFFERSIZE);
 	ast_string_field_set(ast, language, lang);
 
-	misdn_cfg_get(port, MISDN_CFG_MUSICCLASS, localmusicclass, BUFFERSIZE);
-	ast_string_field_set(ast, musicclass, localmusicclass);
+	misdn_cfg_get(port, MISDN_CFG_MUSICCLASS, ch->mohinterpret, sizeof(ch->mohinterpret));
 
 	misdn_cfg_get(port, MISDN_CFG_TXGAIN, &bc->txgain, sizeof(int));
 	misdn_cfg_get(port, MISDN_CFG_RXGAIN, &bc->rxgain, sizeof(int));
@@ -1822,6 +2013,8 @@
 	if (orig == ORG_AST) {
 		char callerid[BUFFERSIZE + 1];
 
+		/* ORIGINATOR Asterisk (outgoing call) */
+
 		misdn_cfg_get(port, MISDN_CFG_TE_CHOOSE_CHANNEL, &(bc->te_choose_channel), sizeof(int));
 
  		if (strstr(faxdetect, "outgoing") || strstr(faxdetect, "both")) {
@@ -1845,7 +2038,8 @@
 		debug_numplan(port, bc->cpnnumplan, "CTON");
 
 		ch->overlap_dial = 0;
-	} else { /** ORIGINATOR MISDN **/
+	} else {
+		/* ORIGINATOR MISDN (incoming call) */
 		char prefix[BUFFERSIZE + 1] = "";
 
  		if (strstr(faxdetect, "incoming") || strstr(faxdetect, "both")) {
@@ -2095,7 +2289,7 @@
 	}
 
 	if (!p->bc) {
-		chan_misdn_log(1, 0, " --> Got Answer, but theres no bc obj ??\n");
+		chan_misdn_log(1, 0, " --> Got Answer, but there is no bc obj ??\n");
 
 		ast_queue_hangup(ast);
 	}
@@ -2320,7 +2514,7 @@
 			start_bc_tones(p);
 		break;
 	case AST_CONTROL_HOLD:
-		ast_moh_start(ast,data,ast->musicclass); 
+		ast_moh_start(ast, data, p->mohinterpret); 
 		chan_misdn_log(1, p->bc->port, " --> *\tHOLD pid:%d\n", p->bc ? p->bc->pid : -1);
 		break;
 	case AST_CONTROL_UNHOLD:
@@ -2730,7 +2924,7 @@
 		return 0;
 	}
 	
-#if MISDN_DEBUG
+#ifdef MISDN_DEBUG
 	{
 		int i, max = 5 > frame->samples ? frame->samples : 5;
 
@@ -3040,6 +3234,8 @@
 		char cfg_group[BUFFERSIZE + 1];
 		struct robin_list *rr = NULL;
 
+		/* Group dial */
+
 		if (misdn_cfg_is_group_method(group, METHOD_ROUND_ROBIN)) {
 			chan_misdn_log(4, port, " --> STARTING ROUND ROBIN...\n");
 			rr = get_robin_position(group);
@@ -3140,7 +3336,8 @@
 					, group);
 			return NULL;
 		}
-	} else { /* 'Normal' Port dial * Port dial */
+	} else {
+		/* 'Normal' Port dial * Port dial */
 		if (channel)
 			chan_misdn_log(1, port, " --> preselected_channel: %d\n", channel);
 		newbc = misdn_lib_get_free_bc(port, channel, 0, dec);
@@ -3677,6 +3874,7 @@
 }
 
 
+/*! \brief Import parameters from the dialplan environment variables */
 void import_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch)
 {
 	const char *tmp;
@@ -3710,6 +3908,7 @@
 	}
 }
 
+/*! \brief Export parameters to the dialplan environment variables */
 void export_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch)
 {
 	char tmp[32];
@@ -4184,9 +4383,9 @@
 		}
 
 		/*
-		   added support for s extension hope it will help those poor cretains
-		   which haven't overlap dial.
-		   */
+		 * added support for s extension hope it will help those poor cretains
+		 * which haven't overlap dial.
+		 */
 		misdn_cfg_get(bc->port, MISDN_CFG_ALWAYS_IMMEDIATE, &ai, sizeof(ai));
 		if (ai) {
 			do_immediate_setup(bc, ch, chan);
@@ -4936,7 +5135,8 @@
 		"   jb - Set jitter buffer length, optarg is length\n"
 		"   jt - Set jitter buffer upper threshold, optarg is threshold\n"
 		"   jn - Disable jitter buffer\n"
-		"    n - disable DSP on channel, disables: Echocancel, DTMF Detection and Volume Control.\n"
+		"    n - Disable mISDN DSP on channel.\n"
+		"        Disables: echo cancel, DTMF detection, and volume control.\n"
 		"    p - Caller ID presentation,\n"
 		"        optarg is either 'allowed' or 'restricted'\n"
 		"    s - Send Non-inband DTMF as inband\n"

Modified: team/oej/cancel_elsewhere_1.4/channels/chan_sip.c
URL: http://svn.digium.com/svn-view/asterisk/team/oej/cancel_elsewhere_1.4/channels/chan_sip.c?view=diff&rev=168475&r1=168474&r2=168475
==============================================================================
--- team/oej/cancel_elsewhere_1.4/channels/chan_sip.c (original)
+++ team/oej/cancel_elsewhere_1.4/channels/chan_sip.c Mon Jan 12 05:29:06 2009
@@ -629,6 +629,7 @@
 	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 */
+	AST_LIST_ENTRY(sip_request) next;
 };
 
 /*
@@ -1022,6 +1023,8 @@
 	struct sip_history_head *history;	/*!< History of this SIP dialog */
 	size_t history_entries;			/*!< Number of entires in the history */
 	struct ast_variable *chanvars;		/*!< Channel variables to set for inbound call */
+	AST_LIST_HEAD_NOLOCK(request_queue, sip_request) request_queue; /*!< Requests that arrived but could not be processed immediately */
+	int request_queue_sched_id;		/*!< Scheduler ID of any scheduled action to process queued requests */
 	struct sip_pvt *next;			/*!< Next dialog in chain */
 	struct sip_invite_param *options;	/*!< Options for INVITE */
 	int autoframing;
@@ -3100,6 +3103,7 @@
 {
 	struct sip_pvt *cur, *prev = NULL;
 	struct sip_pkt *cp;
+	struct sip_request *req;
 
 	/* We absolutely cannot destroy the rtp struct while a bridge is active or we WILL crash */
 	if (p->rtp && ast_rtp_get_bridged(p->rtp)) {
@@ -3155,6 +3159,7 @@
 	AST_SCHED_DEL(sched, p->initid);
 	AST_SCHED_DEL(sched, p->waitid);
 	AST_SCHED_DEL(sched, p->autokillid);
+	AST_SCHED_DEL(sched, p->request_queue_sched_id);
 
 	if (p->rtp) {
 		ast_rtp_destroy(p->rtp);
@@ -3185,6 +3190,10 @@
 		}
 		free(p->history);
 		p->history = NULL;
+	}
+
+	while ((req = AST_LIST_REMOVE_HEAD(&p->request_queue, next))) {
+		ast_free(req);
 	}
 
 	for (prev = NULL, cur = iflist; cur; prev = cur, cur = cur->next) {
@@ -4503,6 +4512,7 @@
 	p->initid = -1;
 	p->waitid = -1;
 	p->autokillid = -1;
+	p->request_queue_sched_id = -1;
 	p->subscribed = NONE;
 	p->stateid = -1;
 	p->prefs = default_prefs;		/* Set default codecs for this call */
@@ -4600,6 +4610,8 @@
 		p->t38.jointcapability = p->t38.capability;
 	}
 	ast_string_field_set(p, context, default_context);
+
+	AST_LIST_HEAD_INIT_NOLOCK(&p->request_queue);
 
 	/* Add to active dialog list */
 	ast_mutex_lock(&iflock);
@@ -5442,7 +5454,7 @@
 				found = 1;
 				if (option_debug > 2)
 					ast_log(LOG_DEBUG, "MaxBufferSize:%d\n",x);
-			} else if ((sscanf(a, "T38MaxBitRate:%d", &x) == 1)) {
+			} else if ((sscanf(a, "T38MaxBitRate:%d", &x) == 1) || (sscanf(a, "T38FaxMaxRate:%d", &x) == 1)) {
 				found = 1;
 				if (option_debug > 2)
 					ast_log(LOG_DEBUG,"T38MaxBitRate: %d\n",x);
@@ -5474,31 +5486,48 @@
 					peert38capability |= T38FAX_VERSION_0;
 				else if (x == 1)
 					peert38capability |= T38FAX_VERSION_1;
-			} else if ((sscanf(a, "T38FaxMaxDatagram:%d", &x) == 1)) {
+			} else if ((sscanf(a, "T38FaxMaxDatagram:%d", &x) == 1) || (sscanf(a, "T38MaxDatagram:%d", &x) == 1)) {
 				found = 1;
 				if (option_debug > 2)
 					ast_log(LOG_DEBUG, "FaxMaxDatagram: %d\n",x);
 				ast_udptl_set_far_max_datagram(p->udptl, x);
 				ast_udptl_set_local_max_datagram(p->udptl, x);
-			} else if ((sscanf(a, "T38FaxFillBitRemoval:%d", &x) == 1)) {
+			} else if ((strncmp(a, "T38FaxFillBitRemoval", 20) == 0)) {
 				found = 1;
-				if (option_debug > 2)
-					ast_log(LOG_DEBUG, "FillBitRemoval: %d\n",x);
-				if (x == 1)
-					peert38capability |= T38FAX_FILL_BIT_REMOVAL;
-			} else if ((sscanf(a, "T38FaxTranscodingMMR:%d", &x) == 1)) {
+				if ((sscanf(a, "T38FaxFillBitRemoval:%d", &x) == 1)) {
+				    if (option_debug > 2)
+					    ast_log(LOG_DEBUG, "FillBitRemoval: %d\n",x);
+				    if (x == 1)
+					    peert38capability |= T38FAX_FILL_BIT_REMOVAL;
+				} else {
+				    if (option_debug > 2)
+					    ast_log(LOG_DEBUG, "FillBitRemoval\n");
+				    peert38capability |= T38FAX_FILL_BIT_REMOVAL;
+				}
+			} else if ((strncmp(a, "T38FaxTranscodingMMR", 20) == 0)) {
 				found = 1;
-				if (option_debug > 2)
-					ast_log(LOG_DEBUG, "Transcoding MMR: %d\n",x);
-				if (x == 1)
-					peert38capability |= T38FAX_TRANSCODING_MMR;
-			}
-			if ((sscanf(a, "T38FaxTranscodingJBIG:%d", &x) == 1)) {
+				if ((sscanf(a, "T38FaxTranscodingMMR:%d", &x) == 1)) {
+				    if (option_debug > 2)
+					    ast_log(LOG_DEBUG, "Transcoding MMR: %d\n",x);
+				    if (x == 1)
+					    peert38capability |= T38FAX_TRANSCODING_MMR;
+				} else {
+				    if (option_debug > 2)
+					    ast_log(LOG_DEBUG, "Transcoding MMR\n");
+				    peert38capability |= T38FAX_TRANSCODING_MMR;
+				}
+			} else if ((strncmp(a, "T38FaxTranscodingJBIG", 21) == 0)) {
 				found = 1;
-				if (option_debug > 2)
-					ast_log(LOG_DEBUG, "Transcoding JBIG: %d\n",x);
-				if (x == 1)
-					peert38capability |= T38FAX_TRANSCODING_JBIG;
+				if ((sscanf(a, "T38FaxTranscodingJBIG:%d", &x) == 1)) {
+				    if (option_debug > 2)
+					    ast_log(LOG_DEBUG, "Transcoding JBIG: %d\n",x);
+				    if (x == 1)
+					    peert38capability |= T38FAX_TRANSCODING_JBIG;
+				} else {
+				    if (option_debug > 2)
+					    ast_log(LOG_DEBUG, "Transcoding JBIG\n");
+				    peert38capability |= T38FAX_TRANSCODING_JBIG;
+				}
 			} else if ((sscanf(a, "T38FaxRateManagement:%255s", s) == 1)) {
 				found = 1;
 				if (option_debug > 2)
@@ -6360,31 +6389,31 @@
 	
 	if (maxrate & T38FAX_RATE_14400) {
 		if (option_debug > 1)
-			ast_log(LOG_DEBUG, "T38MaxFaxRate 14400 found\n");
+			ast_log(LOG_DEBUG, "T38MaxBitRate 14400 found\n");
 		return 14400;
 	} else if (maxrate & T38FAX_RATE_12000) {
 		if (option_debug > 1)
-			ast_log(LOG_DEBUG, "T38MaxFaxRate 12000 found\n");
+			ast_log(LOG_DEBUG, "T38MaxBitRate 12000 found\n");
 		return 12000;
 	} else if (maxrate & T38FAX_RATE_9600) {
 		if (option_debug > 1)
-			ast_log(LOG_DEBUG, "T38MaxFaxRate 9600 found\n");
+			ast_log(LOG_DEBUG, "T38MaxBitRate 9600 found\n");
 		return 9600;
 	} else if (maxrate & T38FAX_RATE_7200) {
 		if (option_debug > 1)
-			ast_log(LOG_DEBUG, "T38MaxFaxRate 7200 found\n");
+			ast_log(LOG_DEBUG, "T38MaxBitRate 7200 found\n");
 		return 7200;
 	} else if (maxrate & T38FAX_RATE_4800) {
 		if (option_debug > 1)
-			ast_log(LOG_DEBUG, "T38MaxFaxRate 4800 found\n");
+			ast_log(LOG_DEBUG, "T38MaxBitRate 4800 found\n");
 		return 4800;
 	} else if (maxrate & T38FAX_RATE_2400) {
 		if (option_debug > 1)
-			ast_log(LOG_DEBUG, "T38MaxFaxRate 2400 found\n");
+			ast_log(LOG_DEBUG, "T38MaxBitRate 2400 found\n");
 		return 2400;
 	} else {
 		if (option_debug > 1)
-			ast_log(LOG_DEBUG, "Strange, T38MaxFaxRate NOT found in peers T38 SDP.\n");
+			ast_log(LOG_DEBUG, "Strange, T38MaxBitRate NOT found in peers T38 SDP.\n");
 		return 0;
 	}
 }
@@ -6459,9 +6488,12 @@
 		ast_build_string(&a_modem_next, &a_modem_left, "a=T38FaxVersion:1\r\n");
 	if ((x = t38_get_rate(p->t38.jointcapability)))
 		ast_build_string(&a_modem_next, &a_modem_left, "a=T38MaxBitRate:%d\r\n",x);
-	ast_build_string(&a_modem_next, &a_modem_left, "a=T38FaxFillBitRemoval:%d\r\n", (p->t38.jointcapability & T38FAX_FILL_BIT_REMOVAL) ? 1 : 0);
-	ast_build_string(&a_modem_next, &a_modem_left, "a=T38FaxTranscodingMMR:%d\r\n", (p->t38.jointcapability & T38FAX_TRANSCODING_MMR) ? 1 : 0);
-	ast_build_string(&a_modem_next, &a_modem_left, "a=T38FaxTranscodingJBIG:%d\r\n", (p->t38.jointcapability & T38FAX_TRANSCODING_JBIG) ? 1 : 0);
+	if ((p->t38.jointcapability & T38FAX_FILL_BIT_REMOVAL) == T38FAX_FILL_BIT_REMOVAL)
+		ast_build_string(&a_modem_next, &a_modem_left, "a=T38FaxFillBitRemoval\r\n");
+	if ((p->t38.jointcapability & T38FAX_TRANSCODING_MMR) == T38FAX_TRANSCODING_MMR)
+		ast_build_string(&a_modem_next, &a_modem_left, "a=T38FaxTranscodingMMR\r\n");
+	if ((p->t38.jointcapability & T38FAX_TRANSCODING_JBIG) == T38FAX_TRANSCODING_JBIG)
+		ast_build_string(&a_modem_next, &a_modem_left, "a=T38FaxTranscodingJBIG\r\n");
 	ast_build_string(&a_modem_next, &a_modem_left, "a=T38FaxRateManagement:%s\r\n", (p->t38.jointcapability & T38FAX_RATE_MANAGEMENT_LOCAL_TCF) ? "localTCF" : "transferredTCF");
 	x = ast_udptl_get_local_max_datagram(p->udptl);
 	ast_build_string(&a_modem_next, &a_modem_left, "a=T38FaxMaxBuffer:%d\r\n",x);
@@ -11309,6 +11341,7 @@
 	unsigned int event;
 	const char *c = get_header(req, "Content-Type");
 
+	check_via(p, req);
 	/* Need to check the media/type */
 	if (!strcasecmp(c, "application/dtmf-relay") ||
 	    !strcasecmp(c, "application/vnd.nortelnetworks.digits")) {
@@ -13557,6 +13590,7 @@
 	char *eventid = NULL;
 	char *sep;
 
+	check_via(p, req);
 	if( (sep = strchr(event, ';')) ) {	/* XXX bug here - overwriting string ? */
 		*sep++ = '\0';
 		eventid = sep;
@@ -13684,7 +13718,7 @@
 {
 	int res;
 
-
+	check_via(p, req);
 	/* XXX Should we authenticate OPTIONS? XXX */
 
 	if (p->lastinvite) {
@@ -14198,7 +14232,6 @@
 			char *uri = ast_strdupa(req->rlPart2);
 			char *at = strchr(uri, '@');
 			char *peerorhost;
-			struct sip_pkt *pkt = NULL;
 			if (option_debug > 2) {
 				ast_log(LOG_DEBUG, "Potential spiral detected. Original RURI was %s, new RURI is %s\n", p->initreq.rlPart2, req->rlPart2);
 			}
@@ -14209,14 +14242,12 @@
 			if ((peerorhost = strchr(uri, ':'))) {
 				*peerorhost++ = '\0';
 			}
-			create_addr(p, peerorhost);
 			ast_string_field_free(p, theirtag);
-			for (pkt = p->packets; pkt; pkt = pkt->next) {
-				if (pkt->seqno == p->icseq && pkt->method == SIP_INVITE) {
-					AST_SCHED_DEL(sched, pkt->retransid);
-				}
-			}
-			return transmit_invite(p, SIP_INVITE, 1, 3);
+			/* Treat this as if there were a call forward instead...
+			 */
+			ast_string_field_set(p->owner, call_forward, peerorhost);
+			ast_queue_control(p->owner, AST_CONTROL_BUSY);
+			return 0;
 		}
 	}
 	
@@ -14883,6 +14914,7 @@
 
 	int res = 0;
 
+	check_via(p, req);
 	if (ast_test_flag(req, SIP_PKT_DEBUG))
 		ast_verbose("Call %s got a SIP call transfer from %s: (REFER)!\n", p->callid, ast_test_flag(&p->flags[0], SIP_OUTGOING) ? "callee" : "caller");
 
@@ -15333,6 +15365,7 @@
 static int handle_request_message(struct sip_pvt *p, struct sip_request *req)
 {
 	if (!ast_test_flag(req, SIP_PKT_IGNORE)) {
+		check_via(p, req);
 		if (ast_test_flag(req, SIP_PKT_DEBUG))
 			ast_verbose("Receiving message!\n");
 		receive_message(p, req);
@@ -15910,6 +15943,88 @@
 	return res;
 }
 
+static void process_request_queue(struct sip_pvt *p, int *recount, int *nounlock)
+{
+	struct sip_request *req;
+
+	while ((req = AST_LIST_REMOVE_HEAD(&p->request_queue, next))) {
+		if (handle_request(p, req, &p->recv, recount, nounlock) == -1) {
+			/* Request failed */
+			if (option_debug) {
+				ast_log(LOG_DEBUG, "SIP message could not be handled, bad request: %-70.70s\n", p->callid[0] ? p->callid : "<no callid>");
+			}
+		}
+		ast_free(req);
+	}
+}
+
+static int scheduler_process_request_queue(const void *data)
+{
+	struct sip_pvt *p = (struct sip_pvt *) data;
+	int recount = 0;
+	int nounlock = 0;
+	int lockretry;
+
+	for (lockretry = 10; lockretry > 0; lockretry--) {
+		ast_mutex_lock(&p->lock);
+
+		/* lock the owner if it has one -- we may need it */
+		/* because this is deadlock-prone, we need to try and unlock if failed */
+		if (!p->owner || !ast_channel_trylock(p->owner)) {
+			break;	/* locking succeeded */
+		}
+
+		if (lockretry != 1) {
+			ast_mutex_unlock(&p->lock);
+			/* Sleep for a very short amount of time */
+			usleep(1);
+		}
+	}
+
+	if (!lockretry) {
+		int retry = !AST_LIST_EMPTY(&p->request_queue);
+
+		/* we couldn't get the owner lock, which is needed to process
+		   the queued requests, so return a non-zero value, which will
+		   cause the scheduler to run this request again later if there
+		   still requests to be processed
+		*/
+		ast_mutex_unlock(&p->lock);
+		return retry;
+	};
+
+	process_request_queue(p, &recount, &nounlock);
+	p->request_queue_sched_id = -1;
+
+	if (p->owner && !nounlock) {
+		ast_channel_unlock(p->owner);
+	}
+	ast_mutex_unlock(&p->lock);
+
+	if (recount) {
+		ast_update_use_count();
+	}
+
+	return 0;
+}
+
+static int queue_request(struct sip_pvt *p, const struct sip_request *req)
+{
+	struct sip_request *newreq;
+
+	if (!(newreq = ast_calloc(1, sizeof(*newreq)))) {
+		return -1;
+	}
+
+	copy_request(newreq, req);
+	AST_LIST_INSERT_TAIL(&p->request_queue, newreq, next);
+	if (p->request_queue_sched_id == -1) {
+		p->request_queue_sched_id = ast_sched_add(sched, 10, scheduler_process_request_queue, p);
+	}
+
+	return 0;
+}
+
 /*! \brief Read data from SIP socket
 \note sipsock_read locks the owner channel while we are processing the SIP message
 \return 1 on error, 0 on success
@@ -15922,7 +16037,7 @@
 	struct sip_pvt *p;
 	int res;
 	socklen_t len = sizeof(sin);
-	int nounlock;
+	int nounlock = 0;
 	int recount = 0;
 	int lockretry;
 
@@ -15962,7 +16077,7 @@
 		return 1;
 
 	/* Process request, with netlock held, and with usual deadlock avoidance */
-	for (lockretry = 100; lockretry > 0; lockretry--) {

[... 1829 lines stripped ...]



More information about the asterisk-commits mailing list