.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
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)
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
fi
+dont-optimize:
+ make OPTIMIZE= K6OPT= install
+
+valgrind: dont-optimize
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;
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;
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)
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) &&
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) &&
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;
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);
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;
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;
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;
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);
}
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 */
} 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;
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:
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) {
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) {
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);
}
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;
}
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);
}
}
{
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;
+}
+
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
#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 */
######### 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
# 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)
#
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
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
; 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]
;
; 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];
;
; 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.
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)
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;
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;
data = strsep(&stringp, "\"");
stringp++;
} else {
- data = strsep(&stringp, ",");
+ if (stringp)
+ data = strsep(&stringp, ",");
+ else
+ data = "";
}
cidmatch = strchr(ext, '/');
if (cidmatch) {
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;
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;
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);
}