[asterisk-commits] dvossel: branch 1.4 r173248 - /branches/1.4/channels/chan_iax2.c
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Tue Feb 3 17:35:55 CST 2009
Author: dvossel
Date: Tue Feb 3 17:35:55 2009
New Revision: 173248
URL: http://svn.digium.com/svn-view/asterisk?view=rev&rev=173248
Log:
Fixes issue with IAX2 transfer not handing off calls.
Fixes issue with IAX2 transfers not taking place. As it was, a call that was being transfered would never be handed off correctly to the call ends because of how call numbers were stored in a hash table. The hash table, "iax_peercallno_pvt", storing all the current call numbers did not take into account the complications associated with transferring a call, so a separate hash table was required. This second hash table "iax_transfercallno_pvt" handles calls being transfered, once the call transfer is complete the call is removed from the transfer hash table and added to the peer hash table resuming normal operations. Addition functions were created to handle storing, removing, and comparing items in the iax_transfercallno_pvt table.
(issue #13468)
Modified:
branches/1.4/channels/chan_iax2.c
Modified: branches/1.4/channels/chan_iax2.c
URL: http://svn.digium.com/svn-view/asterisk/branches/1.4/channels/chan_iax2.c?view=diff&rev=173248&r1=173247&r2=173248
==============================================================================
--- branches/1.4/channels/chan_iax2.c (original)
+++ branches/1.4/channels/chan_iax2.c Tue Feb 3 17:35:55 2009
@@ -823,6 +823,13 @@
*/
static struct ao2_container *iax_peercallno_pvts;
+/*!
+ * * \brief Another container of iax2_pvt structures
+ *
+ * Active IAX2 pvt stucts used during transfering a call are stored here.
+ */
+static struct ao2_container *iax_transfercallno_pvts;
+
/* Flag to use with trunk calls, keeping these calls high up. It halves our effective use
but keeps the division between trunked and non-trunked better. */
#define TRUNK_CALL_START ARRAY_LEN(iaxs) / 2
@@ -1247,6 +1254,25 @@
AST_SCHED_DEL(sched, pvt->jbid);
}
+static void store_by_transfercallno(struct chan_iax2_pvt *pvt)
+{
+ if (!pvt->transfercallno) {
+ ast_log(LOG_ERROR, "This should not be called without a transfer call number.\n");
+ return;
+ }
+
+ ao2_link(iax_transfercallno_pvts, pvt);
+}
+
+static void remove_by_transfercallno(struct chan_iax2_pvt *pvt)
+{
+ if (!pvt->transfercallno) {
+ ast_log(LOG_ERROR, "This should not be called without a transfer call number.\n");
+ return;
+ }
+
+ ao2_unlink(iax_transfercallno_pvts, pvt);
+}
static void store_by_peercallno(struct chan_iax2_pvt *pvt)
{
if (!pvt->peercallno) {
@@ -1327,6 +1353,10 @@
if (pvt->peercallno) {
remove_by_peercallno(pvt);
+ }
+
+ if (pvt->transfercallno) {
+ remove_by_transfercallno(pvt);
}
if (!owner) {
@@ -1551,28 +1581,40 @@
char host[80];
if (new <= NEW_ALLOW) {
- if (callno) {
- struct chan_iax2_pvt *pvt;
- struct chan_iax2_pvt tmp_pvt = {
- .callno = dcallno,
- .peercallno = callno,
- /* hack!! */
- .frames_received = check_dcallno,
- };
-
- memcpy(&tmp_pvt.addr, sin, sizeof(tmp_pvt.addr));
-
- if ((pvt = ao2_find(iax_peercallno_pvts, &tmp_pvt, OBJ_POINTER))) {
- if (return_locked) {
- ast_mutex_lock(&iaxsl[pvt->callno]);
- }
- res = pvt->callno;
- ao2_ref(pvt, -1);
- pvt = NULL;
- return res;
- }
- }
-
+ if (callno) {
+ struct chan_iax2_pvt *pvt;
+ struct chan_iax2_pvt tmp_pvt = {
+ .callno = dcallno,
+ .peercallno = callno,
+ .transfercallno = callno,
+ /* hack!! */
+ .frames_received = check_dcallno,
+ };
+
+ memcpy(&tmp_pvt.addr, sin, sizeof(tmp_pvt.addr));
+ /* this works for finding normal call numbers not involving transfering */
+ if ((pvt = ao2_find(iax_peercallno_pvts, &tmp_pvt, OBJ_POINTER))) {
+ if (return_locked) {
+ ast_mutex_lock(&iaxsl[pvt->callno]);
+ }
+ res = pvt->callno;
+ ao2_ref(pvt, -1);
+ pvt = NULL;
+ return res;
+ }
+ /* this searches for transfer call numbers that might not get caught otherwise */
+ memset(&tmp_pvt.addr, 0, sizeof(tmp_pvt.addr));
+ memcpy(&tmp_pvt.transfer, sin, sizeof(tmp_pvt.addr));
+ if ((pvt = ao2_find(iax_transfercallno_pvts, &tmp_pvt, OBJ_POINTER))) {
+ if (return_locked) {
+ ast_mutex_lock(&iaxsl[pvt->callno]);
+ }
+ res = pvt->callno;
+ ao2_ref(pvt, -1);
+ pvt = NULL;
+ return res;
+ }
+ }
/* This will occur on the first response to a message that we initiated,
* such as a PING. */
if (dcallno) {
@@ -1590,7 +1632,6 @@
if (dcallno) {
ast_mutex_unlock(&iaxsl[dcallno]);
}
-
#ifdef IAX_OLD_FIND
/* If we get here, we SHOULD NOT find a call structure for this
callno; if we do, it means that there is a call structure that
@@ -5885,10 +5926,11 @@
pvt->transfer.sin_family = AF_INET;
pvt->transferring = TRANSFER_BEGIN;
pvt->transferid = ies->transferid;
+ store_by_transfercallno(pvt);
if (ies->transferid)
iax_ie_append_int(&ied, IAX_IE_TRANSFERID, ies->transferid);
send_command_transfer(pvt, AST_FRAME_IAX, IAX_COMMAND_TXCNT, 0, ied.buf, ied.pos);
- return 0;
+ return 0;
}
static int complete_dpreply(struct chan_iax2_pvt *pvt, struct iax_ies *ies)
@@ -5965,6 +6007,7 @@
ast_log(LOG_WARNING, "Invalid transfer request\n");
return -1;
}
+ remove_by_transfercallno(pvt);
memcpy(&pvt->addr, &pvt->transfer, sizeof(pvt->addr));
memset(&pvt->transfer, 0, sizeof(pvt->transfer));
/* Reset sequence numbers */
@@ -5977,8 +6020,8 @@
remove_by_peercallno(pvt);
}
pvt->peercallno = peercallno;
+ /*this is where the transfering call swiches hash tables */
store_by_peercallno(pvt);
-
pvt->transferring = TRANSFER_NONE;
pvt->svoiceformat = -1;
pvt->voiceformat = 0;
@@ -11187,6 +11230,7 @@
ao2_ref(peers, -1);
ao2_ref(users, -1);
ao2_ref(iax_peercallno_pvts, -1);
+ ao2_ref(iax_transfercallno_pvts, -1);
return 0;
}
@@ -11225,6 +11269,23 @@
pvt2->frames_received) ? CMP_MATCH | CMP_STOP : 0;
}
+static int transfercallno_pvt_hash_cb(const void *obj, const int flags)
+{
+ const struct chan_iax2_pvt *pvt = obj;
+
+ return pvt->transfercallno;
+}
+
+static int transfercallno_pvt_cmp_cb(void *obj, void *arg, int flags)
+{
+ struct chan_iax2_pvt *pvt = obj, *pvt2 = arg;
+
+ /* The frames_received field is used to hold whether we're matching
+ * against a full frame or not ... */
+
+ return match(&pvt2->transfer, pvt2->transfercallno, pvt2->callno, pvt,
+ pvt2->frames_received) ? CMP_MATCH | CMP_STOP : 0;
+}
/*! \brief Load IAX2 module, load configuraiton ---*/
static int load_module(void)
{
@@ -11247,7 +11308,13 @@
ao2_ref(users, -1);
return AST_MODULE_LOAD_FAILURE;
}
-
+ iax_transfercallno_pvts = ao2_container_alloc(IAX_MAX_CALLS, transfercallno_pvt_hash_cb, transfercallno_pvt_cmp_cb);
+ if (!iax_transfercallno_pvts) {
+ ao2_ref(peers, -1);
+ ao2_ref(users, -1);
+ ao2_ref(iax_peercallno_pvts, -1);
+ return AST_MODULE_LOAD_FAILURE;
+ }
ast_custom_function_register(&iaxpeer_function);
iax_set_output(iax_debug_output);
More information about the asterisk-commits
mailing list