[asterisk-commits] murf: branch murf/bug11210 r99023 - /team/murf/bug11210/channels/chan_iax2.c

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Fri Jan 18 10:09:43 CST 2008


Author: murf
Date: Fri Jan 18 10:09:43 2008
New Revision: 99023

URL: http://svn.digium.com/view/asterisk?view=rev&rev=99023
Log:
A checkpoint in keeping the findcall hash tables up to date

Modified:
    team/murf/bug11210/channels/chan_iax2.c

Modified: team/murf/bug11210/channels/chan_iax2.c
URL: http://svn.digium.com/view/asterisk/team/murf/bug11210/channels/chan_iax2.c?view=diff&rev=99023&r1=99022&r2=99023
==============================================================================
--- team/murf/bug11210/channels/chan_iax2.c (original)
+++ team/murf/bug11210/channels/chan_iax2.c Fri Jan 18 10:09:43 2008
@@ -674,6 +674,48 @@
    find_callno routine -- Any time one of the keys is modified, the pvt must
    be removed from the table, updated, and relinked into the table. */
 
+/* Design:
+   At the time I implemented this, the match() routine (If you explode the
+   conditionals, did these 4 tests, and in this order:
+
+   1. same(sin,cur->addr) && callno == cur->peercallno
+   2. same(sin,cur->addr) && callno == 0 && dcallno == cur->callno
+   3. same(sin,cur->transfer) && cur->transferring != 0 && dcallno == cur->callno
+   4. same(sin,cur->transfer) && cur->transferring == TRANSFER_MEDIAPASS && callno == cur->transfercallno
+
+Any of the terms above that involve callno, dcallno, or sin, can be determined at run time,
+and are not involved in the hash tables themselves, so you can ignore them, sort of, when you
+try to figure out what the hash mech should track. the fields in cur that we will end up using
+as keys are:
+    addr, transfer,  callno,  transfercallno, peercallno, transferring.
+
+The 4 tables follow the above 4 conditionals, and serve as the lookup mechanism, for each
+corresponding conditional.
+
+In the find_callno routine, the idea will be to consult the 4 tables in sequence, 
+with the appropriate data set up for the comparison, and to end the search with the
+first success.
+
+The trickiest/messiest part of this, will be to keep the hash tables in sync with the current
+state of the channel driver. Important to note, is that many of the key fields can change.
+Thus we need to unlink, update, and relink each entry in each table as appropriate, whenever
+it's key field is modified.
+
+Special conditions for findcall3: only those callno's are entered, that have cur->transferring set to non-zero.
+                       findcall4: only those callno's are entered, that have cur->transferring set to MEDIAPASS
+
+Work scope: Probable number of places to make changes:
+
+->peercallno set in ~5 places
+->callno set in ~20 places
+->transfercallno set in ~2 places
+->addr ~3 places; address passed to functions ~8 times
+->transfer ~7 places, addr passed to functions ~3 times.
+->transferring  ~14 places
+
+
+*/
+
 static struct ao2_container *findcall1; /* keys: pvt->addr & pvt->peercallno */
 static struct ao2_container *findcall2; /* keys: pvt->addr & pvt->callno */
 static struct ao2_container *findcall3; /* keys: pvt->transfer & pvt->callno */
@@ -1268,10 +1310,10 @@
 	return !strcasecmp(user->name, user2->name) ? CMP_MATCH : 0;
 }
 
-/*!
- * \note The only members of the pvt passed here guaranteed to be set are the addr and peercallno fields
- */
-static int findcall1_hash_cb(const void *obj, const int flags)
+ /*!
+  * \note The keys are the addr and peercallno fields
+  */
+ static int findcall1_hash_cb(const void *obj, const int flags)
 {
 	const struct chan_iax2_pvt *pvt = obj;
 	int x = pvt->addr.sin_addr.s_addr + pvt->addr.sin_port + pvt->peercallno;
@@ -1282,7 +1324,7 @@
 }
 
 /*!
- * \note The only members of the pvt passed here guaranteed to be set are the addr and peercallno fields
+ * \note The keys are the addr and peercallno fields
  */
 static int findcall1_cmp_cb(void *obj, void *arg, int flags)
 {
@@ -1298,7 +1340,7 @@
 }
 
 /*!
- * \note The only members of the pvt passed here guaranteed to be set are the addr and callno fields
+ * \note The keys are the addr and callno fields
  */
 static int findcall2_hash_cb(const void *obj, const int flags)
 {
@@ -1311,7 +1353,7 @@
 }
 
 /*!
- * \note The only members of the pvt passed here guaranteed to be set are the addr and callno fields
+ * \note The keys are the addr and callno fields
  */
 static int findcall2_cmp_cb(void *obj, void *arg, int flags)
 {
@@ -1327,7 +1369,7 @@
 }
 
 /*!
- * \note The only members of the pvt passed here guaranteed to be set are the transfer and callno fields
+ * \note The keys are the transfer and transfercallno fields
  */
 static int findcall3_hash_cb(const void *obj, const int flags)
 {
@@ -1340,7 +1382,7 @@
 }
 
 /*!
- * \note The only members of the pvt passed here guaranteed to be set are the transfer and transfercallno fields
+ * \note The keys are the transfer and transfercallno fields
  */
 static int findcall3_cmp_cb(void *obj, void *arg, int flags)
 {
@@ -1356,7 +1398,7 @@
 }
 
 /*!
- * \note The only members of the pvt passed here guaranteed to be set are the addr and peercallno fields
+ * \note The keys are the addr and peercallno fields
  */
 static int findcall4_hash_cb(const void *obj, const int flags)
 {
@@ -1369,7 +1411,7 @@
 }
 
 /*!
- * \note The only members of the pvt passed here guaranteed to be set are the addr and peercallno fields
+ * \note The keys are the addr and peercallno fields
  */
 static int findcall4_cmp_cb(void *obj, void *arg, int flags)
 {
@@ -1694,11 +1736,15 @@
 			ast_string_field_set(iaxs[x], accountcode, accountcode);
 			ast_string_field_set(iaxs[x], mohinterpret, mohinterpret);
 			ast_string_field_set(iaxs[x], mohsuggest, mohsuggest);
+			ao2_t_link(findcall1, iaxs[x], "a new pvt is borne!");
+			ao2_t_link(findcall2, iaxs[x], "a new pvt is borne!");
+			/* it appears that findcall3 and findcall4 will not be linked, as the transferring field is 0 */
 		} else {
 			ast_log(LOG_WARNING, "Out of resources\n");
 			ast_mutex_unlock(&iaxsl[x]);
 			return 0;
 		}
+		
 		ast_mutex_unlock(&iaxsl[x]);
 		res = x;
 	}
@@ -3737,6 +3783,9 @@
 	struct iax_ie_data ied0;
 	struct iax_ie_data ied1;
 	unsigned int transferid = (unsigned int)ast_random();
+	int old0 = iaxs[callno0]->transferring;
+	int old1 = iaxs[callno1]->transferring;
+	
 	memset(&ied0, 0, sizeof(ied0));
 	iax_ie_append_addr(&ied0, IAX_IE_APPARENT_ADDR, &iaxs[callno1]->addr);
 	iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[callno1]->peercallno);
@@ -3755,6 +3804,14 @@
 		return -1;
 	iaxs[callno0]->transferring = mediaonly ? TRANSFER_MBEGIN : TRANSFER_BEGIN;
 	iaxs[callno1]->transferring = mediaonly ? TRANSFER_MBEGIN : TRANSFER_BEGIN;
+	if (!old0)
+		ao2_t_link(findcall3,iaxs[callno0],"adding to findcall3 (callno0) because transfer is beginning");
+	if (!old1)
+		ao2_t_link(findcall3,iaxs[callno1],"adding to findcall3 (callno1) because transfer is beginning");
+	if (old0 == TRANSFER_MEDIAPASS) /* seems improbable, but I'd better be complete for the moment... */
+		ao2_t_unlink(findcall4,iaxs[callno0],"removing from findcall4 (callno0) because transfer is beginning, but was in MEDIAPASS");
+	if (old1 == TRANSFER_MEDIAPASS)
+		ao2_t_unlink(findcall4,iaxs[callno1],"removing from findcall4 (callno1) because transfer is beginning, but was in MEDIAPASS");
 	return 0;
 }
 
@@ -6313,7 +6370,7 @@
 	char newip[256];
 	struct iax_ie_data ied;
 	struct sockaddr_in new;
-	
+	int old1 = pvt->transferring;
 	
 	memset(&ied, 0, sizeof(ied));
 	if (ies->apparent_addr)
@@ -6329,6 +6386,9 @@
 	inet_aton(newip, &pvt->transfer.sin_addr);
 	pvt->transfer.sin_family = AF_INET;
 	pvt->transferring = TRANSFER_BEGIN;
+	if (!old1)
+		ao2_t_link(findcall3,pvt,"adding this entry to findcall3, because transferring was previously 0");
+	
 	pvt->transferid = ies->transferid;
 	if (ies->transferid)
 		iax_ie_append_int(&ied, IAX_IE_TRANSFERID, ies->transferid);
@@ -6394,6 +6454,12 @@
 		ast_log(LOG_WARNING, "Invalid transfer request\n");
 		return -1;
 	}
+	if (pvt->transferring == TRANSFER_MEDIAPASS)
+		ao2_t_unlink(findcall4, pvt, "Removing pvt from findcall4; was MEDIAPASS, now 0");
+	if (pvt->transferring)
+		ao2_t_unlink(findcall3, pvt, "Removing pvt from findcall3; was non-0, now 0");
+	ao2_t_unlink(findcall1, pvt, "Removing pvt from findcall1, we are going to change addr");
+	ao2_t_unlink(findcall2, pvt, "Removing pvt from findcall2, we are going to change addr");
 	memcpy(&pvt->addr, &pvt->transfer, sizeof(pvt->addr));
 	memset(&pvt->transfer, 0, sizeof(pvt->transfer));
 	/* Reset sequence numbers */
@@ -6401,6 +6467,7 @@
 	pvt->rseqno = 0;
 	pvt->iseqno = 0;
 	pvt->aseqno = 0;
+	ao2_t_unlink(findcall1, pvt, "remove pvt from findcall1 so we can set peercallno");
 	pvt->peercallno = peercallno;
 	pvt->transferring = TRANSFER_NONE;
 	pvt->svoiceformat = -1;
@@ -6419,6 +6486,9 @@
 	pvt->lastsent = 0;
 	pvt->nextpred = 0;
 	pvt->pingtime = DEFAULT_RETRY_TIME;
+	ao2_t_link(findcall1, pvt, "Adding pvt back to findcall1, we changed addr/peercallno");
+	ao2_t_link(findcall2, pvt, "Removing pvt from findcall2, we changed addr");
+	
 	AST_LIST_LOCK(&frame_queue);
 	AST_LIST_TRAVERSE(&frame_queue, cur, list) {
 		/* We must cancel any packets that would have been transmitted
@@ -7861,7 +7931,10 @@
 	if (!inaddrcmp(&sin, &iaxs[fr->callno]->addr) && !minivid &&
 		f.subclass != IAX_COMMAND_TXCNT &&		/* for attended transfer */
 		f.subclass != IAX_COMMAND_TXACC) {		/* for attended transfer */
+		if (iaxs[fr->callno]->peercallno)
+			ao2_t_unlink(findcall1,iaxs[fr->callno],"remove pvt from findcall1, we are changing the peercallno field");
 		iaxs[fr->callno]->peercallno = (unsigned short)(ntohs(mh->callno) & ~IAX_FLAG_FULL);
+		ao2_t_link(findcall1,iaxs[fr->callno],"replace pvt in findcall1, we are changing the peercallno field");
 	}
 	if (ntohs(mh->callno) & IAX_FLAG_FULL) {
 		if (iaxdebug)
@@ -9015,7 +9088,7 @@
 								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[iaxs[fr->callno]->bridgecallno]->transferring = TRANSFER_MEDIA; /* no action required in findcall3/4 */
 								iaxs[fr->callno]->transferring = TRANSFER_MEDIA;
 
 								memset(&ied0, 0, sizeof(ied0));
@@ -9025,13 +9098,24 @@
 								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 {
+								int oldbdg = iaxs[iaxs[fr->callno]->bridgecallno]->transferring;
+								int oldfr = iaxs[fr->callno]->transferring;
+								
 								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>");
-
+								if (oldbdg == TRANSFER_MEDIAPASS)
+									ao2_t_unlink(findcall4,iaxs[iaxs[fr->callno]->bridgecallno],"changing from transferring MEDIAPASS to TRANSFER_RELEASED");
+								if (oldfr == TRANSFER_MEDIAPASS)
+									ao2_t_unlink(findcall4,iaxs[fr->callno],"changing from transferring MEDIAPASS to TRANSFER_RELEASED");
+								
 								iaxs[iaxs[fr->callno]->bridgecallno]->transferring = TRANSFER_RELEASED;
 								iaxs[fr->callno]->transferring = TRANSFER_RELEASED;
 								ast_set_flag(iaxs[iaxs[fr->callno]->bridgecallno], IAX_ALREADYGONE);
 								ast_set_flag(iaxs[fr->callno], IAX_ALREADYGONE);
+								if (!oldbdg)
+									ao2_t_link(findcall3,iaxs[iaxs[fr->callno]->bridgecallno],"changing from !transferring TRANSFER_RELEASED");
+								if (!oldfr)
+									ao2_t_unlink(findcall3,iaxs[fr->callno],"changing from transferring MEDIAPASS to TRANSFER_RELEASED");
 
 								/* Stop doing lag & ping requests */
 								stop_stuff(fr->callno);
@@ -9073,6 +9157,7 @@
 					AST_LIST_UNLOCK(&frame_queue);
 					/* Start sending our media to the transfer address, but otherwise leave the call as-is */
 					iaxs[fr->callno]->transferring = TRANSFER_MEDIAPASS;
+					ao2_t_link(findcall4, iaxs[fr->callno], "This pvt is being set in MEDIAPASS state, adding to findcall4");
 				}
 				break;	
 			case IAX_COMMAND_DPREP:




More information about the asterisk-commits mailing list