[asterisk-commits] oej: branch oej/bufo-manager-contexts-1.8 r392697 - in /team/oej/bufo-manager...
SVN commits to the Asterisk project
asterisk-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(®exbuf, 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(®exbuf, 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(®exbuf, 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(®exbuf);
-
- 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 asterisk-commits
mailing list