From 87f28fa6dd6c2ce1ecc44a8a0b143740a40c462e Mon Sep 17 00:00:00 2001 From: Mark Spencer <markster@digium.com> Date: Sun, 1 Feb 2004 20:08:36 +0000 Subject: [PATCH] Add "iaxcompat" option to allow nested switch statements, still might fail if you have an IAX call going to something with a switch... git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@2104 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- channels/chan_iax2.c | 111 +++++++++++++++++++++++++++++++--------- configs/iax.conf.sample | 5 ++ 2 files changed, 93 insertions(+), 23 deletions(-) diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c index 85fc30ef40..9d8ba48e25 100755 --- a/channels/chan_iax2.c +++ b/channels/chan_iax2.c @@ -106,6 +106,7 @@ static int maxnontrunkcall = 1; static int maxjitterbuffer=3000; static int trunkfreq = 20; static int authdebug = 1; +static int iaxcompat = 0; static int iaxdefaultdpcache=10 * 60; /* Cache dialplan entries for 10 minutes by default */ @@ -3925,6 +3926,75 @@ static int timing_read(int *id, int fd, short events, void *cbdata) return 1; } +struct dpreq_data { + int callno; + char context[AST_MAX_EXTENSION]; + char callednum[AST_MAX_EXTENSION]; + char *callerid; +}; + +static void dp_lookup(int callno, char *context, char *callednum, char *callerid, int skiplock) +{ + unsigned short dpstatus = 0; + struct iax_ie_data ied1; + int mm; + + memset(&ied1, 0, sizeof(ied1)); + mm = ast_matchmore_extension(NULL, context, callednum, 1, callerid); + /* Must be started */ + if (ast_exists_extension(NULL, context, callednum, 1, callerid)) { + dpstatus = IAX_DPSTATUS_EXISTS; + } else if (ast_canmatch_extension(NULL, context, callednum, 1, callerid)) { + dpstatus = IAX_DPSTATUS_CANEXIST; + } else { + dpstatus = IAX_DPSTATUS_NONEXISTANT; + } + if (ast_ignore_pattern(context, callednum)) + dpstatus |= IAX_DPSTATUS_IGNOREPAT; + if (mm) + dpstatus |= IAX_DPSTATUS_MATCHMORE; + if (!skiplock) + ast_mutex_lock(&iaxsl[callno]); + if (iaxs[callno]) { + iax_ie_append_str(&ied1, IAX_IE_CALLED_NUMBER, callednum); + iax_ie_append_short(&ied1, IAX_IE_DPSTATUS, dpstatus); + iax_ie_append_short(&ied1, IAX_IE_REFRESH, iaxdefaultdpcache); + send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_DPREP, 0, ied1.buf, ied1.pos, -1); + } + if (!skiplock) + ast_mutex_unlock(&iaxsl[callno]); +} + +static void *dp_lookup_thread(void *data) +{ + /* Look up for dpreq */ + struct dpreq_data *dpr = data; + dp_lookup(dpr->callno, dpr->context, dpr->callednum, dpr->callerid, 0); + if (dpr->callerid) + free(dpr->callerid); + free(dpr); + return NULL; +} + +static void spawn_dp_lookup(int callno, char *context, char *callednum, char *callerid) +{ + pthread_t newthread; + struct dpreq_data *dpr; + dpr = malloc(sizeof(struct dpreq_data)); + if (dpr) { + memset(dpr, 0, sizeof(struct dpreq_data)); + dpr->callno = callno; + strncpy(dpr->context, context, sizeof(dpr->context) - 1); + strncpy(dpr->callednum, callednum, sizeof(dpr->callednum) - 1); + if (callerid) + dpr->callerid = strdup(callerid); + if (pthread_create(&newthread, NULL, dp_lookup_thread, dpr)) { + ast_log(LOG_WARNING, "Unable to start lookup thread!\n"); + } + } else + ast_log(LOG_WARNING, "Out of memory!\n"); +} + static int socket_read(int *id, int fd, short events, void *cbdata) { struct sockaddr_in sin; @@ -3951,7 +4021,6 @@ static int socket_read(int *id, int fd, short events, void *cbdata) struct iax_ie_data ied0, ied1; int format; int exists; - int mm; int minivid = 0; unsigned int ts; char empty[32]=""; /* Safety measure */ @@ -4346,9 +4415,12 @@ retryowner: fr.callno = make_trunk(fr.callno, 1); } /* This might re-enter the IAX code and need the lock */ - ast_mutex_unlock(&iaxsl[fr.callno]); - exists = ast_exists_extension(NULL, iaxs[fr.callno]->context, iaxs[fr.callno]->exten, 1, iaxs[fr.callno]->callerid); - ast_mutex_lock(&iaxsl[fr.callno]); + if (strcasecmp(iaxs[fr.callno]->exten, "TBD")) { + ast_mutex_unlock(&iaxsl[fr.callno]); + exists = ast_exists_extension(NULL, iaxs[fr.callno]->context, iaxs[fr.callno]->exten, 1, iaxs[fr.callno]->callerid); + ast_mutex_lock(&iaxsl[fr.callno]); + } else + exists = 0; if (!strlen(iaxs[fr.callno]->secret) && !strlen(iaxs[fr.callno]->inkeys)) { if (strcmp(iaxs[fr.callno]->exten, "TBD") && !exists) { memset(&ied0, 0, sizeof(ied0)); @@ -4411,25 +4483,13 @@ retryowner: /* Request status in the dialplan */ if ((iaxs[fr.callno]->state & IAX_STATE_TBD) && !(iaxs[fr.callno]->state & IAX_STATE_STARTED) && ies.called_number) { - unsigned short dpstatus = 0; - memset(&ied1, 0, sizeof(ied1)); - mm = ast_matchmore_extension(NULL, iaxs[fr.callno]->context, ies.called_number, 1, iaxs[fr.callno]->callerid); - /* Must be started */ - if (ast_exists_extension(NULL, iaxs[fr.callno]->context, ies.called_number, 1, iaxs[fr.callno]->callerid)) { - dpstatus = IAX_DPSTATUS_EXISTS; - } else if (ast_canmatch_extension(NULL, iaxs[fr.callno]->context, ies.called_number, 1, iaxs[fr.callno]->callerid)) { - dpstatus = IAX_DPSTATUS_CANEXIST; + if (iaxcompat) { + /* Spawn a thread for the lookup */ + spawn_dp_lookup(fr.callno, iaxs[fr.callno]->context, ies.called_number, iaxs[fr.callno]->callerid); } else { - dpstatus = IAX_DPSTATUS_NONEXISTANT; + /* Just look it up */ + dp_lookup(fr.callno, iaxs[fr.callno]->context, ies.called_number, iaxs[fr.callno]->callerid, 1); } - if (ast_ignore_pattern(iaxs[fr.callno]->context, ies.called_number)) - dpstatus |= IAX_DPSTATUS_IGNOREPAT; - if (mm) - dpstatus |= IAX_DPSTATUS_MATCHMORE; - iax_ie_append_str(&ied1, IAX_IE_CALLED_NUMBER, ies.called_number); - iax_ie_append_short(&ied1, IAX_IE_DPSTATUS, dpstatus); - iax_ie_append_short(&ied1, IAX_IE_REFRESH, iaxdefaultdpcache); - send_command(iaxs[fr.callno], AST_FRAME_IAX, IAX_COMMAND_DPREP, 0, ied1.buf, ied1.pos, -1); } break; case IAX_COMMAND_HANGUP: @@ -4603,8 +4663,11 @@ retryowner: send_command_final(iaxs[fr.callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); break; } - /* This might re-enter the IAX code and need the lock */ - exists = ast_exists_extension(NULL, iaxs[fr.callno]->context, iaxs[fr.callno]->exten, 1, iaxs[fr.callno]->callerid); + if (strcasecmp(iaxs[fr.callno]->exten, "TBD")) { + /* This might re-enter the IAX code and need the lock */ + exists = ast_exists_extension(NULL, iaxs[fr.callno]->context, iaxs[fr.callno]->exten, 1, iaxs[fr.callno]->callerid); + } else + exists = 0; if (strcmp(iaxs[fr.callno]->exten, "TBD") && !exists) { if (authdebug) ast_log(LOG_NOTICE, "Rejected connect attempt from %s, request '%s@%s' does not exist\n", inet_ntoa(sin.sin_addr), iaxs[fr.callno]->exten, iaxs[fr.callno]->context); @@ -5563,6 +5626,8 @@ static int set_config(char *config_file, struct sockaddr_in* sin){ capability &= ~format; } else if (!strcasecmp(v->name, "register")) { iax2_register(v->value, v->lineno); + } else if (!strcasecmp(v->name, "iaxcompat")) { + iaxcompat = ast_true(v->value); } else if (!strcasecmp(v->name, "tos")) { if (sscanf(v->value, "%i", &format) == 1) tos = format & 0xff; diff --git a/configs/iax.conf.sample b/configs/iax.conf.sample index 06ee8de2f3..42f5ed9e51 100755 --- a/configs/iax.conf.sample +++ b/configs/iax.conf.sample @@ -10,6 +10,11 @@ port=5036 ;bindaddr=192.168.0.1 ; +; Set iaxcompat to yes if you plan to use layered +; switches. It incurs a small performance hit to enable it +; +;iaxcompat=yes +; ; You may specify a global default AMA flag for iaxtel calls. It must be ; one of 'default', 'omit', 'billing', or 'documentation'. These flags ; are used in the generation of call detail records. -- GitLab