diff options
-rw-r--r-- | channels/chan_misdn.c | 312 |
1 files changed, 151 insertions, 161 deletions
diff --git a/channels/chan_misdn.c b/channels/chan_misdn.c index 94d107605..af093fb75 100644 --- a/channels/chan_misdn.c +++ b/channels/chan_misdn.c @@ -3758,7 +3758,6 @@ int add_in_calls(int port) int max_in_calls; misdn_cfg_get( port, MISDN_CFG_MAX_IN, &max_in_calls, sizeof(max_in_calls)); - misdn_in_calls[port]++; if (max_in_calls >=0 && max_in_calls<misdn_in_calls[port]) { @@ -3786,7 +3785,24 @@ int add_out_calls(int port) return 0; } +static void wait_for_digits(struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan) { + ch->state=MISDN_WAITING4DIGS; + misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE ); + if (bc->nt) + dialtone_indicate(ch); +} +static void start_pbx(struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan) { + if (pbx_start_chan(ch)<0) { + hangup_chan(ch); + chan_misdn_log(-1, bc->port, "ast_pbx_start returned <0 in SETUP\n"); + if (bc->nt) { + hanguptone_indicate(ch); + misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE ); + } else + misdn_lib_send_event(bc, EVENT_RELEASE); + } +} /************************************************************/ /* Receive Events from isdn_lib here */ @@ -3918,41 +3934,30 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) case EVENT_INFORMATION: { - int stop_tone; - misdn_cfg_get( 0, MISDN_GEN_STOP_TONE, &stop_tone, sizeof(int)); + int l; - if ( (ch->state != MISDN_CONNECTED) && stop_tone ) { + if ( ch->state != MISDN_CONNECTED ) stop_indicate(ch); - } if (!ch->ast) break; if (ch->state == MISDN_WAITING4DIGS ) { /* Ok, incomplete Setup, waiting till extension exists */ - if (ast_strlen_zero(bc->info_dad) && ! ast_strlen_zero(bc->keypad)) { chan_misdn_log(1, bc->port, " --> using keypad as info\n"); strcpy(bc->info_dad,bc->keypad); } - { - int l = sizeof(bc->dad); - strncat(bc->dad,bc->info_dad, l); - bc->dad[l-1] = 0; - } - - - { - int l = sizeof(ch->ast->exten); - strncpy(ch->ast->exten, bc->dad, l); - ch->ast->exten[l-1] = 0; - } -/* chan_misdn_log(5, bc->port, "Can Match Extension: dad:%s oad:%s\n",bc->dad,bc->oad);*/ - + l = sizeof(bc->dad); + strncat(bc->dad,bc->info_dad, l); + bc->dad[l-1] = 0; + + l = sizeof(ch->ast->exten); + strncpy(ch->ast->exten, bc->dad, l); + ch->ast->exten[l-1] = 0; + /* Check for Pickup Request first */ if (!strcmp(ch->ast->exten, ast_pickup_ext())) { - int ret;/** Sending SETUP_ACK**/ - ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE ); if (ast_pickup_call(ch->ast)) { hangup_chan(ch); } else { @@ -3966,15 +3971,23 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) } if(!ast_canmatch_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) { + if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->oad)) { + ast_log(LOG_WARNING, "Extension can never match, So jumping to 'i' extension. port(%d)\n",bc->port); + strcpy(ch->ast->exten, "i"); + start_pbx(ch, bc, ch->ast); + break; + } + + ast_log(LOG_WARNING, "Extension can never match, so disconnecting on port(%d)." + "maybe you want to add an 'i' extension to catch this case.\n", + bc->port); - chan_misdn_log(-1, bc->port, "Extension can never match, so disconnecting\n"); if (bc->nt) hanguptone_indicate(ch); ch->state=MISDN_EXTCANTMATCH; bc->out_cause=1; misdn_lib_send_event(bc, EVENT_DISCONNECT ); - break; } @@ -3989,21 +4002,8 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) break; } - if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) { - ch->state=MISDN_DIALING; - - stop_indicate(ch); -/* chan_misdn_log(1, bc->port, " --> * Starting Ast ctx:%s\n", ch->context);*/ - if (pbx_start_chan(ch)<0) { - hangup_chan(ch); - - chan_misdn_log(-1, bc->port, "ast_pbx_start returned < 0 in INFO\n"); - if (bc->nt) hanguptone_indicate(ch); - - misdn_lib_send_event(bc, EVENT_DISCONNECT ); - } - } - + if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) + start_pbx(ch, bc, ch->ast); } else { /* sending INFOS as DTMF-Frames :) */ struct ast_frame fr; @@ -4051,7 +4051,6 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) } } } - int msn_valid = misdn_cfg_is_msn_valid(bc->port, bc->dad); if (!bc->nt && ! msn_valid) { @@ -4071,12 +4070,28 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) print_bearer(bc); { + int msn_valid = misdn_cfg_is_msn_valid(bc->port, bc->dad); + if (!bc->nt && ! msn_valid) { + chan_misdn_log(1, bc->port, " --> Ignoring Call, its not in our MSN List\n"); + return RESPONSE_IGNORE_SETUP; /* Ignore MSNs which are not in our List */ + } + + if (bc->cw) { + chan_misdn_log(0, bc->port, " --> Call Waiting on PMP sending RELEASE_COMPLETE\n"); + int cause; + misdn_cfg_get( bc->port, MISDN_CFG_REJECT_CAUSE, &cause, sizeof(cause)); + bc->out_cause=cause?cause:16; + return RESPONSE_RELEASE_SETUP; + } + + print_bearer(bc); + struct chan_list *ch=init_chan_list(ORG_MISDN); struct ast_channel *chan; int exceed; if (!ch) { chan_misdn_log(-1, bc->port, "cb_events: malloc for chan_list failed!\n"); return 0;} - + ch->bc = bc; ch->l3id=bc->l3_id; ch->addr=bc->addr; @@ -4092,7 +4107,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) } read_config(ch, ORG_MISDN); - + export_ch(chan, bc, ch); ch->ast->rings=1; @@ -4102,49 +4117,48 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) switch (bc->pres) { case 1: - pres=AST_PRES_RESTRICTED; chan_misdn_log(2,bc->port," --> PRES: Restricted (1)\n"); - break; + pres=AST_PRES_RESTRICTED; chan_misdn_log(2,bc->port," --> PRES: Restricted (1)\n"); + break; case 2: - pres=AST_PRES_UNAVAILABLE; chan_misdn_log(2,bc->port," --> PRES: Restricted (2)\n"); - break; + pres=AST_PRES_UNAVAILABLE; chan_misdn_log(2,bc->port," --> PRES: Restricted (2)\n"); + break; default: - pres=AST_PRES_ALLOWED; chan_misdn_log(2,bc->port," --> PRES: Restricted (%d)\n", bc->pres); + pres=AST_PRES_ALLOWED; chan_misdn_log(2,bc->port," --> PRES: Restricted (%d)\n", bc->pres); } switch (bc->screen) { case 0: - screen=AST_PRES_USER_NUMBER_UNSCREENED; chan_misdn_log(2,bc->port," --> SCREEN: Unscreened (0)\n"); - break; + screen=AST_PRES_USER_NUMBER_UNSCREENED; chan_misdn_log(2,bc->port," --> SCREEN: Unscreened (0)\n"); + break; case 1: - screen=AST_PRES_USER_NUMBER_PASSED_SCREEN; chan_misdn_log(2,bc->port," --> SCREEN: Passed screen (1)\n"); - break; + screen=AST_PRES_USER_NUMBER_PASSED_SCREEN; chan_misdn_log(2,bc->port," --> SCREEN: Passed screen (1)\n"); + break; case 2: - screen=AST_PRES_USER_NUMBER_FAILED_SCREEN; chan_misdn_log(2,bc->port," --> SCREEN: failed screen (2)\n"); - break; + screen=AST_PRES_USER_NUMBER_FAILED_SCREEN; chan_misdn_log(2,bc->port," --> SCREEN: failed screen (2)\n"); + break; case 3: - screen=AST_PRES_NETWORK_NUMBER; chan_misdn_log(2,bc->port," --> SCREEN: Network Number (3)\n"); - break; + screen=AST_PRES_NETWORK_NUMBER; chan_misdn_log(2,bc->port," --> SCREEN: Network Number (3)\n"); + break; default: - screen=AST_PRES_USER_NUMBER_UNSCREENED; chan_misdn_log(2,bc->port," --> SCREEN: Unscreened (%d)\n",bc->screen); + screen=AST_PRES_USER_NUMBER_UNSCREENED; chan_misdn_log(2,bc->port," --> SCREEN: Unscreened (%d)\n",bc->screen); } chan->cid.cid_pres=pres+screen; pbx_builtin_setvar_helper(chan, "TRANSFERCAPABILITY", ast_transfercapability2str(bc->capability)); chan->transfercapability=bc->capability; - + switch (bc->capability) { - case INFO_CAPABILITY_DIGITAL_UNRESTRICTED: - pbx_builtin_setvar_helper(chan,"CALLTYPE","DIGITAL"); - break; - default: - pbx_builtin_setvar_helper(chan,"CALLTYPE","SPEECH"); + case INFO_CAPABILITY_DIGITAL_UNRESTRICTED: + pbx_builtin_setvar_helper(chan,"CALLTYPE","DIGITAL"); + break; + default: + pbx_builtin_setvar_helper(chan,"CALLTYPE","SPEECH"); } /** queue new chan **/ cl_queue_chan(&cl_te, ch) ; - if (!strstr(ch->allowed_bearers,"all")) { int i; for (i=0; i< sizeof(allowed_bearers_array)/sizeof(struct allowed_bearers); i++) { @@ -4152,16 +4166,16 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) if ( !strstr( ch->allowed_bearers, allowed_bearers_array[i].name)) { chan_misdn_log(0,bc->port,"Bearer Not allowed\b"); bc->out_cause=88; - + ch->state=MISDN_EXTCANTMATCH; misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE ); return RESPONSE_OK; } } - + } } - + /* Check for Pickup Request first */ if (!strcmp(chan->exten, ast_pickup_ext())) { if (!ch->noautorespond_on_setup) { @@ -4180,41 +4194,43 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) break; } } - + /* - added support for s extension hope it will help those poor cretains - which haven't overlap dial. - */ - { - int ai; - misdn_cfg_get( bc->port, MISDN_CFG_ALWAYS_IMMEDIATE, &ai, sizeof(ai)); - if ( ai ) { - do_immediate_setup(bc, ch , chan); - break; - } - - - + added support for s extension hope it will help those poor cretains + which haven't overlap dial. + */ + int ai; + misdn_cfg_get( bc->port, MISDN_CFG_ALWAYS_IMMEDIATE, &ai, sizeof(ai)); + if ( ai ) { + do_immediate_setup(bc, ch , chan); + break; } /* check if we should jump into s when we have no dad */ - { - int im; - misdn_cfg_get( bc->port, MISDN_CFG_IMMEDIATE, &im, sizeof(im)); - if ( im && ast_strlen_zero(bc->dad) ) { - do_immediate_setup(bc, ch , chan); - break; - } + int im; + misdn_cfg_get( bc->port, MISDN_CFG_IMMEDIATE, &im, sizeof(im)); + if ( im && ast_strlen_zero(bc->dad) ) { + do_immediate_setup(bc, ch , chan); + break; } - - chan_misdn_log(5,bc->port,"CONTEXT:%s\n",ch->context); - if(!ast_canmatch_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) { - - chan_misdn_log(-1, bc->port, "Extension can never match, so disconnecting\n"); + chan_misdn_log(5,bc->port,"CONTEXT:%s\n",ch->context); + if(!ast_canmatch_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) { + if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->oad)) { + ast_log(LOG_WARNING, "Extension can never match, So jumping to 'i' extension. port(%d)\n",bc->port); + strcpy(ch->ast->exten, "i"); + misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE); + ch->state=MISDN_DIALING; + start_pbx(ch, bc, chan); + break; + } + ast_log(LOG_WARNING, "Extension can never match, so disconnecting on port(%d)." + "maybe you want to add an 'i' extension to catch this case.\n", + bc->port); if (bc->nt) hanguptone_indicate(ch); + ch->state=MISDN_EXTCANTMATCH; bc->out_cause=1; @@ -4222,91 +4238,65 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE ); else misdn_lib_send_event(bc, EVENT_RELEASE ); - + break; } - - if (!ch->overlap_dial && ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) { - + + /* Whatever happens, when sending_complete is set or we are PTMP TE, we will definitely + * jump into the dialplan, when the dialed extension does not exist, the 's' extension + * will be used by Asterisk automatically. */ + if (bc->sending_complete || (!bc->nt && !misdn_lib_is_ptp(bc->port))) { if (!ch->noautorespond_on_setup) { ch->state=MISDN_DIALING; - - if (!bc->sending_complete && - (bc->nt || (bc->need_more_infos && misdn_lib_is_ptp(bc->port)))) { - int ret; - ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE ); - } else { - int ret; - ret= misdn_lib_send_event(bc, EVENT_PROCEEDING ); - } + misdn_lib_send_event(bc, EVENT_PROCEEDING ); } else { ch->state = MISDN_INCOMING_SETUP; } - - if (pbx_start_chan(ch)<0) { - hangup_chan(ch); + start_pbx(ch, bc, chan); + break; + } - chan_misdn_log(-1, bc->port, "ast_pbx_start returned <0 in SETUP\n"); - chan=NULL; + /* + * If overlapdial we will definitely send a SETUP_ACKNOWLEDGE and wait for more + * Infos with a Interdigit Timeout. + * */ + if (ch->overlap_dial) { + ast_mutex_lock(&ch->overlap_tv_lock); + ch->overlap_tv = ast_tvnow(); + ast_mutex_unlock(&ch->overlap_tv_lock); - if (bc->nt) { - hanguptone_indicate(ch); - misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE ); - } else - misdn_lib_send_event(bc, EVENT_RELEASE); - } - } else { + if (ch->overlap_dial_task == -1) + ch->overlap_dial_task = + misdn_tasks_add_variable(ch->overlap_dial, misdn_overlap_dial_task, ch); - if (bc->sending_complete) { - ch->state=MISDN_EXTCANTMATCH; - bc->out_cause=1; - - if (bc->nt) { - chan_misdn_log(0,bc->port," --> sending_complete so we never match ..\n"); - misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE); - } else { - chan_misdn_log(0,bc->port," --> sending_complete so we never match ..\n"); - misdn_lib_send_event(bc, EVENT_RELEASE); - } + wait_for_digits(ch, bc, chan); + break; + } - } else { - int ret= misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE ); - if (ret == -ENOCHAN) { - ast_log(LOG_WARNING,"Channel was catched, before we could Acknowledge\n"); - misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE); - } - /* send tone to phone :) */ - - /** ADD IGNOREPAT **/ - - int stop_tone, dad_len; - ch->state=MISDN_WAITING4DIGS; + /* If the extension does not exist and we're not TE_PTMP we wait for more digis + * without interdigit timeout. + * */ + if (!ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) { + wait_for_digits(ch, bc, chan); + break; + } - misdn_cfg_get( 0, MISDN_GEN_STOP_TONE, &stop_tone, sizeof(int)); + /* + * If the extension exists let's just jump into it. + * */ + if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) { + if (bc->need_more_infos) + misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE ); + else + misdn_lib_send_event(bc, EVENT_PROCEEDING); - dad_len = ast_strlen_zero(bc->dad); - - if ( !dad_len && stop_tone ) - stop_indicate(ch); - else - if (bc->nt) - dialtone_indicate(ch); - - - if (ch->overlap_dial && !dad_len) { - ast_mutex_lock(&ch->overlap_tv_lock); - ch->overlap_tv = ast_tvnow(); - ast_mutex_unlock(&ch->overlap_tv_lock); - if (ch->overlap_dial_task == -1) { - ch->overlap_dial_task = - misdn_tasks_add_variable(ch->overlap_dial, misdn_overlap_dial_task, ch); - } - } - } + ch->state=MISDN_DIALING; + start_pbx(ch, bc, chan); + break; } - } break; + case EVENT_SETUP_ACKNOWLEDGE: { ch->state = MISDN_CALLING_ACKNOWLEDGE; |