[asterisk-commits] russell: trunk r48360 - /trunk/channels/chan_iax2.c

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Sat Dec 9 00:11:08 MST 2006


Author: russell
Date: Sat Dec  9 01:10:55 2006
New Revision: 48360

URL: http://svn.digium.com/view/asterisk?view=rev&rev=48360
Log:
chan_iax2 has an extremely large function, socket_process(), to handle incoming
frames.  The function, before this commit, was roughly 1400 lines long.  So, I
am working on breaking this up into functions so that the code is easier to
follow and debug.  Also, I will be committing these changes in chunks as I do
them to ease tracking down any potentially introduced problems.

Break out roughly 150 lines from socket_process() and introduce a new function, 
socket_process_meta() which handles the parsing of an incoming meta frame.
Also, restructure some of this code a bit to reduce the deep nesting that was
in this code.

Modified:
    trunk/channels/chan_iax2.c

Modified: trunk/channels/chan_iax2.c
URL: http://svn.digium.com/view/asterisk/trunk/channels/chan_iax2.c?view=diff&rev=48360&r1=48359&r2=48360
==============================================================================
--- trunk/channels/chan_iax2.c (original)
+++ trunk/channels/chan_iax2.c Sat Dec  9 01:10:55 2006
@@ -1087,10 +1087,6 @@
 	}
 		
 	tmp->prefs = prefs;
-	tmp->callno = 0;
-	tmp->peercallno = 0;
-	tmp->transfercallno = 0;
-	tmp->bridgecallno = 0;
 	tmp->pingid = -1;
 	tmp->lagid = -1;
 	tmp->autoid = -1;
@@ -6280,36 +6276,156 @@
 	return 1;
 }
 
+static int socket_process_meta(int packet_len, struct ast_iax2_meta_hdr *meta, struct sockaddr_in *sin, int sockfd,
+	struct iax_frame *fr)
+{
+	unsigned char metatype;
+	struct ast_iax2_meta_trunk_mini *mtm;
+	struct ast_iax2_meta_trunk_hdr *mth;
+	struct ast_iax2_meta_trunk_entry *mte;
+	struct iax2_trunk_peer *tpeer;
+	unsigned int ts;
+	void *ptr;
+	struct timeval rxtrunktime;
+	struct ast_frame f = { 0, };
+
+	if (packet_len < sizeof(*meta)) {
+		ast_log(LOG_WARNING, "Rejecting packet from '%s.%d' that is flagged as a meta frame but is too short\n", 
+			ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port));
+		return 1;
+	}
+
+	if (meta->metacmd != IAX_META_TRUNK)
+		return 1;
+
+	if (packet_len < (sizeof(*meta) + sizeof(*mth))) {
+		ast_log(LOG_WARNING, "midget meta trunk packet received (%d of %zd min)\n", packet_len,
+			sizeof(*meta) + sizeof(*mth));
+		return 1;
+	}
+	mth = (struct ast_iax2_meta_trunk_hdr *)(meta->data);
+	ts = ntohl(mth->ts);
+	metatype = meta->cmddata;
+	packet_len -= (sizeof(*meta) + sizeof(*mth));
+	ptr = mth->data;
+	tpeer = find_tpeer(sin, sockfd);
+	if (!tpeer) {
+		ast_log(LOG_WARNING, "Unable to accept trunked packet from '%s:%d': No matching peer\n", 
+			ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port));
+		return 1;
+	}
+	tpeer->trunkact = ast_tvnow();
+	if (!ts || ast_tvzero(tpeer->rxtrunktime))
+		tpeer->rxtrunktime = tpeer->trunkact;
+	rxtrunktime = tpeer->rxtrunktime;
+	ast_mutex_unlock(&tpeer->lock);
+	while (packet_len >= sizeof(*mte)) {
+		/* Process channels */
+		unsigned short callno, trunked_ts, len;
+
+		if (metatype == IAX_META_TRUNK_MINI) {
+			mtm = (struct ast_iax2_meta_trunk_mini *) ptr;
+			ptr += sizeof(*mtm);
+			packet_len -= sizeof(*mtm);
+			len = ntohs(mtm->len);
+			callno = ntohs(mtm->mini.callno);
+			trunked_ts = ntohs(mtm->mini.ts);
+		} else if (metatype == IAX_META_TRUNK_SUPERMINI) {
+			mte = (struct ast_iax2_meta_trunk_entry *)ptr;
+			ptr += sizeof(*mte);
+			packet_len -= sizeof(*mte);
+			len = ntohs(mte->len);
+			callno = ntohs(mte->callno);
+			trunked_ts = 0;
+		} else {
+			ast_log(LOG_WARNING, "Unknown meta trunk cmd from '%s:%d': dropping\n", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port));
+			break;
+		}
+		/* Stop if we don't have enough data */
+		if (len > packet_len)
+			break;
+		fr->callno = find_callno(callno & ~IAX_FLAG_FULL, 0, sin, NEW_PREVENT, 1, sockfd);
+		if (!fr->callno)
+			continue;
+
+		ast_mutex_lock(&iaxsl[fr->callno]);
+
+		/* If it's a valid call, deliver the contents.  If not, we
+		   drop it, since we don't have a scallno to use for an INVAL */
+		/* Process as a mini frame */
+		f.frametype = AST_FRAME_VOICE;
+		if (!iaxs[fr->callno]) {
+			/* drop it */
+		} else if (iaxs[fr->callno]->voiceformat == 0) {
+			ast_log(LOG_WARNING, "Received trunked frame before first full voice frame\n ");
+			iax2_vnak(fr->callno);
+		} else {
+			f.subclass = iaxs[fr->callno]->voiceformat;
+			f.datalen = len;
+			if (f.datalen >= 0) {
+				if (f.datalen)
+					f.data = ptr;
+				else
+					f.data = NULL;
+				if (trunked_ts)
+					fr->ts = (iaxs[fr->callno]->last & 0xFFFF0000L) | (trunked_ts & 0xffff);
+				else
+					fr->ts = fix_peerts(&rxtrunktime, fr->callno, ts);
+				/* Don't pass any packets until we're started */
+				if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED)) {
+					struct iax_frame *duped_fr;
+
+					/* Common things */
+					f.src = "IAX2";
+					f.mallocd = 0;
+					f.offset = 0;
+					if (f.datalen && (f.frametype == AST_FRAME_VOICE)) 
+						f.samples = ast_codec_get_samples(&f);
+					else
+						f.samples = 0;
+					fr->outoforder = 0;
+					iax_frame_wrap(fr, &f);
+					duped_fr = iaxfrdup2(fr);
+					if (duped_fr)
+						schedule_delivery(duped_fr, 1, 1, &fr->ts);
+					if (iaxs[fr->callno]->last < fr->ts)
+						iaxs[fr->callno]->last = fr->ts;
+				}
+			} else {
+				ast_log(LOG_WARNING, "Datalen < 0?\n");
+			}
+		}
+		ast_mutex_unlock(&iaxsl[fr->callno]);
+		ptr += len;
+		packet_len -= len;
+	}
+
+	return 1;
+}
+
 static int socket_process(struct iax2_thread *thread)
 {
 	struct sockaddr_in sin;
 	int res;
 	int updatehistory=1;
 	int new = NEW_PREVENT;
-	void *ptr;
 	int dcallno = 0;
 	struct ast_iax2_full_hdr *fh = (struct ast_iax2_full_hdr *)thread->buf;
 	struct ast_iax2_mini_hdr *mh = (struct ast_iax2_mini_hdr *)thread->buf;
 	struct ast_iax2_meta_hdr *meta = (struct ast_iax2_meta_hdr *)thread->buf;
 	struct ast_iax2_video_hdr *vh = (struct ast_iax2_video_hdr *)thread->buf;
-	struct ast_iax2_meta_trunk_hdr *mth;
-	struct ast_iax2_meta_trunk_entry *mte;
-	struct ast_iax2_meta_trunk_mini *mtm;
 	struct iax_frame *fr;
 	struct iax_frame *cur;
 	struct ast_frame f;
 	struct ast_channel *c;
 	struct iax2_dpcache *dp;
 	struct iax2_peer *peer;
-	struct iax2_trunk_peer *tpeer;
-	struct timeval rxtrunktime;
 	struct iax_ies ies;
 	struct iax_ie_data ied0, ied1;
 	int format;
 	int fd;
 	int exists;
 	int minivid = 0;
-	unsigned int ts;
 	char empty[32]="";		/* Safety measure */
 	struct iax_frame *duped_fr;
 	char host_pref_buf[128];
@@ -6339,123 +6455,8 @@
 		/* This is a video frame, get call number */
 		fr->callno = find_callno(ntohs(vh->callno) & ~0x8000, dcallno, &sin, new, 1, fd);
 		minivid = 1;
-	} else if ((meta->zeros == 0) && !(ntohs(meta->metacmd) & 0x8000)) {
-		unsigned char metatype;
-
-		if (res < sizeof(*meta)) {
-			ast_log(LOG_WARNING, "Rejecting packet from '%s.%d' that is flagged as a meta frame but is too short\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
-			return 1;
-		}
-
-		/* This is a meta header */
-		switch(meta->metacmd) {
-		case IAX_META_TRUNK:
-			if (res < (sizeof(*meta) + sizeof(*mth))) {
-				ast_log(LOG_WARNING, "midget meta trunk packet received (%d of %zd min)\n", res,
-					sizeof(*meta) + sizeof(*mth));
-				return 1;
-			}
-			mth = (struct ast_iax2_meta_trunk_hdr *)(meta->data);
-			ts = ntohl(mth->ts);
-			metatype = meta->cmddata;
-			res -= (sizeof(*meta) + sizeof(*mth));
-			ptr = mth->data;
-			tpeer = find_tpeer(&sin, fd);
-			if (!tpeer) {
-				ast_log(LOG_WARNING, "Unable to accept trunked packet from '%s:%d': No matching peer\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
-				return 1;
-			}
-			tpeer->trunkact = ast_tvnow();
-			if (!ts || ast_tvzero(tpeer->rxtrunktime))
-				tpeer->rxtrunktime = tpeer->trunkact;
-			rxtrunktime = tpeer->rxtrunktime;
-			ast_mutex_unlock(&tpeer->lock);
-			while(res >= sizeof(*mte)) {
-				/* Process channels */
-				unsigned short callno, trunked_ts, len;
-
-				if (metatype == IAX_META_TRUNK_MINI) {
-					mtm = (struct ast_iax2_meta_trunk_mini *)ptr;
-					ptr += sizeof(*mtm);
-					res -= sizeof(*mtm);
-					len = ntohs(mtm->len);
-					callno = ntohs(mtm->mini.callno);
-					trunked_ts = ntohs(mtm->mini.ts);
-				} else if (metatype == IAX_META_TRUNK_SUPERMINI) {
-					mte = (struct ast_iax2_meta_trunk_entry *)ptr;
-					ptr += sizeof(*mte);
-					res -= sizeof(*mte);
-					len = ntohs(mte->len);
-					callno = ntohs(mte->callno);
-					trunked_ts = 0;
-				} else {
-					ast_log(LOG_WARNING, "Unknown meta trunk cmd from '%s:%d': dropping\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
-					break;
-				}
-				/* Stop if we don't have enough data */
-				if (len > res)
-					break;
-				fr->callno = find_callno(callno & ~IAX_FLAG_FULL, 0, &sin, NEW_PREVENT, 1, fd);
-				if (fr->callno) {
-					ast_mutex_lock(&iaxsl[fr->callno]);
-					/* If it's a valid call, deliver the contents.  If not, we
-					   drop it, since we don't have a scallno to use for an INVAL */
-					/* Process as a mini frame */
-					f.frametype = AST_FRAME_VOICE;
-					if (iaxs[fr->callno]) {
-						if (iaxs[fr->callno]->voiceformat > 0) {
-							f.subclass = iaxs[fr->callno]->voiceformat;
-							f.datalen = len;
-							if (f.datalen >= 0) {
-								if (f.datalen)
-									f.data = ptr;
-								else
-									f.data = NULL;
-								if(trunked_ts) {
-									fr->ts = (iaxs[fr->callno]->last & 0xFFFF0000L) | (trunked_ts & 0xffff);
-								} else
-									fr->ts = fix_peerts(&rxtrunktime, fr->callno, ts);
-								/* Don't pass any packets until we're started */
-								if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED)) {
-									/* Common things */
-									f.src = "IAX2";
-									f.mallocd = 0;
-									f.offset = 0;
-									if (f.datalen && (f.frametype == AST_FRAME_VOICE)) 
-										f.samples = ast_codec_get_samples(&f);
-									else
-										f.samples = 0;
-									fr->outoforder = 0;
-									iax_frame_wrap(fr, &f);
-									duped_fr = iaxfrdup2(fr);
-									if (duped_fr) {
-										schedule_delivery(duped_fr, updatehistory, 1, &fr->ts);
-									}
-									if (iaxs[fr->callno]->last < fr->ts) {
-										iaxs[fr->callno]->last = fr->ts;
-#if 1
-										if (option_debug && iaxdebug)
-											ast_log(LOG_DEBUG, "For call=%d, set last=%d\n", fr->callno, fr->ts);
-#endif
-									}
-								}
-							} else {
-								ast_log(LOG_WARNING, "Datalen < 0?\n");
-							}
-						} else {
-							ast_log(LOG_WARNING, "Received trunked frame before first full voice frame\n ");
-							iax2_vnak(fr->callno);
-						}
-					}
-					ast_mutex_unlock(&iaxsl[fr->callno]);
-				}
-				ptr += len;
-				res -= len;
-			}
-			
-		}
-		return 1;
-	}
+	} else if ((meta->zeros == 0) && !(ntohs(meta->metacmd) & 0x8000))
+		return socket_process_meta(res, meta, &sin, fd, fr);
 
 #ifdef DEBUG_SUPPORT
 	if (iaxdebug && (res >= sizeof(*fh)))



More information about the asterisk-commits mailing list