📄 chan_misdn.c
字号:
ast_log(LOG_WARNING, " --> ! misdn_call called on ast_channel *ast where ast == NULL\n"); return -1; } if (((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) || !dest ) { ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name); ast->hangupcause=41; ast_setstate(ast, AST_STATE_DOWN); return -1; } if (!ch) { ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name); ast->hangupcause=41; ast_setstate(ast, AST_STATE_DOWN); return -1; } newbc=ch->bc; if (!newbc) { ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name); ast->hangupcause=41; ast_setstate(ast, AST_STATE_DOWN); return -1; } port=newbc->port; if ((exceed=add_out_calls(port))) { char tmp[16]; sprintf(tmp,"%d",exceed); pbx_builtin_setvar_helper(ast,"MAX_OVERFLOW",tmp); return -1; } chan_misdn_log(1, port, "* CALL: %s\n",dest); chan_misdn_log(2, port, " --> * dad:%s tech:%s ctx:%s\n",ast->exten,ast->name, ast->context); chan_misdn_log(3, port, " --> * adding2newbc ext %s\n",ast->exten); if (ast->exten) { int l = sizeof(newbc->dad); strncpy(ast->exten,ext,sizeof(ast->exten)); strncpy(newbc->dad,ext,l); newbc->dad[l-1] = 0; } if (ast->cid.cid_rdnis) strcpy(newbc->rad, ast->cid.cid_rdnis); else newbc->rad[0]=0; chan_misdn_log(3, port, " --> * adding2newbc callerid %s\n",ast->cid.cid_num); if (ast_strlen_zero(newbc->oad) && ast->cid.cid_num ) { if (ast->cid.cid_num) { int l = sizeof(newbc->oad); strncpy(newbc->oad,ast->cid.cid_num, l); newbc->oad[l-1] = 0; } } { int bridging; struct chan_list *ch=MISDN_ASTERISK_TECH_PVT(ast); if (!ch) { ast_verbose("No chan_list in misdn_call\n"); return -1;} newbc->capability=ast->transfercapability; pbx_builtin_setvar_helper(ast,"TRANSFERCAPABILITY",ast_transfercapability2str(newbc->capability)); if ( ast->transfercapability == INFO_CAPABILITY_DIGITAL_UNRESTRICTED) { chan_misdn_log(2, port, " --> * Call with flag Digital\n"); } /* update screening and presentation */ update_config(ch,ORG_AST); /* fill in some ies from channel vary*/ import_ch(ast, newbc, ch); /* Finally The Options Override Everything */ if (opts) misdn_set_opt_exec(ast,opts); else chan_misdn_log(2,port,"NO OPTS GIVEN\n"); /*check for bridging*/ misdn_cfg_get( 0, MISDN_GEN_BRIDGING, &bridging, sizeof(int)); if (bridging && ch->other_ch) {#ifdef MISDN_1_2 chan_misdn_log(1, port, "Disabling EC (aka Pipeline) on both Sides\n"); *ch->bc->pipeline=0; *ch->other_ch->bc->pipeline=0;#else chan_misdn_log(1, port, "Disabling EC on both Sides\n"); ch->bc->ec_enable=0; ch->other_ch->bc->ec_enable=0;#endif } r=misdn_lib_send_event( newbc, EVENT_SETUP ); /** we should have l3id after sending setup **/ ch->l3id=newbc->l3_id; } if ( r == -ENOCHAN ) { chan_misdn_log(0, port, " --> * Theres no Channel at the moment .. !\n"); chan_misdn_log(1, port, " --> * SEND: State Down pid:%d\n",newbc?newbc->pid:-1); ast->hangupcause=34; ast_setstate(ast, AST_STATE_DOWN); return -1; } chan_misdn_log(2, port, " --> * SEND: State Dialing pid:%d\n",newbc?newbc->pid:1); ast_setstate(ast, AST_STATE_DIALING); ast->hangupcause=16; if (newbc->nt) stop_bc_tones(ch); ch->state=MISDN_CALLING; return 0; }static int misdn_answer(struct ast_channel *ast){ struct chan_list *p; if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast)) ) return -1; chan_misdn_log(1, p? (p->bc? p->bc->port : 0) : 0, "* ANSWER:\n"); if (!p) { ast_log(LOG_WARNING, " --> Channel not connected ??\n"); ast_queue_hangup(ast); } if (!p->bc) { chan_misdn_log(1, 0, " --> Got Answer, but theres no bc obj ??\n"); ast_queue_hangup(ast); } { const char *tmp_key = pbx_builtin_getvar_helper(p->ast, "CRYPT_KEY"); if (tmp_key ) { chan_misdn_log(1, p->bc->port, " --> Connection will be BF crypted\n"); { int l = sizeof(p->bc->crypt_key); strncpy(p->bc->crypt_key,tmp_key, l); p->bc->crypt_key[l-1] = 0; } } else { chan_misdn_log(3, p->bc->port, " --> Connection is without BF encryption\n"); } } { const char *nodsp=pbx_builtin_getvar_helper(ast, "MISDN_DIGITAL_TRANS"); if (nodsp) { chan_misdn_log(1, p->bc->port, " --> Connection is transparent digital\n"); p->bc->nodsp=1; p->bc->hdlc=0; p->bc->nojitter=1; } } p->state = MISDN_CONNECTED; stop_indicate(p); if ( ast_strlen_zero(p->bc->cad) ) { chan_misdn_log(2,p->bc->port," --> empty cad using dad\n"); ast_copy_string(p->bc->cad,p->bc->dad,sizeof(p->bc->cad)); } misdn_lib_send_event( p->bc, EVENT_CONNECT); start_bc_tones(p); return 0;}static int misdn_digit_begin(struct ast_channel *chan, char digit){ /* XXX Modify this callback to support Asterisk controlling the length of DTMF */ return 0;}static int misdn_digit_end(struct ast_channel *ast, char digit, unsigned int duration){ struct chan_list *p; struct misdn_bchannel *bc; if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast))) return -1; bc=p->bc; chan_misdn_log(1, bc?bc->port:0, "* IND : Digit %c\n",digit); if (!bc) { ast_log(LOG_WARNING, " --> !! Got Digit Event without having bchannel Object\n"); return -1; } switch (p->state ) { case MISDN_CALLING: { int l; char buf[8]; buf[0]=digit; buf[1]=0; l = sizeof(bc->infos_pending); strncat(bc->infos_pending, buf, l - strlen(bc->infos_pending) - 1); } break; case MISDN_CALLING_ACKNOWLEDGE: { bc->info_dad[0]=digit; bc->info_dad[1]=0; { int l = sizeof(bc->dad); strncat(bc->dad, bc->info_dad, l - strlen(bc->dad) - 1); } { int l = sizeof(p->ast->exten); strncpy(p->ast->exten, bc->dad, l); p->ast->exten[l-1] = 0; } misdn_lib_send_event( bc, EVENT_INFORMATION); } break; default: /* Do not send Digits in CONNECTED State, when * the other side is too mISDN. */ if (p->other_ch ) return 0; if ( bc->send_dtmf ) send_digit_to_chan(p,digit); break; } return 0;}static int misdn_fixup(struct ast_channel *oldast, struct ast_channel *ast){ struct chan_list *p; if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast) )) return -1; chan_misdn_log(1, p->bc?p->bc->port:0, "* IND: Got Fixup State:%s L3id:%x\n", misdn_get_ch_state(p), p->l3id); p->ast = ast ; return 0;}static int misdn_indication(struct ast_channel *ast, int cond, const void *data, size_t datalen){ struct chan_list *p; if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast))) { ast_log(LOG_WARNING, "Returned -1 in misdn_indication\n"); return -1; } if (!p->bc ) { chan_misdn_log(1, 0, "* IND : Indication from %s\n",ast->exten); ast_log(LOG_WARNING, "Private Pointer but no bc ?\n"); return -1; } chan_misdn_log(5, p->bc->port, "* IND : Indication [%d] from %s\n",cond, ast->exten); switch (cond) { case AST_CONTROL_BUSY: chan_misdn_log(1, p->bc->port, "* IND :\tbusy pid:%d\n",p->bc?p->bc->pid:-1); ast_setstate(ast,AST_STATE_BUSY); p->bc->out_cause=17; if (p->state != MISDN_CONNECTED) { start_bc_tones(p); misdn_lib_send_event( p->bc, EVENT_DISCONNECT); } else { chan_misdn_log(-1, p->bc->port, " --> !! Got Busy in Connected State !?! ast:%s\n", ast->name); } return -1; break; case AST_CONTROL_RING: chan_misdn_log(1, p->bc->port, "* IND :\tring pid:%d\n",p->bc?p->bc->pid:-1); return -1; break; case AST_CONTROL_RINGING: chan_misdn_log(1, p->bc->port, "* IND :\tringing pid:%d\n",p->bc?p->bc->pid:-1); switch (p->state) { case MISDN_ALERTING: chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d but I was Ringing before, so ignoring it\n",p->bc?p->bc->pid:-1); break; case MISDN_CONNECTED: chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d but Connected, so just send TONE_ALERTING without state changes \n",p->bc?p->bc->pid:-1); return -1; break; default: p->state=MISDN_ALERTING; chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d\n",p->bc?p->bc->pid:-1); misdn_lib_send_event( p->bc, EVENT_ALERTING); if (p->other_ch && p->other_ch->bc) { if (misdn_inband_avail(p->other_ch->bc)) { chan_misdn_log(2,p->bc->port, " --> other End is mISDN and has inband info available\n"); break; } if (!p->other_ch->bc->nt) { chan_misdn_log(2,p->bc->port, " --> other End is mISDN TE so it has inband info for sure (?)\n"); break; } } chan_misdn_log(3, p->bc->port, " --> * SEND: State Ring pid:%d\n",p->bc?p->bc->pid:-1); ast_setstate(ast,AST_STATE_RINGING); if ( !p->bc->nt && (p->originator==ORG_MISDN) && !p->incoming_early_audio ) chan_misdn_log(2,p->bc->port, " --> incoming_early_audio off\n"); else return -1; } break; case AST_CONTROL_ANSWER: chan_misdn_log(1, p->bc->port, " --> * IND :\tanswer pid:%d\n",p->bc?p->bc->pid:-1); start_bc_tones(p); break; case AST_CONTROL_TAKEOFFHOOK: chan_misdn_log(1, p->bc->port, " --> *\ttakeoffhook pid:%d\n",p->bc?p->bc->pid:-1); return -1; break; case AST_CONTROL_OFFHOOK: chan_misdn_log(1, p->bc->port, " --> *\toffhook pid:%d\n",p->bc?p->bc->pid:-1); return -1; break; case AST_CONTROL_FLASH: chan_misdn_log(1, p->bc->port, " --> *\tflash pid:%d\n",p->bc?p->bc->pid:-1); break; case AST_CONTROL_PROGRESS: chan_misdn_log(1, p->bc->port, " --> * IND :\tprogress pid:%d\n",p->bc?p->bc->pid:-1); misdn_lib_send_event( p->bc, EVENT_PROGRESS); break; case AST_CONTROL_PROCEEDING: chan_misdn_log(1, p->bc->port, " --> * IND :\tproceeding pid:%d\n",p->bc?p->bc->pid:-1); misdn_lib_send_event( p->bc, EVENT_PROCEEDING); break; case AST_CONTROL_CONGESTION: chan_misdn_log(1, p->bc->port, " --> * IND :\tcongestion pid:%d\n",p->bc?p->bc->pid:-1); p->bc->out_cause=42; start_bc_tones(p); misdn_lib_send_event( p->bc, EVENT_DISCONNECT); if (p->bc->nt) { hanguptone_indicate(p); } break; case -1 : chan_misdn_log(1, p->bc->port, " --> * IND :\t-1! (stop indication) pid:%d\n",p->bc?p->bc->pid:-1); stop_indicate(p); if (p->state == MISDN_CONNECTED) start_bc_tones(p); break; case AST_CONTROL_HOLD: ast_moh_start(ast,data,ast->musicclass); chan_misdn_log(1, p->bc->port, " --> *\tHOLD pid:%d\n",p->bc?p->bc->pid:-1); break; case AST_CONTROL_UNHOLD: ast_moh_stop(ast); chan_misdn_log(1, p->bc->port, " --> *\tUNHOLD pid:%d\n",p->bc?p->bc->pid:-1); break; default: chan_misdn_log(1, p->bc->port, " --> * Unknown Indication:%d pid:%d\n",cond,p->bc?p->bc->pid:-1); } return 0;}static int misdn_hangup(struct ast_channel *ast){ struct chan_list *p; struct misdn_bchannel *bc=NULL; ast_log(LOG_DEBUG, "misdn_hangup(%s)\n", ast->name); if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast) ) ) return -1; if (!p) { chan_misdn_log(3, 0, "misdn_hangup called, without chan_list obj.\n"); return 0 ; } bc=p->bc; if (bc) { const char *tmp=pbx_builtin_getvar_helper(ast,"MISDN_USERUSER"); if (tmp) { ast_log(LOG_NOTICE, "MISDN_USERUSER: %s\n", tmp); strcpy(bc->uu, tmp); bc->uulen=strlen(bc->uu); } } MISDN_ASTERISK_TECH_PVT(ast)=NULL; p->ast=NULL; if (ast->_state == AST_STATE_RESERVED || p->state == MISDN_NOTHING || p->state == MISDN_HOLDED || p->state == MISDN_HOLD_DISCONNECT ) { CLEAN_CH: /* between request and call */ ast_log(LOG_DEBUG, "State Reserved (or nothing) => chanIsAvail\n"); MISDN_ASTERISK_TECH_PVT(ast)=NULL; ast_mutex_lock(&release_lock); cl_dequeue_chan(&cl_te, p); close(p->pipe[0]); close(p->pipe[1]); free(p); ast_mutex_unlock(&release_lock); if (bc) misdn_lib_release(bc); return 0; } if (!bc) { ast_log(LOG_WARNING,"Hangup with private but no bc ? state:%s l3id:%x\n", misdn_get_ch_state(p), p->l3id); goto CLEAN_CH; } p->need_hangup=0; p->need_queue_hangup=0; p->need_busy=0; if (!p->bc->nt) stop_bc_tones(p); { const char *varcause=NULL; bc->out_cause=ast->hangupcause?ast->hangupcause:16; if ( (varcause=pbx_builtin_getvar_helper(ast, "HANGUPCAUSE")) || (varcause=pbx_builtin_getvar_helper(ast, "PRI_CAUSE"))) { int tmpcause=atoi(varcause); bc->out_cause=tmpcause?tmpcause:16; } chan_misdn_log(1, bc->port, "* IND : HANGUP\tpid:%d ctx:%s dad:%s oad:%s State:%s\n",p->bc?p->bc->pid:-1, ast->context, ast->exten, ast->cid.cid_num, misdn_get_ch_state(p)); chan_misdn_log(3, bc->port, " --> l3id:%x\n",p->l3id); chan_misdn_log(3, bc->port, " --> cause:%d\n",bc->cause); chan_misdn_log(2, bc->port, " --> out_cause:%d\n",bc->out_cause); chan_misdn_log(2, bc->port, " --> state:%s\n", misdn_get_ch_state(p)); switch (p->state) { case MISDN_CALLING: case MISDN_INCOMING_SETUP: /* This is the only place in misdn_hangup, where we * can call release_chan, else it might create lot's of trouble * */ ast_log(LOG_NOTICE, "release channel, in CALLING/INCOMING_SETUP state.. no other events happened\n"); release_chan(bc); p->state=MISDN_CLEANING; if (bc->need_release_complete) misdn_lib_send_event( bc, EVENT_RELEASE_COMPLETE); break; case MISDN_HOLDED: case MISDN_DIALING: start_bc_tones(p); hanguptone_indicate(p
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -