diff --git a/Makefile b/Makefile index cd2a4a1457cdf269c32255bce0a57334f62d92b0..9edd35c6a38f6eb665bdfdc8824bf6780ae5931d 100755 --- a/Makefile +++ b/Makefile @@ -13,6 +13,34 @@ .EXPORT_ALL_VARIABLES: +# Pentium Pro Optimize +#PROC=i686 +# Pentium Optimize +#PROC=i586 +#PROC=k6 +#PROC=ppc +PROC=$(shell uname -m) + +######### More GSM codec optimization +######### Uncomment to enable MMXTM optimizations for x86 architecture CPU's +######### which support MMX instructions. This should be newer pentiums, +######### ppro's, etc, as well as the AMD K6 and K7. +K6OPT = #-DK6OPT + +#Tell gcc to optimize the asterisk's code +OPTIMIZE=-O6 + +#Include debug symbols in the executables (-g) and profiling info (-pg) +DEBUG=-g #-pg + +# Optional debugging parameters +DEBUG_THREADS = #-DDO_CRASH -DDEBUG_THREADS + +# Uncomment next one to enable ast_frame tracing (for debugging) +TRACE_FRAMES = #-DTRACE_FRAMES + +# Where to install asterisk after compiling +# Default -> leave empty INSTALL_PREFIX= ASTLIBDIR=$(INSTALL_PREFIX)/usr/lib/asterisk @@ -30,18 +58,9 @@ ASTVARRUNDIR=$(INSTALL_PREFIX)/var/run MODULES_DIR=$(ASTLIBDIR)/modules AGI_DIR=$(ASTVARLIBDIR)/agi-bin -# Pentium Pro Optimize -#PROC=i686 -# Pentium Optimize -#PROC=i586 -#PROC=k6 -#PROC=ppc -PROC=$(shell uname -m) - -DEBUG=-g #-pg INCLUDE=-Iinclude -I../include CFLAGS=-pipe -Wall -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations $(DEBUG) $(INCLUDE) -D_REENTRANT -D_GNU_SOURCE #-DMAKE_VALGRIND_HAPPY -#CFLAGS+=-O6 +CFLAGS+=$(OPTIMIZE) CFLAGS+=$(shell if $(CC) -march=$(PROC) -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-march=$(PROC)"; fi) CFLAGS+=$(shell if uname -m | grep -q ppc; then echo "-fsigned-char"; fi) @@ -62,10 +81,8 @@ CFLAGS+=-DASTCONFPATH=\"$(ASTCONFPATH)\" CFLAGS+=-DASTMODDIR=\"$(MODULES_DIR)\" CFLAGS+=-DASTAGIDIR=\"$(AGI_DIR)\" -# Optional debugging parameters -CFLAGS+= -DDO_CRASH -DDEBUG_THREADS -# Uncomment next one to enable ast_frame tracing (for debugging) -#CFLAGS+= -DTRACE_FRAMES +CFLAGS+= $(DEBUG_THREADS) +CFLAGS+= $(TRACE_FRAMES) CFLAGS+=# -fomit-frame-pointer SUBDIRS=res channels pbx apps codecs formats agi cdr astman LIBS=-ldl -lpthread -lncurses -lm #-lnjamd @@ -311,3 +328,7 @@ config: fi +dont-optimize: + make OPTIMIZE= K6OPT= install + +valgrind: dont-optimize diff --git a/apps/app_substring.c b/apps/app_substring.c index 97f0fea0a2d4beec7f0611dc6523aa13972d0b33..4d3ccceb3231aeae9473a50fd7af3fa2e346b184 100755 --- a/apps/app_substring.c +++ b/apps/app_substring.c @@ -56,6 +56,7 @@ static int substring_exec(struct ast_channel *chan, void *data) char *count1, *count2; char *first, *second, *stringp; stringp=alloca(strlen(data)+1); + ast_log(LOG_WARNING, "The use of Substring application is deprecated. Please use ${variable:a:b} instead\n"); strncpy(stringp,data,strlen(data)+1); if (strchr(stringp,'|')&&strchr(stringp,'=')) { int icount1,icount2; diff --git a/channel.c b/channel.c index 0a7eed39d554fef8e274551ea5c9779ea42bd18b..684adac62ca3e6709fcf1e740683391c9b40f5b3 100755 --- a/channel.c +++ b/channel.c @@ -347,7 +347,8 @@ int ast_queue_frame(struct ast_channel *chan, struct ast_frame *fin, int lock) cur = cur->next; qlen++; } - if (qlen > 128) { + /* Allow up to 96 voice frames outstanding, and up to 128 total frames */ + if (((fin->frametype == AST_FRAME_VOICE) && (qlen > 96)) || (qlen > 128)) { if (fin->frametype != AST_FRAME_VOICE) { ast_log(LOG_WARNING, "Exceptionally long queue length queuing to %s\n", chan->name); CRASH; diff --git a/channels/chan_iax.c b/channels/chan_iax.c index 3cf6813ddde90d22048c6a5d7d952a727e2f78e7..894aa67c292c33350bb7b1b3f811d444a19a1760 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 c58e24e3d4fdc567f8c270aa08fa60760c3fdeae..b1d2402ce7395f47dfe7c89124c77b8e173839c8 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 ff47ba88ff16e4b2c8ec2a6ac87e147387ca9ca1..cb9bb6f568f9b84b5b4997fe76f5575f96f19cde 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 4d8e460b018a4e06a68c554e041da294baf02335..ac51aad3795e897606523b429cb46dd9449a47a1 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 6e27d6ffd604916de954b1a7c98fbcfb68a80732..f7020562b8472582d938e4393ee39291630c452a 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 903a44383724309a4fb4ae2c3bb8bfb91c46d93e..e34ca1ca7cbf86c873e6ca1d1bd8280bec40180b 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 e42591c2d5203ddeb2d5bb1191a734d7c9e0f907..88ffe0ca0881fe4365a020a290ebef5c98b49d00 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 */ diff --git a/codecs/gsm/Makefile b/codecs/gsm/Makefile index 9e211f57598d95aab968bb543e3b5088223f7efa..721879da95df5372d94a628c8e37876e55a2679b 100755 --- a/codecs/gsm/Makefile +++ b/codecs/gsm/Makefile @@ -31,7 +31,7 @@ WAV49 = -DWAV49 ######### manual page on gsm_option(3). #K6OPT = -DK6OPT -K6OPT = +#K6OPT = ######### Define to enable MMXTM optimizations for x86 architecture CPU's ######### which support MMX instructions. This should be newer pentiums, ######### ppro's, etc, as well as the AMD K6 and K7. The compile will @@ -54,7 +54,7 @@ PG = # CC = /usr/lang/acc # CCFLAGS = -c -O -CC = gcc -ansi -pedantic -O6 -mpentium -fschedule-insns2 -fomit-frame-pointer +CC = gcc -ansi -pedantic $(OPTIMIZE) -march=$(PROC) -fschedule-insns2 -fomit-frame-pointer CCFLAGS += -c -DNeedFunctionPrototypes=1 -finline-functions -funroll-loops LD = $(CC) diff --git a/codecs/lpc10/Makefile b/codecs/lpc10/Makefile index af5131d77862eee661ffbf5c4145034a584fbe67..61d87740c73b34d53050016d6799465537dc34cd 100755 --- a/codecs/lpc10/Makefile +++ b/codecs/lpc10/Makefile @@ -22,8 +22,9 @@ LIB_TARGET_DIR = . # WARNINGS = -Wall -Wno-comment -Wno-error -CFLAGS = -O6 -I$(LIB_TARGET_DIR) $(WARNINGS) -CFLAGS+= $(shell if uname -m | grep -q 86; then echo "-mpentium" ; fi) +CFLAGS = $(OPTIMIZE) -I$(LIB_TARGET_DIR) $(WARNINGS) +#CFLAGS+= $(shell if uname -m | grep -q 86; then echo "-mpentium" ; fi) +CFLAGS+= -march=$(PROC) LIB = $(LIB_TARGET_DIR)/liblpc10.a diff --git a/configs/extensions.conf.sample b/configs/extensions.conf.sample index 0499a3351cc2d30e7b9414331c7de9dad3a6c9eb..f7135ecf6b5f00a472f7055c6d2149b1c347a470 100755 --- a/configs/extensions.conf.sample +++ b/configs/extensions.conf.sample @@ -31,7 +31,7 @@ CONSOLE=Console/dsp ; Console interface for demo IAXINFO=guest ; IAXtel username/password ;IAXINFO=myuser:mypass TRUNK=Zap/g2 ; Trunk interface -;TRUNK=IAX/user:pass@provider +;TRUNK=IAX2/user:pass@provider ; ; Any category other than "General" and "Globals" represent @@ -84,10 +84,10 @@ TRUNK=Zap/g2 ; Trunk interface ; up, please go to www.gnophone.com or www.iaxtel.com ; [iaxtel700] -exten => _91700NXXXXXX,1,Dial(IAX/${IAXINFO}@iaxtel.com/${EXTEN:1}@iaxtel) +exten => _91700NXXXXXX,1,Dial(IAX2/${IAXINFO}@iaxtel.com/${EXTEN:1}@iaxtel) [iaxprovider] -;switch => IAX/user:[key]@myserver/mycontext +;switch => IAX2/user:[key]@myserver/mycontext [trunkint] ; @@ -155,7 +155,7 @@ include => provider ; extensions that are not known here, for example with remote ; IAX switching you transparently get access to the remote ; -; switch => IAX/user:password@bigserver/local +; switch => IAX2/user:password@bigserver/local [macro-stdexten]; ; @@ -218,7 +218,7 @@ exten => i,1,Playback(invalid) ; "That's not valid, try again" ; Asterisk demo. ; exten => 500,1,Playback(demo-abouttotry); Let them know what's going on -exten => 500,2,Dial(IAX/guest@misery.digium.com/s@default) ; Call the Asterisk demo +exten => 500,2,Dial(IAX2/guest@misery.digium.com/s@default) ; Call the Asterisk demo exten => 500,3,Playback(demo-nogo) ; Couldn't connect to the demo site exten => 500,4,Goto(s,6) ; Return to the start over message. diff --git a/frame.c b/frame.c index 34ec9950251d7c0027b080dbccabef7266edb267..695c5573e1639e46a2cb5854a44c72c7a0255568 100755 --- a/frame.c +++ b/frame.c @@ -238,15 +238,37 @@ struct ast_frame *ast_frisolate(struct ast_frame *fr) struct ast_frame *ast_frdup(struct ast_frame *f) { - struct ast_frame *ret; - int p; - p = f->mallocd; - f->mallocd = 0; - /* Make frisolate think this is a 100% static frame, and make a duplicate */ - ret = ast_frisolate(f); - /* Restore its true malloc status */ - f->mallocd = p; - return ret; + struct ast_frame *out; + int len; + void *buf; + /* Start with standard stuff */ + len = sizeof(struct ast_frame) + AST_FRIENDLY_OFFSET + f->datalen; + /* If we have a source, add space for it */ + if (f->src && strlen(f->src)) + len += strlen(f->src) + 1; + buf = malloc(len); + if (!buf) + return NULL; + out = buf; + /* Set us as having malloc'd header only, so it will eventually + get freed. */ + out->frametype = f->frametype; + out->subclass = f->subclass; + out->datalen = f->datalen; + out->samples = f->samples; + out->mallocd = AST_MALLOCD_HDR; + out->offset = AST_FRIENDLY_OFFSET; + out->data = buf + sizeof(struct ast_frame) + AST_FRIENDLY_OFFSET; + if (f->src && strlen(f->src)) { + out->src = out->data + f->datalen; + /* Must have space since we allocated for it */ + strcpy(out->src, f->src); + } else + out->src = NULL; + out->prev = NULL; + out->next = NULL; + memcpy(out->data, f->data, out->datalen); + return out; } struct ast_frame *ast_fr_fdread(int fd) diff --git a/pbx.c b/pbx.c index 63f251ed251d432a5ace9d02b5321b305cc73b60..1115580aa018e1fc4dcfc5ce36bb8b9e5c9f4bae 100755 --- a/pbx.c +++ b/pbx.c @@ -678,97 +678,125 @@ static struct ast_exten *pbx_find_extension(struct ast_channel *chan, char *cont static void pbx_substitute_variables_temp(struct ast_channel *c,char *cp3,char **cp4) { - int offset; + char *first,*second; + int offset,offset2; struct ast_var_t *variables; char *name, *num; /* for callerid name + num variables */ struct varshead *headp; char pri[80]; headp=&c->varshead; *cp4=NULL; - /* Now we have the variable name on cp3 */ - if (!strcmp(cp3, "CALLERIDNUM")) { - char cid[256] = ""; - if (c->callerid) - strncpy(cid, c->callerid, sizeof(cid) - 1); - ast_callerid_parse(cid, &name, &num); - if (num) { - ast_shrink_phone_number(num); - *cp4 = num; - } else - *cp4 = ""; - } else if (!strcmp(cp3, "CALLERIDNAME")) { - char cid[256] = ""; - if (c->callerid) - strncpy(cid, c->callerid, sizeof(cid) - 1); - ast_callerid_parse(cid, &name, &num); - if (name) - *cp4 = name; - else - *cp4 = ""; - } else if (!strcmp(cp3, "CALLERID")) { - *cp4 = c->callerid; - if (!(*cp4)) - *cp4 = ""; - } else if (!strcmp(cp3, "EXTEN")) { - *cp4 = c->exten; - } else if (!strncmp(cp3, "EXTEN-", strlen("EXTEN-")) && - /* XXX Remove me eventually */ - (sscanf(cp3 + strlen("EXTEN-"), "%d", &offset) == 1)) { - if (offset < 0) - offset=0; - if (offset > strlen(c->exten)) - offset = strlen(c->exten); - *cp4 = c->exten + offset; - ast_log(LOG_WARNING, "The use of 'EXTEN-foo' has been derprecated in favor of 'EXTEN:foo'\n"); - } else if (!strncmp(cp3, "EXTEN:", strlen("EXTEN:")) && - (sscanf(cp3 + strlen("EXTEN:"), "%d", &offset) == 1)) { - if (offset < 0) - offset=0; - if (offset > strlen(c->exten)) - offset = strlen(c->exten); - *cp4 = c->exten + offset; - } else if (!strcmp(cp3, "RDNIS")) { - *cp4 = c->rdnis; - if (!(*cp4)) - *cp4 = ""; - } else if (!strcmp(cp3, "CONTEXT")) { - *cp4 = c->context; - } else if (!strcmp(cp3, "PRIORITY")) { - snprintf(pri, sizeof(pri), "%d", c->priority); - *cp4 = pri; - } else { - AST_LIST_TRAVERSE(headp,variables,entries) { + /* Now we have the variable name on cp3 */ + if ((first=strchr(cp3,':'))) { + *first='\0'; + offset=atoi(first+1); + if ((second=strchr(first+1,':'))) { + *second='\0'; + offset2=atoi(second+1); + } else { + offset2=offset; + offset=0; + } + pbx_substitute_variables_temp(c,cp3,cp4); + if (!(*cp4)) return; + if (abs(offset)>strlen(*cp4)) { + if (offset>=0) offset=strlen(*cp4); + else offset=-strlen(*cp4); + } + if ((offset<0 && offset2>-offset) || (offset>=0 && offset+offset2>strlen(*cp4))) { + if (offset>=0) offset2=strlen(*cp4)-offset; + else offset2=strlen(*cp4)+offset; + } + if (offset>=0) + *cp4+=offset; + else + *cp4+=strlen(*cp4)+offset; + (*cp4)[offset2] = '\0'; + } else if (!strcmp(cp3, "CALLERIDNUM")) { + char cid[256] = ""; + if (c->callerid) + strncpy(cid, c->callerid, sizeof(cid) - 1); + ast_callerid_parse(cid, &name, &num); + if (num) { + ast_shrink_phone_number(num); + *cp4 = num; + } else + *cp4 = ""; + } else if (!strcmp(cp3, "CALLERIDNAME")) { + char cid[256] = ""; + if (c->callerid) + strncpy(cid, c->callerid, sizeof(cid) - 1); + ast_callerid_parse(cid, &name, &num); + if (name) + *cp4 = name; + else + *cp4 = ""; + } else if (!strcmp(cp3, "CALLERID")) { + *cp4 = c->callerid; + if (!(*cp4)) + *cp4 = ""; + } else if (!strcmp(cp3, "EXTEN")) { + *cp4 = c->exten; + } else if (!strncmp(cp3, "EXTEN-", strlen("EXTEN-")) && + /* XXX Remove me eventually */ + (sscanf(cp3 + strlen("EXTEN-"), "%d", &offset) == 1)) { + if (offset < 0) + offset=0; + if (offset > strlen(c->exten)) + offset = strlen(c->exten); + *cp4 = c->exten + offset; + ast_log(LOG_WARNING, "The use of 'EXTEN-foo' has been derprecated in favor of 'EXTEN:foo'\n"); #if 0 - ast_log(LOG_WARNING,"Comparing variable '%s' with '%s'\n",cp3,ast_var_name(variables)); + } else if (!strncmp(cp3, "EXTEN:", strlen("EXTEN:")) && + (sscanf(cp3 + strlen("EXTEN:"), "%d", &offset) == 1)) { + if (offset < 0) + offset=0; + if (offset > strlen(c->exten)) + offset = strlen(c->exten); + *cp4 = c->exten + offset; #endif - if (strcasecmp(ast_var_name(variables),cp3)==0) - *cp4=ast_var_value(variables); - } - if (!(*cp4)) { - /* Try globals */ - AST_LIST_TRAVERSE(&globals,variables,entries) { + } else if (!strcmp(cp3, "RDNIS")) { + *cp4 = c->rdnis; + if (!(*cp4)) + *cp4 = ""; + } else if (!strcmp(cp3, "CONTEXT")) { + *cp4 = c->context; + } else if (!strcmp(cp3, "PRIORITY")) { + snprintf(pri, sizeof(pri), "%d", c->priority); + *cp4 = pri; + } else { + AST_LIST_TRAVERSE(headp,variables,entries) { #if 0 - ast_log(LOG_WARNING,"Comparing variable '%s' with '%s'\n",cp3,ast_var_name(variables)); + ast_log(LOG_WARNING,"Comparing variable '%s' with '%s'\n",cp3,ast_var_name(variables)); #endif - if (strcasecmp(ast_var_name(variables),cp3)==0) - *cp4=ast_var_value(variables); - } - } - if (!(*cp4)) { - int len=strlen(cp3); - int len_env=strlen("ENV("); - if (len > (len_env+1) && !strncasecmp(cp3,"ENV(",len_env) && !strcmp(cp3+len-1,")")) { - cp3[len-1]='\0'; - *cp4=getenv(cp3+len_env); - } - } - } + if (strcasecmp(ast_var_name(variables),cp3)==0) + *cp4=ast_var_value(variables); + } + if (!(*cp4)) { + /* Try globals */ + AST_LIST_TRAVERSE(&globals,variables,entries) { +#if 0 + ast_log(LOG_WARNING,"Comparing variable '%s' with '%s'\n",cp3,ast_var_name(variables)); +#endif + if (strcasecmp(ast_var_name(variables),cp3)==0) + *cp4=ast_var_value(variables); + } + } + if (!(*cp4)) { + int len=strlen(cp3); + int len_env=strlen("ENV("); + if (len > (len_env+1) && !strncasecmp(cp3,"ENV(",len_env) && !strcmp(cp3+len-1,")")) { + cp3[len-1]='\0'; + *cp4=getenv(cp3+len_env); + } + } + } } static void pbx_substitute_variables_helper(struct ast_channel *c,char *cp1,char **ecp2,int count) { char *cp4,*cp2; - char *tmp,*wherearewe,*finish,*ltmp,*lval,*nextvar; + char *tmp,*wherearewe,*finish=NULL,*ltmp,*lval,*nextvar; int length,variables=0; wherearewe=tmp=cp1; diff --git a/pbx/pbx_config.c b/pbx/pbx_config.c index ab2543895361619b9efa6289ee15bb0f7dadbb3e..f7b143dafb06def00e0252cbfd8cbb5040d09001 100755 --- a/pbx/pbx_config.c +++ b/pbx/pbx_config.c @@ -1512,8 +1512,12 @@ static int pbx_load_module(void) appl = stringp; if (!appl) appl=""; - if (!(start = strchr(appl, '('))) - appl = strsep(&stringp, ","); + if (!(start = strchr(appl, '('))) { + if (stringp) + appl = strsep(&stringp, ","); + else + appl = ""; + } if (start && (end = strrchr(appl, ')'))) { *start = *end = '\0'; data = start + 1; @@ -1525,7 +1529,10 @@ static int pbx_load_module(void) data = strsep(&stringp, "\""); stringp++; } else { - data = strsep(&stringp, ","); + if (stringp) + data = strsep(&stringp, ","); + else + data = ""; } cidmatch = strchr(ext, '/'); if (cidmatch) { diff --git a/res/res_musiconhold.c b/res/res_musiconhold.c index ab347f9d45bee312d56b5b26e5e516f552b9c5d6..dc1839d039ce3bad66bc005b42688bdc254ca654 100755 --- a/res/res_musiconhold.c +++ b/res/res_musiconhold.c @@ -221,8 +221,8 @@ static void *monmp3thread(void *data) res = read(class->pseudofd, buf, sizeof(buf)); } else { /* otherwise just sleep (unreliable) */ - usleep(250000); - res = 2000; + usleep(100000); /* Sleep 100 ms */ + res = 800; /* 800 samples */ } if (!class->members) continue; @@ -328,7 +328,7 @@ static struct mohdata *mohalloc(struct mohclass *cl) static void moh_release(struct ast_channel *chan, void *data) { struct mohdata *moh = data, *prev, *cur; - int oldrfmt, oldwfmt; + int oldwfmt; ast_pthread_mutex_lock(&moh_lock); /* Unlink */ prev = NULL; @@ -350,8 +350,8 @@ static void moh_release(struct ast_channel *chan, void *data) oldwfmt = moh->origwfmt; free(moh); if (chan) { - if (ast_set_write_format(chan, oldwfmt)) - ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %d/%d\n", chan->name, oldwfmt, oldrfmt); + if (oldwfmt && ast_set_write_format(chan, oldwfmt)) + ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %d\n", chan->name, oldwfmt); if (option_verbose > 2) ast_verbose(VERBOSE_PREFIX_3 "Stopped music on hold on %s\n", chan->name); }