Newer
Older
Christian Richter
committed
tone_indicate(ch,TONE_DIAL);
chan_misdn_log(1, bc->port, "* Starting Ast ctx:%s dad:%s oad:%s with 's' extension\n", ast->context, ast->exten, AST_CID_P(ast));
strncpy(ast->exten,"s", 2);
if (ast_pbx_start(ast)<0) {
ast=NULL;
tone_indicate(ch,TONE_BUSY);
Christian Richter
committed
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
else
misdn_lib_send_event(bc, EVENT_DISCONNECT );
}
while (!ast_strlen_zero(p) ) {
fr.frametype = AST_FRAME_DTMF;
fr.subclass = *p ;
fr.src=NULL;
fr.data = NULL ;
fr.datalen = 0;
fr.samples = 0 ;
fr.mallocd =0 ;
fr.offset= 0 ;
if (ch->ast && MISDN_ASTERISK_PVT(ch->ast) && MISDN_ASTERISK_TECH_PVT(ch->ast)) {
ast_queue_frame(ch->ast, &fr);
}
p++;
}
}
Christian Richter
committed
static void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel*bc) {
ast->hangupcause=bc->cause;
switch ( bc->cause) {
case 1: /** Congestion Cases **/
case 2:
case 3:
case 4:
case 22:
case 27:
Christian Richter
committed
/*
* Not Queueing the Congestion anymore, since we want to hear
* the inband message
*
chan_misdn_log(1, bc?bc->port:0, " --> * SEND: Queue Congestion pid:%d\n", bc?bc->pid:-1);
ast_queue_control(ast, AST_CONTROL_CONGESTION);
Christian Richter
committed
*/
break;
case 21:
case 17: /* user busy */
chan_misdn_log(1, bc?bc->port:0, " --> * SEND: Queue Busy pid:%d\n", bc?bc->pid:-1);
ast_queue_control(ast, AST_CONTROL_BUSY);
break;
}
}
void import_ies(struct ast_channel *chan, struct misdn_bchannel *bc)
{
Kevin P. Fleming
committed
const char *tmp;
tmp=pbx_builtin_getvar_helper(chan,"PRI_MODE");
if (tmp) bc->mode=atoi(tmp);
tmp=pbx_builtin_getvar_helper(chan,"PRI_URATE");
if (tmp) bc->urate=atoi(tmp);
tmp=pbx_builtin_getvar_helper(chan,"PRI_RATE");
if (tmp) bc->rate=atoi(tmp);
tmp=pbx_builtin_getvar_helper(chan,"PRI_USER1");
if (tmp) bc->user1=atoi(tmp);
tmp=pbx_builtin_getvar_helper(chan,"RDNIS");
if (tmp) ast_copy_string(bc->rad,tmp,sizeof(bc->rad));
}
void export_ies(struct ast_channel *chan, struct misdn_bchannel *bc)
{
char tmp[32];
sprintf(tmp,"%d",bc->mode);
pbx_builtin_setvar_helper(chan,"PRI_MODE",tmp);
sprintf(tmp,"%d",bc->urate);
pbx_builtin_setvar_helper(chan,"PRI_URATE",tmp);
sprintf(tmp,"%d",bc->rate);
pbx_builtin_setvar_helper(chan,"PRI_RATE",tmp);
sprintf(tmp,"%d",bc->user1);
pbx_builtin_setvar_helper(chan,"PRI_USER1",tmp);
pbx_builtin_setvar_helper(chan,"RDNIS",bc->rad);
/************************************************************/
/* Receive Events from isdn_lib here */
/************************************************************/
Christian Richter
committed
static enum event_response_e
cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
{
struct chan_list *ch=find_chan_by_bc(cl_te, bc);
if (!ch)
ch=find_chan_by_l3id(cl_te, bc->l3_id);
if (event != EVENT_BCHAN_DATA && event != EVENT_TONE_GENERATE) { /* Debug Only Non-Bchan */
Christian Richter
committed
chan_misdn_log(1, bc->port, "I IND :%s oad:%s dad:%s\n", manager_isdn_get_info(event), bc->oad, bc->dad);
misdn_lib_log_ies(bc);
chan_misdn_log(2,bc->port," --> bc_state:%s\n",bc_state2str(bc->bc_state));
}
if (event != EVENT_SETUP) {
if (!ch) {
if (event != EVENT_CLEANUP )
ast_log(LOG_WARNING, "Chan not existing at the moment bc->l3id:%x bc:%p event:%s port:%d channel:%d\n",bc->l3_id, bc, manager_isdn_get_info( event), bc->port,bc->channel);
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
return -1;
}
}
if (ch ) {
switch (event) {
case EVENT_RELEASE:
case EVENT_RELEASE_COMPLETE:
case EVENT_CLEANUP:
break;
default:
if ( !ch->ast || !MISDN_ASTERISK_PVT(ch->ast) || !MISDN_ASTERISK_TECH_PVT(ch->ast)) {
if (event!=EVENT_BCHAN_DATA)
ast_log(LOG_WARNING, "No Ast or No private Pointer in Event (%d:%s)\n", event, manager_isdn_get_info(event));
return -1;
}
}
}
switch (event) {
case EVENT_BCHAN_ACTIVATED:
break;
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
case EVENT_NEW_L3ID:
ch->l3id=bc->l3_id;
break;
case EVENT_NEW_BC:
if (bc)
ch->bc=bc;
break;
case EVENT_DTMF_TONE:
{
/* sending INFOS as DTMF-Frames :) */
struct ast_frame fr;
memset(&fr, 0 , sizeof(fr));
fr.frametype = AST_FRAME_DTMF;
fr.subclass = bc->dtmf ;
fr.src=NULL;
fr.data = NULL ;
fr.datalen = 0;
fr.samples = 0 ;
fr.mallocd =0 ;
fr.offset= 0 ;
chan_misdn_log(2, bc->port, " --> DTMF:%c\n", bc->dtmf);
ast_queue_frame(ch->ast, &fr);
}
break;
case EVENT_STATUS:
break;
case EVENT_INFORMATION:
{
int stop_tone;
misdn_cfg_get( 0, MISDN_GEN_STOP_TONE, &stop_tone, sizeof(int));
if ( stop_tone ) {
tone_indicate(ch,TONE_NONE);
}
if (ch->state == MISDN_WAITING4DIGS ) {
/* Ok, incomplete Setup, waiting till extension exists */
{
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);*/
/* 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)) {
ast_hangup(ch->ast);
} else {
struct ast_channel *chan=ch->ast;
ch->state = MISDN_CALLING_ACKNOWLEDGE;
ch->ast=NULL;
ast_setstate(chan, AST_STATE_DOWN);
ast_hangup(chan);
break;
}
}
Christian Richter
committed
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");
tone_indicate(ch,TONE_BUSY);
ch->state=MISDN_EXTCANTMATCH;
bc->out_cause=1;
Christian Richter
committed
misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
else
misdn_lib_send_event(bc, EVENT_DISCONNECT );
break;
}
Christian Richter
committed
if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
ch->state=MISDN_DIALING;
tone_indicate(ch,TONE_NONE);
Christian Richter
committed
/* chan_misdn_log(1, bc->port, " --> * Starting Ast ctx:%s\n", ch->context);*/
if (ast_pbx_start(ch->ast)<0) {
Christian Richter
committed
chan_misdn_log(-1, bc->port, "ast_pbx_start returned < 0 in INFO\n");
tone_indicate(ch,TONE_BUSY);
Christian Richter
committed
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
else
misdn_lib_send_event(bc, EVENT_DISCONNECT );
}
}
} else {
/* sending INFOS as DTMF-Frames :) */
struct ast_frame fr;
fr.frametype = AST_FRAME_DTMF;
fr.subclass = bc->info_dad[0] ;
fr.src=NULL;
fr.data = NULL ;
fr.datalen = 0;
fr.samples = 0 ;
fr.mallocd =0 ;
fr.offset= 0 ;
int digits;
misdn_cfg_get( 0, MISDN_GEN_APPEND_DIGITS2EXTEN, &digits, sizeof(int));
int l = sizeof(bc->dad);
strncat(bc->dad,bc->info_dad, l);
bc->dad[l-1] = 0;
strncpy(ch->ast->exten, bc->dad, l);
ch->ast->exten[l-1] = 0;
}
ast_queue_frame(ch->ast, &fr);
}
}
}
break;
case EVENT_SETUP:
{
struct chan_list *ch=find_chan_by_bc(cl_te, bc);
if (ch && ch->state != MISDN_NOTHING ) {
chan_misdn_log(1, bc->port, " --> Ignoring Call we have already one\n");
return RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE; /* Ignore MSNs which are not in our List */
}
}
Christian Richter
committed
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 */
}
print_bearer(bc);
{
struct chan_list *ch=init_chan_list();
struct ast_channel *chan;
Christian Richter
committed
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;
ch->orginator = ORG_MISDN;
Christian Richter
committed
chan=misdn_new(ch, AST_STATE_RESERVED,bc->dad, bc->oad, AST_FORMAT_ALAW, bc->port, bc->channel);
Christian Richter
committed
read_config(ch, ORG_MISDN);
Christian Richter
committed
ch->ast->rings=1;
ast_setstate(ch->ast, AST_STATE_RINGING);
if ( bc->pres ) {
chan->cid.cid_pres=AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
} else {
chan->cid.cid_pres=AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN;
}
pbx_builtin_setvar_helper(chan, "TRANSFERCAPABILITY", ast_transfercapability2str(bc->capability));
chan->transfercapability=bc->capability;
Christian Richter
committed
switch (bc->capability) {
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) ;
/* Check for Pickup Request first */
if (!strcmp(chan->exten, ast_pickup_ext())) {
int ret;/** Sending SETUP_ACK**/
ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
if (ast_pickup_call(chan)) {
ast_hangup(chan);
} else {
ch->state = MISDN_CALLING_ACKNOWLEDGE;
ch->ast=NULL;
ast_setstate(chan, AST_STATE_DOWN);
ast_hangup(chan);
break;
}
}
Christian Richter
committed
/*
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;
}
Christian Richter
committed
}
/* 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;
}
chan_misdn_log(5,bc->port,"CONTEXT:%s\n",ch->context);
Christian Richter
committed
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");
tone_indicate(ch,TONE_BUSY);
ch->state=MISDN_EXTCANTMATCH;
bc->out_cause=1;
Christian Richter
committed
misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
else
misdn_lib_send_event(bc, EVENT_DISCONNECT );
break;
}
Christian Richter
committed
if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
ch->state=MISDN_DIALING;
Christian Richter
committed
if (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 );
}
if (ast_pbx_start(chan)<0) {
Christian Richter
committed
chan_misdn_log(-1, bc->port, "ast_pbx_start returned <0 in SETUP\n");
tone_indicate(ch,TONE_BUSY);
Christian Richter
committed
misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
else
misdn_lib_send_event(bc, EVENT_DISCONNECT );
}
} 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 :) */
Christian Richter
committed
/** ADD IGNOREPAT **/
int stop_tone;
misdn_cfg_get( 0, MISDN_GEN_STOP_TONE, &stop_tone, sizeof(int));
if ( (!ast_strlen_zero(bc->dad)) && stop_tone )
tone_indicate(ch,TONE_NONE);
tone_indicate(ch,TONE_DIAL);
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
ch->state=MISDN_WAITING4DIGS;
}
}
break;
case EVENT_SETUP_ACKNOWLEDGE:
{
ch->state = MISDN_CALLING_ACKNOWLEDGE;
if (!ast_strlen_zero(bc->infos_pending)) {
/* TX Pending Infos */
{
int l = sizeof(bc->dad);
strncat(bc->dad,bc->infos_pending, l - strlen(bc->dad));
bc->dad[l-1] = 0;
}
{
int l = sizeof(ch->ast->exten);
strncpy(ch->ast->exten, bc->dad, l);
ch->ast->exten[l-1] = 0;
}
{
int l = sizeof(bc->info_dad);
strncpy(bc->info_dad, bc->infos_pending, l);
bc->info_dad[l-1] = 0;
}
strncpy(bc->infos_pending,"", 1);
misdn_lib_send_event(bc, EVENT_INFORMATION);
}
}
break;
case EVENT_PROCEEDING:
{
if ( misdn_cap_is_speech(bc->capability) &&
misdn_inband_avail(bc) ) {
start_bc_tones(ch);
}
Christian Richter
committed
ch->state = MISDN_PROCEEDING;
ast_queue_control(ch->ast, AST_CONTROL_PROCEEDING);
}
break;
case EVENT_PROGRESS:
if ( misdn_cap_is_speech(bc->capability) &&
misdn_inband_avail(bc)
) {
start_bc_tones(ch);
}
ast_queue_control(ch->ast, AST_CONTROL_PROGRESS);
ch->state=MISDN_PROGRESS;
}
break;
case EVENT_ALERTING:
{
ch->state = MISDN_ALERTING;
ast_queue_control(ch->ast, AST_CONTROL_RINGING);
ast_setstate(ch->ast, AST_STATE_RINGING);
cb_log(1,bc->port,"Set State Ringing\n");
if ( misdn_cap_is_speech(bc->capability) && misdn_inband_avail(bc)) {
start_bc_tones(ch);
}
}
break;
case EVENT_CONNECT:
{
misdn_lib_send_event(bc,EVENT_CONNECT_ACKNOWLEDGE);
struct ast_channel *bridged=AST_BRIDGED_P(ch->ast);
if (bridged && strcasecmp(bridged->tech->type,"mISDN")) {
struct chan_list *bridged_ch=MISDN_ASTERISK_TECH_PVT(bridged);
chan_misdn_log(1,bc->port," --> copying cpndialplan:%d and cad:%s to the A-Channel\n",bc->cpnnumplan,bc->cad);
bridged_ch->bc->cpnnumplan=bc->cpnnumplan;
ast_copy_string(bridged_ch->bc->cad,bc->cad,sizeof(bc->cad));
}
}
case EVENT_CONNECT_ACKNOWLEDGE:
{
ch->l3id=bc->l3_id;
ch->addr=bc->addr;
start_bc_tones(ch);
ch->state = MISDN_CONNECTED;
ast_queue_control(ch->ast, AST_CONTROL_ANSWER);
}
break;
case EVENT_DISCONNECT:
{
struct chan_list *holded_ch=find_holded(cl_te, bc);
send_cause2ast(ch->ast,bc);
if (misdn_inband_avail(bc) && ch->state != MISDN_CONNECTED) {
/* If there's inband information available (e.g. a
recorded message saying what was wrong with the
dialled number, or perhaps even giving an
alternative number, then play it instead of
immediately releasing the call */
Christian Richter
committed
chan_misdn_log(0,bc->port, " --> Inband Info Avail, not sending RELEASE\n");
ch->state = MISDN_DISCONNECTED;
start_bc_tones(ch);
break;
}
/*Check for holded channel, to implement transfer*/
if (holded_ch ) {
if (ch->state == MISDN_CONNECTED ) {
misdn_transfer_bc(ch, holded_ch) ;
misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
break;
}
}
stop_bc_tones(ch);
Christian Richter
committed
/*bc->out_cause=16;*/
bc->out_cause=-1;
Christian Richter
committed
Christian Richter
committed
/*if (ch->state == MISDN_CONNECTED)
misdn_lib_send_event(bc,EVENT_RELEASE);
else
misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
*/
Christian Richter
committed
misdn_lib_send_event(bc,EVENT_RELEASE);
}
break;
case EVENT_RELEASE:
{
switch ( bc->cause) {
case -1:
/*
OK, it really sucks, this is a RELEASE from NT-Stack So we take
it and return easylie, It seems that we've send a DISCONNECT
before, so we should RELEASE_COMPLETE after that Disconnect
(looks like ALERTING State at misdn_hangup !!
*/
Christian Richter
committed
/*return RESPONSE_OK;*/
break;
}
bc->out_cause=16;
Christian Richter
committed
/*stop_bc_tones(ch);
release_chan(bc);*/
misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
}
break;
case EVENT_RELEASE_COMPLETE:
{
stop_bc_tones(ch);
release_chan(bc);
}
break;
case EVENT_TONE_GENERATE:
int tone_len=bc->tone_cnt;
struct ast_channel *ast=ch->ast;
void *tmp;
int res;
int (*generate)(struct ast_channel *chan, void *tmp, int datalen, int samples);
chan_misdn_log(9,bc->port,"TONE_GEN: len:%d\n");
if (!ast->generator) break;
tmp = ast->generatordata;
ast->generatordata = NULL;
generate = ast->generator->generate;
res = generate(ast, tmp, tone_len, tone_len);
ast->generatordata = tmp;
if (res) {
ast_log(LOG_WARNING, "Auto-deactivating generator\n");
ast_deactivate_generator(ast);
} else {
bc->tone_cnt=0;
}
}
break;
case EVENT_BCHAN_DATA:
{
if ( !misdn_cap_is_speech(ch->bc->capability) || bc->nojitter) {
misdn_tx2ast_frm(ch, bc->bframe, bc->bframe_len );
} else {
int len=bc->bframe_len;
ast_log(LOG_DEBUG, "sbuf overflow!\n");
if (len == 0) {
ast_log(LOG_WARNING, "BCHAN_DATA: write buffer overflow port:%d channel:%d!\n",bc->port,bc->channel);
}
{
char blah[1]="\0";
#ifdef FLATTEN_JITTER
{
struct timeval tv;
gettimeofday(&tv,NULL);
if (tv.tv_usec % 10000 > 0 ) {
write(ch->pipe[1], blah,sizeof(blah));
bc->time_usec=tv.tv_usec;
}
}
#else
write(ch->pipe[1], blah,sizeof(blah));
#endif
}
}
}
break;
case EVENT_TIMEOUT:
Christian Richter
committed
misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
break;
{
switch (ch->state) {
case MISDN_CALLING:
Christian Richter
committed
chan_misdn_log(-1, bc?bc->port:0, "GOT TIMOUT AT CALING pid:%d\n", bc?bc->pid:-1);
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
break;
case MISDN_DIALING:
case MISDN_PROGRESS:
break;
default:
misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
}
}
break;
case EVENT_CLEANUP:
{
stop_bc_tones(ch);
release_chan(bc);
}
break;
/***************************/
/** Suplementary Services **/
/***************************/
case EVENT_RETRIEVE:
{
struct ast_channel *hold_ast=AST_BRIDGED_P(ch->ast);
ch->state = MISDN_CONNECTED;
if (hold_ast) {
ast_moh_stop(hold_ast);
}
if ( misdn_lib_send_event(bc, EVENT_RETRIEVE_ACKNOWLEDGE) < 0)
misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
}
break;
case EVENT_HOLD:
{
int hold_allowed;
misdn_cfg_get( bc->port, MISDN_CFG_HOLD_ALLOWED, &hold_allowed, sizeof(int));
if (!hold_allowed) {
Christian Richter
committed
chan_misdn_log(-1, bc->port, "Hold not allowed this port.\n");
misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
break;
}
{
struct chan_list *holded_ch=find_holded(cl_te, bc);
if (holded_ch) {
misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
Christian Richter
committed
chan_misdn_log(-1, bc->port, "We can't use RETRIEVE at the moment due to mISDN bug!\n");
break;
}
}
struct ast_channel *bridged=AST_BRIDGED_P(ch->ast);
if (bridged){
struct chan_list *bridged_ch=MISDN_ASTERISK_TECH_PVT(bridged);
ch->state = MISDN_HOLDED;
ch->l3id = bc->l3_id;
misdn_lib_send_event(bc, EVENT_HOLD_ACKNOWLEDGE);
ast_moh_start(bridged, NULL);
} else {
misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
chan_misdn_log(0, bc->port, "We aren't bridged to anybody\n");
}
}
break;
Christian Richter
committed
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
case EVENT_FACILITY:
print_facility(bc);
switch (bc->fac_type) {
case FACILITY_CALLDEFLECT:
{
struct ast_channel *bridged=AST_BRIDGED_P(ch->ast);
struct chan_list *ch;
if (bridged && MISDN_ASTERISK_TECH_PVT(bridged)) {
ch=MISDN_ASTERISK_TECH_PVT(bridged);
//ch->state=MISDN_FACILITY_DEFLECTED;
if (ch->bc) {
/* todo */
}
}
}
break;
default:
chan_misdn_log(1, bc->port," --> not yet handled\n");
Christian Richter
committed
}
break;
case EVENT_RESTART:
break;
Christian Richter
committed
default:
ast_log(LOG_WARNING, "Got Unknown Event\n");
break;
}
return RESPONSE_OK;
}
/** TE STUFF END **/
/******************************************
*
* Asterisk Channel Endpoint END
*
*
*******************************************/
Christian Richter
committed
static int g_config_initialized=0;
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
int load_module(void)
{
int i;
char ports[256]="";
max_ports=misdn_lib_maxports_get();
if (max_ports<=0) {
ast_log(LOG_ERROR, "Unable to initialize mISDN\n");
return -1;
}
misdn_cfg_init(max_ports);
g_config_initialized=1;
misdn_debug = (int *)malloc(sizeof(int) * (max_ports+1));
misdn_cfg_get( 0, MISDN_GEN_DEBUG, &misdn_debug[0], sizeof(int));
for (i = 1; i <= max_ports; i++)
misdn_debug[i] = misdn_debug[0];
misdn_debug_only = (int *)calloc(max_ports + 1, sizeof(int));
{
char tempbuf[BUFFERSIZE+1];
misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, tempbuf, BUFFERSIZE);
if (strlen(tempbuf))
tracing = 1;
}
ast_mutex_init(&cl_te_lock);
ast_mutex_init(&release_lock_mutex);
misdn_cfg_update_ptp();
misdn_cfg_get_ports_string(ports);
if (strlen(ports))
chan_misdn_log(0, 0, "Got: %s from get_ports\n",ports);
{
struct misdn_lib_iface iface = {
.cb_event = cb_events,
.cb_log = chan_misdn_log,
Christian Richter
committed
.cb_jb_empty = chan_misdn_jb_empty,
};
if (misdn_lib_init(ports, &iface, NULL))
chan_misdn_log(0, 0, "No te ports initialized\n");
}
{
if (ast_channel_register(&misdn_tech)) {
Christian Richter
committed
ast_log(LOG_ERROR, "Unable to register channel class %s\n", misdn_type);
unload_module();
return -1;
}
}
ast_cli_register(&cli_send_display);
ast_cli_register(&cli_send_cd);
ast_cli_register(&cli_send_digit);
ast_cli_register(&cli_toggle_echocancel);
ast_cli_register(&cli_set_tics);
ast_cli_register(&cli_show_cls);
ast_cli_register(&cli_show_cl);
ast_cli_register(&cli_show_config);
ast_cli_register(&cli_show_port);
ast_cli_register(&cli_show_stacks);
ast_cli_register(&cli_restart_port);
ast_cli_register(&cli_port_up);
Christian Richter
committed
ast_cli_register(&cli_port_down);
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
ast_cli_register(&cli_set_debug);
ast_cli_register(&cli_set_crypt_debug);
ast_cli_register(&cli_reload);
ast_register_application("misdn_set_opt", misdn_set_opt_exec, "misdn_set_flags",
"misdn_set_opt(:<opt><optarg>:<opt><optarg>..):\n"
"Sets mISDN opts. and optargs\n"
"\n"
);
ast_register_application("misdn_facility", misdn_facility_exec, "misdn_facility",
"misdn_facility(<FACILITY_TYPE>|<ARG1>|..)\n"
"Sends the Facility Message FACILITY_TYPE with \n"
"the given Arguments to the current ISDN Channel\n"
"Supported Facilities are:\n"
"\n"
"type=calldeflect args=Nr where to deflect\n"
"\n"
);
Christian Richter
committed
misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
chan_misdn_log(0, 0, "-- mISDN Channel Driver Registred -- (BE AWARE THIS DRIVER IS EXPERIMENTAL!)\n");
return 0;
}
int unload_module(void)
{
/* First, take us out of the channel loop */
Christian Richter
committed
ast_log(LOG_VERBOSE, "-- Unregistering mISDN Channel Driver --\n");
if (!g_config_initialized) return 0;
ast_cli_unregister(&cli_send_display);
ast_cli_unregister(&cli_send_cd);
ast_cli_unregister(&cli_send_digit);
ast_cli_unregister(&cli_toggle_echocancel);
ast_cli_unregister(&cli_set_tics);
ast_cli_unregister(&cli_show_cls);
ast_cli_unregister(&cli_show_cl);
ast_cli_unregister(&cli_show_config);
ast_cli_unregister(&cli_show_port);
ast_cli_unregister(&cli_show_stacks);
ast_cli_unregister(&cli_restart_port);
ast_cli_unregister(&cli_port_up);
Christian Richter
committed
ast_cli_unregister(&cli_port_down);
ast_cli_unregister(&cli_set_debug);
ast_cli_unregister(&cli_set_crypt_debug);
ast_cli_unregister(&cli_reload);
/* ast_unregister_application("misdn_crypt"); */
ast_unregister_application("misdn_set_opt");
ast_unregister_application("misdn_facility");
ast_channel_unregister(&misdn_tech);
Christian Richter
committed
free_robin_list();
misdn_cfg_destroy();
misdn_lib_destroy();
if (misdn_debug)
free(misdn_debug);
if (misdn_debug_only)
free(misdn_debug_only);
return 0;
}
int reload(void)
{
reload_config();
return 0;
}