diff options
author | matteo <matteo@f38db490-d61c-443f-a65b-d21fe96a405b> | 2003-03-18 06:00:18 +0000 |
---|---|---|
committer | matteo <matteo@f38db490-d61c-443f-a65b-d21fe96a405b> | 2003-03-18 06:00:18 +0000 |
commit | 15d2f7aa97d8aeb5c079eb0f8f12e34566cc25e3 (patch) | |
tree | f8415b483851763c16dc9983cd34c8bb265982d9 /channels | |
parent | 5ed6a971dafbe158e7406bc15694187df80047c4 (diff) |
Tue Mar 18 07:00:01 CET 2003
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@652 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channels')
-rwxr-xr-x | channels/chan_iax.c | 3 | ||||
-rwxr-xr-x | channels/chan_iax2.c | 191 | ||||
-rwxr-xr-x | channels/chan_sip.c | 14 | ||||
-rwxr-xr-x | channels/chan_zap.c | 1 | ||||
-rwxr-xr-x | channels/iax2-parser.c | 154 | ||||
-rwxr-xr-x | channels/iax2-parser.h | 1 | ||||
-rwxr-xr-x | channels/iax2.h | 2 |
7 files changed, 197 insertions, 169 deletions
diff --git a/channels/chan_iax.c b/channels/chan_iax.c index 3cf6813dd..894aa67c2 100755 --- a/channels/chan_iax.c +++ b/channels/chan_iax.c @@ -3409,7 +3409,6 @@ static int socket_read(int *id, int fd, short events, void *cbdata) char rel0[256]; char rel1[255]; char empty[32]=""; /* Safety measure */ - fr.ts=0; /* make Valgrind happy */ res = recvfrom(netsocket, buf, sizeof(buf), 0,(struct sockaddr *) &sin, &len); if (res < 0) { if (errno != ECONNREFUSED) @@ -3473,6 +3472,7 @@ static int socket_read(int *id, int fd, short events, void *cbdata) ast_log(LOG_DEBUG, "Received packet %d, (%d, %d)\n", ntohs(fh->seqno), f.frametype, f.subclass); /* Check if it's out of order (and not an ACK or INVAL) */ fr.seqno = ntohs(fh->seqno); + fr.ts = ntohl(fh->ts); if ((iaxs[fr.callno]->iseqno != fr.seqno) && (iaxs[fr.callno]->iseqno || ((f.subclass != AST_IAX_COMMAND_TXCNT) && @@ -3525,7 +3525,6 @@ static int socket_read(int *id, int fd, short events, void *cbdata) f.data = buf + sizeof(struct ast_iax_full_hdr); else f.data = empty; - fr.ts = ntohl(fh->ts); /* Unless this is an ACK or INVAL frame, ack it */ if ((f.frametype != AST_FRAME_IAX) || ((f.subclass != AST_IAX_COMMAND_ACK) && diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c index c58e24e3d..b1d2402ce 100755 --- a/channels/chan_iax2.c +++ b/channels/chan_iax2.c @@ -1786,6 +1786,7 @@ static int iax2_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags struct ast_frame *f; struct chan_iax2_pvt *p0 = c0->pvt->pvt; struct chan_iax2_pvt *p1 = c1->pvt->pvt; + struct timeval waittimer = {0, 0}, tv; /* Put them in native bridge mode */ p0->bridgecallno = p1->callno; @@ -1814,13 +1815,18 @@ static int iax2_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 |= AST_SOFTHANGUP_DEV; - c1->_softhangup |= AST_SOFTHANGUP_DEV; - *fo = NULL; - *rc = c0; - res = 0; - break; + gettimeofday(&tv, NULL); + if (!waittimer.tv_sec && !waittimer.tv_usec) { + waittimer.tv_sec = tv.tv_sec; + waittimer.tv_usec = tv.tv_usec; + } else if (tv.tv_sec - waittimer.tv_sec > IAX_LINGER_TIMEOUT) { + c0->_softhangup |= AST_SOFTHANGUP_DEV; + c1->_softhangup |= AST_SOFTHANGUP_DEV; + *fo = NULL; + *rc = c0; + res = 0; + break; + } } to = 1000; who = ast_waitfor_n(cs, 2, &to); @@ -2164,7 +2170,10 @@ static int iax2_send(struct chan_iax2_pvt *pvt, struct ast_frame *f, unsigned in fh->scallno = htons(fr->callno | IAX_FLAG_FULL); fh->ts = htonl(fr->ts); fh->oseqno = fr->oseqno; - fh->iseqno = fr->iseqno; + if (transfer) { + fh->iseqno = 0; + } else + fh->iseqno = fr->iseqno; /* Keep track of the last thing we've acknowledged */ pvt->aseqno = fr->iseqno; fh->type = fr->af.frametype & 0xFF; @@ -2206,6 +2215,7 @@ static int iax2_send(struct chan_iax2_pvt *pvt, struct ast_frame *f, unsigned in ast_log(LOG_WARNING, "Out of trunk data space on call number %d, dropping\n", pvt->callno); pvt->trunkerror = 1; } + res = 0; } else { /* Mini-frames have no sequence number */ fr->oseqno = -1; @@ -3355,146 +3365,6 @@ static int iax2_poke_peer_s(void *data) return 0; } -static int parse_ies(struct iax_ies *ies, unsigned char *data, int datalen) -{ - /* Parse data into information elements */ - int len; - int ie; - memset(ies, 0, sizeof(struct iax_ies)); - ies->msgcount = -1; - while(datalen >= 2) { - ie = data[0]; - len = data[1]; - if (len > datalen - 2) { - ast_log(LOG_WARNING, "Information element length exceeds message size\n"); - return -1; - } - switch(ie) { - case IAX_IE_CALLED_NUMBER: - ies->called_number = data + 2; - break; - case IAX_IE_CALLING_NUMBER: - ies->calling_number = data + 2; - break; - case IAX_IE_CALLING_ANI: - ies->calling_ani = data + 2; - break; - case IAX_IE_CALLING_NAME: - ies->calling_name = data + 2; - break; - case IAX_IE_CALLED_CONTEXT: - ies->called_context = data + 2; - break; - case IAX_IE_USERNAME: - ies->username = data + 2; - break; - case IAX_IE_PASSWORD: - ies->password = data + 2; - break; - case IAX_IE_CAPABILITY: - if (len != sizeof(unsigned int)) - ast_log(LOG_WARNING, "Expecting capability to be %d bytes long but was %d\n", sizeof(unsigned int), len); - else - ies->capability = ntohl(*((unsigned int *)(data + 2))); - break; - case IAX_IE_FORMAT: - if (len != sizeof(unsigned int)) - ast_log(LOG_WARNING, "Expecting format to be %d bytes long but was %d\n", sizeof(unsigned int), len); - else - ies->format = ntohl(*((unsigned int *)(data + 2))); - break; - case IAX_IE_LANGUAGE: - ies->language = data + 2; - break; - case IAX_IE_VERSION: - if (len != sizeof(unsigned short)) - ast_log(LOG_WARNING, "Expecting version to be %d bytes long but was %d\n", sizeof(unsigned short), len); - else - ies->version = ntohs(*((unsigned short *)(data + 2))); - break; - case IAX_IE_ADSICPE: - if (len != sizeof(unsigned short)) - ast_log(LOG_WARNING, "Expecting adsicpe to be %d bytes long but was %d\n", sizeof(unsigned short), len); - else - ies->adsicpe = ntohs(*((unsigned short *)(data + 2))); - break; - case IAX_IE_DNID: - ies->dnid = data + 2; - break; - case IAX_IE_AUTHMETHODS: - if (len != sizeof(unsigned short)) - ast_log(LOG_WARNING, "Expecting authmethods to be %d bytes long but was %d\n", sizeof(unsigned short), len); - else - ies->authmethods = ntohs(*((unsigned short *)(data + 2))); - break; - case IAX_IE_CHALLENGE: - ies->challenge = data + 2; - break; - case IAX_IE_MD5_RESULT: - ies->md5_result = data + 2; - break; - case IAX_IE_RSA_RESULT: - ies->rsa_result = data + 2; - break; - case IAX_IE_APPARENT_ADDR: - ies->apparent_addr = ((struct sockaddr_in *)(data + 2)); - break; - case IAX_IE_REFRESH: - if (len != sizeof(unsigned short)) - ast_log(LOG_WARNING, "Expecting refresh to be %d bytes long but was %d\n", sizeof(unsigned short), len); - else - ies->refresh = ntohs(*((unsigned short *)(data + 2))); - break; - case IAX_IE_DPSTATUS: - if (len != sizeof(unsigned short)) - ast_log(LOG_WARNING, "Expecting dpstatus to be %d bytes long but was %d\n", sizeof(unsigned short), len); - else - ies->dpstatus = ntohs(*((unsigned short *)(data + 2))); - break; - case IAX_IE_CALLNO: - if (len != sizeof(unsigned short)) - ast_log(LOG_WARNING, "Expecting callno to be %d bytes long but was %d\n", sizeof(unsigned short), len); - else - ies->callno = ntohs(*((unsigned short *)(data + 2))); - break; - case IAX_IE_CAUSE: - ies->cause = data + 2; - break; - case IAX_IE_IAX_UNKNOWN: - if (len == 1) - ies->iax_unknown = data[2]; - else - ast_log(LOG_WARNING, "Expected single byte Unknown command, but was %d long\n", len); - break; - case IAX_IE_MSGCOUNT: - if (len != sizeof(unsigned short)) - ast_log(LOG_WARNING, "Expecting msgcount to be %d bytes long but was %d\n", sizeof(unsigned short), len); - else - ies->msgcount = ntohs(*((unsigned short *)(data + 2))); - break; - case IAX_IE_AUTOANSWER: - ies->autoanswer = 1; - break; - case IAX_IE_MUSICONHOLD: - ies->musiconhold = 1; - break; - default: - ast_log(LOG_NOTICE, "Ignoring unknown information element '%s' (%d) of length %d\n", iax_ie2str(ie), ie, len); - } - /* Overwrite information element with 0, to null terminate previous portion */ - data[0] = 0; - datalen -= (len + 2); - data += (len + 2); - } - /* Null-terminate last field */ - *data = '\0'; - if (datalen) { - ast_log(LOG_WARNING, "Invalid information element contents, strange boundary\n"); - return -1; - } - return 0; -} - static int send_trunk(struct iax2_peer *peer) { int x; @@ -3777,9 +3647,8 @@ static int socket_read(int *id, int fd, short events, void *cbdata) ast_pthread_mutex_unlock(&iaxsl[fr.callno]); return 1; } - if (((f.subclass != IAX_COMMAND_TXCNT) && - (f.subclass != IAX_COMMAND_TXACC)) || (f.frametype != AST_FRAME_IAX)) - iaxs[fr.callno]->peercallno = (short)(ntohs(mh->callno) & ~IAX_FLAG_FULL); + if (!memcmp(&sin, &iaxs[fr.callno]->addr, sizeof(sin))) + iaxs[fr.callno]->peercallno = (unsigned short)(ntohs(mh->callno) & ~IAX_FLAG_FULL); if (ntohs(mh->callno) & IAX_FLAG_FULL) { if (option_debug) ast_log(LOG_DEBUG, "Received packet %d, (%d, %d)\n", fh->oseqno, f.frametype, f.subclass); @@ -3840,9 +3709,11 @@ static int socket_read(int *id, int fd, short events, void *cbdata) } f.datalen = res - sizeof(struct ast_iax2_full_hdr); - /* Handle implicit ACKing unless this is an INVAL */ - if (((f.subclass != IAX_COMMAND_INVAL)) || - (f.frametype != AST_FRAME_IAX)) { + /* Handle implicit ACKing unless this is an INVAL, and only if this is + from the real peer, not the transfer peer */ + if (!memcmp(&sin, &iaxs[fr.callno]->addr, sizeof(sin)) && + (((f.subclass != IAX_COMMAND_INVAL)) || + (f.frametype != AST_FRAME_IAX))) { unsigned char x; /* XXX This code is not very efficient. Surely there is a better way which still properly handles boundary conditions? XXX */ @@ -3883,10 +3754,18 @@ static int socket_read(int *id, int fd, short events, void *cbdata) } else ast_log(LOG_DEBUG, "Received iseqno %d not within window %d->%d\n", fr.iseqno, iaxs[fr.callno]->rseqno, iaxs[fr.callno]->oseqno); } + if (memcmp(&sin, &iaxs[fr.callno]->addr, sizeof(sin)) && + ((f.frametype != AST_FRAME_IAX) || + ((f.subclass != IAX_COMMAND_TXACC) && + (f.subclass != IAX_COMMAND_TXCNT)))) { + /* Only messages we accept from a transfer host are TXACC and TXCNT */ + ast_pthread_mutex_unlock(&iaxsl[fr.callno]); + return 1; + } if (f.datalen) { if (f.frametype == AST_FRAME_IAX) { - if (parse_ies(&ies, buf + sizeof(struct ast_iax2_full_hdr), f.datalen)) { + if (iax_parse_ies(&ies, buf + sizeof(struct ast_iax2_full_hdr), f.datalen)) { ast_log(LOG_WARNING, "undecodable frame received\n"); ast_pthread_mutex_unlock(&iaxsl[fr.callno]); return 1; @@ -4385,6 +4264,8 @@ static int socket_read(int *id, int fd, short events, void *cbdata) send_command_transfer(iaxs[fr.callno], AST_FRAME_IAX, IAX_COMMAND_TXACC, 0, NULL, 0); break; case IAX_COMMAND_TXREL: + /* Send ack immediately, rather than waiting until we've changed addresses */ + send_command_immediate(iaxs[fr.callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr.ts, NULL, 0,fr.iseqno); complete_transfer(fr.callno, &ies); break; case IAX_COMMAND_DPREP: diff --git a/channels/chan_sip.c b/channels/chan_sip.c index ff47ba88f..cb9bb6f56 100755 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -473,7 +473,7 @@ static void sip_prefs_free(void) static void sip_pref_remove(int format) { - struct sip_codec_pref *cur, *prev; + struct sip_codec_pref *cur, *prev=NULL; cur = prefs; while(cur) { if (cur->codec == format) { @@ -744,10 +744,9 @@ static int sip_hangup(struct ast_channel *ast) static int sip_answer(struct ast_channel *ast) { - int res = 0,fmt,capability; + int res = 0,fmt; char *codec; struct sip_pvt *p = ast->pvt->pvt; - struct sip_codec_pref *oldpref=NULL; if (ast->_state != AST_STATE_UP) { @@ -759,10 +758,6 @@ static int sip_answer(struct ast_channel *ast) ast_log(LOG_NOTICE, "Changing codec to '%s' for this call because of ${SIP_CODEC) variable\n",codec); fmt=ast_getformatbyname(codec); if (fmt) { - oldpref=prefs; - prefs=NULL; - sip_pref_append(fmt); - capability=p->capability; p->capability=fmt; } else ast_log(LOG_NOTICE, "Ignoring ${SIP_CODEC} variable because of unrecognized codec: %s\n",codec); } @@ -771,11 +766,6 @@ static int sip_answer(struct ast_channel *ast) if (option_debug) ast_log(LOG_DEBUG, "sip_answer(%s)\n", ast->name); res = transmit_response_with_sdp(p, "200 OK", &p->initreq); - sip_prefs_free(); - if (oldpref) { - prefs=oldpref; - p->capability=capability; - } } return res; } diff --git a/channels/chan_zap.c b/channels/chan_zap.c index 4d8e460b0..ac51aad37 100755 --- a/channels/chan_zap.c +++ b/channels/chan_zap.c @@ -2732,6 +2732,7 @@ static struct ast_frame *zt_handle_event(struct ast_channel *ast) p->owner = p->subs[SUB_REAL].owner; if (p->subs[SUB_REAL].owner && p->subs[SUB_REAL].owner->bridge) ast_moh_stop(p->subs[SUB_REAL].owner->bridge); + zt_enable_ec(p); } } diff --git a/channels/iax2-parser.c b/channels/iax2-parser.c index 6e27d6ffd..f7020562b 100755 --- a/channels/iax2-parser.c +++ b/channels/iax2-parser.c @@ -342,3 +342,157 @@ void iax_set_error(void (*func)(const char *)) { errorf = func; } + +int iax_parse_ies(struct iax_ies *ies, unsigned char *data, int datalen) +{ + /* Parse data into information elements */ + int len; + int ie; + char tmp[256]; + memset(ies, 0, sizeof(struct iax_ies)); + ies->msgcount = -1; + while(datalen >= 2) { + ie = data[0]; + len = data[1]; + if (len > datalen - 2) { + errorf("Information element length exceeds message size\n"); + return -1; + } + switch(ie) { + case IAX_IE_CALLED_NUMBER: + ies->called_number = data + 2; + break; + case IAX_IE_CALLING_NUMBER: + ies->calling_number = data + 2; + break; + case IAX_IE_CALLING_ANI: + ies->calling_ani = data + 2; + break; + case IAX_IE_CALLING_NAME: + ies->calling_name = data + 2; + break; + case IAX_IE_CALLED_CONTEXT: + ies->called_context = data + 2; + break; + case IAX_IE_USERNAME: + ies->username = data + 2; + break; + case IAX_IE_PASSWORD: + ies->password = data + 2; + break; + case IAX_IE_CAPABILITY: + if (len != sizeof(unsigned int)) { + snprintf(tmp, sizeof(tmp), "Expecting capability to be %d bytes long but was %d\n", sizeof(unsigned int), len); + errorf(tmp); + } else + ies->capability = ntohl(*((unsigned int *)(data + 2))); + break; + case IAX_IE_FORMAT: + if (len != sizeof(unsigned int)) { + snprintf(tmp, sizeof(tmp), "Expecting format to be %d bytes long but was %d\n", sizeof(unsigned int), len); + errorf(tmp); + } else + ies->format = ntohl(*((unsigned int *)(data + 2))); + break; + case IAX_IE_LANGUAGE: + ies->language = data + 2; + break; + case IAX_IE_VERSION: + if (len != sizeof(unsigned short)) { + snprintf(tmp, sizeof(tmp), "Expecting version to be %d bytes long but was %d\n", sizeof(unsigned short), len); + errorf(tmp); + } else + ies->version = ntohs(*((unsigned short *)(data + 2))); + break; + case IAX_IE_ADSICPE: + if (len != sizeof(unsigned short)) { + snprintf(tmp, sizeof(tmp), "Expecting adsicpe to be %d bytes long but was %d\n", sizeof(unsigned short), len); + errorf(tmp); + } else + ies->adsicpe = ntohs(*((unsigned short *)(data + 2))); + break; + case IAX_IE_DNID: + ies->dnid = data + 2; + break; + case IAX_IE_AUTHMETHODS: + if (len != sizeof(unsigned short)) { + snprintf(tmp, sizeof(tmp), "Expecting authmethods to be %d bytes long but was %d\n", sizeof(unsigned short), len); + errorf(tmp); + } else + ies->authmethods = ntohs(*((unsigned short *)(data + 2))); + break; + case IAX_IE_CHALLENGE: + ies->challenge = data + 2; + break; + case IAX_IE_MD5_RESULT: + ies->md5_result = data + 2; + break; + case IAX_IE_RSA_RESULT: + ies->rsa_result = data + 2; + break; + case IAX_IE_APPARENT_ADDR: + ies->apparent_addr = ((struct sockaddr_in *)(data + 2)); + break; + case IAX_IE_REFRESH: + if (len != sizeof(unsigned short)) { + snprintf(tmp, sizeof(tmp), "Expecting refresh to be %d bytes long but was %d\n", sizeof(unsigned short), len); + errorf(tmp); + } else + ies->refresh = ntohs(*((unsigned short *)(data + 2))); + break; + case IAX_IE_DPSTATUS: + if (len != sizeof(unsigned short)) { + snprintf(tmp, sizeof(tmp), "Expecting dpstatus to be %d bytes long but was %d\n", sizeof(unsigned short), len); + errorf(tmp); + } else + ies->dpstatus = ntohs(*((unsigned short *)(data + 2))); + break; + case IAX_IE_CALLNO: + if (len != sizeof(unsigned short)) { + snprintf(tmp, sizeof(tmp), "Expecting callno to be %d bytes long but was %d\n", sizeof(unsigned short), len); + errorf(tmp); + } else + ies->callno = ntohs(*((unsigned short *)(data + 2))); + break; + case IAX_IE_CAUSE: + ies->cause = data + 2; + break; + case IAX_IE_IAX_UNKNOWN: + if (len == 1) + ies->iax_unknown = data[2]; + else { + snprintf(tmp, sizeof(tmp), "Expected single byte Unknown command, but was %d long\n", len); + errorf(tmp); + } + break; + case IAX_IE_MSGCOUNT: + if (len != sizeof(unsigned short)) { + snprintf(tmp, sizeof(tmp), "Expecting msgcount to be %d bytes long but was %d\n", sizeof(unsigned short), len); + errorf(tmp); + } else + ies->msgcount = ntohs(*((unsigned short *)(data + 2))); + break; + case IAX_IE_AUTOANSWER: + ies->autoanswer = 1; + break; + case IAX_IE_MUSICONHOLD: + ies->musiconhold = 1; + break; + default: + snprintf(tmp, sizeof(tmp), "Ignoring unknown information element '%s' (%d) of length %d\n", iax_ie2str(ie), ie, len); + errorf(tmp); + } + /* Overwrite information element with 0, to null terminate previous portion */ + data[0] = 0; + datalen -= (len + 2); + data += (len + 2); + } + /* Null-terminate last field */ + *data = '\0'; + if (datalen) { + errorf("Invalid information element contents, strange boundary\n"); + return -1; + } + return 0; +} + diff --git a/channels/iax2-parser.h b/channels/iax2-parser.h index 903a44383..e34ca1ca7 100755 --- a/channels/iax2-parser.h +++ b/channels/iax2-parser.h @@ -106,5 +106,6 @@ extern int iax_ie_append_short(struct iax_ie_data *ied, unsigned char ie, unsign extern int iax_ie_append_str(struct iax_ie_data *ied, unsigned char ie, unsigned char *str); extern int iax_ie_append_byte(struct iax_ie_data *ied, unsigned char ie, unsigned char dat); extern int iax_ie_append(struct iax_ie_data *ied, unsigned char ie); +extern int iax_parse_ies(struct iax_ies *ies, unsigned char *data, int datalen); #endif diff --git a/channels/iax2.h b/channels/iax2.h index e42591c2d..88ffe0ca0 100755 --- a/channels/iax2.h +++ b/channels/iax2.h @@ -66,6 +66,8 @@ #define IAX_DEFAULT_REG_EXPIRE 60 /* By default require re-registration once per minute */ +#define IAX_LINGER_TIMEOUT 10 /* How long to wait before closing bridged call */ + #define IAX_DEFAULT_PORTNO 4569 /* IAX Information elements */ |