aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xMakefile49
-rwxr-xr-xapps/app_substring.c1
-rwxr-xr-xchannel.c3
-rwxr-xr-xchannels/chan_iax.c3
-rwxr-xr-xchannels/chan_iax2.c191
-rwxr-xr-xchannels/chan_sip.c14
-rwxr-xr-xchannels/chan_zap.c1
-rwxr-xr-xchannels/iax2-parser.c154
-rwxr-xr-xchannels/iax2-parser.h1
-rwxr-xr-xchannels/iax2.h2
-rwxr-xr-xcodecs/gsm/Makefile4
-rwxr-xr-xcodecs/lpc10/Makefile5
-rwxr-xr-xconfigs/extensions.conf.sample10
-rwxr-xr-xframe.c40
-rwxr-xr-xpbx.c180
-rwxr-xr-xpbx/pbx_config.c13
-rwxr-xr-xres/res_musiconhold.c10
17 files changed, 395 insertions, 286 deletions
diff --git a/Makefile b/Makefile
index cd2a4a145..9edd35c6a 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 97f0fea0a..4d3ccceb3 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 0a7eed39d..684adac62 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 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 */
diff --git a/codecs/gsm/Makefile b/codecs/gsm/Makefile
index 9e211f575..721879da9 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 af5131d77..61d87740c 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 0499a3351..f7135ecf6 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 34ec99502..695c5573e 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 63f251ed2..1115580aa 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 ab2543895..f7b143daf 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 ab347f9d4..dc1839d03 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);
}