diff options
author | russell <russell@f38db490-d61c-443f-a65b-d21fe96a405b> | 2006-12-09 07:10:55 +0000 |
---|---|---|
committer | russell <russell@f38db490-d61c-443f-a65b-d21fe96a405b> | 2006-12-09 07:10:55 +0000 |
commit | da4a5d26c71f203f5e065a11be9d0e0720904e9b (patch) | |
tree | ec843963c184f8a2417123b9defe9cbabe557159 | |
parent | 6bfcfe83698db2d3c24791d4611e42171ad44a56 (diff) |
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.
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@48360 f38db490-d61c-443f-a65b-d21fe96a405b
-rw-r--r-- | channels/chan_iax2.c | 257 |
1 files changed, 129 insertions, 128 deletions
diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c index e493a049e..efe946d48 100644 --- a/channels/chan_iax2.c +++ b/channels/chan_iax2.c @@ -1087,10 +1087,6 @@ static struct chan_iax2_pvt *new_iax(struct sockaddr_in *sin, int lockpeer, cons } 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 @@ static int socket_read(int *id, int fd, short events, void *cbdata) 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 @@ static int socket_process(struct iax2_thread *thread) /* 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))) |