From d08e5f9e359d895f61b70c288f90b77bb78a2183 Mon Sep 17 00:00:00 2001 From: markster Date: Thu, 8 Aug 2002 19:53:54 +0000 Subject: Version 0.2.0 from FTP git-svn-id: http://svn.digium.com/svn/asterisk/trunk@502 f38db490-d61c-443f-a65b-d21fe96a405b --- channels/chan_iax.c | 79 +++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 59 insertions(+), 20 deletions(-) (limited to 'channels/chan_iax.c') diff --git a/channels/chan_iax.c b/channels/chan_iax.c index bc7d4aa5b..7f8e23391 100755 --- a/channels/chan_iax.c +++ b/channels/chan_iax.c @@ -891,9 +891,17 @@ static void iax_destroy(int callno) pvt->alreadygone = 1; if (pvt->owner) { - /* If there's an owner, prod it to give up */ - ast_queue_hangup(pvt->owner, 1); - return; + if (ast_pthread_mutex_lock(&pvt->owner->lock)) { + ast_log(LOG_WARNING, "Unable to lock channel %s\n", pvt->owner->name); + } else if (!pvt->owner || (pvt->owner->pvt->pvt != pvt)) { + ast_log(LOG_WARNING, "Something very strange happened...\n"); + } else { + /* If there's an owner, prod it to give up */ + pvt->owner->pvt->pvt = NULL; + pvt->owner->_softhangup |= AST_SOFTHANGUP_DEV; + ast_queue_hangup(pvt->owner, 0); + ast_pthread_mutex_unlock(&pvt->owner->lock); + } } iaxs[callno] = NULL; @@ -930,12 +938,13 @@ static int attempt_transmit(void *data) iax_destroy(f->callno); } else { if (iaxs[f->callno]->owner) - ast_log(LOG_WARNING, "Max retries exceeded to host %s (type = %d, subclass = %d, ts=%d, seqno=%d)\n", inet_ntoa(iaxs[f->callno]->addr.sin_addr), f->f->frametype, f->f->subclass, f->ts, f->seqno); + ast_log(LOG_WARNING, "Max retries exceeded to host %s on %s (type = %d, subclass = %d, ts=%d, seqno=%d)\n", inet_ntoa(iaxs[f->callno]->addr.sin_addr),iaxs[f->callno]->owner->name , f->f->frametype, f->f->subclass, f->ts, f->seqno); iaxs[f->callno]->error = ETIMEDOUT; - if (iaxs[f->callno]->owner) + if (iaxs[f->callno]->owner) { /* Hangup the fd */ + ast_softhangup(iaxs[f->callno]->owner, AST_SOFTHANGUP_DEV); ast_queue_hangup(iaxs[f->callno]->owner, 1); - else { + } else { if (iaxs[f->callno]->reg) { memset(&iaxs[f->callno]->reg->us, 0, sizeof(iaxs[f->callno]->reg->us)); iaxs[f->callno]->reg->regstate = REG_STATE_TIMEOUT; @@ -1120,6 +1129,10 @@ static int forward_delivery(struct ast_iax_frame *fr) struct chan_iax_pvt *p1, *p2; p1 = iaxs[fr->callno]; p2 = iaxs[p1->bridgecallno]; + if (!p1) + return -1; + if (!p2) + return -1; /* Fix relative timestamp */ fr->ts = calc_fakestamp(p1, p2, fr->ts); /* Now just send it send on the 2nd one @@ -1377,7 +1390,7 @@ static int iax_call(struct ast_channel *c, char *dest, int timeout) char context[AST_MAX_EXTENSION] =""; char *portno = NULL; struct chan_iax_pvt *p = c->pvt->pvt; - if ((c->state != AST_STATE_DOWN) && (c->state != AST_STATE_RESERVED)) { + if ((c->_state != AST_STATE_DOWN) && (c->_state != AST_STATE_RESERVED)) { ast_log(LOG_WARNING, "Line is already in use (%s)?\n", c->name); return -1; } @@ -1453,7 +1466,7 @@ static int iax_call(struct ast_channel *c, char *dest, int timeout) ast_verbose(VERBOSE_PREFIX_3 "Calling using options '%s'\n", requeststr); send_command((struct chan_iax_pvt *)c->pvt->pvt, AST_FRAME_IAX, AST_IAX_COMMAND_NEW, 0, requeststr, strlen(requeststr) + 1, -1); - c->state = AST_STATE_RINGING; + ast_setstate(c, AST_STATE_RINGING); return 0; } @@ -1475,7 +1488,7 @@ static int iax_predestroy(struct chan_iax_pvt *pvt) } c = pvt->owner; if (c) { - c->softhangup = 1; + c->_softhangup |= AST_SOFTHANGUP_DEV; c->pvt->pvt = NULL; pvt->owner = NULL; ast_pthread_mutex_lock(&usecnt_lock); @@ -1488,10 +1501,12 @@ static int iax_predestroy(struct chan_iax_pvt *pvt) return 0; } -static int iax_hangup(struct ast_channel *c) { +static int iax_hangup(struct ast_channel *c) +{ struct chan_iax_pvt *pvt = c->pvt->pvt; int alreadygone; if (pvt) { + ast_log(LOG_DEBUG, "We're hanging up %s now...\n", c->name); alreadygone = pvt->alreadygone; /* Send the hangup unless we have had a transmission error or are already gone */ if (!pvt->error && !alreadygone) @@ -1527,8 +1542,9 @@ static int iax_setoption(struct ast_channel *c, int option, void *data, int data } static struct ast_frame *iax_read(struct ast_channel *c) { + static struct ast_frame f = { AST_FRAME_NULL, }; ast_log(LOG_NOTICE, "I should never be called!\n"); - return NULL; + return &f; } static int iax_start_transfer(struct ast_channel *c0, struct ast_channel *c1) @@ -1586,8 +1602,8 @@ static int iax_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, if ((p0->transferring == TRANSFER_RELEASED) && (p1->transferring == TRANSFER_RELEASED)) { /* Call has been transferred. We're no longer involved */ sleep(1); - c0->softhangup++; - c1->softhangup++; + c0->_softhangup |= AST_SOFTHANGUP_DEV; + c1->_softhangup |= AST_SOFTHANGUP_DEV; *fo = NULL; *rc = c0; res = 0; @@ -1749,7 +1765,7 @@ static struct ast_channel *ast_iax_new(struct chan_iax_pvt *i, int state, int ca tmp->pvt->fixup = iax_fixup; i->owner = tmp; i->capability = capability; - tmp->state = state; + ast_setstate(tmp, state); ast_pthread_mutex_lock(&usecnt_lock); usecnt++; ast_pthread_mutex_unlock(&usecnt_lock); @@ -2115,6 +2131,8 @@ static struct ast_cli_entry cli_no_debug = static int iax_write(struct ast_channel *c, struct ast_frame *f) { struct chan_iax_pvt *i = c->pvt->pvt; + if (!i) + return -1; /* If there's an outstanding error, return failure now */ if (i->error) { ast_log(LOG_DEBUG, "Write error: %s\n", strerror(errno)); @@ -3172,6 +3190,10 @@ static int socket_read(int *id, int fd, short events, void *cbdata) #endif if ((f.frametype == AST_FRAME_IAX) && ((f.subclass == AST_IAX_COMMAND_NEW) || (f.subclass == AST_IAX_COMMAND_REGREQ))) new = NEW_ALLOW; + } else { + /* Don't knwo anything about it yet */ + f.frametype = AST_FRAME_NULL; + f.subclass = 0; } ast_pthread_mutex_lock(&iaxs_lock); fr.callno = find_callno(ntohs(mh->callno) & ~AST_FLAG_FULL, dcallno, &sin, new); @@ -3207,7 +3229,8 @@ static int socket_read(int *id, int fd, short events, void *cbdata) ((f.subclass != AST_IAX_COMMAND_ACK) && (f.subclass != AST_IAX_COMMAND_INVAL) && (f.subclass != AST_IAX_COMMAND_TXCNT) && - (f.subclass != AST_IAX_COMMAND_TXACC)) || + (f.subclass != AST_IAX_COMMAND_TXACC) && + (f.subclass != AST_IAX_COMMAND_VNAK)) || (f.frametype != AST_FRAME_IAX)) { /* If it's not an ACK packet, it's out of order. */ if (option_debug) @@ -3229,11 +3252,12 @@ static int socket_read(int *id, int fd, short events, void *cbdata) return 1; } } else { - /* Increment unless it's an ACK */ + /* Increment unless it's an ACK or VNAK */ if (((f.subclass != AST_IAX_COMMAND_ACK) && (f.subclass != AST_IAX_COMMAND_INVAL) && (f.subclass != AST_IAX_COMMAND_TXCNT) && - (f.subclass != AST_IAX_COMMAND_TXACC)) || + (f.subclass != AST_IAX_COMMAND_TXACC) && + (f.subclass != AST_IAX_COMMAND_VNAK)) || (f.frametype != AST_FRAME_IAX)) iaxs[fr.callno]->iseqno++; } @@ -3254,10 +3278,25 @@ static int socket_read(int *id, int fd, short events, void *cbdata) ((f.subclass != AST_IAX_COMMAND_ACK) && (f.subclass != AST_IAX_COMMAND_TXCNT) && (f.subclass != AST_IAX_COMMAND_TXACC) && - (f.subclass != AST_IAX_COMMAND_INVAL))) + (f.subclass != AST_IAX_COMMAND_INVAL) && + (f.subclass != AST_IAX_COMMAND_VNAK))) send_command_immediate(iaxs[fr.callno], AST_FRAME_IAX, AST_IAX_COMMAND_ACK, fr.ts, NULL, 0,fr.seqno); - if (f.frametype == AST_FRAME_VOICE) - iaxs[fr.callno]->voiceformat = f.subclass; + if (f.frametype == AST_FRAME_VOICE) { + if (f.subclass != iaxs[fr.callno]->voiceformat) { + iaxs[fr.callno]->voiceformat = f.subclass; + ast_log(LOG_DEBUG, "Ooh, voice format changed to %d\n", f.subclass); + if (iaxs[fr.callno]->owner) { + int orignative; + ast_pthread_mutex_lock(&iaxs[fr.callno]->owner->lock); + orignative = iaxs[fr.callno]->owner->nativeformats; + iaxs[fr.callno]->owner->nativeformats = f.subclass; + if (iaxs[fr.callno]->owner->readformat) + ast_set_read_format(iaxs[fr.callno]->owner, iaxs[fr.callno]->owner->readformat); + iaxs[fr.callno]->owner->nativeformats = orignative; + ast_pthread_mutex_unlock(&iaxs[fr.callno]->owner->lock); + } + } + } if (f.frametype == AST_FRAME_IAX) { /* Handle the IAX pseudo frame itself */ if (option_debug) -- cgit v1.2.3