[svn-commits] oej: branch oej/bufo-manager-contexts-1.8 r392697 - in /team/oej/bufo-manager...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Mon Jun 24 07:07:46 CDT 2013


Author: oej
Date: Mon Jun 24 07:07:43 2013
New Revision: 392697

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=392697
Log:
Resetting this branch

Modified:
    team/oej/bufo-manager-contexts-1.8/   (props changed)
    team/oej/bufo-manager-contexts-1.8/CHANGES
    team/oej/bufo-manager-contexts-1.8/UPGRADE.txt
    team/oej/bufo-manager-contexts-1.8/addons/chan_ooh323.c
    team/oej/bufo-manager-contexts-1.8/apps/app_meetme.c
    team/oej/bufo-manager-contexts-1.8/apps/app_mixmonitor.c
    team/oej/bufo-manager-contexts-1.8/apps/app_queue.c
    team/oej/bufo-manager-contexts-1.8/channels/chan_dahdi.c
    team/oej/bufo-manager-contexts-1.8/channels/chan_iax2.c
    team/oej/bufo-manager-contexts-1.8/channels/chan_sip.c
    team/oej/bufo-manager-contexts-1.8/channels/misdn/isdn_msg_parser.c
    team/oej/bufo-manager-contexts-1.8/channels/sip/include/sip.h
    team/oej/bufo-manager-contexts-1.8/configs/queues.conf.sample
    team/oej/bufo-manager-contexts-1.8/configure
    team/oej/bufo-manager-contexts-1.8/configure.ac
    team/oej/bufo-manager-contexts-1.8/include/asterisk/autoconfig.h.in
    team/oej/bufo-manager-contexts-1.8/include/asterisk/utils.h
    team/oej/bufo-manager-contexts-1.8/main/channel.c
    team/oej/bufo-manager-contexts-1.8/main/config.c
    team/oej/bufo-manager-contexts-1.8/main/features.c
    team/oej/bufo-manager-contexts-1.8/main/loader.c
    team/oej/bufo-manager-contexts-1.8/main/lock.c
    team/oej/bufo-manager-contexts-1.8/main/logger.c
    team/oej/bufo-manager-contexts-1.8/main/manager.c
    team/oej/bufo-manager-contexts-1.8/main/pbx.c
    team/oej/bufo-manager-contexts-1.8/main/slinfactory.c
    team/oej/bufo-manager-contexts-1.8/main/utils.c
    team/oej/bufo-manager-contexts-1.8/pbx/pbx_dundi.c
    team/oej/bufo-manager-contexts-1.8/res/res_rtp_asterisk.c
    team/oej/bufo-manager-contexts-1.8/res/res_srtp.c
    team/oej/bufo-manager-contexts-1.8/sounds/Makefile
    team/oej/bufo-manager-contexts-1.8/utils/   (props changed)
    team/oej/bufo-manager-contexts-1.8/utils/Makefile

Propchange: team/oej/bufo-manager-contexts-1.8/
------------------------------------------------------------------------------
    automerge = Is-there-life-off-net?

Propchange: team/oej/bufo-manager-contexts-1.8/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Mon Jun 24 07:07:43 2013
@@ -24,3 +24,4 @@
 makeopts.embed_rules
 aclocal.m4
 update.log
+doxygen.log

Propchange: team/oej/bufo-manager-contexts-1.8/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Mon Jun 24 07:07:43 2013
@@ -1,1 +1,1 @@
-/branches/1.8:1-386604
+/branches/1.8:1-392696

Modified: team/oej/bufo-manager-contexts-1.8/CHANGES
URL: http://svnview.digium.com/svn/asterisk/team/oej/bufo-manager-contexts-1.8/CHANGES?view=diff&rev=392697&r1=392696&r2=392697
==============================================================================
--- team/oej/bufo-manager-contexts-1.8/CHANGES (original)
+++ team/oej/bufo-manager-contexts-1.8/CHANGES Mon Jun 24 07:07:43 2013
@@ -7,6 +7,15 @@
 === and the other UPGRADE files for older releases.
 ===
 ======================================================================
+
+------------------------------------------------------------------------------
+--- Functionality changes since Asterisk 1.8.19.1 ----------------------------
+------------------------------------------------------------------------------
+
+App_queue
+---------
+ * App_queue will now play periodic announcements for the caller that
+   holds the first position in the queue while waiting for answer.
 
 ------------------------------------------------------------------------------
 --- Functionality changes since Asterisk 1.8.12.0 ----------------------------

Modified: team/oej/bufo-manager-contexts-1.8/UPGRADE.txt
URL: http://svnview.digium.com/svn/asterisk/team/oej/bufo-manager-contexts-1.8/UPGRADE.txt?view=diff&rev=392697&r1=392696&r2=392697
==============================================================================
--- team/oej/bufo-manager-contexts-1.8/UPGRADE.txt (original)
+++ team/oej/bufo-manager-contexts-1.8/UPGRADE.txt Mon Jun 24 07:07:43 2013
@@ -22,6 +22,12 @@
 * The default settings for chan_sip are now overriden properly by the general
   settings in sip.conf.  Please look over your settings upon upgrading.
 
+* It is now possible to play the Queue prompts to the first user waiting in a call queue.
+  Note that this may impact the ability for agents to talk with users, as a prompt may
+  still be playing when an agent connects to the user. This ability is disabled by
+  default but can be enabled on an individual queue using the 'announce-to-first-user'
+  option.
+
 from 1.8.21.0 to 1.8.22.0:
 * Added the 'n' option to MeetMe to prevent application of the DENOISE function
   to a channel joining a conference. Some channel drivers that vary the number

Modified: team/oej/bufo-manager-contexts-1.8/addons/chan_ooh323.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/bufo-manager-contexts-1.8/addons/chan_ooh323.c?view=diff&rev=392697&r1=392696&r2=392697
==============================================================================
--- team/oej/bufo-manager-contexts-1.8/addons/chan_ooh323.c (original)
+++ team/oej/bufo-manager-contexts-1.8/addons/chan_ooh323.c Mon Jun 24 07:07:43 2013
@@ -286,6 +286,8 @@
 int onCallCleared(ooCallData *call);
 void onModeChanged(ooCallData *call, int t38mode);
 
+extern OOH323EndPoint gH323ep;
+
 static char gLogFile[256] = DEFAULT_LOGFILE;
 static int  gPort = 1720;
 static char gIP[20];
@@ -629,6 +631,7 @@
 		ooh323_destroy(p);
 		ast_mutex_unlock(&iflock);
 		ast_log(LOG_ERROR, "Destination format is not supported\n");
+		*cause = AST_CAUSE_INVALID_NUMBER_FORMAT;
 		return NULL;
 	}
 
@@ -671,6 +674,10 @@
 			ast_mutex_unlock(&p->lock);
 			ooh323_destroy(p);
 			ast_mutex_unlock(&iflock);
+			return NULL;
+		} else if (gH323ep.gkClient && gH323ep.gkClient->state != GkClientRegistered) {
+			ast_log(LOG_ERROR, "Gatekeeper client is configured but not registered\n");
+			*cause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
 			return NULL;
 		}
 		p->g729onlyA = g729onlyA;

Modified: team/oej/bufo-manager-contexts-1.8/apps/app_meetme.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/bufo-manager-contexts-1.8/apps/app_meetme.c?view=diff&rev=392697&r1=392696&r2=392697
==============================================================================
--- team/oej/bufo-manager-contexts-1.8/apps/app_meetme.c (original)
+++ team/oej/bufo-manager-contexts-1.8/apps/app_meetme.c Mon Jun 24 07:07:43 2013
@@ -6156,8 +6156,8 @@
 
 	ast_mutex_lock(&sla.lock);
 
-	if (!AST_LIST_EMPTY(&sla.event_q) || !AST_LIST_EMPTY(&sla.ringing_trunks) 
-		|| !AST_LIST_EMPTY(&sla.ringing_stations)) {
+	if (!AST_LIST_EMPTY(&sla.event_q) || !AST_LIST_EMPTY(&sla.ringing_trunks)
+		|| !AST_LIST_EMPTY(&sla.ringing_stations) || !AST_LIST_EMPTY(&sla.failed_stations)) {
 		ast_mutex_unlock(&sla.lock);
 		return;
 	}
@@ -6175,8 +6175,9 @@
 
 	AST_RWLIST_RDLOCK(&sla_trunks);
 	AST_RWLIST_TRAVERSE(&sla_trunks, trunk, entry) {
-		if (trunk->ref_count)
+		if (trunk->ref_count || trunk->chan || trunk->active_stations || trunk->hold_stations) {
 			break;
+		}
 	}
 	AST_RWLIST_UNLOCK(&sla_trunks);
 	if (trunk) {
@@ -6432,7 +6433,7 @@
 		return 0;
 	}
 
-	AST_RWLIST_RDLOCK(&sla_stations);
+	AST_RWLIST_WRLOCK(&sla_stations);
 	station = sla_find_station(station_name);
 	if (station)
 		ast_atomic_fetchadd_int((int *) &station->ref_count, 1);
@@ -6644,7 +6645,7 @@
 		}
 	}
 
-	AST_RWLIST_RDLOCK(&sla_trunks);
+	AST_RWLIST_WRLOCK(&sla_trunks);
 	trunk = sla_find_trunk(args.trunk_name);
 	if (trunk)
 		ast_atomic_fetchadd_int((int *) &trunk->ref_count, 1);

Modified: team/oej/bufo-manager-contexts-1.8/apps/app_mixmonitor.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/bufo-manager-contexts-1.8/apps/app_mixmonitor.c?view=diff&rev=392697&r1=392696&r2=392697
==============================================================================
--- team/oej/bufo-manager-contexts-1.8/apps/app_mixmonitor.c (original)
+++ team/oej/bufo-manager-contexts-1.8/apps/app_mixmonitor.c Mon Jun 24 07:07:43 2013
@@ -381,6 +381,8 @@
 
 	ast_verb(2, "End MixMonitor Recording %s\n", mixmonitor->name);
 	mixmonitor_free(mixmonitor);
+
+	ast_module_unref(ast_module_info->self);
 	return NULL;
 }
 
@@ -414,7 +416,7 @@
 	return 0;
 }
 
-static void launch_monitor_thread(struct ast_channel *chan, const char *filename, unsigned int flags,
+static int launch_monitor_thread(struct ast_channel *chan, const char *filename, unsigned int flags,
 				  int readvol, int writevol, const char *post_process) 
 {
 	pthread_t thread;
@@ -442,26 +444,26 @@
 
 	/* Pre-allocate mixmonitor structure and spy */
 	if (!(mixmonitor = ast_calloc(1, len))) {
-		return;
+		return -1;
 	}
 
 	/* Setup the actual spy before creating our thread */
 	if (ast_audiohook_init(&mixmonitor->audiohook, AST_AUDIOHOOK_TYPE_SPY, mixmonitor_spy_type)) {
 		mixmonitor_free(mixmonitor);
-		return;
+		return -1;
 	}
 
 	/* Copy over flags and channel name */
 	mixmonitor->flags = flags;
 	if (!(mixmonitor->autochan = ast_autochan_setup(chan))) {
 		mixmonitor_free(mixmonitor);
-		return;
+		return -1;
 	}
 
 	if (setup_mixmonitor_ds(mixmonitor, chan)) {
 		ast_autochan_destroy(mixmonitor->autochan);
 		mixmonitor_free(mixmonitor);
-		return;
+		return -1;
 	}
 	mixmonitor->name = (char *) mixmonitor + sizeof(*mixmonitor);
 	strcpy(mixmonitor->name, chan->name);
@@ -485,10 +487,10 @@
 			mixmonitor_spy_type, chan->name);
 		ast_audiohook_destroy(&mixmonitor->audiohook);
 		mixmonitor_free(mixmonitor);
-		return;
-	}
-
-	ast_pthread_create_detached_background(&thread, NULL, mixmonitor_thread, mixmonitor);
+		return -1;
+	}
+
+	return ast_pthread_create_detached_background(&thread, NULL, mixmonitor_thread, mixmonitor);
 }
 
 static int mixmonitor_exec(struct ast_channel *chan, const char *data)
@@ -567,7 +569,12 @@
 	ast_mkdir(tmp, 0777);
 
 	pbx_builtin_setvar_helper(chan, "MIXMONITOR_FILENAME", args.filename);
-	launch_monitor_thread(chan, args.filename, flags.flags, readvol, writevol, args.post_process);
+
+	/* If launch_monitor_thread works, the module reference must not be released until it is finished. */
+	ast_module_ref(ast_module_info->self);
+	if (launch_monitor_thread(chan, args.filename, flags.flags, readvol, writevol, args.post_process)) {
+		ast_module_unref(ast_module_info->self);
+	}
 
 	return 0;
 }

Modified: team/oej/bufo-manager-contexts-1.8/apps/app_queue.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/bufo-manager-contexts-1.8/apps/app_queue.c?view=diff&rev=392697&r1=392696&r2=392697
==============================================================================
--- team/oej/bufo-manager-contexts-1.8/apps/app_queue.c (original)
+++ team/oej/bufo-manager-contexts-1.8/apps/app_queue.c Mon Jun 24 07:07:43 2013
@@ -1126,6 +1126,7 @@
 	unsigned int dead:1;
 	unsigned int eventwhencalled:2;
 	unsigned int ringinuse:1;
+	unsigned int announce_to_first_user:1; /*!< Whether or not we announce to the first user in a queue */
 	unsigned int setinterfacevar:1;
 	unsigned int setqueuevar:1;
 	unsigned int setqueueentryvar:1;
@@ -1730,6 +1731,7 @@
 	q->roundingseconds = 0; /* Default - don't announce seconds */
 	q->servicelevel = 0;
 	q->ringinuse = 1;
+	q->announce_to_first_user = 0;
 	q->setinterfacevar = 0;
 	q->setqueuevar = 0;
 	q->setqueueentryvar = 0;
@@ -1992,6 +1994,8 @@
 		ast_string_field_set(q, sound_reporthold, val);
 	} else if (!strcasecmp(param, "announce-frequency")) {
 		q->announcefrequency = atoi(val);
+	} else if (!strcasecmp(param, "announce-to-first-user")) {
+		q->announce_to_first_user = ast_true(val);
 	} else if (!strcasecmp(param, "min-announce-frequency")) {
 		q->minannouncefrequency = atoi(val);
 		ast_debug(1, "%s=%s for queue '%s'\n", param, val, q->name);
@@ -3607,7 +3611,7 @@
  *
  * \todo eventually all call forward logic should be intergerated into and replaced by ast_call_forward()
  */
-static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callattempt *outgoing, int *to, char *digit, int prebusies, int caller_disconnect, int forwardsallowed)
+static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callattempt *outgoing, int *to, char *digit, int prebusies, int caller_disconnect, int forwardsallowed, int ringing)
 {
 	const char *queue = qe->parent->name;
 	struct callattempt *o, *start = NULL, *prev = NULL;
@@ -4087,6 +4091,16 @@
 		}
 	}
 
+	/* Make a position announcement, if enabled */
+ 	if (qe->parent->announcefrequency && qe->parent->announce_to_first_user) {
+		say_position(qe, ringing);
+	}
+
+ 	/* Make a periodic announcement, if enabled */
+ 	if (qe->parent->periodicannouncefrequency && qe->parent->announce_to_first_user) {
+ 		say_periodic_announcement(qe, ringing);
+ 	}
+ 
 	if (!*to) {
 		for (o = start; o; o = o->call_next) {
 			rna(orig, qe, o->interface, o->member->membername, 1);
@@ -4833,7 +4847,7 @@
 	ring_one(qe, outgoing, &numbusies);
 	lpeer = wait_for_answer(qe, outgoing, &to, &digit, numbusies,
 		ast_test_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT),
-		forwardsallowed);
+		forwardsallowed, ringing);
 	/* The ast_channel_datastore_remove() function could fail here if the
 	 * datastore was moved to another channel during a masquerade. If this is
 	 * the case, don't free the datastore here because later, when the channel
@@ -8429,6 +8443,7 @@
 	MEMBER(call_queue, dead, AST_DATA_BOOLEAN)			\
 	MEMBER(call_queue, eventwhencalled, AST_DATA_BOOLEAN)		\
 	MEMBER(call_queue, ringinuse, AST_DATA_BOOLEAN)			\
+	MEMBER(call_queue, announce_to_first_user, AST_DATA_BOOLEAN)	\
 	MEMBER(call_queue, setinterfacevar, AST_DATA_BOOLEAN)		\
 	MEMBER(call_queue, setqueuevar, AST_DATA_BOOLEAN)		\
 	MEMBER(call_queue, setqueueentryvar, AST_DATA_BOOLEAN)		\

Modified: team/oej/bufo-manager-contexts-1.8/channels/chan_dahdi.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/bufo-manager-contexts-1.8/channels/chan_dahdi.c?view=diff&rev=392697&r1=392696&r2=392697
==============================================================================
--- team/oej/bufo-manager-contexts-1.8/channels/chan_dahdi.c (original)
+++ team/oej/bufo-manager-contexts-1.8/channels/chan_dahdi.c Mon Jun 24 07:07:43 2013
@@ -5015,9 +5015,12 @@
 				if (drc) {
 					k = drc_sample(k, drc);
 				}
-				k = (float)k*linear_gain;
-				if (k > 32767) k = 32767;
-				if (k < -32767) k = -32767;
+				k = (float)k * linear_gain;
+				if (k > 32767) {
+					k = 32767;
+				} else if (k < -32768) {
+					k = -32768;
+				}
 				g->txgain[j] = AST_LIN2A(k);
 			} else {
 				g->txgain[j] = j;
@@ -5031,9 +5034,12 @@
 				if (drc) {
 					k = drc_sample(k, drc);
 				}
-				k = (float)k*linear_gain;
-				if (k > 32767) k = 32767;
-				if (k < -32767) k = -32767;
+				k = (float)k * linear_gain;
+				if (k > 32767) {
+					k = 32767;
+				} else if (k < -32768) {
+					k = -32768;
+				}
 				g->txgain[j] = AST_LIN2MU(k);
 
 			} else {
@@ -5058,9 +5064,12 @@
 				if (drc) {
 					k = drc_sample(k, drc);
 				}
-				k = (float)k*linear_gain;
-				if (k > 32767) k = 32767;
-				if (k < -32767) k = -32767;
+				k = (float)k * linear_gain;
+				if (k > 32767) {
+					k = 32767;
+				} else if (k < -32768) {
+					k = -32768;
+				}
 				g->rxgain[j] = AST_LIN2A(k);
 			} else {
 				g->rxgain[j] = j;
@@ -5074,9 +5083,12 @@
 				if (drc) {
 					k = drc_sample(k, drc);
 				}
-				k = (float)k*linear_gain;
-				if (k > 32767) k = 32767;
-				if (k < -32767) k = -32767;
+				k = (float)k * linear_gain;
+				if (k > 32767) {
+					k = 32767;
+				} else if (k < -32768) {
+					k = -32768;
+				}
 				g->rxgain[j] = AST_LIN2MU(k);
 			} else {
 				g->rxgain[j] = j;

Modified: team/oej/bufo-manager-contexts-1.8/channels/chan_iax2.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/bufo-manager-contexts-1.8/channels/chan_iax2.c?view=diff&rev=392697&r1=392696&r2=392697
==============================================================================
--- team/oej/bufo-manager-contexts-1.8/channels/chan_iax2.c (original)
+++ team/oej/bufo-manager-contexts-1.8/channels/chan_iax2.c Mon Jun 24 07:07:43 2013
@@ -11369,65 +11369,99 @@
 				}
 				break;
 			case IAX_COMMAND_TXREJ:
-				iaxs[fr->callno]->transferring = 0;
+				if (iaxs[fr->callno]->bridgecallno) {
+					while (ast_mutex_trylock(&iaxsl[iaxs[fr->callno]->bridgecallno])) {
+						DEADLOCK_AVOIDANCE(&iaxsl[fr->callno]);
+					}
+					if (!iaxs[fr->callno]) {
+						break;
+					}
+				}
+
+				iaxs[fr->callno]->transferring = TRANSFER_NONE;
 				ast_verb(3, "Channel '%s' unable to transfer\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>");
 				memset(&iaxs[fr->callno]->transfer, 0, sizeof(iaxs[fr->callno]->transfer));
+
+				if (!iaxs[fr->callno]->bridgecallno) {
+					break;
+				}
+
+				if (iaxs[iaxs[fr->callno]->bridgecallno]->transferring) {
+					iaxs[iaxs[fr->callno]->bridgecallno]->transferring = TRANSFER_NONE;
+					send_command(iaxs[iaxs[fr->callno]->bridgecallno], AST_FRAME_IAX, IAX_COMMAND_TXREJ, 0, NULL, 0, -1);
+				}
+				ast_mutex_unlock(&iaxsl[iaxs[fr->callno]->bridgecallno]);
+				break;
+			case IAX_COMMAND_TXREADY:
 				if (iaxs[fr->callno]->bridgecallno) {
-					if (iaxs[iaxs[fr->callno]->bridgecallno]->transferring) {
-						iaxs[iaxs[fr->callno]->bridgecallno]->transferring = 0;
-						send_command(iaxs[iaxs[fr->callno]->bridgecallno], AST_FRAME_IAX, IAX_COMMAND_TXREJ, 0, NULL, 0, -1);
+					while (ast_mutex_trylock(&iaxsl[iaxs[fr->callno]->bridgecallno])) {
+						DEADLOCK_AVOIDANCE(&iaxsl[fr->callno]);
+					}
+					if (!iaxs[fr->callno]) {
+						break;
 					}
 				}
-				break;
-			case IAX_COMMAND_TXREADY:
-				if ((iaxs[fr->callno]->transferring == TRANSFER_BEGIN) ||
-				    (iaxs[fr->callno]->transferring == TRANSFER_MBEGIN)) {
-					if (iaxs[fr->callno]->transferring == TRANSFER_MBEGIN)
-						iaxs[fr->callno]->transferring = TRANSFER_MREADY;
-					else
-						iaxs[fr->callno]->transferring = TRANSFER_READY;
-					ast_verb(3, "Channel '%s' ready to transfer\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>");
+
+				if (iaxs[fr->callno]->transferring == TRANSFER_BEGIN) {
+					iaxs[fr->callno]->transferring = TRANSFER_READY;
+				} else if (iaxs[fr->callno]->transferring == TRANSFER_MBEGIN) {
+					iaxs[fr->callno]->transferring = TRANSFER_MREADY;
+				} else {
 					if (iaxs[fr->callno]->bridgecallno) {
-						if ((iaxs[iaxs[fr->callno]->bridgecallno]->transferring == TRANSFER_READY) ||
-						    (iaxs[iaxs[fr->callno]->bridgecallno]->transferring == TRANSFER_MREADY)) {
-							/* They're both ready, now release them. */
-							if (iaxs[fr->callno]->transferring == TRANSFER_MREADY) {
-								ast_verb(3, "Attempting media bridge of %s and %s\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>",
-										iaxs[iaxs[fr->callno]->bridgecallno]->owner ? iaxs[iaxs[fr->callno]->bridgecallno]->owner->name : "<Unknown>");
-
-								iaxs[iaxs[fr->callno]->bridgecallno]->transferring = TRANSFER_MEDIA;
-								iaxs[fr->callno]->transferring = TRANSFER_MEDIA;
-
-								memset(&ied0, 0, sizeof(ied0));
-								memset(&ied1, 0, sizeof(ied1));
-								iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[iaxs[fr->callno]->bridgecallno]->peercallno);
-								iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[fr->callno]->peercallno);
-								send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXMEDIA, 0, ied0.buf, ied0.pos, -1);
-								send_command(iaxs[iaxs[fr->callno]->bridgecallno], AST_FRAME_IAX, IAX_COMMAND_TXMEDIA, 0, ied1.buf, ied1.pos, -1);
-							} else {
-								ast_verb(3, "Releasing %s and %s\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>",
-										iaxs[iaxs[fr->callno]->bridgecallno]->owner ? iaxs[iaxs[fr->callno]->bridgecallno]->owner->name : "<Unknown>");
-
-								iaxs[iaxs[fr->callno]->bridgecallno]->transferring = TRANSFER_RELEASED;
-								iaxs[fr->callno]->transferring = TRANSFER_RELEASED;
-								ast_set_flag64(iaxs[iaxs[fr->callno]->bridgecallno], IAX_ALREADYGONE);
-								ast_set_flag64(iaxs[fr->callno], IAX_ALREADYGONE);
-
-								/* Stop doing lag & ping requests */
-								stop_stuff(fr->callno);
-								stop_stuff(iaxs[fr->callno]->bridgecallno);
-
-								memset(&ied0, 0, sizeof(ied0));
-								memset(&ied1, 0, sizeof(ied1));
-								iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[iaxs[fr->callno]->bridgecallno]->peercallno);
-								iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[fr->callno]->peercallno);
-								send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXREL, 0, ied0.buf, ied0.pos, -1);
-								send_command(iaxs[iaxs[fr->callno]->bridgecallno], AST_FRAME_IAX, IAX_COMMAND_TXREL, 0, ied1.buf, ied1.pos, -1);
-							}
-
-						}
+						ast_mutex_unlock(&iaxsl[iaxs[fr->callno]->bridgecallno]);
 					}
+					break;
 				}
+				ast_verb(3, "Channel '%s' ready to transfer\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>");
+
+				if (!iaxs[fr->callno]->bridgecallno) {
+					break;
+				}
+
+				if (!(iaxs[iaxs[fr->callno]->bridgecallno]->transferring == TRANSFER_READY) &&
+				    !(iaxs[iaxs[fr->callno]->bridgecallno]->transferring == TRANSFER_MREADY)) {
+					ast_mutex_unlock(&iaxsl[iaxs[fr->callno]->bridgecallno]);
+					break;
+				}
+
+				/* Both sides are ready */
+
+				/* XXX what isn't checked here is that both sides match transfer types. */
+
+				if (iaxs[fr->callno]->transferring == TRANSFER_MREADY) {
+					ast_verb(3, "Attempting media bridge of %s and %s\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>",
+							iaxs[iaxs[fr->callno]->bridgecallno]->owner ? iaxs[iaxs[fr->callno]->bridgecallno]->owner->name : "<Unknown>");
+
+					iaxs[iaxs[fr->callno]->bridgecallno]->transferring = TRANSFER_MEDIA;
+					iaxs[fr->callno]->transferring = TRANSFER_MEDIA;
+
+					memset(&ied0, 0, sizeof(ied0));
+					memset(&ied1, 0, sizeof(ied1));
+					iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[iaxs[fr->callno]->bridgecallno]->peercallno);
+					iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[fr->callno]->peercallno);
+					send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXMEDIA, 0, ied0.buf, ied0.pos, -1);
+					send_command(iaxs[iaxs[fr->callno]->bridgecallno], AST_FRAME_IAX, IAX_COMMAND_TXMEDIA, 0, ied1.buf, ied1.pos, -1);
+				} else {
+					ast_verb(3, "Releasing %s and %s\n", iaxs[fr->callno]->owner ? iaxs[fr->callno]->owner->name : "<Unknown>",
+							iaxs[iaxs[fr->callno]->bridgecallno]->owner ? iaxs[iaxs[fr->callno]->bridgecallno]->owner->name : "<Unknown>");
+
+					iaxs[iaxs[fr->callno]->bridgecallno]->transferring = TRANSFER_RELEASED;
+					iaxs[fr->callno]->transferring = TRANSFER_RELEASED;
+					ast_set_flag64(iaxs[iaxs[fr->callno]->bridgecallno], IAX_ALREADYGONE);
+					ast_set_flag64(iaxs[fr->callno], IAX_ALREADYGONE);
+
+					/* Stop doing lag & ping requests */
+					stop_stuff(fr->callno);
+					stop_stuff(iaxs[fr->callno]->bridgecallno);
+
+					memset(&ied0, 0, sizeof(ied0));
+					memset(&ied1, 0, sizeof(ied1));
+					iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[iaxs[fr->callno]->bridgecallno]->peercallno);
+					iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[fr->callno]->peercallno);
+					send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXREL, 0, ied0.buf, ied0.pos, -1);
+					send_command(iaxs[iaxs[fr->callno]->bridgecallno], AST_FRAME_IAX, IAX_COMMAND_TXREL, 0, ied1.buf, ied1.pos, -1);
+				}
+				ast_mutex_unlock(&iaxsl[iaxs[fr->callno]->bridgecallno]);
 				break;
 			case IAX_COMMAND_TXREQ:
 				try_transfer(iaxs[fr->callno], &ies);

Modified: team/oej/bufo-manager-contexts-1.8/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/bufo-manager-contexts-1.8/channels/chan_sip.c?view=diff&rev=392697&r1=392696&r2=392697
==============================================================================
--- team/oej/bufo-manager-contexts-1.8/channels/chan_sip.c (original)
+++ team/oej/bufo-manager-contexts-1.8/channels/chan_sip.c Mon Jun 24 07:07:43 2013
@@ -1211,6 +1211,8 @@
 		(head) = (element)->next;	\
 	} while (0)
 
+struct show_peers_context;
+
 /*---------------------------- Forward declarations of functions in chan_sip.c */
 /* Note: This is added to help splitting up chan_sip.c into several files
 	in coming releases. */
@@ -1377,6 +1379,7 @@
 static int peer_status(struct sip_peer *peer, char *status, int statuslen);
 static char *sip_show_sched(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
 static char * _sip_show_peers(int fd, int *total, struct mansession *s, const struct message *m, int argc, const char *argv[]);
+static struct sip_peer *_sip_show_peers_one(int fd, struct mansession *s, struct show_peers_context *cont, struct sip_peer *peer);
 static char *sip_show_peers(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
 static char *sip_show_objects(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
 static void  print_group(int fd, ast_group_t group, int crlf);
@@ -13370,7 +13373,20 @@
 
 	p->pendinginvite = p->ocseq;	/* Remember that we have a pending NOTIFY in order not to confuse the NOTIFY subsystem */
 
-	return send_request(p, &req, XMIT_RELIABLE, p->ocseq);
+	/* Send as XMIT_CRITICAL as we may never receive a 200 OK Response which clears p->pendinginvite.
+	 *
+	 * extensionstate_update() uses p->pendinginvite for queuing control.
+	 * Updates stall if pendinginvite <> 0.
+	 *
+	 * The most appropriate solution is to remove the subscription when the NOTIFY transaction fails.
+	 * The client will re-subscribe after restarting or maxexpiry timeout.
+	 */
+
+	/* RFC6665 4.2.2.  Sending State Information to Subscribers
+	 * If the NOTIFY request fails due to expiration of SIP Timer F (transaction timeout),
+	 * the notifier SHOULD remove the subscription.
+	 */
+	return send_request(p, &req, XMIT_CRITICAL, p->ocseq);
 }
 
 /*! \brief Notify user of messages waiting in voicemail (RFC3842)
@@ -17317,44 +17333,56 @@
 	return strcmp((*ap)->name, (*bp)->name);
 }
 
+/* the last argument is left-aligned, so we don't need a size anyways */
+#define PEERS_FORMAT2 "%-25.25s %-39.39s %-3.3s %-10.10s %-3.3s %-8s %-10s %s\n"
+
+/*! \brief Used in the sip_show_peers functions to pass parameters */
+struct show_peers_context {
+	regex_t regexbuf;
+	int havepattern;
+	char idtext[256];
+	int realtimepeers;
+	int peers_mon_online;
+	int peers_mon_offline;
+	int peers_unmon_offline;
+	int peers_unmon_online;
+};
 
 /*! \brief Execute sip show peers command */
 static char *_sip_show_peers(int fd, int *total, struct mansession *s, const struct message *m, int argc, const char *argv[])
 {
-	regex_t regexbuf;
-	int havepattern = FALSE;
+	struct show_peers_context cont = {
+		.havepattern = FALSE,
+		.idtext = "",
+
+		.peers_mon_online = 0,
+		.peers_mon_offline = 0,
+		.peers_unmon_online = 0,
+		.peers_unmon_offline = 0,
+	};
 	struct sip_peer *peer;
 	struct ao2_iterator* it_peers;
 
-/* the last argument is left-aligned, so we don't need a size anyways */
-#define FORMAT2 "%-25.25s  %-39.39s %-3.3s %-10.10s %-3.3s %-8s %-10s %s\n"
-
-	char name[256];
 	int total_peers = 0;
-	int peers_mon_online = 0;
-	int peers_mon_offline = 0;
-	int peers_unmon_offline = 0;
-	int peers_unmon_online = 0;
 	const char *id;
-	char idtext[256] = "";
-	int realtimepeers;
 	struct sip_peer **peerarray;
 	int k;
 
-	realtimepeers = ast_check_realtime("sippeers");
+	cont.realtimepeers = ast_check_realtime("sippeers");
 
 	if (s) {	/* Manager - get ActionID */
 		id = astman_get_header(m, "ActionID");
-		if (!ast_strlen_zero(id))
-			snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id);
+		if (!ast_strlen_zero(id)) {
+			snprintf(cont.idtext, sizeof(cont.idtext), "ActionID: %s\r\n", id);
+		}
 	}
 
 	switch (argc) {
 	case 5:
 		if (!strcasecmp(argv[3], "like")) {
-			if (regcomp(&regexbuf, argv[4], REG_EXTENDED | REG_NOSUB))
+			if (regcomp(&cont.regexbuf, argv[4], REG_EXTENDED | REG_NOSUB))
 				return CLI_SHOWUSAGE;
-			havepattern = TRUE;
+			cont.havepattern = TRUE;
 		} else
 			return CLI_SHOWUSAGE;
 	case 3:
@@ -17365,7 +17393,7 @@
 
 	if (!s) {
 		/* Normal list */
-		ast_cli(fd, FORMAT2, "Name/username", "Host", "Dyn", "Forcerport", "ACL", "Port", "Status", (realtimepeers ? "Realtime" : ""));
+		ast_cli(fd, PEERS_FORMAT2, "Name/username", "Host", "Dyn", "Forcerport", "ACL", "Port", "Status", (cont.realtimepeers ? "Realtime" : ""));
 	}
 
 	ao2_lock(peers);
@@ -17391,7 +17419,7 @@
 			continue;
 		}
 
-		if (havepattern && regexec(&regexbuf, peer->name, 0, NULL, 0)) {
+		if (cont.havepattern && regexec(&cont.regexbuf, peer->name, 0, NULL, 0)) {
 			ao2_unlock(peer);
 			unref_peer(peer, "toss iterator peer ptr before continue");
 			continue;
@@ -17404,116 +17432,120 @@
 
 	qsort(peerarray, total_peers, sizeof(struct sip_peer *), peercomparefunc);
 
-	for(k=0; k < total_peers; k++) {
-		char status[20] = "";
-		char srch[2000];
-		char pstatus;
-
-		/*
-		 * tmp_port and tmp_host store copies of ast_sockaddr_stringify strings since the
-		 * string pointers for that function aren't valid between subsequent calls to
-		 * ast_sockaddr_stringify functions
-		 */
-		char *tmp_port;
-		char *tmp_host;
-
-		peer = peerarray[k];
-
-		tmp_port = ast_sockaddr_isnull(&peer->addr) ?
-			"0" : ast_strdupa(ast_sockaddr_stringify_port(&peer->addr));
-
-		tmp_host = ast_sockaddr_isnull(&peer->addr) ?
-			"(Unspecified)" : ast_strdupa(ast_sockaddr_stringify_addr(&peer->addr));
-
-		ao2_lock(peer);
-		if (havepattern && regexec(&regexbuf, peer->name, 0, NULL, 0)) {
-			ao2_unlock(peer);
-			peer = peerarray[k] = unref_peer(peer, "toss iterator peer ptr before continue");
-			continue;
-		}
-
-		if (!ast_strlen_zero(peer->username) && !s)
-			snprintf(name, sizeof(name), "%s/%s", peer->name, peer->username);
-		else
-			ast_copy_string(name, peer->name, sizeof(name));
-
-		pstatus = peer_status(peer, status, sizeof(status));
-		if (pstatus == 1)
-			peers_mon_online++;
-		else if (pstatus == 0)
-			peers_mon_offline++;
-		else {
-			if (ast_sockaddr_isnull(&peer->addr) ||
-			    !ast_sockaddr_port(&peer->addr)) {
-				peers_unmon_offline++;
-			} else {
-				peers_unmon_online++;
-			}
-		}
-
-		snprintf(srch, sizeof(srch), FORMAT2, name,
-			tmp_host,
-			peer->host_dynamic ? " D " : "   ",	/* Dynamic or not? */
-			ast_test_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT) ? " N " : "   ",	/* NAT=yes? */
-			peer->ha ? " A " : "   ",	/* permit/deny */
-			tmp_port, status,
-			realtimepeers ? (peer->is_realtime ? "Cached RT":"") : "");
-
-		if (!s)  {/* Normal CLI list */
-			ast_cli(fd, FORMAT2, name,
-			tmp_host,
-			peer->host_dynamic ? " D " : "   ",	/* Dynamic or not? */
-			ast_test_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT) ? " N " : "   ",	/* NAT=yes? */
-			peer->ha ? " A " : "   ",       /* permit/deny */
-			tmp_port, status,
-			realtimepeers ? (peer->is_realtime ? "Cached RT":"") : "");
-		} else {	/* Manager format */
-			/* The names here need to be the same as other channels */
-			astman_append(s,
-			"Event: PeerEntry\r\n%s"
-			"Channeltype: SIP\r\n"
-			"ObjectName: %s\r\n"
-			"ChanObjectType: peer\r\n"	/* "peer" or "user" */
-			"IPaddress: %s\r\n"
-			"IPport: %s\r\n"
-			"Dynamic: %s\r\n"
-			"Forcerport: %s\r\n"
-			"VideoSupport: %s\r\n"
-			"TextSupport: %s\r\n"
-			"ACL: %s\r\n"
-			"Status: %s\r\n"
-			"RealtimeDevice: %s\r\n\r\n",
-			idtext,
-			peer->name,
-			ast_sockaddr_isnull(&peer->addr) ? "-none-" : tmp_host,
-			ast_sockaddr_isnull(&peer->addr) ? "0" : tmp_port,
-			peer->host_dynamic ? "yes" : "no",	/* Dynamic or not? */
-			ast_test_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT) ? "yes" : "no",	/* NAT=yes? */
-			ast_test_flag(&peer->flags[1], SIP_PAGE2_VIDEOSUPPORT) ? "yes" : "no",	/* VIDEOSUPPORT=yes? */
-			ast_test_flag(&peer->flags[1], SIP_PAGE2_TEXTSUPPORT) ? "yes" : "no",	/* TEXTSUPPORT=yes? */
-			peer->ha ? "yes" : "no",       /* permit/deny */
-			status,
-			realtimepeers ? (peer->is_realtime ? "yes":"no") : "no");
-		}
+	for(k = 0; k < total_peers; k++) {
+		peerarray[k] = _sip_show_peers_one(fd, s, &cont, peerarray[k]);
+	}
+
+	if (!s) {
+		ast_cli(fd, "%d sip peers [Monitored: %d online, %d offline Unmonitored: %d online, %d offline]\n",
+		        total_peers, cont.peers_mon_online, cont.peers_mon_offline, cont.peers_unmon_online, cont.peers_unmon_offline);
+	}
+
+	if (cont.havepattern) {
+		regfree(&cont.regexbuf);
+	}
+
+	if (total) {
+		*total = total_peers;
+	}
+
+	ast_free(peerarray);
+
+	return CLI_SUCCESS;
+}
+
+/*! \brief Emit informations for one peer during sip show peers command */
+static struct sip_peer *_sip_show_peers_one(int fd, struct mansession *s, struct show_peers_context *cont, struct sip_peer *peer)
+{
+	/* _sip_show_peers_one() is separated from _sip_show_peers() to properly free the ast_strdupa
+	 * (this is executed in a loop in _sip_show_peers() )
+	 */
+
+	char name[256];
+	char status[20] = "";
+	char pstatus;
+
+	/*
+	 * tmp_port and tmp_host store copies of ast_sockaddr_stringify strings since the
+	 * string pointers for that function aren't valid between subsequent calls to
+	 * ast_sockaddr_stringify functions
+	 */
+	char *tmp_port;
+	char *tmp_host;
+
+	tmp_port = ast_sockaddr_isnull(&peer->addr) ?
+		"0" : ast_strdupa(ast_sockaddr_stringify_port(&peer->addr));
+
+	tmp_host = ast_sockaddr_isnull(&peer->addr) ?
+		"(Unspecified)" : ast_strdupa(ast_sockaddr_stringify_addr(&peer->addr));
+
+	ao2_lock(peer);
+	if (cont->havepattern && regexec(&cont->regexbuf, peer->name, 0, NULL, 0)) {
 		ao2_unlock(peer);
-		peer = peerarray[k] = unref_peer(peer, "toss iterator peer ptr");
-	}
-
-	if (!s)
-		ast_cli(fd, "%d sip peers [Monitored: %d online, %d offline Unmonitored: %d online, %d offline]\n",
-		        total_peers, peers_mon_online, peers_mon_offline, peers_unmon_online, peers_unmon_offline);
-
-	if (havepattern)
-		regfree(&regexbuf);
-
-	if (total)
-		*total = total_peers;
-
-	ast_free(peerarray);
-
-	return CLI_SUCCESS;
-#undef FORMAT2
-}
+		return unref_peer(peer, "toss iterator peer ptr no match");
+	}
+
+	if (!ast_strlen_zero(peer->username) && !s) {
+		snprintf(name, sizeof(name), "%s/%s", peer->name, peer->username);
+	} else {
+		ast_copy_string(name, peer->name, sizeof(name));
+	}
+
+	pstatus = peer_status(peer, status, sizeof(status));
+	if (pstatus == 1) {
+		cont->peers_mon_online++;
+	} else if (pstatus == 0) {
+		cont->peers_mon_offline++;
+	} else {
+		if (ast_sockaddr_isnull(&peer->addr) ||
+		    !ast_sockaddr_port(&peer->addr)) {
+			cont->peers_unmon_offline++;
+		} else {
+			cont->peers_unmon_online++;
+		}
+	}
+
+	if (!s) { /* Normal CLI list */
+		ast_cli(fd, PEERS_FORMAT2, name,
+		tmp_host,
+		peer->host_dynamic ? " D " : "   ",	/* Dynamic or not? */
+		ast_test_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT) ? " N " : "   ",	/* NAT=yes? */
+		peer->ha ? " A " : "   ",       /* permit/deny */
+		tmp_port, status,
+		cont->realtimepeers ? (peer->is_realtime ? "Cached RT":"") : "");
+	} else {	/* Manager format */
+		/* The names here need to be the same as other channels */
+		astman_append(s,
+		"Event: PeerEntry\r\n%s"
+		"Channeltype: SIP\r\n"
+		"ObjectName: %s\r\n"
+		"ChanObjectType: peer\r\n"	/* "peer" or "user" */
+		"IPaddress: %s\r\n"
+		"IPport: %s\r\n"
+		"Dynamic: %s\r\n"
+		"Forcerport: %s\r\n"
+		"VideoSupport: %s\r\n"
+		"TextSupport: %s\r\n"
+		"ACL: %s\r\n"
+		"Status: %s\r\n"
+		"RealtimeDevice: %s\r\n",
+		cont->idtext,
+		peer->name,
+		ast_sockaddr_isnull(&peer->addr) ? "-none-" : tmp_host,
+		ast_sockaddr_isnull(&peer->addr) ? "0" : tmp_port,
+		peer->host_dynamic ? "yes" : "no",	/* Dynamic or not? */
+		ast_test_flag(&peer->flags[0], SIP_NAT_FORCE_RPORT) ? "yes" : "no",	/* NAT=yes? */
+		ast_test_flag(&peer->flags[1], SIP_PAGE2_VIDEOSUPPORT) ? "yes" : "no",	/* VIDEOSUPPORT=yes? */
+		ast_test_flag(&peer->flags[1], SIP_PAGE2_TEXTSUPPORT) ? "yes" : "no",	/* TEXTSUPPORT=yes? */
+		peer->ha ? "yes" : "no",       /* permit/deny */
+		status,
+		cont->realtimepeers ? (peer->is_realtime ? "yes":"no") : "no");
+	}
+	ao2_unlock(peer);
+
+	return unref_peer(peer, "toss iterator peer ptr");
+}
+#undef PEERS_FORMAT2
 
 static int peer_dump_func(void *userobj, void *arg, int flags)
 {
@@ -19305,7 +19337,6 @@
  				if (cur->stimer->st_active == TRUE) {
  					ast_cli(a->fd, "  S-Timer Interval:       %d\n", cur->stimer->st_interval);
  					ast_cli(a->fd, "  S-Timer Refresher:      %s\n", strefresher2str(cur->stimer->st_ref));
- 					ast_cli(a->fd, "  S-Timer Expirys:        %d\n", cur->stimer->st_expirys);
  					ast_cli(a->fd, "  S-Timer Sched Id:       %d\n", cur->stimer->st_schedid);
  					ast_cli(a->fd, "  S-Timer Peer Sts:       %s\n", cur->stimer->st_active_peer_ua ? "Active" : "Inactive");
  					ast_cli(a->fd, "  S-Timer Cached Min-SE:  %d\n", cur->stimer->st_cached_min_se);
@@ -20951,7 +20982,7 @@
 		}
 
 		/* Check for Session-Timers related headers */
-		if (st_get_mode(p, 0) != SESSION_TIMER_MODE_REFUSE && p->outgoing_call == TRUE && !reinvite) {
+		if (st_get_mode(p, 0) != SESSION_TIMER_MODE_REFUSE) {
 			p_hdrval = (char*)get_header(req, "Session-Expires");
 			if (!ast_strlen_zero(p_hdrval)) {
 				/* UAS supports Session-Timers */
@@ -23600,9 +23631,6 @@
 			}
 
 			restart_session_timer(p);
-			if (p->stimer->st_expirys > 0) {
-				p->stimer->st_expirys--;
-			}
 		}
 	}
 
@@ -26686,6 +26714,8 @@
 /*! \brief Session-Timers: Start session timer */
 static void start_session_timer(struct sip_pvt *p)
 {
+	unsigned int timeout_ms;
+
 	if (!p->stimer) {
 		ast_log(LOG_WARNING, "Null stimer in start_session_timer - %s\n", p->callid);
 		return;
@@ -26698,14 +26728,31 @@
 			dialog_unref(p, "unref stimer->st_schedid from dialog"));
 	}
 
-	p->stimer->st_schedid  = ast_sched_add(sched, p->stimer->st_interval * 1000 / 2, proc_session_timer, 
+	/*
+	 * RFC 4028 Section 10
+	 * If the side not performing refreshes does not receive a
+	 * session refresh request before the session expiration, it SHOULD send
+	 * a BYE to terminate the session, slightly before the session
+	 * expiration.  The minimum of 32 seconds and one third of the session
+	 * interval is RECOMMENDED.
+	 */
+
+	timeout_ms = (1000 * p->stimer->st_interval);
+	if (p->stimer->st_ref == SESSION_TIMER_REFRESHER_US) {
+		timeout_ms /= 2;
+	} else {
+		timeout_ms -= MIN(timeout_ms / 3, 32000);
+	}
+
+	p->stimer->st_schedid = ast_sched_add(sched, timeout_ms, proc_session_timer,
 			dialog_ref(p, "adding session timer ref"));
+
 	if (p->stimer->st_schedid < 0) {
 		dialog_unref(p, "removing session timer ref");
 		ast_log(LOG_ERROR, "ast_sched_add failed - %s\n", p->callid);
 	} else {
 		p->stimer->st_active = TRUE;
-		ast_debug(2, "Session timer started: %d - %s\n", p->stimer->st_schedid, p->callid);
+		ast_debug(2, "Session timer started: %d - %s %ums\n", p->stimer->st_schedid, p->callid, timeout_ms);
 	}
 }
 
@@ -26739,28 +26786,23 @@
 			transmit_reinvite_with_sdp(p, FALSE, TRUE);
 		}
 	} else {
-		p->stimer->st_expirys++;
-		if (p->stimer->st_expirys >= 2) {
-			if (p->stimer->quit_flag) {
+		if (p->stimer->quit_flag) {
+			goto return_unref;
+		}
+		ast_log(LOG_WARNING, "Session-Timer expired - %s\n", p->callid);
+		sip_pvt_lock(p);
+		while (p->owner && ast_channel_trylock(p->owner)) {
+			sip_pvt_unlock(p);
+			usleep(1);
+			if (p->stimer && p->stimer->quit_flag) {
 				goto return_unref;
 			}
-			ast_log(LOG_WARNING, "Session-Timer expired - %s\n", p->callid);
 			sip_pvt_lock(p);
-			while (p->owner && ast_channel_trylock(p->owner)) {
-				sip_pvt_unlock(p);
-				usleep(1);
-				if (p->stimer && p->stimer->quit_flag) {
-					goto return_unref;
-				}
-				sip_pvt_lock(p);
-			}
-
-			ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_DEV);

[... 618 lines stripped ...]



More information about the svn-commits mailing list